Cmake的使用
CMake是什么
Cmake是一种跨平台的项目构建工具,它使用符合CMake要求的项目来生成平台原生的项目,从而利用平台原生的工具来构建你的项目。
例如:
平台类型 | 生成的项目类型 |
---|---|
UNIX/LINUX | Makefile构建的项目 |
Windows | Visual Studio项目 |
Mac OS | XCode项目 |
CMake的用法
cmake [路径] |
即可生成对应的项目,以Linux平台为例,cmake可以为我们制作出Makefile项目,再执行
make |
即可得到我们想要的可执行文件
CMake构建的项目
何为CMake构建的项目?CMake构建的项目使用CMakeLists.txt文件来描述项目的组织情况,一个CMakeLists.txt应该具有如下要素
cmake_minimum_required(VERSION 构建此项目所需的最低cmake版本) |
第一句,制定了此项目所需的最低cmake版本,一般地,此版本应设置为3.0.0;
第二句,设定了该项目的名称;
第三句,设定了一个可执行文件作为target(目标),即此句话的目的是生成该目标,而为了生成该目标,需要对它进行一些描述,一般是指构建它所需的所有源文件名;
第四句,设定了一个库作为target(目标),即此句话的目的是生成该目标;
第五句,用于在需要链接外部库或自己定义的库的时候,用于将它们链接起来。
一些实例
HelloWorld
俗话说得好,不知道写什么的时候就写Hello,World!其实是我说的
项目中文件如下
- main.c
- CMakeLists.txt
# CMakeLists.txt |
// main.c |
再执行
# .代表当前目录,..代表上级目录 |
即可得到可执行文件hello了
多文件项目
项目中文件如下
- main.c
- add.h
- add.c
- CMakeLists.txt
# CMakeLists.txt |
// add.h |
// add.c |
// main.c |
库项目
库是什么?库是程序的一部分,但它不可以直接执行,通常库中包含了库所编写的函数的实现,但并没有main函数,即它不能自己执行,需要别的程序来调用它才能执行。从链接方式上来看,库分为静态库(static)和动态库(dynamic)。
静态库类似多文件项目中,某源文件编译过程中生成的二进制文件,它保留了函数入口及实现。将在链接后被包含到可执行文件中;
动态库在链接时仅告诉可执行文件一些函数的信息,而不告诉它具体的实现,而在运行时,可执行文件会在某些规则下寻找动态库文件并将其载入内存中进行函数调用。
不难看出,动态库的优点在于节省了可执行文件的体积,而且多个不同的可执行文件可以共享一份动态库文件,从而有效节约硬盘资源。但其也有弊端,比如程序在别的计算机上运行时,可能那台计算机并没有所需的动态库,则需要将动态库也拷贝一份,否则程序将无法执行,而使用静态库的程序只要拷贝一个可执行文件就可以运行了。
此处我们使用一个静态库项目来举例
项目中文件如下
- add.h
- add.c
- CMakeLists.txt
# CMakeLists.txt |
// add.h |
// add.c |
Linux平台下构建得到libadd.a文件,a是指archive,译为档案,就是静态库的意思,add是我们生成的库名,通过执行
ar -t ./libadd.a |
可以得到这个档案中所包含的内容,此处为add.c.o,正是我们add.c在编译时产生的二进制文件!也就是称库与源文件编译过程中生成的二进制文件类似的原因。
同理Windows下会得到后缀名为lib的库文件,lib是library的意思。
使用库的项目
我们写好了一个库,那就要给别人/自己用啊。如何利用cmake来将库加入自己的项目中呢?
项目中文件如下
- add.h
- main.c
- libadd.a
- CMakeLists.txt
# CMakeLists.txt |
// add.h |
// main.c |
想要使用库文件,必须知道我们需要使用的函数的定义,即拥有上例add库的头文件add.h
而在链接时需要函数实现,故还需add库生成的libadd.a文件
我们与多文件项目相比可谓是多此一举,但使用库有什么意义呢?
答案是隐藏了你的源码。在使用库的项目测试中,无需add.c来告诉编译器add函数如何实现,只是借add.h告诉了编译器:“我有个函数叫add,使用两个int做参数,使用int做返回值,你看着办!” 而编译器会在链接时,尝试找到所有未实现的函数并把它们的定义和其实现(在库文件中)进行关联,从而生成可执行程序。
而且用户无需考虑你的具体实现,只要调用它即可。现在很多项目都是使用这种方法来提供自己的API(Application Programming Interface,类似于此处的函数定义)的。
其他实例
更多实例请看这个开源项目