make和cmake
当工程中只有一个源文件时,可以直接使用gcc命令来编译,但若有多个源文件并且引用了外包时,包与包之间可能还存在各种依赖,使用gcc编译则会显得非常复杂混乱。在这种情况下,make则可以让整个过程变得简洁高效。make命令本身是没有编译、链接的功能,而是通过调用用户在Makefile中的命令来执行编译链接工作。Makefile中可以调用gcc等各种编译器或其他命令来执行任务。值得一提的是,当源码文件发生变化时,make可以自动的指出哪一个文件需要更新,同时也自动确定以适当的顺序进行更新文件,当一个非源码文件依赖的另一个非源码文件发生改变时。 每次当我们改变了系统中的一小部分源码的时候,重新编译整个程序的效率是很低的。而make仅仅更新那些直接或者间接依赖这些改变了的源码文件的非源码文件。但若想实现跨平台的编译,则得重新写Makefile文件(比如在Linux中,Makefile中使用gcc作为编译器,但在windows(Visual Studio)则应该换成cl.exe作为编译器,命令的参数也应该做相应的修改),也是不小的工程量。cmake则是用来处理跨平台的问题。它可以根据CMakeLists.txt来跨平台生成对应平台能用的makefile。
1. Make是用来执行Makefile的,Makefile里面是类Unix环境下的与Windows的批处理文件(.bat)类似的脚本文件。其基本语法是: 目标+依赖+命令,只有在目标文件不存在或目标比依赖的文件更旧,命令才会被执行。由此可见,Makefile和make可适用于任意工作,不限于编程。比如,可以用来管理latex。Makefile的语法举例:假设有五个文件file1.cpp, file2.cpp, file2.h,其中file1.cpp中include了file2.h。若想生成可执行文件a.out,Makefile文件如下:
a.out: file1.o file2.o
gcc file1.o file2.o -o a.out
file1.o:file1.c file1.h
gcc -c file1.c -o file1.o
file2.o:file2.c file2.h
gcc -c file2.c -o file2.o
clean:
rm -rf *.o helloworld
注意:每个命令行前都必须有tab符号。
解释:
a.out: file1.o file2.o # a.out依赖file1.o file2.o两个目标文件。
gcc file1.o file2.o -o helloworld # 编译出a.out可执行文件。-o表示你指定的目标文件名。
file1.o: file1.c # file1.o依赖file1.c文件。
gcc -c file1.c -o file1.o: # 编译出file1.o文件。-c表示gcc 只把给它的文件编译成目标文件。
clean:
rm -rf *.o a.out
当用户键入make clean命令时,会删除 *.o 和a.out文件。
写好Makefile文件,在命令行中直接键入make命令,就会执行Makefile中的内容了。
2. Makefile+make过于基础,抽象程度不高,而且在windows下不太友好(针对visual studio用户),于是就有了跨平台项目管理工具cmake。cmake用更抽象的语法来组织项目,cmake命令执行的CMakeLists.txt文件。虽然,仍然是目标,依赖之类的东西,但更为抽象和友好,比如你可用math表示数学库,而不需要再具体指定到底是math.dll还是libmath.so,在windows下它会支持生成visual studio的工程,在linux下它会生成Makefile。也就是说,从同一个抽象规则出发,它为各个编译器定制工程文件。
总结:make用来执行Makefile,cmake用来执行CMakeLists.txt。Makefile的抽象层次最低,cmake在Linux等环境下会生成一个Makefile。cmake通过生成指定编译器的工程文件来支持跨平台的。
具体使用时,Linux下,只有少数几个文件,可以直接使用gcc来编译,小工程可手动写Makefile,大工程用cmake生成Makefile从而实现跨平台。
参考
https://www.zhihu.com/question/27455963/answer/36722992