[TOC]
1 CMakeLists.txt基础模板 1.1 最小项目 CMakeLists.txt
1 2 3 4 5 6 cmake_minimum_required (VERSION 2.6 )project (Tutorial)add_executable (Tutorial tutorial.cxx)
tutorial.cxx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #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 ; } const double inputValue = atof (argv[1 ]); const double outputValue = sqrt (inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; return 0 ; }
1.2 构建、编译和运行 安装CMake、MinGW64并配置环境变量。终端进入到CMakeLists.txt
目录,输入:
1 2 3 4 5 6 7 8 mkdir buildcd build # 构建 cmake -G"MinGW Makefiles" .. # 编译链接 cmake --build . # 运行 .\Tutorial.exe 25
cmake -G<编译器名称> <CMakeLists.txt路径>
cmake –build <编译生成文件存放路径>
2 CMakeLists.txt优化 2.1 set 与 PROJECT_NAME 1 2 3 4 5 6 7 8 cmake_minimum_required (VERSION 2.6 )project (Tutorial)SET (SRC_LIST tutorial.cxx)add_executable (${PROJECT_NAME} ${SRC_LIST} )
2.2 添加版本号和配置头文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 cmake_minimum_required (VERSION 2.6 )project (Tutorial VERSION 1.0 )SET (SRC_LIST tutorial.cxx)configure_file ( "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" "${PROJECT_BINARY_DIR}/TutorialConfig.h" )include_directories ("${PROJECT_BINARY_DIR}" )add_executable (${PROJECT_NAME} ${SRC_LIST} )
TutorialConfig.h.in
1 2 3 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
自动生成的TutorialConfig.h
:
1 2 3 #define Tutorial_VERSION_MAJOR 1 #define Tutorial_VERSION_MINOR 0
修改tutorial.cxx
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <stdio.h> #include <stdlib.h> #include <math.h> #include "TutorialConfig.h" #include <iostream> int main (int argc, char *argv[]) { if (argc < 2 ) { 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 ; }
运行结果如下:
1 2 3 4 PS D:\CMAKE_Learn\build> .\Tutorial.exeD:\CMAKE_Learn \build \Tutorial.exe Version 1.0 Usage : D :\CMAKE_Learn \build \Tutorial.exe number PS D :\CMAKE_Learn \build >
2.3 指定 C++ 标准 1 2 3 set (CMAKE_CXX_STANDARD 11 )set (CMAKE_CXX_STANDARD_REQUIRED True )
3 添加库 一般我们将库的源码放在项目源文件目录下的MathFunctions子目录中,并在该子目录 (该目录下包含头文件MathFunctions.h
和相关源文件mysqrt.cxx
)下新建一个CMakeLists.txt
,添加如下内容:
1 2 add_library (MathFunctions mysqrt.cxx)
此时项目文件结构如下:
1 2 3 4 5 6 7 8 9 CMAKE_Learn/ build/ MathFunctions/ CMakeLists.txt MathFunctions.h mysqrt.cxx CMakeLists.txt tutorial.cxx TutorialConfig.h.in
再在顶层目录下的CMakeLists.txt文件中添加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 add_subdirectory (MathFunctions)add_executable (${PROJECT_NAME} tutorial.cpp)target_link_libraries (${PROJECT_NAME} PUBLIC MathFunctions)target_include_directories (${PROJECT_NAME} PUBLIC ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR} /MathFunctions )
CMake中target_xxx
关键字指定编译给定目标时相关内容 ,在上面命令中即指定Tutorial这个项目编译过程中包含的头文件目录和库文件目录。
4 将库设置为可选项 第一步是向顶级 CMakeLists.txt 文件添加一个选项。
1 option (USE_MYMATH "Use tutorial provided math implementation" ON )
option
表示提供用户可以选择的选项。命令格式为:option(<variable> "description [initial value])
。USE_MYMATH
选项的缺省值为 ON
。
下一步创建if语句,
1 2 3 4 5 6 7 8 9 10 11 12 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
如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #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
:
在构建项目时可以选择性地使用库:
1 2 # 在构建项目时不使用库 cmake -DUSE_MYMATH=OFF ..
5 添加库的使用要求 库的使用要求有三个:
INTERFACE :表示用户需要,开发者不需要;
PRIVATE :表示用户不需要,开发者需要;
PUBLIC :表示用户和开发者都需要。
6 动态库和静态库构建 1 2 3 add_library (<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
添加一个名为<name>
的库文件,该库文件将会根据调用的命令里列出的源文件来创建。STATIC
为静态库,SHARED
为动态库。
静态库和动态库的区别
静态库的扩展名一般为“.a”或“.lib”;动态库的扩展名一般为“.so”或“.dll”;
静态库在编译链接阶段 会直接整合到目标程序中,编译链接成功的可执行文件可独立运行;
动态库在编译时不会放到链接的目标程序中,而是在运行阶段 加载,即可执行文件无法单独运行。
7 包含第三方库 1 2 3 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