文章目录
1 CMakeLists.txt基础模板
1.1 最小项目
CMakeLists.txt
# 指定使用 CMake 的最低版本号
cmake_minimum_required (VERSION 2.6)
# 指定项目名称
project (Tutorial)
# 添加可执行文件
add_executable(Tutorial tutorial.cxx)
tutorial.cxx
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <string>
int main(int argc, char* argv[])
{
if (argc < 2) {
std::cout << "Usage: " << argv[0] << " number" << std::endl;
return 1;
}
// convert input to double
const double inputValue = atof(argv[1]);
// calculate square root
const double outputValue = sqrt(inputValue);
std::cout << "The square root of " << inputValue
<< " is " << outputValue
<< std::endl;
return 0;
}
1.2 构建、编译和运行
安装CMake、MinGW64并配置环境变量。终端进入到CMakeLists.txt
目录,输入:
mkdir build
cd build
# 构建
cmake -G"MinGW Makefiles" ..
# 编译链接
cmake --build .
# 运行
.\Tutorial.exe 25
- cmake -G<编译器名称> <CMakeLists.txt路径>
- cmake --build <编译生成文件存放路径>
2 CMakeLists.txt优化
2.1 set 与 PROJECT_NAME
cmake_minimum_required(VERSION 2.6)
project(Tutorial)
## SET(<变量名> <变量值>)
SET(SRC_LIST tutorial.cxx)
# ${变量名}: 获取变量的值
add_executable(${PROJECT_NAME} ${SRC_LIST})
2.2 添加版本号和配置头文件
cmake_minimum_required (VERSION 2.6)
# 指定项目名及其版本号
project(Tutorial VERSION 1.0)
# 版本号也可以通过下面方式指定
## project(Tutorial)
## set (Tutorial_VERSION_MAJOR 1)
## set (Tutorial_VERSION_MINOR 0)
SET(SRC_LIST tutorial.cxx)
# 配置一个头文件,通过它向源代码中传递一些CMake设置。TutorialConfig.h.in需要我们编写,TutorialConfig.h自动生成
configure_file (
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" # TutorialConfig.h.in在源文件目录下
"${PROJECT_BINARY_DIR}/TutorialConfig.h" # TutorialConfig.h在生成的二进制文件树目录下
)
# 将二进制文件树添加到包含文件的搜索路径中,这样我们可以找到TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")
# 添加可执行文件
add_executable(${PROJECT_NAME} ${SRC_LIST})
TutorialConfig.h.in
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
自动生成的TutorialConfig.h
:
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR 1
#define Tutorial_VERSION_MINOR 0
修改tutorial.cxx
:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TutorialConfig.h"
#include <iostream>
int main (int argc, char *argv[]) {
if (argc < 2) {
// report version
std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR << std::endl;
std::cout << "Usage: " << argv[0] << " number" << std::endl;
return 1;
}
double inputValue = atof(argv[1]);
double outputValue = sqrt(inputValue);
fprintf(stdout,"The square root of %g is %g\n", inputValue, outputValue);
return 0;
}
运行结果如下:
PS D:\CMAKE_Learn\build> .\Tutorial.exe
D:\CMAKE_Learn\build\Tutorial.exe Version 1.0
Usage: D:\CMAKE_Learn\build\Tutorial.exe number
PS D:\CMAKE_Learn\build>
2.3 指定 C++ 标准
# 指定C++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
3 添加库
一般我们将库的源码放在项目源文件目录下的MathFunctions子目录中,并在该子目录(该目录下包含头文件MathFunctions.h
和相关源文件mysqrt.cxx
)下新建一个CMakeLists.txt
,添加如下内容:
# 添加一个叫 MathFunctions 的库文件
add_library(MathFunctions mysqrt.cxx)
此时项目文件结构如下:
CMAKE_Learn/
build/
MathFunctions/
CMakeLists.txt
MathFunctions.h
mysqrt.cxx
CMakeLists.txt
tutorial.cxx
TutorialConfig.h.in
再在顶层目录下的CMakeLists.txt文件中添加如下内容:
# 向当前工程添加存放源文件的子目录,指定库所在的子目录
add_subdirectory(MathFunctions)
#生成可执行文件
add_executable(${PROJECT_NAME} tutorial.cpp)
# 指定将MathFunctions库链接到项目Tutorial的可执行文件
target_link_libraries(${PROJECT_NAME} PUBLIC MathFunctions)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR} # CMake生成的TutorialConfig.h存放目录
${PROJECT_SOURCE_DIR}/MathFunctions # 库的头文件存放目录
)
CMake中
target_xxx
关键字指定编译给定目标时相关内容,在上面命令中即指定Tutorial这个项目编译过程中包含的头文件目录和库文件目录。
4 将库设置为可选项
第一步是向顶级 CMakeLists.txt 文件添加一个选项。
option(USE_MYMATH "Use tutorial provided math implementation" ON)
option
表示提供用户可以选择的选项。命令格式为:option(<variable> "description [initial value])
。USE_MYMATH
选项的缺省值为 ON
。
下一步创建if语句,
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES ${PROJECT_SOURCE_DIR}/MathFunctions)
endif()
add_executable(${PROJECT_NAME} tutorial.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC ${EXTRA_LIBS})
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR}
${EXTRA_INCLUDES}
)
APPEND
表示将元素MathFunctions
追加到列表EXTRA_LIBS
中,将元素 ${PROJECT_SOURCE_DIR}/MathFunctions
追加到列表EXTRA_INCLUDES
中。EXTRA_LIBS
存储 MathFunctions 库,EXTRA_INCLUDES
存储 MathFunctions 头文件。因此在target_link_libraries
和target_include_directories
中用${EXTRA_LIBS}
和${EXTRA_INCLUDES}
分别获取库文件和头文件目录。
当然也可以通过TutorialConfig.h.in配置文件实现上述效果,修改tutorial.cxx
如下:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TutorialConfig.h"
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
int main (int argc, char *argv[]) {
if (argc < 2) {
fprintf(stdout,"%s Version %d.%d\n", argv[0],
Tutorial_VERSION_MAJOR,
Tutorial_VERSION_MINOR);
fprintf(stdout,"Usage: %s number\n",argv[0]);
return 1;
}
double inputValue = atof(argv[1]);
#ifdef USE_MYMATH
double outputValue = mysqrt(inputValue);
#else
double outputValue = sqrt(inputValue);
#endif
fprintf(stdout,"The square root of %g is %g\n", inputValue, outputValue);
return 0;
}
在TutorialConfig.h.in
中添加一行,添加宏USE_MYMATH
:
#cmakedefine USE_MYMATH
在构建项目时可以选择性地使用库:
# 在构建项目时不使用库
cmake -DUSE_MYMATH=OFF ..
5 添加库的使用要求
库的使用要求有三个:
- INTERFACE:表示用户需要,开发者不需要;
- PRIVATE:表示用户不需要,开发者需要;
- PUBLIC:表示用户和开发者都需要。
6 动态库和静态库构建
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
source1 source2 ... sourceN)
添加一个名为<name>
的库文件,该库文件将会根据调用的命令里列出的源文件来创建。STATIC
为静态库,SHARED
为动态库。
静态库和动态库的区别
- 静态库的扩展名一般为“.a”或“.lib”;动态库的扩展名一般为“.so”或“.dll”;
- 静态库在编译链接阶段会直接整合到目标程序中,编译链接成功的可执行文件可独立运行;
- 动态库在编译时不会放到链接的目标程序中,而是在运行阶段加载,即可执行文件无法单独运行。
7 包含第三方库
find_package(<package> [version] [EXACT] [QUIET]
[[REQUIRED|COMPONENTS] [components...]]
[NO_POLICY_SCOPE])
查找并加载第三方库。该命令会设置<package>_FOUND
变量,用来指示要找的包是否被找到了。REQUIRED
选项表示如果报没有找到的话,cmake的过程会终止,并输出警告信息。[version]
参数为第三方库的最低版本。COMPONENTS
选项后面可以列出要查找的库列表(components list)。
参考
[1] https://zhuanlan.zhihu.com/p/500002865
[2] CMake Tutorial — CMake 3.25.1 Documentation
[3] https://blog.csdn.net/qq_44074143/article/details/123244847