[MakeFile] Project management (BSP) and general makefile writing under Linux

1. Principles of BSP Engineering Management

​ The purpose of BSP project management is to modularize the code, and files with the same attribute are stored in the same directory.

​ 1. Create the required folder and put the files with the same attribute in the corresponding folder.

​ 2. Modify the clk, led, and delay drivers, create the corresponding driver files, and place them in the corresponding directories.

3. Modify the content of the main.c file according to the new driver file written.

2. Makefile preparation

API function description:

patsubst function:

Format:

$(patsubst pattern,replacement,text)

Function brief:

This is a replacement function that replaces the text of text with replacement in turn according to the pattern rules

When replacing, the text of text is divided by "space", "TAB", "carriage return and line feed" to match one by one, whether it conforms to the pattern pattern. If the match is successful, it will be replaced with replacement. Both pattern and replacement can use % as a wildcard (if necessary The original % needs to be escaped with %)

Example: Add a -I to all character fields in the INCLUDES variable.

$(patsubst %, -I %, $(INCLUDES))

foreach function:

Format:

$(foreach <var>,<list>,<text> )

Function brief:

Execute the specified function in a loop, take out the words in the list one by one, put them in the variable specified by the parameter var, and then execute the function of text. The return value of the function is the combination of all text strings, and var is a local temporary variable, which is released after the function is executed.

Example:

src := 1 2 3 4
out := $(foreach i, $(src), i.c)

The out at this time is

1.c 2.c 3.c 4.c

wildcard function:

Format:

$(wildcard PATTERN...) 

Function description:
Expand wildcards. Because $ refers to a variable, the wildcard will be invalid, so use this to expand the characters matched by the wildcard

Example: There are four C files 1.c 2.c 3.c 4.c in the directory

obj := $(patsubst %.c, %o,$(wildcard *.c))

The wildcard * will be assigned to these four c files in turn, $(wildcard *.c) expands to 1.c 2.c 3.c 4.c string, and then the patsubst function replaces .c with .o, and returns the replacement result. At this point: obj is 1.o 2.o 3.o 4.o

notdir function

Format:

$(notdir <names...> )

Function brief:

A function to strip file paths, preserving suffixes.

Example:

dir :=./led/led.c
src :=$(notdir $(dir))

Remove the path, at this time the src result is led.c

VPATH

The special variable "VPATH" in the Makefile file is to complete this function. If this variable is not specified, make will only look for dependent files and object files in the current directory. If this variable is defined, then make will go to the specified directory to find the file when the current directory cannot be found.

static mode

Feature Description: Easier to define multi-objective rules.
Format:

<targets ...>:<target-pattern>:<prereq-patterns>
<commands>
...

Targets defines a series of target files, which are a collection and can have wildcards.
The target-pattern indicates the pattern of the targets, that is, the target set pattern
prereq-patterns is the dependency pattern of the target, and the pattern formed by the target-pattern is defined in turn depending on the target.
$(SOBJS) : obj/%.o : %.S means to compile all .S into .o and store it in the obj directory.

Project file structure

.
├── bsp                              # 板级支持包
│   ├── clk                          # 时钟驱动
│   │   ├── bsp_clk.c
│   │   └── bsp_clk.h
│   ├── delay                        # 延时驱动
│   │   ├── bsp_delay.c
│   │   └── bsp_delay.h
│   └── led                          # 链接驱动                 
│       ├── bsp_led.c
│       └── bsp_led.h
├── imx6ul                           # imx6ul官方库函数
│   ├── cc.h
│   ├── fsl_common.h
│   ├── fsl_iomuxc.h
│   ├── imx6ul.h
│   └── MCIMX6Y2.h
├── imx6ul.lds                       # 链接脚本
├── imxdownload                      # 下载脚本
├── ledc_bsp.code-workspace          # vsc工程
├── load.imx
├── Makefile                         
├── obj                              # 存放obj文件
└── project                          # 工程main和start文件
    ├── main.c
    └── start.S

Link script:

SECTIONS{
        . = 0X87800000;
        .text :
        {
                obj/start.o
                *(.text)
        }
        .rodata ALIGN(4) : {*(.rodata*)}
        .data ALIGN(4)   : { *(.data) }
        __bss_start = .;
        .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
        __bss_end = .;
}

Makefile

Writing steps:
1. Define the variables of the object file and the cross-compilation chain
2. Define the variables of the source file path and the header file path
3. Refer to the header file and add -I (patsubst)
4. Find the source files in the corresponding path, c and S file. (foreach wildcard)
5. Convert to source file name without path
6. Define object file
7. Specify VPATH path, and tell make where to look for dependency files and object files
8.
9. Write clear to clear compiled files. (.PHONY)

TARGET                          ?= test
CROSS_COMPILER                  ?= arm-linux-gnueabihf-
																	
CC                              := $(CROSS_COMPILER)gcc
LD                              := $(CROSS_COMPILER)ld

OBJCOPY                         := $(CROSS_COMPILER)objcopy
OBJDUMP                         := $(CROSS_COMPILER)objdump

INCDIRS                         := imx6ul\
                                   project\
                                   bsp/led\
								   bsp/delay\
								   bsp/clk
							
SRCDIRS                         := imx6ul\
                                   project\
                                   bsp/led\
								   bsp/delay\
								   bsp/clk
                                   

INCLUDE                         := $(patsubst %, -I %,$(INCDIRS))

# 所有C、S文件的路径及文件名
CFILES                          := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
SFILES                          := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))

# 所有C、S文件
CFILENDIR                       := $(notdir $(CFILES))
SFILENDIR                       := $(notdir $(SFILES))

# 所有C -> obj文件,放在obj目录下
COBJS                           := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
SOBJS                           := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))

# 所有的.o文件
OBJS                            := $(SOBJS) $(COBJS)

VPATH                           := $(SRCDIRS)

$(TARGET).bin : $(OBJS)
	$(LD) -Timx6ul.lds -o $(TARGET).elf $^
	$(OBJCOPY) -O binary -S $(TARGET).elf $@
	$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis

$(SOBJS) : obj/%.o : %.S
	$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<


$(COBJS) : obj/%.o : %.c
	$(CC) -Wall -nostdlib -c -O2  $(INCLUDE) -o $@ $<



.PHONY:clear
clear:
	rm -rf $(OBJS) $(TARGET).bin  $(TARGET).elf  $(TARGET).dis

print:
	@echo INCLUDE = $(INCLUDE)
	@echo CFILES  = $(CFILES) $(SFILES)
	@echo CFILENDIR  = $(CFILENDIR)
	@echo SFILENDIR  = $(SFILENDIR)
	@echo ---OBJ = $(OBJS)

Summarize:

1.VPATH is used to specify the directory of source files. (When the current directory cannot be found, look for it in the VPATH directory) It cannot be less.

2. -o problem, originally 输入-o 输出If you write a block of input and output, you can only write -o like this输出 输入

3. gcc parameter description:

-Wall编译后显示所有警告
-nostdlib 不链接标准库(启动文件)
-O2 优化编译及效率

4. Static mode

<targets ...>: <target-pattern>: <prereq-patterns ...>

$(OBJS): obj/%.o : %.S 表示将所有的.S文件编译为.o并且存放到obj目录下去。

Guess you like

Origin blog.csdn.net/qq_44078824/article/details/119948816