CMake用
CMakeLists.txt
来描述代码间的组织关系。
一个最简单的CMakeLists.txt
包含3部分内容:所需CMake版本、项目信息以及编译过程。
CMake版本
在CMakeLists.txt
中用cmake_minimum_required
来指定所需CMake的最低版本,例如以下语句说明编译所需CMake最低版本为3.2:
cmake_minimum_required(VERSION 3.2)
项目信息
每一个CMake项目都需要一个project()
语句来描述项目信息,通常项目信息出现在cmake_minimum_required
语句之后。用来描述项目信息的语句遵循以下形式:
project(projectName
[VERSION major[.minor[.patch[.tweak]]]]
[LANGUAGES languageName ...]
)
其中,projectName
是项目名称;[VERSION major[.minor[.patch[.tweak]]]]
代表项目的版本号,包含主版本号(major)、子版本号(minor)、修正版本号(patch)和微调版本号(tweak),其中可以只写主版本号;[LANGUAGES languageName ...]
表示项目所涉及的语言,CMake在配置时将会检查对应的语言编译器/解释器等信息,如果涉及多种语言,中间用空格隔开。
这里边必须写的是项目名称,而其它两个可以不写。如果没有写项目涉及的语言,CMake默认会寻找C和C++语言。以下为描述项目信息的一个示例,项目名称为MyApp
,版本1.0
,采用C++
语言:
project(MyApp VERSION 1.0 LANGUAGES CXX)
编译过程
编译目标对象
CMakeLists.txt
当然一定要包含编译目标。编译的目标对象实际上可以分为两类,一类是可执行文件,另一类是库文件。
可执行文件
下面是描述编译可执行文件语句的一般形式:
add_executable(targetName [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...]
)
其中,
targetName
是可执行文件的名称,例如在Windows系统下会生成targetName.exe
。WIN32
是在Windows平台会用到的一个参数,在其他平台这个参数会被忽略。这个参数表示这个目标可执行文件是一个Windows GUI程序,对应Visual Studio中将项目属性-链接器-系统中的子系统这一项设置成了窗口(/SUBSYSTEM:WINDOWS)
。例如,使用库wxWidgets
,生成GUI可执行文件时要加上这一参数,否则会报错。MACOSX_BUNDLE
参数表明在Apple平台上构建的是一个应用程序捆绑包(app bundle)。EXCLUDE_FROM_ALL
参数表明当不指明生成这一目标时,不会被默认生成。在不指明编译目标时,默认会编译ALL
目标,也就是全部目标,该参数表明这个目标不在ALL
目标中。除非显示指明要生成该目标,或者其它需要编译的目标依赖于这个目标,这个目标不会被编译。
库文件
在较大的项目中,除了需要构建可执行文件以外,还需要构建许多库文件。描述编译目标为库文件的一般形式如下:
add_library(targetName [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...]
)
其中,
targetName
为所编译库的名字。STATIC | SHARED | MODULE
对应不同的库种类,包含动态库、静态库以及模块库。这里建议省略这一参数,然后在运行cmake的时候视情况来加上-DBUILD_SHARED_LIBS=YES
参数指明要编译动态库。source1
、source2
为编译库所需的源文件。
链接
在项目中,库与库、应用程序与库之间常常存在依赖关系,也就是说库会被链接到库或应用程序上。一般来讲,依赖关系可以分为以下三种:
- PRIVATE(私有)
私有依赖表示A库在自己的内部实现中用到了B库,任何用到A库的代码不需要知道B库。 - PUBLIC(公共)
公共依赖表示A库不光在内部实现中用到了B库,甚至还在其接口中用到了B库,这意味着没有B库,A库也用不了,所有用到A库的代码都直接依赖于B库。 - INTERFACE(接口)
接口依赖表示为了用A库,必须用到B库的一部分。接口依赖与公共依赖之间的不同之处在于,在接口依赖中,A库的内部实现中并没有用到B库,而仅在接口中用到了B库。
在CMake中,用target_link_libraries
来描述依赖关系,其一般形式如下:
target_link_libraries(targetName
<PRIVATE|PUBLIC|INTERFACE> item1 [item2 ...]
[<PRIVATE|PUBLIC|INTERFACE> item3 [item4 ...]]
...
)
其中,
targetName
是要链接的库/应用程序名称。<PRIVATE|PUBLIC|INTERFACE>
是可选参数,描述之间的依赖关系。item1
依赖的库的名称。
完整示例
假设项目目录中的文件如下所示:
project
|-- func.h
|-- func.cpp
|-- main.cpp
|-- CMakeLists.txt
func.h
中的内容:
#ifndef __FUNC_H
#define __FUNC_H
int func();
#endif
func.cpp
中的内容:
#include "func.h"
int func(){
return 2;
}
main.cpp
中的内容:
#include <iostream>
#include "func.h"
int main(){
std::cout << func() << std::endl;
return 0;
}
CMakeLists
中的内容:
# 版本
cmake_minimum_required(VERSION 3.2)
# 项目信息
project(simple VERSION 1.0 LANGUAGES CXX)
# 编译目标
add_library(func func.cpp)
add_executable(main main.cpp)
# 依赖关系
target_link_libraries(main PRIVATE func)
CMake编译过程:
- 新建
build
目录并进入 - 命令行输入
cmake ..
- CMake配置完成之后命令行输入
cmake --build .
- 在
Debug
文件夹中找到可执行文件
相关链接