CMake是一个跨平台的软件,在很多平台可以使用。一般在windows下,我们会直接使用VS生成项目,在linux下面,我们也可以使用QT Creater生成项目,但是两个不同平台上面的项目不能相互移植。这就有了CMake的用武之地,我们可以先编写一个CMakeLists.txt文件,将需要的.h和.cpp文件包含进来,然后在不同的平台使用CMake调用各自的编译器生成各自的工程。
Makefile是linux下面的文件,对于一个包含很多文件的工程,如果直接编译,那么我们就需要使用一些命令将所有的文件都包括进来。如果我们对其中的一些文件稍做修改,那么我们需要重新输入这些命令。Makefile文件就可以很好的解决这个问题,它将所需要的命令都包含在这个Makefile文件中,然后简单的make一下就完成了所有的步骤。
make的简单使用
这是我自己写的一份makefile文件,最简单的一个
1 | BSoftInst: BSoftInst.cpp ReadXML.cpp main.cpp ireg.cpp ntreg.cpp SoftwareInst.cpp |
2 | g++ -o BSoftInst BSoftInst.cpp ReadXML.cpp main.cpp ireg.cpp ntreg.cpp SoftwareInst.cpp -Wformat -fpermissive -I/usr/include/libxml2 -L/usr/lib/i386-linux-gnu -lxml2 -lguestfs |
1.makefile的书写规则为
1 | target ... : prerequisites ... |
2 | [Tab] command |
target是需要要生成的目标文件
prerequisites是生成目标所依赖的文件
command是命令,其开头需要是一个tab,而不是一系列空格
2.变量的使用
关于编译程序,和编译选项,我们是可以使用变量指定的,这样方便维护,特别当你的工程很大的时候
如可以改成下面这个形式
01 | #Which compiler |
02 | CC = g++ |
03 | #Where are include files kept |
04 | INCLUDE = . |
05 | #Options for development |
06 | CFLAGS = -g -Wall -ansi -Wformat -fpermissive -I/usr/include/libxml2 -L/usr/lib/i386-linux-gnu -lxml2 -lguestfs |
07 | #Options for release |
08 | #CFLAGS = -O -Wall -ansi |
09 | |
10 | BSoftInst: BSoftInst.cpp ReadXML.cpp main.cpp ireg.cpp ntreg.cpp SoftwareInst.cpp |
11 | $(CC) -o BSoftInst BSoftInst.cpp ReadXML.cpp main.cpp ireg.cpp ntreg.cpp SoftwareInst.cpp |
3.完整的依赖关系
之前的版本,是把所有.cpp文件都罗列在一块了,没有清晰的罗列出来他们之间的依赖关系。
我是为了偷懒,但是当文件很多是,这种方式就不行了。需要想下面那样罗列他们之间的关系
1 | BSoftInst: BSoftInst.o ReadXML.o main.o ireg.o ntreg.o SoftwareInst.o |
2 | $(CC) -o $@ BSoftInst.o ReadXML.o main.o ireg.o ntreg.o SoftwareInst.o |
3 | BSoftInst.o: BSoftInst.cpp BSoftInst.h ReadXML.h |
4 | ReadXML.o: ReadXML.cpp ReadXML.h |
5 | main.o: main.cpp ireg.h BSoftInst.h ReadXML.h |
6 | ireg.o: ireg.cpp ireg.h ntreg.h |
7 | ntreg.o: ntreg.cpp ntreg.h |
8 | SoftwareInst.o: SoftwareInst.cpp SoftwareInst.h |
也可以在依赖关系的后面加上编译命令,如
1 | BSoftInst.o: BSoftInst.cpp BSoftInst.h ReadXML.h |
2 | g++ -c BSoftInst.cpp BSoftInst.h ReadXML.h |
4.伪目标的使用
这个编译过程会产生很多临时文件,如大量的.o文件,需要删除,我们可以在makefile文件中
这样写
1 | clean: |
2 | rm -f *.o |
这两行也符合makefile的规则( target+ prerequisites+ command),只不过其中的依赖关系( prerequisites )没有了。clean被称为伪目标。 “伪目标”并不是一个文件,只是一个标签, 由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有 通过显示地指明这个“目标”才能让其生效。 在命令行输入make clean 后就会执行删除操作了。
当然,“伪目标”的取名不能和文件名重名,为了确保不重名,需要这样做
1 | .PHONY : clean |
只要有这个声明,
不管是否有
“clean”
文件,
要运行
“clean”
这个目标, “make clean”就可以执行之后的命令。
5.默认目标
Makefile中的第一个目标会被作为其默认目标,我们会声明一个伪目标在文件开头,像这样
1 | all : BSoftInst |
这样输入make,就相当于执行make BSoftInst。当你的makefile文件中有好多个目标的时候,会很有用。如果你想输入make一口气编译多个目标需要这样做
1 | all : prog1 prog2 prog3 |
2 | .PHONY : all |
3 | prog1 : prog1.o utils.o |
4 | cc -o prog1 prog1.o utils.o |
5 | prog2 : prog2.o |
6 | cc -o prog2 prog2.o |
7 | prog3 : prog3.o sort .o utils.o |
8 | cc -o prog3 prog3.o sort .o utils.o |
6.对于makefile,我也就知道这么多了。
cmake的简单使用
1.简单使用
kdevelop4目前就使用的是cmake,cmake需要CMakeLists.txt
下面是我的kdevelop生成的一个CMakeLists.txt文件,看上去写一个
CMakeLists.txt要比写makefile简单的多。
1 | project(analysisreg2) |
2 | |
3 | add_executable(analysisreg2 main.cpp ntreg.cpp edlib.cpp) |
PROJECT 指令的语法是:
PROJECT(projectname [CXX] [C] [Java])
你可以用这个指令定义工程名称,并可指定工程支持的语言,支持的语言列表是可以忽略的,
默认情况表示支持所有语言。
ADD_EXECUTABLE(analysisreg2 main.cpp ntreg.cpp edlib.cpp)
定义了这个工程会生成一个文件名为 hello 的可执行文件,后面的参数是其依赖的源文件
cmake会生成一个makefile,而且会针对不同平台生成不同的makefile。
2.变量的使用
1 | PROJECT (Analysisreg2) |
2 | SET(SRC_LIST main.cpp ntreg.cpp edlib.cpp) |
3 | MESSAGE(STATUS "This is BINARY dir " ${Analysisreg2_BINARY_DIR}) |
4 | MESSAGE(STATUS "This is SOURCE dir " ${Analysisreg2_SOURCE_DIR}) |
5 | ADD_EXECUTABLE(analysisreg2 SRC_LIST)<SPAN style= "FONT-FAMILY: ''Microsoft YaHei''; FONT-SIZE: small" ><SPAN style= "LINE-HEIGHT: normal; FONT-FAMILY: 'Microsoft YaHei'; WHITE-SPACE: normal; FONT-SIZE: 14px" > </SPAN></SPAN> |
SET 指令的语法是:
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
现阶段,你只需要了解 SET 指令可以用来显式的定义变量即可。
比如我们用到的是 SET(SRC_LIST
main.c),如果有多个源文件,也可以定义成:
SET(SRC_LIST main.c t1.c t2.c)
MESSAGE 指令的语法是:
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display"
...)
这个指令用于向终端输出用户定义的信息,包含了三种类型:
SEND_ERROR,产生错误,生成过程被跳过。
SATUS,输出前缀为—的信息。
FATAL_ERROR,立即终止所有 cmake 过程.
我们在这里使用的是 STATUS 信息输出,演示了由 PROJECT 指令定义的两个隐式变量
HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR。