Cmake的使用

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) # camke版本号
AUX_SOURCE_DIRECTORY(. SRC_LIST) # 将./下的所有*.cpp加入到SRC_LIST中
ADD_EXECUTABLE(hello ${SRC_LIST})

在singleFile文件夹下执行命令:

1
cmake ./

可以看到编译生成的文件已经在当前目录下生成了:

然后执行命令:

1
make

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

但是这样会有一个问题,就是编译生成的文件都在当前目录下,这样会导致文件夹很乱,所以我们可以创建一个build文件夹,那么文件结构就变为如下所示:

1
2
3
4
singleFile/
| -- CMakeLists.txt
| -- build/
| -- helloWorld.cpp

然后在singleFile/build文件夹下执行命令:

1
cmake ..

可以看到编译生成的文件全部都在build文件夹里生成了

note

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

然后执行命令:

1
make

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

编译多个cpp文件

文件结构如下:

1
2
3
4
5
6
7
8
multiFile/
| -- CMakeList.txt
| -- main.cpp
| -- build/
| -- src/
-- CMakeList.txt
-- test.h
-- test.cpp

main.cpp, test.cpp,以及test.h文件的内容如下:

test.h:

1
2
3
4
5
6
7
8
// test.h
#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
// main.cpp
#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)
# generate *.so
ADD_LIBRARY(TEST SHARED ${DIR_TEST_SRC})

在multiFile/build文件夹下执行命令:

1
cmake ..

如下图所示:

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

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

调用 *.so, *.h,文件结构:

1
2
3
4
5
6
7
8
libTest/
| -- build/
| -- include/
--  test.h
| -- libs/
-- libTEST.so
| -- CMakeLists.txt
| -- main.cpp

这里的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})
# 绝对路径添加 *.so
TARGET_LINK_LIBRARIES(main /home/starmin/Code/testCode/cmakeTest/libTest/libs/libTEST.so)

attention

这里需要注意的是,TARGET_LINK_LIBRARIES后面的libTEST.so路径必须绝对路径,如果想要使用相对路径,需要设置链接库搜索目录(见下文设置链接库搜索目录

在build文件夹下执行cmake命令:

1
cmake ..

然后执行make命令:

CMakelists.txt的常用选项

上面是CMake最基本的集中使用方法,还有一些CMake常用的选项见下文

指定cmake的最小版本

1
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)    # 指定cmake的最小版本

定义工程名称

1
PROJECT(main)   # 定义工程名称

显示定义变量

1
set(var [value]) # 显示定义变量

例如:

1
2
3
4
5
6
7
8
9
# 第一种用法,生成代码文件列表
# 先直接设置SRC_LIST的值
set(SRC_LIST add.h add.cpp)
# 然后再在SRC_LIST中追加main.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(-D宏名称)

例如:

1
2
add_definitions(-DWINDOWS)
add_definitions(-DLINUX)

静态链接库

1
TARGET_LINK_LIBRARIES(main TEST.so)    # 链接库

添加子文件夹

1
add_subdirectory(src)

note

该语句会在执行完当前文件夹CMakeLists.txt之后执行src子目录下的CMakeLists.txt

ADD_SUBDIRECTORY

1
ADD_SUBDIRECTORY(src)   # 添加子目录

源文件名赋值给变量

1
AUX_SOURCE_DIRECTORY(. DIR_SRCS)   # 将当前目录下的所有源文件名赋值给变量DIR_SRCS

参考:


Cmake的使用
https://gstarmin.github.io/2023/07/01/Cmake的使用/
作者
Starmin
发布于
2023年7月1日
许可协议