https://blog.csdn.net/qq_40334837/article/details/80901662
https://blog.csdn.net/xiethon/article/details/78919537
一、Makefile整体过程
一般整个工程的Makefile分为3类:
1. 顶层目录的Makefile2. 顶层目录的Makefile.build
3. 各级子目录的Makefile
(1)顶层目录的Makefile:
它除了定义obj-y来指定根目录下要编进程序去的文件、子目录外,主要是定义工具链、编译参数、链接参数──就是文件中用export导出的各变量。
部分示例代码如下:
# 编译器在编译时的一些通用参数设置
CFLAGS := -Wall -O2 -g -DDEBUG
# 添加头文件路径,不添加的话include目录下的头文件编译时找不到
CFLAGS += -I $(shell pwd)/include -I/opt/libdecode/include
# 链接器的链接参数设置
LDFLAGS := -ljpeg -lz -lpng -L/opt/libdecode/lib
export CFLAGS LDFLAGS
(2)顶层目录的Makefile.build:
这是最复杂的部分,它的功能就是把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为built-in.o
部分示例代码如下:
all:
make -C ./ -f $(TOPDIR)/Makefile.build
$(CC) $(LDFLAGS) -o $(TARGET) built-in.o
(3)各级子目录的Makefile:
它最简单,形式如下:
obj-y += file.o
obj-y += subdir/
"obj-y += file.o"表示把当前目录下的file.c编进程序里,
"obj-y += subdir/"表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。
注意: "subdir/"中的斜杠"/"不可省略
(4)怎么使用这套Makefile: 1.把顶层Makefile, Makefile.build放入程序的顶层目录
2.修改顶层Makefile
2.1 修改工具链
2.2 修改编译选项、链接选项
2.3 修改obj-y决定顶层目录下哪些文件、哪些子目录被编进程序
2.4 修改TARGET,这是用来指定编译出来的程序的名字
3. 在各一个子目录下都建一个Makefile,形式为:
obj-y += file1.o
obj-y += file2.o
obj-y += subdir1/
obj-y += subdir2/
二、Makefile细节
1、伪目标(.PHONY)
(1)伪目标不是为了得到某个文件或东西,而是单纯为了执行这个目标下面的命令。
(2)伪目标一般都没有依赖
(3)但是有时候为了明确声明这个目标是伪目标会在伪目标的前面用.PHONY来明确声明它是伪目标。
示例代码如下: 可以在cp上一行加上 .PHONY:clean all cp标明下,更清楚
cp:
cp ../testproject/ /root/rootfs/ -rf
clean:
rm -f $(shell find -name "*.o")
rm -f $(TARGET)
2、mkdir -p
(1)建立上层目录
比如当然 /root 目录下没有任何目录
mkdir -p /root/test/test
这样就在 /root 目录下建立了 test 目录 ,并在 /root/test目录下还建立了 /root/test/test 目录
3、一些符号用法
(1)= 最简单的赋值
用=赋值的变量,在被解析时他的值取决于最后一次赋值时的值,所以看变量引用的值时不能只往前面看,还要往后面看。
(2):= 一般也是赋值
用:=来赋值的,则是就地直接解析,只用往前看即可。
(3)?= 如果变量前面并没有赋值过则执行这条赋值,如果前面已经赋值过了则本行被忽略。
(4)+= 用来给一个已经赋值的变量接续赋值,意思就是把这次的值加到原来的值的后面。(在shell makefile等文件中,可以认为所有变量都是字符串,+=就相当于给字符串stcat接续内容)(注意一个细节,+=续接的内容和原来的内容之间会自动加一个空格隔开)
(5)* 若干个任意字符
(6)? 1个任意字符
(7)[ ] 将[]中的字符依次去和外面的结合匹配
(8)$(SRC:%.c=%.o) 将SRC变量中所有以.c结尾的文件名替换成对应的以.o结尾的文件名,然后赋回给SRC
(9)一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表
4、变量
(1)常见自动变量:
$@ 规则的目标文件名
$< 规则的依赖文件名
$^ 依赖的文件集合
5、Makefile实战代码:
CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
# export导出的变量是给子目录下的Makefile使用的
export AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP
# 编译器在编译时的参数设置 (比如打印出所有警告、调试信息)
CFLAGS := -Wall -O2 -g -DDEBUG
# 添加头文件路径,不添加的话include目录下的头文件编译时找不到
CFLAGS += -I $(shell pwd)/include
# 链接器的链接参数设置
LDFLAGS :=
export CFLAGS LDFLAGS
TOPDIR := $(shell pwd)
export TOPDIR
# 定义将来编译生成的可执行程序的名字
TARGET := imageplayer
# 添加项目中所有用到的源文件,有顶层目录下的.c文件,和子文件夹
# 添加顶层目录下的.c文件
obj-y += main.o
# 添加顶层目录下的子文件夹(注意目录名后面加一个/)
obj-y += display/
all:
make -C ./ -f $(TOPDIR)/Makefile.build
$(CC) $(LDFLAGS) -o $(TARGET) built-in.o
cp: (../ 当前目录是在makeflie里面,需要../才能进入与makefile同级的目录下)
cp ../lbwproject /root/porting_x210/rootfs/rootfs/ -rf
clean:
rm -f $(shell find -name "*.o")
rm -f $(TARGET)
distclean:
rm -f $(shell find -name "*.o")
rm -f $(shell find -name "*.d")
rm -f $(TARGET)