Learning of Embedded Makefile

Keywords: Makefile Linux shell Ubuntu

This article is suitable for engineers engaged in embedded uboot migration and driver development. It involves a comparative basis of knowledge points, but the content is not so in-depth.

First, Makefile is the necessary file to manage a large project. When a project involves multiple C language programs and. h header file programs, it must be used to compile and link the project. Makefile file file format:

Goal: Dependence
 TAB command

The command is preceded by a Tab key. If and only if it is a Tab key, it cannot be a space. It must be a Tab key. Then write the command.

1. Writing and execution of a simple Makefile file file

1. Writing Makefile files

Compile A. c file to generate the output file of hello.

  1 hello:hello.c
  2     gcc hello.c -o hello 
  3 
  4 clean:
  5     rm hello
                 

Using the make Hello command on the command line of Linux, you can directly execute the code gcc hello.c -o hello; when you type the make clean command on the command line of Linux, you execute the code rm hello and delete the generated Hello executable file. The make command is equivalent to make hello. The default make executes the command corresponding to the first target.

2. Makefile Analysis of Bare Computer Programs

led.bin: start.o 
	arm-linux-ld -Ttext 0x0 -o led.elf $^	//Generate an executable file led.elf, which is not available for burning
	arm-linux-objcopy -O binary led.elf led.bin  ;Used to generate burnable mirror files.
	arm-linux-objdump -D led.elf > led_elf.dis	;Used for disassembly. Just compile it. elf Format executable program, in turn, get assembly source code
	gcc mkv210_image.c -o mkx210	;gcc Is used to generate executable programs, in Ubuntu In order to execute the following code
	./mkx210 led.bin 210.bin		;Make SD The purpose of the card startup mirror is to add a check head.
	
%.o : %.S    ;%yes makefile The wildcard character in,%.o Represent all.o Document, automatic deduction rules
	arm-linux-gcc -o $@ $< -c	;$@Represents the name of the target file. $<Represents the name of the dependent file;-c It means compiling only without links.

%.o : %.c
	arm-linux-gcc -o $@ $< -c 

.PHONY clean
clean:
	rm *.o *.elf *.bin *.dis mkx210 -f

This is the Makefile file file used to compile a bare-computer program, which involves several knowledge points:

1. Makefile Automatic Derivation Rules

For example, when we make, the command corresponding to led.bin will be executed at this time, but before executing the command, the program will automatically detect the source of the dependent file start.o. First, we can not find where the start.o file is. At this time, the program will look for the following target, first of all, to determine whether the. o file is in. S. If it is generated, it will execute the command under the corresponding target to generate the. o file; if not, the program will detect whether the corresponding. c file is generated, and if so, it will execute the corresponding command to generate. o file. This is the automatic deduction rule of Makefile.

2. Makefile's pseudo-target

The purpose of this program is to execute the command corresponding to the pseudo-target without generating any files, so it is called pseudo-target. Representation is in. PHONY, for example, the clean target above is a pseudo target. It's for deletion purposes.

3. Some automatic variables in Makefile

Also make files predefined symbols of special significance.

$@: The name of the target file in the rule.

$<: Rules rely on file names.

$^: Dependent collection of files.

4. Wildcards in Makefile

(1) *: Several arbitrary characters.

(2) One arbitrary character.

(3) []: Combine the characters in [] with the outside matching at one time.

(4)%: Represents arbitrary characters, but only used in rule description, also known as rule wildcards.

For example, there are 1.c, 2.c, 12.c, and test.c files in the project. The output results are obtained by using the following wildcards:

  1 all:1.c 2.c 12.c test.c
  2     echo *.c #Will output all files
  3     echo ?.c   #Output 1.c and 2.c, length 1
  4     echo [12].c    #Output 1.c and 2.c
  5 

5. Other Notices

(1) The same annotations in Makefile and shell are annotated with #.

(2) Call @ before the command to indicate silent execution, and makefile will not output the command when it is executed. Instead, it outputs the results directly.

(3) The assignment symbols of variables:

"?=": It means that if a variable has been defined before, it will not be assigned. If there is no definition of the variable before, it will be assigned.

"+=": You can think of variables in Makefile as strings, and the assignment operator is equivalent to the strcat function of strings, linking strings together.

"=": The assignment of variables needs to be considered both before and after, not only the value of the former variable, but also if the value of the latter variable changes, it will have an effect on this.

":=": The assignment of variables, only considering the previous code. The code is used to explain the following.

  1 
  2 
  3 A=abc
  4 B=$(A)def
  5 A=ght
  6 
  7 all:
  8     echo $B    
#The output of this code is ghtdef 

  1 
  2 
  3 A=abc
  4 B:=$(A)def
  5 A=ght
  6 
  7 target1:
  8     echo $B
#The output of this code is abcdef

3. How to associate sub-Makefile with main Makefile

When multiple Makefiles are involved in a project, how to manage these makefiles can be divided into two categories: the main Makefile and the sub-Makefile. So how can we make the Makefile work well here without any problems? How can we compile all the files corresponding to the sub-Makefile through the main Makefile?

For example, here are two Makefile files.

 

#Sub Makefile file file
objs := div64.o lib1funcs.o ctype.o muldi3.o printf.o string.o vsprintf.o

libc.a: $(objs)
	${AR} -r -o $@ $^   #Using AR, this command is passed from the main Makefile file file to generate library files
	
%.o:%.c
	${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

%.o:%.S
	${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

clean:
	rm -f libc.a *.o		

 

 

#Main Makefile file file
CC		= arm-linux-gcc
LD 		= arm-linux-ld
OBJCOPY	= arm-linux-objcopy
OBJDUMP	= arm-linux-objdump
AR		= arm-linux-ar

INCDIR	:= $(shell pwd)
# C preprocessor flag, flag is the compiler's optional option
CPPFLAGS	:= -nostdlib -nostdinc -I$(INCDIR)/include
# C compiler flag,-O2 optimization level, -fno-builtin uses local files and header files when compiling links
CFLAGS		:= -Wall -O2 -fno-builtin

#Exporting these variables globally is actually for Makefile under the subfolder
export CC LD OBJCOPY OBJDUMP AR CPPFLAGS CFLAGS


objs := start.o sdram_init.o led.o uart.o main.o
#objs += clock.o
objs += lib/libc.a 

uart.bin: $(objs)
	$(LD) -Tlink.lds -o uart.elf $^
	$(OBJCOPY) -O binary uart.elf uart.bin
	$(OBJDUMP) -D uart.elf > uart_elf.dis
	gcc mkv210_image.c -o mkx210
	./mkx210 uart.bin 210.bin

lib/libc.a:
	cd lib;	make;	cd ..
	
%.o : %.S
	$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c

%.o : %.c
	$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c

clean:
	rm *.o *.elf *.bin *.dis mkx210 -f
	cd lib; make clean; cd ..

	
	

1. The code objs += lib/libc.a is the code that associates the main Makefile with the sub-Makefile. When the target is executed, the main Makefile will determine the source of the dependent file, and then the corresponding target of the libc.a file will be detected and executed.

lib/libc.a:
    cd lib;    make;    cd ..

Corresponding commands, pay attention to these sentences of code, need to be written in one line. First, it's like a sub-Makefile file, then it executes the sub-Makefile, and then it's rolled out.

 

 

 

 

 

 

 

 

 

Posted by toppac on Mon, 16 Sep 2019 23:45:55 -0700