on
cmake 介绍
## 简介
开源、跨平台的构建工具,具体可看官方文档 cmake org。源码可以在 github-cmake 查阅。 历史可以看 cmake history,目前 Android、LLVM、QT 等都默认推荐使用 cmake。 除去官方文档,还有 modern cmake 及其中文版 Modern CMake 简体中文版 可以参看。
以 Android 为例,简单的流程可以理解为:
CMakeLists.txt -> cmake
-> Makefile -> make
-> so 库
cmake 常用参数
-G <generator>
:指定要使用的构建系统生成器(如-G Ninja
)-D <var>=<value>
:定义或覆盖 CMake 变量(如-D CMAKE_BUILD_TYPE=Release
)-S <source_path>
:指定源代码路径(如-S . -B build
)-B <build_path>
:指定构建目录-C <initial_cache>
:预先加载 CMake 缓存文件-E <command>
:执行 CMake 的内置命令(如:cmake -E make_directory build
)--build <build_path>
:调用构建工具来构建项目,通常与--config
一起使用(如cmake --build build --config Release
)--install <build_path>
:安装构建的目标到指定位置(如cmake --install build
)--version
:显示 CMake 的版本信息--trace
cmake 命令
以下是 CMake 中几个常用命令的使用简介和示例,整理成表格形式,cmake-commands
脚本命令
以下是 CMake 中更多常用命令的使用简介和示例,以表格形式展示:
命令 | 简介 | 示例 |
---|---|---|
block |
定义一个代码块,用于组织和控制语句的执行。 | block(my_block)<br>message("Inside block")<br>endblock |
break |
退出循环或块,停止执行当前的循环或块。 | foreach(i RANGE 5)<br>if(i EQUAL 3)<br>break<br>endif<br>endforeach |
cmake_host_system_information |
获取主机系统的信息,如操作系统、处理器架构等。 | cmake_host_system_information(RESULT my_os QUERY OS_NAME) |
cmake_language |
执行 CMake 语言的特定命令,如运行 CMake 脚本。 | cmake_language(SET my_var "Hello") |
cmake_minimum_required |
指定所需的最低 CMake 版本。 | cmake_minimum_required(VERSION 3.10) |
cmake_parse_arguments |
解析传递给函数或宏的参数,便于处理命令行选项。 | cmake_parse_arguments(PARSE_VAR my_option "A" "B" "C") |
cmake_path |
操作路径字符串,例如转换路径格式。 | cmake_path(TO_CMAKE_PATH my_path) |
cmake_pkg_config |
使用 pkg-config 查找库和头文件信息。 | cmake_pkg_config(my_lib REQUIRED) |
cmake_policy |
设置或查询 CMake 的策略。 | cmake_policy(SET CMP0012 NEW) |
configure_file |
处理文件并生成输出文件,通常用于配置头文件。 | configure_file(config.h.in config.h) |
continue |
继续下一个循环迭代,跳过当前的循环体。 | foreach(i RANGE 5)<br>if(i EQUAL 3)<br>continue<br>endif<br>endforeach |
else |
在条件语句中定义 “否则” 的分支。 | if(ENABLE_FEATURE)<br>message("Enabled")<br>else<br>message("Disabled")<br>endif |
elseif |
在条件语句中定义附加的 “如果” 分支。 | if(A)<br>message("A")<br>elseif(B)<br>message("B")<br>endif |
endblock |
结束一个代码块,与 block 搭配使用。 |
endblock |
endforeach |
结束 foreach 循环。 |
foreach(i RANGE 5)<br>message("Number: ${i}")<br>endforeach |
endfunction |
结束自定义函数的定义。 | function(my_function)<br>message("Hello")<br>endfunction |
endif |
结束 if 语句的分支。 |
if(CONDITION)<br>message("True")<br>endif |
endmacro |
结束宏的定义。 | macro(my_macro)<br>message("Inside macro")<br>endmacro |
endwhile |
结束 while 循环。 |
while(CONDITION)<br>message("Loop")<br>endwhile |
execute_process |
执行外部命令并获取结果,适合用于运行脚本或命令行工具。 | execute_process(COMMAND my_command OUTPUT_VARIABLE result) |
file |
处理文件相关操作,如复制、删除或读取文件内容。 | file(READ "my_file.txt" content) |
find_file |
查找指定的文件,返回找到的路径。 | find_file(MY_FILE my_header.h PATHS /usr/include) |
find_library |
查找指定的库文件,返回找到的路径。 | find_library(MY_LIB my_library PATHS /usr/lib) |
find_package |
查找并配置指定的包或库,通常与 CMake 模块配合使用。 | find_package(MyLib REQUIRED) |
find_path |
查找指定的目录,返回找到的路径。 | find_path(MY_INCLUDE_DIR my_header.h PATHS /usr/include) |
find_program |
查找指定的程序,返回找到的路径。 | find_program(MY_EXEC my_program PATHS /usr/bin) |
foreach |
对集合中的每个元素执行一段代码。 | foreach(item IN LISTS my_list)<br>message("${item}")<br>endforeach |
function |
定义一个新的 CMake 函数,便于复用代码。 | function(my_function)<br>message("Hello")<br>endfunction |
get_cmake_property |
获取 CMake 变量或属性的值。 | get_cmake_property(VERSION VERSION) |
get_directory_property |
获取当前目录的属性。 | get_directory_property(MY_PROPERTY PROPERTIES) |
get_filename_component |
获取文件路径的组成部分,如文件名或扩展名。 | get_filename_component(MY_NAME "path/to/file.txt" NAME) |
get_property |
获取指定对象的属性,如目标、变量等。 | get_property(MY_TARGET_INCLUDE_DIRS my_library INCLUDE_DIRECTORIES) |
if |
条件判断,执行条件语句。 | if(DEFINED MY_VAR)<br>message("Variable is defined")<br>endif |
include |
包含另一个 CMake 文件或模块,便于代码复用。 | include(my_module.cmake) |
include_guard |
防止 CMake 文件被多次包含,通常用于模块文件。 | include_guard(GLOBAL) |
list |
操作列表,如添加、移除或查找元素。 | list(APPEND my_list "new_item") |
macro |
定义一个新的 CMake 宏,便于复用代码。 | macro(my_macro)<br>message("Hello")<br>endmacro |
mark_as_advanced |
将变量标记为高级变量,不在普通用户界面中显示。 | mark_as_advanced(MY_VARIABLE) |
math |
执行数学计算。 | math(EXPR RESULT "5 + 10") |
message |
输出信息到控制台,便于调试。 | message("Building MyProject") |
option |
定义一个选项变量,通常用于配置开关。 | option(MY_OPTION "Enable feature" ON) |
return |
从函数或宏中返回,终止执行。 | function(my_function)<br>return()<br>endfunction |
separate_arguments |
将字符串分隔为列表。 | separate_arguments(MY_LIST "arg1;arg2;arg3") |
set |
设置变量的值或属性。 | set(MY_VAR "Hello, World!") |
set_directory_properties |
设置当前目录的属性。 | set_directory_properties(PROPERTIES MY_PROPERTY "Value") |
set_property |
设置对象的属性,如目标、目录等。 | set_property(TARGET my_library PROPERTY VERSION 1.0) |
site_name |
获取当前 CMake 项目的站点名称。 | message("Site Name: ${CMAKE_SYSTEM_NAME}") |
string |
执行字符串操作,如拼接、替换或查找。 | string(APPEND my_string " World!") |
unset |
删除变量或属性。 | unset(MY_VAR) |
variable_watch |
监视变量的变化并输出调试信息。 | variable_watch(MY_VAR) |
while |
循环执行,直到条件不再满足。 | set(i 0)<br>while(i LESS 5)<br>message("${i}")<br>math(EXPR i "${i} + 1")<br>endwhile |
项目命令
命令 | 一句话简介 | 示例 |
---|---|---|
add_compile_definitions |
添加编译时定义的宏,适用于所有目标。 | add_compile_definitions(MY_DEFINE) |
add_compile_options |
添加编译选项,适用于所有目标。 | add_compile_options(-Wall -Wextra) |
add_custom_command |
创建自定义命令,执行特定的操作,如生成文件。 | add_custom_command(OUTPUT output.txt<br>COMMAND echo "Hello" > output.txt) |
add_custom_target |
创建自定义构建目标,可以与其他目标相互依赖。 | add_custom_target(MyTarget DEPENDS output.txt) |
add_definitions |
添加编译时定义的宏,适用于所有目标(不推荐使用)。 | add_definitions(-DMY_DEFINE) |
add_dependencies |
指定目标间的依赖关系,确保构建顺序。 | add_dependencies(my_executable my_library) |
add_executable |
定义一个可执行文件目标。 | add_executable(my_app main.cpp) |
add_library |
定义一个库目标,可以是静态库或共享库。 | add_library(my_library SHARED library.cpp) |
add_link_options |
添加链接选项,适用于所有目标。 | add_link_options(-static) |
add_subdirectory |
将子目录添加到构建系统中,便于管理大型项目。 | add_subdirectory(src) |
add_test |
注册测试用例,以便使用 CTest 运行。 | add_test(NAME MyTest COMMAND my_app) |
aux_source_directory |
自动查找指定目录中的源文件并将其添加到变量中。 | aux_source_directory(src DIR_SOURCES) |
build_command |
在自定义命令中执行构建操作。 | set(BUILD_CMD "make")<br>add_custom_command(OUTPUT output.txt COMMAND ${BUILD_CMD}) |
cmake_file_api |
启用 CMake 文件 API,以支持外部工具访问构建信息。 | set(CMAKE_FILE_API TRUE) |
create_test_sourcelist |
创建一个测试源文件列表,便于管理多个测试文件。 | create_test_sourcelist(MyTests test_files.cxx ${CMAKE_SOURCE_DIR}/tests/*.cpp) |
define_property |
定义自定义属性,允许为目标或其他对象添加新属性。 | define_property(MY_PROPERTY TYPE STRING) |
enable_language |
启用指定的编程语言支持,如 C、C++、Fortran 等。 | enable_language(CXX) |
enable_testing |
启用 CTest 测试框架,允许添加和运行测试。 | enable_testing() |
export |
导出目标及其属性,以供其他 CMakeLists.txt 使用。 | export(TARGETS my_library FILE my_library.cmake) |
fltk_wrap_ui |
为 FLTK 创建用户界面文件的包装器。 | fltk_wrap_ui(MY_UIC_FILES my_ui_file.ui) |
get_source_file_property |
获取源文件的属性,例如编译选项或包含目录。 | get_source_file_property(MY_SOURCE my_file.cpp LOCATION) |
get_target_property |
获取目标的属性,如链接库或编译选项。 | get_target_property(MY_LIB_INCLUDE_DIRS my_library INCLUDE_DIRECTORIES) |
get_test_property |
获取测试的属性,例如期望结果或状态。 | get_test_property(MY_TEST TIMEOUT) |
include_directories |
指定要包含的头文件目录。 | include_directories(${CMAKE_SOURCE_DIR}/include) |
include_external_msproject |
将外部 Microsoft 项目包含到 CMake 项目中。 | include_external_msproject(MyProject "path/to/project.vcproj") |
include_regular_expression |
指定正则表达式以匹配文件,通常用于查找文件。 | include_regular_expression("^.*\\.cpp$") |
install |
定义安装规则,指定如何安装目标和文件。 | install(TARGETS my_app DESTINATION bin) |
link_directories |
指定链接器查找库文件的目录。 | link_directories(/usr/local/lib) |
link_libraries |
指定要链接的库,可以是目标名或库文件。 | link_libraries(my_library) |
load_cache |
从 CMake 缓存加载变量和设置。 | load_cache("my_cache.cmake") |
project |
定义项目的名称和使用的语言。 | project(MyProject CXX) |
remove_definitions |
从编译选项中移除指定的定义宏。 | remove_definitions(-DMY_DEFINE) |
set_source_files_properties |
设置源文件的特定属性,如编译选项或语言标准。 | set_source_files_properties(my_file.cpp PROPERTIES LANGUAGE CXX) |
set_target_properties |
设置目标的特定属性,如输出名称或链接库。 | set_target_properties(my_library PROPERTIES VERSION 1.0) |
set_tests_properties |
设置测试的特定属性,如超时或期望结果。 | set_tests_properties(my_test PROPERTIES TIMEOUT 10) |
source_group |
将源文件组织到特定的组中,以便在 IDE 中更易管理。 | source_group("Source Files" FILES main.cpp other.cpp) |
target_compile_definitions |
为特定目标添加编译时定义的宏。 | target_compile_definitions(my_app PRIVATE MY_DEFINE) |
target_compile_features |
指定特定目标支持的编译特性和语言标准。 | target_compile_features(my_app PRIVATE cxx_std_11) |
target_compile_options |
为特定目标添加编译选项。 | target_compile_options(my_app PRIVATE -Wall) |
target_include_directories |
为特定目标指定包含目录。 | target_include_directories(my_library PUBLIC ${CMAKE_SOURCE_DIR}/include) |
target_link_directories |
为特定目标指定链接库的搜索目录。 | target_link_directories(my_app PRIVATE /usr/local/lib) |
target_link_libraries |
为特定目标指定链接的库或其他目标。 | target_link_libraries(my_app PRIVATE my_library) |
target_link_options |
为特定目标添加链接选项。 | target_link_options(my_app PRIVATE -static) |
target_precompile_headers |
为特定目标指定预编译头文件。 | target_precompile_headers(my_app PRIVATE "pch.h") |
target_sources |
为特定目标添加源文件。 | target_sources(my_library PRIVATE source1.cpp source2.cpp) |
try_compile |
尝试编译一个简单的源文件,测试特性或库的可用性。 | try_compile(COMPILER_TEST_BINARY ${CMAKE_BINARY_DIR} test.cpp) |
try_run |
尝试运行一个可执行文件,测试其行为。 | try_run(RUN_TEST_BINARY ${CMAKE_BINARY_DIR} test.cpp) |
常用命令详解
定义变量 set(var hello) 使用变量:${var}
math(EXPR
file(RENAME “test.txt” “new.txt”),文件重命名
file(GLOB ROOT_SOURCE .cpp),GLOB 指令会将所有匹配 .cpp 表达式的文件组成一个列表,并保存在 ROOT_SOURCE 变量中
file(GLOB_RECURSE CORE_SOURCE ./detail/*.cpp),而 GLOB_RECURSE 指令和 GLOB 类似,但是它会遍历匹配目录的所有文件以及子目录下面的文件
预定义的常量 在 CMake 中有许多预定义的常量,使用好这些常量能起到事半功倍的效果。
- CMAKE_CURRENT_SOURCE_DIR
- 指当前 CMake 文件所在的文件夹路径
- CMAKE_SOURCE_DIR
- 指当前工程的 CMake 文件所在路径
- CMAKE_CURRENT_LIST_FILE
- 指当前 CMake 文件的完整路径
- PROJECT_SOURCE_DIR
- 指当前工程的路径
其他
对于 NDK 18rc 以上版本,gnustl_static 已经不在支持(https://blog.csdn.net/huangkangying/article/details/90048927) 新版本的NDK改用libc++作为默认的STL,而OpenCV Android 3.4版本使用的是gnustl。可以升级到OpenCV 4.0版本来兼容新版本的NDK,或者可以使用libc++重新编译OpenCV
-DANDROID_STL=c++_static or -DANDROID_STL=c++_shared
其他参考
- https://www.cnblogs.com/mingfeng002/p/6773217.html
- https://glumes.com/post/android/cmake-best-practices/