CMake 命令分类
CMake命令主要分为以下四种:
- 脚本命令(始终可用)
- 项目命令(仅在CMake项目中可用)
- CTest命令(仅在CTest脚本中可用)
- 不推荐使用的命令(已弃用,仅可用于维护向后兼容性。每个命令的文档都声明了不推荐使用的CMake版本。不要在新代码中使用这些命令)
脚本命令
- break
- cmake_host_system_information
- cmake_language
- cmake_minimum_required
- cmake_parse_arguments
- cmake_policy
- configure_file
- continue
- else
- elseif
- endforeach
- endfunction
- endif
- endmacro
- endwhile
- execute_process
- file
- find_file
- find_library
- find_package
- find_path
- find_program
- foreach
- function
- get_cmake_property
- get_directory_property
- get_filename_component
- get_property
- if
- include
- include_guard
- list
- macro
- mark_as_advanced
- math
- message
- option
- return
- separate_arguments
- set
- set_directory_properties
- set_property
- site_name
- string
- unset
- variable_watch
- while
项目命令
- add_compile_definitions
- add_compile_options
- add_custom_command
- add_custom_target
- add_definitions
- add_dependencies
- add_executable
- add_library
- add_link_options
- add_subdirectory
- add_test
- aux_source_directory
- build_command
- create_test_sourcelist
- define_property
- enable_language
- enable_testing
- export
- fltk_wrap_ui
- get_source_file_property
- get_target_property
- get_test_property
- include_directories
- include_external_msproject
- include_regular_expression
- install
- link_directories
- link_libraries
- load_cache
- project
- remove_definitions
- set_source_files_properties
- set_target_properties
- set_tests_properties
- source_group
- target_compile_definitions
- target_compile_features
- target_compile_options
- target_include_directories
- target_link_directories
- target_link_libraries
- target_link_options
- target_precompile_headers
- target_sources
- try_compile
- try_run
CTest 命令
- ctest_build
- ctest_configure
- ctest_coverage
- ctest_empty_binary_directory
- ctest_memcheck
- ctest_read_custom_files
- ctest_run_script
- ctest_sleep
- ctest_start
- ctest_submit
- ctest_test
- ctest_update
- ctest_upload
不推荐使用的命令
- build_name
- exec_program
- export_library_dependencies
- install_files
- install_programs
- install_targets
- load_command
- make_directory
- output_required_files
- qt_wrap_cpp
- qt_wrap_ui
- remove
- subdir_depends
- subdirs
- use_mangled_mesa
- utility_source
- variable_requires
- write_file
CMake 重要指令&常用变量
- CMake 得基本语法格式:
指令(参数 1 参数 2...)
-
参数使用括弧括起
-
参数之间使用空格或分号分开
- 指令是大小写无关的,参数和变量是大小写相关的
set(HELLO hello.cpp)
add_executable(hello main.cpp hello.cpp)
ADD_EXECUTABLE(hello main.cpp ${HELLO})
- 变量使用
${}
方式取值,但是在 IF 控制语句中是直接使用变量名。
CMake 重要指令
- cmake_minimum_required - 指定CMake的最小版本要求
语法: cmake_minimum_required(VERSION versionNumber [FATAL_ERROR])
# CMake最小版本要求为3.10.0
cmake_minimum_required(VERSION 3.10.0)
- project - 定义工程名称,并可指定工程支持的语言
语法:project(projectname [CXX] [C] [Java])
# 指定工程名为HELLOWORLD
project(HELLOWORLD)
- set - 显式的定义变量
语法:set(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
# 定义SRC变量,其值为sayhello.cpp hello.cpp
set(SRC sayhello.cpp hello.cpp)
- include_directories - 向工程添加多个特定的头文件搜索路径(相当于指定 g++ 编译器的 -I 参数)
语法:include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
# 将/usr/include/myincludefolder 和 ./include 添加到头文件搜索路径
include_directories(/usr/include/myincludefolder ./include)
- link_directories - 向工程添加多个特定的库文件搜索路径(相当于指定 g++ 编译器的 -L 参数)
语法:link_directories(dir1 dir2 ...)
# 将/usr/lib/mylibfolder 和 ./lib 添加到库文件搜索路径
link_directories(/usr/lib/mylibfolder ./lib)
- add_library - 生成库文件
语法:add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
# 通过变量 SRC 生成 libhello.so 共享库
add_library(hello SHARED ${SRC})
- add_compile_options - 添加编译参数
语法:add_compile_options(-XXX ...)
# 添加编译参数 -Wall -std=c++11 -O2
add_compile_options(-Wall -std=c++11 -O2)
- add_executable - 生成可执行文件
语法:add_executable(exename source1 source2 ... sourceN)
# 编译main.cpp生成可执行文件main
add_executable(main main.cpp)
- target_link_libraries - 为 target 添加需要链接的共享库(相同于指定 g++ 编译器 -l 参数)
语法:target_link_libraries(target library1<debug | optimized> library2...)
# 将hello动态库文件链接到可执行文件main
target_link_libraries(main hello)
- add_subdirectory - 向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置
语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
# 添加src子目录,src中需有一个CMakeLists.txt
add_subdirectory(src)
- aux_source_directory - 发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表
语法:aux_source_directory(dir VARIABLE)
# 定义SRC变量,其值为当前目录下所有的源代码文件
aux_source_directory(. SRC)
# 编译SRC变量所代表的源代码文件,生成main可执行文件
add_executable(main ${SRC})
CMake 常用变量
-
CMAKE_C_FLAGS:gcc编译选项
-
CMAKE_CXX_FLAGS:g++编译选项
# 在CMAKE_CXX_FLAGS编译选项后追加-std=c++11
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
- CMAKE_BUILD_TYPE:编译类型(Debug, Release)
# 设定编译类型为debug,调试时需要选择debug
set(CMAKE_BUILD_TYPE Debug)
# 设定编译类型为release,发布时需要选择release
set(CMAKE_BUILD_TYPE Release)
- CMAKE_BINARY_DIR
PROJECT_BINARY_DIR
_BINARY_DIR
- 这三个变量指代的内容是一致的。
- 如果是 in source build,指的就是工程顶层目录。
- 如果是 out-of-source 编译,指的是工程编译发生的目录。
- PROJECT_BINARY_DIR 跟其他指令稍有区别,不过现在,你可以理解为他们是一致
的。
- CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
_SOURCE_DIR
- 这三个变量指代的内容是一致的,不论采用何种编译方式,都是工程顶层目录。
- 也就是在 in source build时,他跟 CMAKE_BINARY_DIR 等变量一致。
- PROJECT_SOURCE_DIR 跟其他指令稍有区别,现在,你可以理解为他们是一致的。
- CMAKE_C_COMPILER:指定C编译器
- CMAKE_CXX_COMPILER:指定C++编译器
- EXECUTABLE_OUTPUT_PATH:可执行文件输出的存放
- LIBRARY_OUTPUT_PATH:库文件输出的存放路径
CMake 编译流程
CMake目录结构:项目主目录存在一个CMakeLists.txt文件
两种方式设置编译规则:
- 包含源文件的子文件夹包含CMakeLists.txt文件,主目录的CMakeLists.txt通过add_subdirectory 添加子目录即可;
- 包含源文件的子文件夹未包含CMakeLists.txt文件,子目录编译规则体现在主目录的
CMakeLists.txt中;
linux 平台下使用 CMake 构建C/C++工程的流程如下:
-
手动编写 CMakeLists.txt。
-
执行命令 cmake PATH 生成 Makefile ( PATH 是顶层CMakeLists.txt 所在的目录 )。
-
执行命令 make 进行编译。
# important tips . # 表示当前目录 ./ # 表示当前目录 .. # 表示上级目录 ../ # 表示上级目录
CMake 两种构建方式:
- 内部构建(in-source build):不推荐使用
内部构建会在同级目录下产生一大堆中间文件,这些中间文件并不是我们最终所需要的,和工程源文件放在一起会显得杂乱无章。
## 内部构建
# 在当前目录下,编译本目录的CMakeLists.txt,生成Makefile和其他文件
cmake .
# 执行make命令,生成target
make
- 外部构建(out-of-source build):推荐使用
将编译输出文件与源文件放到不同目录中
## 外部构建
# 1. 在当前目录下,创建build文件夹
mkdir build
# 2. 进入到build文件夹
cd build
# 3. 编译上级目录的CMakeLists.txt,生成Makefile和其他文件
cmake ..
# 4. 执行make命令,生成target
make