CMake
cmake的定义是 -- 高级编译配置工具
当多人用不同的语言或者编译器开发一个项目,最终要输出一个可执行文件或者共享库(dll,so等等)这时候就需要用到 ------ CMake
所有操作都是通过编译 CMakeLists.txt 来完成的
官方网站是 www.cmake.org
学习CMake的目的,为将来处理大型的C/C++/JAVA项目做准备
CMake安装
- CMake:https://cmake.org/download/
- MinGW:https://sourceforge.net/projects/mingw-w64/files/mingw-w64/
构建和运行
- 创建一个文件夹,里面再创建一个 src 文件夹,src文件夹中包含:main.cpp,CMakeLists.txt
main.cpp:
| #include<iostream> |
| using namespace std; |
| |
| int main() |
| { |
| cout<<"Hello World"<<endl; |
| return 0; |
| } |
CMakeLists.txt:
| cmake_minimum_required(VERSION 3.10) |
| |
| |
| project(demo) |
| |
| |
| add_executable(demo main.cpp) |
- 新建一个构建目录
- 进入该目录进行配置项目
如果 cmake ../src 报错,则说明不是使用默认的Generator,应当添加 -G 选项:
| cmake -G "MinGW Makefiles" ../src |
说明
- cmake命令不区分大小些写,但是参数、变量区分大小写
- 参数使用空格或者分号隔开
- 使用 ${VAR} 引用变量
- 引号可加可不加,但如果字符串中有空格必须加
概念
- 目标文件(target):可执行文件(add_executable)、库文件(add_library)
- 命令(cmake-command):下面要讲的函数
- 变量(cmake-variable):以 CMAKE_ 开头的变量名
- 属性(cmake-properties):文件/文件夹都有各自的属性
命令
cmake_minimum_required
设置最低cmake版本
| cmake_minimum_required(VERSION <min>) |
| cmake_minimum_required(VERSION 3.10) |
project
设置项目名
| project(<PROJECT-NAME> [<language-name>...]) |
| project(<PROJECT-NAME> |
| [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]] |
| [DESCRIPTION <project-description-string>] |
| [HOMEPAGE_URL <url-string>] |
| [LANGUAGES <language-name>...]) |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| project(demo VERSION 1.0 LANGUAGES CXX) |
| |
| message(${PROJECT_NAME}) |
| |
| message(${PROJECT_SOURCE_DIR}) |
| message(${demo_SOURCE_DIR}) |
| |
| message(${PROJECT_BINARY_DIR}) |
| message(${demo_BINARY_DIR}) |
| |
| message(${PROJECT_VERSION}) |
| message(${PROJECT_VERSION_MAJOR}) |
| message(${PROJECT_VERSION_MINOR}) |
add_executable
用指定的源文件为项目添加可执行文件
| add_executable(<name> [WIN32] [MACOSX_BUNDLE] |
| [EXCLUDE_FROM_ALL] |
| [source1] [source2 ...]) |
| |
| |
| |
| add_executable(demo main.cpp) |
message
打印信息
| message([<mode>] "message text" ...) |
| |
| |
| |
| |
| message(STATUS "${PROJECT_VERSION_MAJOR}") |
set
将变量设置为指定值
| set(<variable> <value>) |
| |
| |
| set(A 1) |
| message(${A}) |
设置C++标准
| |
| set(CMAKE_CXX_STANDARD 11) |
设置输出文件的位置
| |
| set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) |
| |
| |
| set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) |
| |
| set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) |
| |
| |
| |--build |
| |--lib |
| |--*** |
| |--src |
| *** |
option
定义一个开关
| option(<variable> "<help_text>" [value]) |
| |
| |
| |
将输入文件进行替换并生成输出文件
1.
| configure_file(<input> <output>) |
| |
| |
例1:
在src目录下创建一个config.h.in文件
在CMakeLists.txt中版本号下面添加
| |
| configure_file(config.h.in config.h) |
然后再cmd中配置和构建以后,会再build下生成一个config.h文件
| cmake -G "MinGW Makefiles" ..\src |
| cmake --build . |
现在我们就能够调用config.h中的内容了
在main.cpp中加入
| #include<iostream> |
| #include"../build/config.h" |
| using namespace std; |
| |
| int main() |
| { |
| cout<<"Hello World"<<endl; |
| |
| cout<<"version: "<< PROJECT_VERSION_MAJOR << "." << PROJECT_VERSION_MINOR <<endl; |
| return 0; |
| } |
在CMakeLists.txt中加入
| target_include_directories(demo PUBLIC "${PROJECT_BINARY_DIR}") |
再重新配置和构建,运行可看到运行结果
| cmake -G "MinGW Makefiles" ..\src |
| cmake --build . |
| bin\demo.exe |
| |
| |
| |
2.
| #cmakedefine VAR ... |
| |
| #define VAR ... |
| |
例2:
在CMakeLists.txt中写入
| |
| option(DATE_ENABLE "output date" ON) |
| |
| if(DATE_ENABLE) |
| set(DATE "2022.12.6") |
| endif() |
在config.h.in中加入
配置,构建,之后再config.h中会出现
| cmake -G "MinGW Makefiles" ..\src |
| cmake --build . |
| |
| |
如果 CMakeLists.txt 中的 option 是 OFF
| |
| option(DATE_ENABLE "output date" ON) |
在进行同样的操作(再进行同样操作之前,要将缓存清理掉,就是删除build中的文件,重新配置和构建),这 config.h 中则会出现
include_directories
指定所有目标的头文件路径
| include_directories(dir1 [dir2 ...]) |
| |
| |
| |
| |
| include_directories(${PROJECT_BINARY_DIR}) |
target_include_directories
指定(一个)目标的头文件路径
| target_include_directories(<target> [SYSTEM] [AFTER|BEFORE] |
| <INTERFACE|PUBLIC|PRIVATE> [items1...] |
| [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...]) |
| |
| |
| |
| |
|
INCLUDE_DIRECTORIES |
INTERFACE_INCLUDE_DIRECTORIES |
PRIVATE(自己使用) |
√ |
|
INTERFACE(给别人使用) |
|
√ |
PUBLIC(都能使用) |
√ |
√ |
| |
| target_include_directories(demo PUBLIC ${PROJECT_BINARY_DIR}) |
add_subdirectory
添加源文件目录
| add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL]) |
| |
add_library
用指定的源文件生成库
| add_library(<name> [STATIC | SHARED | MODULE] |
| [EXCLUDE_FROM_ALL] |
| [<source>...]) |
| |
| |
| |
| |
| |
| add_library(addition STATIC addition.cpp) |
| add_library(subtract SHARED subtract.cpp) |
target_link_libraries
为目标链接库
| target_link_libraries(<target> |
| <PRIVATE|PUBLIC|INTERFACE> <item>... |
| [<PRIVATE|PUBLIC|INTERFACE> <item>...]...) |
| |
| |
| |
| |
| |
| target_link_libraries(demo PUBLIC addition) |
| |
| target_link_libraries(demo PUBLIC subtract) |
| |
| |
| target_include_directories(demo PUBLIC ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/calc) |
| |
| |
| #include<iostream> |
| #include"config.h" |
| #include"addition.h" |
| #include"subtract.h" |
| using namespace std; |
| |
| int main() |
| { |
| cout<<"Hello World"<<endl; |
| cout<<"version: "<< PROJECT_VERSION_MAJOR << "." << PROJECT_VERSION_MINOR <<endl; |
| #ifdef DATE |
| cout << "date " << DATE << endl; |
| #endif |
| |
| cout<< "1 + 2 = " << add(1,2) << endl; |
| cout<< "3 - 1 = " << sub(3,1) << endl; |
| |
| return 0; |
| } |
进行配置和构建,构建完之后,由上面 set 设置的文件输出路径可知:
- 动态库生成在 build/bin 下面的 .dll 文件
- 静态库生成在 build/lib 下面的 .a文件
链接外部其他的库
先创建一个文件夹,将要 链接的库和所需的头文件 放入其中,如other_lib
| |--build |
| |--bin |
| *** |
| |--libdivision.dll |
| *** |
| |--other_lib |
| |--libmultiply.a |
| |--multiply.h |
| |--libdivision.dll |
| |--division.h |
| |--src |
在 src 的 CMakeLists.txt 添加
| |
| target_link_libraries(demo PUBLIC "D:/Visual Studio/repos/CMakeDemo01/other_lib/libmultiply.a") |
| |
| target_link_libraries(demo PUBLIC "D:/Visual Studio/repos/CMakeDemo01/other_lib/libdivision.dll") |
| |
| |
| target_include_directories(demo PUBLIC ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/calc ${PROJECT_SOURCE_DIR}/../other_lib) |
之后就能够在 main.cpp 中调用了
| #include<iostream> |
| #include"config.h" |
| #include"addition.h" |
| #include"subtract.h" |
| #include"multiply.h" |
| #include"division.h" |
| using namespace std; |
| |
| int main() |
| { |
| cout<<"Hello World"<<endl; |
| cout<<"version: "<< PROJECT_VERSION_MAJOR << "." << PROJECT_VERSION_MINOR <<endl; |
| #ifdef DATE |
| cout << "date " << DATE << endl; |
| #endif |
| |
| cout<< "1 + 2 = " << add(1,2) << endl; |
| cout<< "3 - 1 = " << sub(3,1) << endl; |
| cout<< "2 * 3 = " << mult(2,3) << endl; |
| cout<< "6 / 2 = " << divi(6,2) << endl; |
| |
| return 0; |
| } |
区分
| |
| include_directories() |
| target_include_directories() |
| |
| |
| link_directories() |
| target_link_directories() |
| |
| |
| link_libraries() |
| target_link_libraries() |
| |
| |
安装
cmake代码
在对应目录的CMakeLists.txt中使用
| install(TARGETS <target> DESTINATION <dir>) |
| install(FILES <file> DESTINATION <dir>) |
| install(PROGRAMS <非目标文件的可执行程序> DESTINATION <dir>) |
| install(DIRECTORY <dir> DESTINATION <dir>) |
在 src 的 CMakeLists.txt 中添加
| |
| install(TARGETS demo DESTINATION bin) |
| |
| install(FILES "D:/Visual Studio/repos/CMakeDemo01/other_lib/libmultiply.a" DESTINATION lib) |
| |
| install(FILES "D:/Visual Studio/repos/CMakeDemo01/other_lib/libdivision.dll" DESTINATION bin) |
| |
| install(FILES "${PROJECT_BINARY_DIR}/config.h" DESTINATION include) |
| |
| install(FILES "D:/Visual Studio/repos/CMakeDemo01/other_lib/multiply.h" DESTINATION include) |
| |
| install(FILES "D:/Visual Studio/repos/CMakeDemo01/other_lib/division.h" DESTINATION include) |
在 calc 的 CMakeLists.txt 中添加
| add_library(addition STATIC addition.cpp) |
| |
| |
| |
| install(TARGETS addition DESTINATION lib) |
| |
| install(FILES addition.h DESTINATION include) |
| |
| |
| add_library(subtract SHARED subtract.cpp) |
| |
| |
| |
| install(TARGETS subtract DESTINATION bin) |
| |
| install(FILES subtract.h DESTINATION include) |
| |
命令行
| cmake --install . |
| CMAKE_INSTALL_PREFIX |
| cmake --install . --prefix <dir> |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了