cmake 常用总结
很多时候不常用容易忘一些语法,自己总结自己看会更快早会感觉。后期持续添加
cmake
- target 前缀都是在 add_library , add_executable 之后编写
- Modern CMake 推荐使用 target 前缀方法 命令:
1 2
cmake --build build //编译 cmake --install 路径
基本内容语法
部分常用的函数和变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
message("ok") #SEND_ERROR,STATUS: -- OK,FATAL_ERROR
#if else
if(aaa)
#如果是 1、ON、YES、TRUE、Y或非零数(包括浮点数),则为 True。
#如果是 0、OFF、 NO、FALSE、N、IGNORE、NOTFOUND、空字符串或以 -NOTFOUND 后缀结尾,则为 False
#布尔常量不区分大小写
elseif(bbb)
#if(COMMAND command-name) 命令、宏或函数是否存在
#if(<variable|string> IN_LIST <variable>) 列表中是否存在
#if(EXISTS path-to-file-or-directory) 文件存在检查
# 还有一些比较少用的字符串 数字 版本号比较大于小于等,还有些冷门
else()
# ...
endif()
变量
1
2
3
4
5
6
7
8
9
10
11
12
${PROJECT_BINARY_DIR} #项目生成后的地址 后缀不带/
${PROJECT_SOURCE_DIR} #资源路径 后缀不带/
$<TARGET_OBJECTS:对象名字> #add_library OBJECT 时候,使用添加 OBJECT 的变量名: add_library,add_executable
CMAKE_PREFIX_PATH #用于指示CMake在查找包和项目所需库文件时的路径。在构建项目时,它可以帮助CMake定位库文件,头文件和执行文件等 -D CMAKE_PREFIX_PATH=/path/to/libA;/path/to/libB
#默认存放静态库的目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}/lib)
#默认存放动态库的目录
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}/lib)
#默认存放可执行文件的目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}/bin)
设置环境变量
一般都是大写和下划线,可以多个值
1
2
3
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_LIST "A" "B")
#与上面一样set(CMAKE_LIST "A;B")
其他目录cmake添加进构建
1
2
#映入cmake文件 默认是同级 可以有目录在前
add_subdirectory(file)
引入头文件文件夹
target_include_directories (
target_include_directories 颗粒度更小,如果是PUBLIC 父级引用它时候就不需要添加 target_include_directories
1
target_include_directories(target PRIVATE dir )
编译添加库文件
link_libraries 和 target_link_libraries 添加库文件不需要后缀 target_link_libraries 更细粒度
- link_libraries用于链接静态库,设置全局链接库,影响所有后续的编译过程
- target_link_libraries:用于链接导入库,即动态库的.lib文件,适用于特定的目标对象
- link_libraries 作为全局链接库设置,需要在add_library或者add_executable命令之前使用,
- target_link_libraries 为特定的目标指定链接库,则需要在add_library 或者add_executable命令之后使用
link_libraries([item1 [item2 […]]] [[debug|optimized|general]
target_link_libraries(
1
target_link_libraries(target PUBLIC lib)
搜索包
- 需要目录下有xxx(OpenCV)Config.cmake,大小写敏感
- 环境变量查找,${CMAKE_MODULE_PATH} 查找
1
find_package(OpenCV REQUIRED)
生成库
window 动态库有点不一样
- SHARED 动态
- STATIC 静态
- MODULE 类似于 SHARED 库,但通常用于运行时通过 dlopen (Linux) 或 LoadLibrary (Windows) 等函数显式加载的插件,而不是在链接时链接。
- OBJECT 作为一编译连接,可以被使用当作是自己一个整体整体 例如: exe -> b(STATIC) -> a(OBJECT) ,会被连接成一个整体
- UNKNOWN 当你使用的外部库的类型未知或不重要时,可以使用 UNKNOWN 类型。例如,你可能只知道库文件的路径和包含目录,但不知道它是静态库还是动态库。
- INTERFACE 没使用过
add_library(名字 <SHARED动态|STATIC静态|MODULE|OBJECT|UNKNOWN|INTERFACE> IMPORTED [GLOBAL])
1
add_library(name STATIC file )
生成可执行文件
1
2
#文件名后是多个管理所需要生成的源码文件 默认是同级 可以有目录在前
add_executable(文件名 main.cpp )
安装
- install(TARGETS
... [...]) - RUNTIME DESTINATION
: 安装运行时组件(例如可执行文件和动态库)到 目录。 - PUBLIC_HEADER DESTINATION
: 安装公共头文件到 目录 (适用于库目标)。 - PRIVATE_HEADER DESTINATION
: 安装私有头文件到 目录 (适用于库目标)。 - INCLUDES DESTINATION
: 通常用于安装头文件,等同于PUBLIC_HEADER DESTINATION - COMPONENT
: 将目标与名为 的组件关联起来。组件可以用于分组安装目标,并允许用户选择性地安装部分组件。 - NAMELINK_COMPONENT
: (自 CMake 3.14 起) 指定处理符号链接的版本化库文件的组件。 - NAMELINK_ONLY / NAMELINK_SKIP: (针对支持 soname 的平台,例如 Linux) NAMELINK_ONLY: 只安装符号链接文件,不安装实际的库文件。 NAMELINK_SKIP: 只安装实际的库文件,不安装符号链接文件。
- RUNTIME DESTINATION
: 安装运行时组件(例如可执行文件和动态库)到 目录。
- RUNTIME DESTINATION
install({FILES PROGRAMS} ... [...]) 用于安装文件或外部程序。 - FILES: 安装普通文件。
- PROGRAMS: 安装可执行程序(非 CMake 构建的目标,例如脚本)。
-
...: 要安装的文件或程序路径列表。 - […]:
- DESTINATION
: 安装文件到 目录。 - PERMISSIONS
: 设置安装文件的权限(例如 OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)。 - COMPONENT
: 将文件与名为 的组件关联起来。 - RENAME
: 安装文件时重命名为 。 - OPTIONAL: 如果文件不存在,则不产生错误。
- DESTINATION
- install(DIRECTORY
... [...]) 用于安装整个目录及其内容。 - DESTINATION
: 安装目录到 目录。 - FILES_MATCHING: 只安装匹配指定模式的文件。
- PATTERN
[EXCLUDE]: 指定匹配模式(可以使用通配符 * 和 ?),EXCLUDE 表示排除匹配的文件。 - COMPONENT
: 将目录与名为 的组件关联起来。
- DESTINATION
- install(SCRIPT
[...]) 用于在安装阶段执行指定的 CMake 脚本文件。 COMPONENT : 指定组件 - install(CODE
[...]) 用于在安装阶段执行指定的 CMake 代码片段。
- install(EXPORT
[...]) : 导出的目标集名称,它通过 export 命令或 install(EXPORT) 命令创建。 - DESTINATION
: 安装导出文件到 目录。 - NAMESPACE
: 为导入的目标添加命名空间前缀。 - FILE
.cmake: 指定导出文件的名称(默认为 .cmake)。 - COMPONENT
: 将导出文件与名为 的组件关联起来。
- DESTINATION
tips > 文件归属权限是安装者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#windows 动态库是 runtime 属性,动态库 cmake 也要添加,写在 install 后面都是 install 相关参数
install(TARGETS cmake_test
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static
)
set(CMAKE_INSTALL_PREFIX "./test") #指定目录
#=======
# 安装 icons 目录
install(DIRECTORY icons/ DESTINATION share/my_project)
install(FILES config.conf DESTINATION etc/my_project)
# 在安装阶段执行 post_install.cmake 脚本
install(SCRIPT post_install.cmake) # 执行一些自定义的安装后操作
# 在安装阶段打印一条消息
install(CODE "message(\"Installation completed!\")")
编译运行程序例子
库+运行文件
1
2
3
4
5
6
7
8
9
10
11
12
目录
| CMakeLists.txt
| main.cpp
\---demo1
| CMakeLists.txt
|
+---header
| add.h
|
\---svc
add.cpp
demo1 CMakeLists.txt
1
2
3
4
5
project(demo1)
add_library(demo1 svc/add.cpp) #改为动态库也是一样
target_include_directories(demo1 PUBLIC header)
#这里使用 PRIVATE `根目录 CMakeLists.txt `也需要引入 target_include_directories(cmake_test PUBLIC demo1/header)
根目录 CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cmake_minimum_required(VERSION 3.30)
project(cmake_test)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}/bin)
set(CMAKE_CXX_STANDARD 20)
add_subdirectory(demo1)
add_executable(cmake_test main.cpp)
target_link_libraries(cmake_test demo1)
运行文件 和一些特殊参数说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#声明cmake 最小最小版本
cmake_minimum_required(VERSION 3.30)
#项目名
project(cmake_test)
#设置 变量 : c++ 版本
set(CMAKE_CXX_STANDARD 20)
#CMAKE_PREFIX_PATH用于指示CMake在查找包和项目所需库文件时的路径。在构建项目时,它可以帮助CMake定位库文件,头文件和执行文件等
#-DCMAKE_PREFIX_PATH=/path/to/libA;/path/to/libB
set(CMAKE_PREFIX_PATH D:/app/qt/6.8.1/msvc2022_64)
#编译
add_executable(cmake_test main.cpp)
windows 与 linux 不同点
动态库和静态库跟linux是有区别的
windows
文件类型与扩展:动态库通常被创建为 .dll 文件,伴随着一个 .lib 文件(导入库),后者包含了需要链接到主可执行文件的符号。
导出符号:需要使用 __declspec(dllexport) 声明 和 __declspec(dllimport) 实现 来显式导出和导入类、函数或变量。
linux
文件类型与扩展:动态库被创建为 .so 文件(Shared Object)。
导出符号:Linux 平台通常不需要像 Windows 那样显式定义导入导出符号,编译器默认会导出所有符号。但为了隐藏不需要公开的符号,可能会使用 GCC 的 attribute((visibility(“default”))) 和 attribute((visibility(“hidden”))) 属性。
链接动态库的 CMake 指令也是相同的,但在 Windows 上需要链接到导入库 .lib 文件,而在 linux 上直接链接到 .so 文件。
1
2
3
4
5
6
7
#windows 防止乱码
#regedit 注册表> 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage >> `OEMCP` 和 `ACP`修改 65001
#程序输出 防止乱码
if(CMAKE_HOST_WIN32)
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
endif()