Cmake的使用
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。
编译一个独立的cpp文件
文件结构如下:
1 2 3
| singleFile/ | -- CMakeLists.txt | -- helloWorld.cpp
|
CMakeLists.txt的文件为:
1 2 3 4
| PROJECT (TEST) cmake_minimum_required(VERSION 3.12) AUX_SOURCE_DIRECTORY(. SRC_LIST) ADD_EXECUTABLE(hello ${SRC_LIST})
|
在singleFile文件夹下执行命令:
可以看到编译生成的文件已经在当前目录下生成了:

然后执行命令:
就可以生成我们程序的可执行文件了:

但是这样会有一个问题,就是编译生成的文件都在当前目录下,这样会导致文件夹很乱,所以我们可以创建一个build文件夹,那么文件结构就变为如下所示:
1 2 3 4
| singleFile/ | -- CMakeLists.txt | -- build/ | -- helloWorld.cpp
|
然后在singleFile/build文件夹下执行命令:
可以看到编译生成的文件全部都在build文件夹里生成了

note
这里需要注意的是,build文件夹的位置是可以改变的,甚至其名字也可以改,但是习惯上使用build作为文件夹的名字,示例里cmake命令后面的参数是两个点,是因为CMakelists.txt文件在上一级目录,所以需要用两个点来表示上一级目录,如果将build文件夹放在其他的地方,那么需要保证执行cmake
命令的之后后边跟的路径是CMakeLists.txt文件所在的路径。
然后执行命令:
就可以生成我们程序的可执行文件了:

编译多个cpp文件
文件结构如下:
1 2 3 4 5 6 7 8
| multiFile/ | | | |
|
main.cpp
,
test.cpp
,以及test.h
文件的内容如下:
test.h:
1 2 3 4 5 6 7 8
| #include<iostream> class Test{ public: Test(); ~Test(); void print(); };
|
test.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include"test.h"
Test::Test() { }
Test::~Test() { }
void Test::print() { std::cout << "Hello World!" << std::endl; }
|
main.cpp:
1 2 3 4 5 6 7 8 9 10 11 12
| #include<iostream> #include"src/test.h" using std::cout;
int main() {
Test test; test.print(); return 0; }
|
根目录下CMakeLists.txt文件为:
1 2 3 4 5 6
| PROJECT(main) CMAKE_MINIMUM_REQUIRED(VERSION 3.12) ADD_SUBDIRECTORY(src) AUX_SOURCE_DIRECTORY(. DIR_SRCS) ADD_EXECUTABLE(main ${DIR_SRCS}) TARGET_LINK_LIBRARIES(main TEST)
|
src文件夹下的CMakeLists.txt文件为:
1 2 3
| AUX_SOURCE_DIRECTORY(. DIR_TEST_SRC)
ADD_LIBRARY(TEST SHARED ${DIR_TEST_SRC})
|
在multiFile/build文件夹下执行命令:
如下图所示:

与编译单个文件时一样,执行make
命令就可以生成可执行文件了:

同时可以看到在"multiFile/build/src"文件夹下生成了.so文件

调用 *.so, *.h,文件结构:
1 2 3 4 5 6 7 8
| libTest/ | | | | |
|
这里的libTEST.so
文件是上面使用cmake
命令生成的.so文件,test.h
是之前的test.h
文件,main.cpp
文件的内容如下:
CMakeLists.txt的文件为:
1 2 3 4 5 6 7
| PROJECT(main) CMAKE_MINIMUM_REQUIRED(VERSION 3.12) INCLUDE_DIRECTORIES(./include) AUX_SOURCE_DIRECTORY(. DIR_SRCS) ADD_EXECUTABLE(main ${DIR_SRCS})
TARGET_LINK_LIBRARIES(main /home/starmin/Code/testCode/cmakeTest/libTest/libs/libTEST.so)
|
attention
这里需要注意的是,TARGET_LINK_LIBRARIES
后面的libTEST.so
路径必须绝对路径,如果想要使用相对路径,需要设置链接库搜索目录(见下文设置链接库搜索目录)
在build文件夹下执行cmake
命令:

然后执行make
命令:

CMakelists.txt的常用选项
上面是CMake最基本的集中使用方法,还有一些CMake常用的选项见下文
指定cmake的最小版本
1
| CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
|
定义工程名称
显示定义变量
例如:
1 2 3 4 5 6 7 8 9
|
set(SRC_LIST add.h add.cpp)
set(SRC_LIST ${SRC_LIST} main.cpp)
set( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib/linux) set( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
|
编译链接库/可执行程序
1 2 3 4 5 6 7 8
| add_library(库名称 STATIC 代码文件名称)
add_library(库名称 SHARED 代码文件名称)
add_executable(可执行程序名 代码文件名称)
|
例如:
1 2 3 4 5 6 7 8 9 10 11
| add_library(add STATIC add.h add.cpp) add_library(add STATIC ${ADD_SRC} ${ADD_HDR})
add_library(add SHARED add.h add.cpp) add_library(add SHARED ${ADD_SRC} ${ADD_HDR})
add_executable(main add.h add.cpp mai.cpp) add_executable(main ${MAIN_SRC} ${MAIN_HDR})
|
指定静态库或者动态库编译输出目录
例如将当前编译的静态库或者动态库输出到当前项目文件夹lib子目录下
1
| set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
|
指定可执行程序编译输出目录
例如将当前可执行程序输出到当前项目文件夹的bin子目录下
1 2
| set( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
|
设置链接库搜索目录
例如将链接库搜索目录设置为当前项目文件夹下lib/linux文件夹
1
| link_directories( ${PROJECT_SOURCE_DIR}/lib/linux)
|
设置包含目录
例如将包含目录设置为当前项目文件夹下include文件夹
1
| INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
|
设置宏定义
例如:
1 2
| add_definitions(-DWINDOWS) add_definitions(-DLINUX)
|
静态链接库
1
| TARGET_LINK_LIBRARIES(main TEST.so)
|
添加子文件夹
note
该语句会在执行完当前文件夹CMakeLists.txt之后执行src子目录下的CMakeLists.txt
ADD_SUBDIRECTORY
源文件名赋值给变量
1
| AUX_SOURCE_DIRECTORY(. DIR_SRCS)
|
参考: