一. Make
在 认识编译器和C/C++编译 一文中介绍过,一个 .c/.cpp 文件从源文件到目标文件的过程叫做编译,但是一个项目中不可能只存在一个文件,这就涉及到多个文件的编译问题,在编译的过程中必然涉及某个文件的先编译,某个文件的后编译。构建过程就是安排文件的编译先后关系。
Make 就是一种构建工具,属于 GNU 项目。在 Mac 上输入 make -version 可查看 make 工具的版本。
>> 执行make -version>> 输出GNU Make 3.81Copyright (C) 2006 Free Software Foundation, Inc.This is free software; see the source for copying conditions.There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR APARTICULAR PURPOSE.This program built for i386-apple-darwin11.3.0
二. Makefile
make 命令执行时,需要一个 makefile 文件,以告诉 make 命令如何去编译和链接程序。makefile 规则的编写可参考 跟我一起写Makefile[1]
举个例子,现在有四个文件
>> add.cppint add (int num1,int num2) { return num1 + num2 + 200;}>> div.cppint div(int num1,int num2) { return num1 / num2;}>> sub.cppint sub(int num1,int num2) { return num1 - num2;}>> hello.cpp#include int add(int num1,int num2);int sub(int num1,int num2);int div(int num1,int num2);int main(int argc,char* argcv[]) { int a = 20; int b = 10; printf("%d+%d=%d",a,b,add(a,b)); printf("%d-%d=%d",a,b,sub(a,b)); printf("%d/%d=%d",a,b,div(a,b));}
由于 hello.cpp 依赖 add.cpp 、div.cpp 、sub.cpp , 所以按照正常的边缘步骤是:
gcc hello.cpp div.cpp sub.cpp add.cpp -o hello>> 拆分来就是先生成所有的 .o 文件gcc -c add.cpp -o add.ogcc -c div.cpp -o div.ogcc -c sub.cpp -o sub.ogcc -c hello.cpp -o hello.ogcc hello.o div.o sub.o add.o -o hello (没有 -c)
使用 Make 就需要编写 Makefile 文件,在源文件目录下添加 Makefile 文件
hello.out:hello.o sub.o div.o add.o gcc hello.o sub.o div.o add.o -o hello.outdiv.o:div.cpp gcc -c div.cpp -o div.osub.o:sub.cpp gcc -c sub.cpp -o sub.oadd.o:add.cpp gcc -c add.cpp -o add.ohello.o:hello.cpp gcc -c hello.cpp -o hello.o
执行 make 命令,make 会自动查找 Makefile 文件并执行。这样就免去了一步步手动编译文件。
三. CMake和CMakeLists.txt
虽然 Make 和 Makefile 简化了手动构建的过程,但是编写 Makefile 文件仍然是一个麻烦的工作,因此就有了 CMake 工具。CMake 工具用于生成 Makefile 文件,而如何生成 Makefile 文件,则由 CMakeLists.txt 文件指定。
举例:通过 CMakeLists.txt 编译 hello.cpp
>> hello.cpp#include int main(int argc,char* argcv[]) { int a = 20; int b = 10; printf("%d+%d",a,b); return 0;}>> 在同目录下编写 CMakeLists.txtPROJECT (HELLO)SET(SRC_LIST hello.cpp)MESSAGE(STATUS "this is BINARY dir" ${HELLO_BINDARY_DIR})MESSAGE(STATUS "this is SOURCE dir" ${HELLO_SOURCE_DIR})MESSAGE(STATUS "this is PRPOJECT_SOURCE" ${PRPOJECT_SOURCE_DIR})ADD_EXECUTABLE(hello.out ${SRC_LIST})>> 执行 cmake CMakeLists.txt 生成 Makefile 文件>> 执行 make 命令编译 hello.cpp 生成 hello.o
最后生成产物如下:
总的来说,Make、Makefile、CMake 和 CMakeLists.txt 的关系可总结为下图:
References
[1]
跟我一起写Makefile: https://seisman.github.io/how-to-write-makefile/overview.html