目录
一、Makefile格式
1. 基本格式:
targets : prerequisties
[tab键]command
- target:目标文件,可以是 OjectFile,也可以是执行文件,还可以是一个标签(Label)。
- prerequisite:要生成那个 target 所需要的文件或是目标。
- command:是 make 需要执行的命令。
# 可以自定义make命令,在系统命令前加 @ 会隐藏系统命令的打印
(base) [root@localhost 03_test]# vim makefile
(base) [root@localhost 03_test]# cat makefile
debug:
echo hello
(base) [root@localhost 03_test]# make debug
echo hello
hello
(base) [root@localhost 03_test]# vim makefile
(base) [root@localhost 03_test]# cat makefile
debug:
@echo hello
(base) [root@localhost 03_test]# make debug
hello
(base) [root@localhost 03_test]# vim makefile
(base) [root@localhost 03_test]# cat makefile
debug:
@echo hello
test:
@echo this is a test
(base) [root@localhost 03_test]# make test
this is a test
(base) [root@localhost 03_test]#
2. Makefile规则:
- make 会在当前目录下找到一个名字叫
Makefile
或makefile
的文件 - 如果找到,它会找文件中第一个目标文件(target),并把这个文件作为最终的目标文件
- 如果 target 文件不存在,或是 target 文件依赖的 .o 文件(prerequities)的文件修改时间要比 target 这个文件新,就会执行后面所定义的命令 command 来生成 target 这个文件
- 如果 target 依赖的 .o 文件(prerequisties)也存在,make 会在当前文件中找到 target 为 .o 文件的依赖性,如果找到,再根据那个规则生成 .o 文件
3. 伪目标
伪目标不是一个文件,只是一个标签。我们要显示地指明这个“目标”才能让其生效。
伪目标取名不能和文件名重名,否则不会执行命令。
为了避免 target 和 Makefile 同级目录下 文件/文件夹
重名的这种情况,我们可以使用一个特殊的标记 .PHONY
来显式地指明一个目标是 "伪目标",向 make 说明,不管是否有这个文件/文件夹,这个目标就是 "伪目标"。
.PHONY : clean
只要有这个声明,不管是否有 "clean" 文件/文件夹,要运行 "clean" 这个目标,只有"make clean" 这个命令。
二、Makefile变量
# 变量的定义,需要给初值
cpp := src/main.cpp
obj := objs/main.o
# 变量的引用,用()或{}
$(obj) : ${cpp}
@g++ -c $(cpp) -o ${obj}
compile: $(obj)
# 预定义变量
$@ :目标(targe)的完整名称
$< :第一个依赖项(prerequisties)的名称
@^ :所有依赖项(prerequisties)的名称
(base) [root@localhost 04_test]# ls
makefile objs src
(base) [root@localhost 04_test]# ls src/
main.cpp
(base) [root@localhost 04_test]# ls objs/
(base) [root@localhost 04_test]# vim makefile
(base) [root@localhost 04_test]# cat makefile
cpp := src/main.cpp
obj := objs/main.o
$(obj) : $(cpp)
g++ -c $(cpp) -o $(obj)
compile: $(obj)
debug:
@echo $(cpp)
@echo $(obj)
clean:
rm -rf objs
.PHONY: debug clean
(base) [root@localhost 04_test]# make compile
g++ -c src/main.cpp -o objs/main.o
(base) [root@localhost 04_test]# ls objs/
main.o
(base) [root@localhost 04_test]# make debug
src/main.cpp
objs/main.o
(base) [root@localhost 04_test]# make clean
rm -rf objs
(base) [root@localhost 04_test]# ls
makefile src
(base) [root@localhost 04_test]#
三、Makefile符号
# 可变赋值符 =
(base) [root@localhost 05_test]# vim makefile
(base) [root@localhost 05_test]# cat makefile
HOST_ARCH = aarch64
TARGET_ARCH = $(HOST_ARCH)
# ...
#
# ...
HOST_ARCH = amd64
debug:
@echo ${TARGET_ARCH}
(base) [root@localhost 05_test]# make debug
amd64
(base) [root@localhost 05_test]#
# 立即赋值符 :=
(base) [root@localhost 05_test]# vim makefile
(base) [root@localhost 05_test]# cat makefile
HOST_ARCH := aarch64
TARGET_ARCH := $(HOST_ARCH)
# ...
#
# ...
HOST_ARCH := amd64
debug:
@echo ${TARGET_ARCH}
(base) [root@localhost 05_test]# make debug
aarch64
(base) [root@localhost 05_test]#
# 默认赋值符 ?=
# 若该变量已定义,则不做任何操作
# 若该变量未定义,则求值并分配
(base) [root@localhost 05_test]# vim makefile
(base) [root@localhost 05_test]# cat makefile
HOST_ARCH = aarch64
HOST_ARCH ?= amd64
TARGET_ARCH ?= amd64
debug:
@echo ${HOST_ARCH}
@echo ${TARGET_ARCH}
(base) [root@localhost 05_test]# make debug
aarch64
amd64
(base) [root@localhost 05_test]#
# 累加 +=
(base) [root@localhost 05_test]# vim makefile
(base) [root@localhost 05_test]# cat makefile
include_path = /usr/include
CXXFLAGS := -m64 -fPIC -g -00 -std=c++11 -w -fopenmp
CXXFLAGS += $(include_path)
debug:
@echo ${CXXFLAGS}
(base) [root@localhost 05_test]# make debug
-m64 -fPIC -g -00 -std=c++11 -w -fopenmp /usr/include
(base) [root@localhost 05_test]#
# 续行符 /
(base) [root@localhost 05_test]# vim makefile
(base) [root@localhost 05_test]# cat makefile
LDLIBS := cudart opencv_core \
gomp nvinfer protobuf cudnn pthread \
cublas nvcaffe_parser nvinfer_plugin
debug:
@echo ${LDLIBS}
(base) [root@localhost 05_test]# make debug
cudart opencv_core gomp nvinfer protobuf cudnn pthread cublas nvcaffe_parser nvinfer_plugin
(base) [root@localhost 05_test]#
# 通配符 * %
# *: 通配符表示匹配任意字符串,可以用在目录名或文件名中
# %: 通配符表示匹配任意字符串,并将匹配到的字符串作为变量使用