Makefile基础
从Makefile入门,逐步推进到CMake
几个概念
编译源文件,需要gcc
但对于大型项目多个文件,需要专门的构建(build)工具,(有些库是需要手动加进去的,比如lpthread,所以要有脚本)
Make就是这样的工具,它需要makefile脚本来知道怎么编译
而makefile的生成可以由Cmake来生成,根据CMakeList.txt文件来生成(自己写Makefile有时也很麻烦,而CMakeList.txt更简单一些)
像Visual Studio这种有专门的内置build tools
The goal of Makefiles is to compile whatever files need to be compiled, based on what files have changed.
makefile语法
targets: [prerequisites]
command
command
command
targets: 生成的目标文件名 (可去后缀)
prerequisities: 可选,需要存在的文件
command: 具体的命令,一定是Tab开头,采用的也是shell指令
举例:
blah: blah.c
cc blah.c -o blah
如果blah文件不存在则会执行
如果已存在,会和blah.c比较是否发生改动,然后决定要不要执行
具体是通过修改时间来判断的,timestamps
targets概念
如果想让Makefile里面每一个都执行:
- 定义一个
all
all: one two three
one:
touch one
two:
touch two
three:
touch three
clean:
rm -f one two three
这样默认是执行all,但是发现one two three都不存在,需要先执行它们
另外target部分可以是多个:
all: f1.o f2.o
f1.o f2.o:
echo $@
Variables
首先数据类型都是字符串,所以也不必打引号,通过:=符号赋值,可以多个赋给一个,等同于define
然后引用变量:$(x)
还有转义字符,但要注意使用,以防被理解为普通字符
-
*:匹配文件名,一般使用它时需要声明:thing_right := $(wildcard *.o)这等同于把所有.o文件名赋给
thing_right -
%:比较复杂,之后再将
还有一些自动变量,类似matlab里的ans
@: 代表target名
^: 代表所有的prerequisites
?: 代表相比于target有更新的prerequisites
make有一种自动编译c/c++的机制,不需要自己写
-
编译C:
$(CC) -c $(CPPFLAGS) $(CFLAGS) $^ -o $@ -
编译CPP:
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $^ -o $@ -
链接.o文件:
$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
只需要给CC CXX这些变量赋值即可
CC = gcc # Flag for implicit rules
CFLAGS = -g # Flag for implicit rules. Turn on debug info
# Implicit rule #1: blah is built via the C linker implicit rule
# Implicit rule #2: blah.o is built via the C compilation implicit rule, because blah.c exists
blah: blah.o
blah.c:
echo "int main() { return 0; }" > blah.c
clean:
rm -f blah*
这里就会自己给编译blah.c
filter函数:
$(filter %.o,$(obj_files)): %.o: %.c
echo "target: $@ prereq: $<"