程序构建工具makefile、cmake、qmake的总结
1.一个简单的例子
现在有一个hello world程序:
#include <stdlib.h>
int main()
{
printf("%s\n","hello world!");
return 0;
}
假如该文件的文件名为helloworld.c
,在linux系统下可以通过下面的命令将程序编译成可执行程序:
gcc -o helloworld helloworld.c
再输入下面的命令运行程序:
./helloworld
就可以看到程序的输出了hello world!
了。
2.多个文件的例子
现在有main.c、file1.c、file1.h、file2.c、file2.h
这几个文件,main.c
中使用了file1.c
和file2.c
中的函数,这时可以使用下面命令来编译生成可执行文件:
gcc -o exe main.c file1.c file2.c
而且实际开发不可能将所有源文件都放同一个目录,如果把file1.c、file1.h
放在folder1
文件夹中,file2.c、file2.h
放在folder2
文件夹中,结构如下
–main.c
–folder1
----file1.c
----file1.h
–folder2
----file2.c
----file2.h
这时候的编译命令如下:
gcc -o main.c foler1/file1.c folder2/file2.c
这是只有3个源文件的情况,假如一个工程中有成千上万的文件,每次编译程序都需要把这些文件输入一遍,这是不现实的。这个时候就有人想:为什么不把这个编译命令用文件储存起来呢?
3.makefile
简介
makefile
就是基于编译器命令,对程序的编译过程记录起来,它具有以下的作用
:
1.保存每次编译时需要输入的编译命令
。
2.加入语法结构,makefile的语法侧重于控制中间文件(从源文件到可执行文件之间)的生成,使得程序的编译命令更容易维护,更利于模块化开发,也更有可读性。
3.加入了变量的概念,使得使得编译命令更加简洁。同时也加入了一些常用的函数,方便文件的编写。
4.加入了自动推导以及批处理的功能,更容易实现大规模工程的编译
关于makefile
的语法规则
,参考:《跟我一起写makefile》
如何使用makefile来构建工程
1.在工程目录下新建makefile
(或者Makefile
)文件
2.根据工程编写makefile
文件
3.输入make
命令
关于makefile
的一个例子,假如现在一个工程的结构如下
–main.c
–main.h
–folder1
----file1.c
----file2.c
----file3.c
–folder2
----file4.c
----file5.c
----file6.c
其中folder1
和folder2
中的文件分别为一个功能模块,main.c
使用了main.h
,那么makefile
可以这么编写:
SRC1 = $(wildcard ./folder1/*.c)
SRC2 = $(wildcard ./folder2/*.c)
MODULE1= $(patsubst %.c,%.o,$(SRC1))
MODULE2= $(patsubst %.c,%.o,$(SRC2))
exe : main.o $(module1) $(module2)
gcc -o $@ $^
main.o : main.h
$(MODULE1):%.o:%.c
gcc -c -o $@ $<
$(MODULE2):%.o:%.c
gcc -c -o $@ $<
./PHONY:clean
clean:
-rm exe main.o $(MODULE1) $(MODULE2)
然后输入make
命令即可生成可执行文件。
由于现在工程规模还太小,使用makefile
在代码量上还看不出什么优势,但是可能看出在结构上makefile
有了很大的提升,具有可读性。随着工程规模的增大,跟直接使用编译命令相比,makefile
的优势会越来越大。
虽然跟直接使用编译命令比较,makefile
已经有了很大的优势,但是如果一个工程目录结构复杂,文件之间的依赖关系比较复杂的时候,即使编写makefile
也会是已经比较复杂的工作,所以又出现了专门用来生成makefile
的工具。
4.cmake
简介
由于makefile是基于平台命令的,所以不同的操作系统下的makefile文件都不相同,那么每次移植工程到其他平台时,就得重新编写makefile文件。另外编写一个makefile文件对于构建复杂的工程来说还是比较麻烦的工作。使用cmake可以隐藏跟平台相关的细节。跟makefile相比,cmake具有以下优点:
(1) cmake是一个跨平台工具,可以对不同平台下的工程进行构建。
(2) 加入了 配置文件的概念,可以通过预定义一些参数和变量,用于控制代码的生成。 利用这个特性,可以很容易实现版本管理,使得工程开发和工程管理分离。
(3) 使用简单,只需要掌握十来个函数和常用的环境变量。
cmake
常用的命令:
- cmake_minimum_requied(VERSION X.X) #设置cmake所需的最低版本号为X.X。
- project(name) #将工程名设置为name。
- set(var value) #将变量var的值设置为value。
- aux_source_directory(dir var) #将目录dir下的所有源文件赋值给变量var,假如var不存在,则新建变量var。
- include_directories(dir) #添加头文件的搜索路径
- link_directories(dir) #添加库文件搜索路径
- add_subdirectory(dir) #添加子目录,子目录中的CMakelists.txt也会被执行
- add_executable(target source1 source2 …) #从参数中的源文件列表生成可执行文件
- target_link_libraries(target lib) #将可执行文件target 链接到库lib
- install(TARGETS target DESTINATION subdir) #将target复制到subdir目录下,subdir的父目录为CMAKE_INSTALL_PREFIX,默认值一般为/usr/local。
- add_library(lib source1 source2 …) #将列表中的源文件生成静态库lib。
- add_library(lib SHARED source1 source2 …) #将列表中的源文件生成动态库lib。
- message([SEND_ERROR | STATUS | FATAL_ERROR] “message to display”) #打印信息
- add_definitions(“options”) #添加编译器的编译参数
cmake
的入门教程:http://www.hahack.com/codes/cmake/
cmake
的使用:
(1). 在工程目录下新建并且编辑所需的CMakeList.txt,如果工程复杂,可以在每个模块目录下再新建CMakeList.txt,用于管理该目录下的文件编译。
(2). 生成makefile文件,在工程主目录下输入命令:
cmake ./
(3). 生成可执行文件:
make
(4). 如果CMakeLists.txt中定义了安装规则,可以使用下面的命令将目标文件安装到设定的目录中:
make install
qmake
简介
qmake
和cmake
一样,都是通过编写一个构建文件(cmake为CMakeLists.txt,qmake为*.pro),然后从构建文件中生成makefile
文件。qmake
相对来说,语法更加直观。比如要添加头文件路径
在CMakeLists.txt中会这么写:
include_directories(path1 path2 ...)
而在qmake的.pro文件中会这么写:
INCLUDEPATH = path1 paht2
qmake的使用也跟cmake类似:
编写.pro文件
->qmake *.pro
->make