1. CMake简介
- CMake 是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的编译过程;他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。
- CMake是一种跨平台编译工具,比make更为高级,使用起来方便得多。CMake主要是编写CMakeLists.txt文件,然后使用cmake命令将CMakeLists.txt文件转化为make所需要的makefile文件,然后用make命令编译源码生成可执行程序或共享库。
2. CMakeList.txt常用命令简介
- cmake_minimum_required(VERSION3.5.1) 指定cmake版本;
cmake_minimum_required(VERSION 2.6)
- project(marianCXXC) 指定项目的名称,一般和项目的文件夹名称对应;
project(module_da_where_what)
- include_directories(marian_SOURCE_DIR/src) 引入头文件;
list(APPEND include_list ${work_home}/include)
list(APPEND include_list ${sug_da_lib_include})
- aux_source_directory(<dir> <variable>) 用于将dir目录下的所有源文件的名字保存在变量variable中;
aux_source_directory(./src ${hello_src})
- set(<variable> <value> [[CACHE <type><docstring> [FORCE]] | PARENT_SCOPE]) 用于设置变量variable的值为value。如果指定了CACHE变量将被放入Cache中;
set(CMAKE_CXX_COMPILER "/usr/local/gcc/bin/c++")
- option 选项,让你可以根据选项值进行条件编译;
option(TARGET_DEBUG_MODE "xxxxx" OFF)
unset 用于移除变量variable。如果指定CACHE变量将被从Cache中移除;
add_executable(<name> [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL] source1 source2 … sourceN) 添加要编译的可执行文件,用于从一组源文件source1 source2 ... source N编译出一个可执行文件且命名为name;
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)
aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/src ${hello_src})
add_executable(${PROJECT_NAME} ${hello_src})
target_link_libraries(${PROJECT_NAME} util)
- target_link_libraries() 添加可执行文件所需要的库;链接所有动态、静态库
target_link_libraries(${target} xxx ${library_list})
- add_subdirectory() 用于添加一个需要进行构建的子目录;
- message(STATUS"Projectname:${PROJECT_NAME}") 打印消息;
message("MODUEL WW INCLUDE")
forearch(dir ${include_list})
message(STATUS ${dir})
endforeach()
add_dependencies(target-name depend-target1 depend-target2 …) 用于指定某个目标(可执行文件或者库文件)依赖于其他的目标。这里的目标必须是add_executable, add_library, add_custom_target命令创建的目标;
find_path(<VAR> name1 [path1 path2 …]) 用于查找包含文件name1的路径,如果找到则将路径保存在VAR中,如果没有找到则结果为<VAR>-NOTFOUND。
find_library(my_ceres libceres.so /home/wenhaolun/ubuntu18.04_lib/ceres/)
find_library(<VAR> name1 [path1 path2 …]) 用于查找库文件name1的路径,如果找到则将路径保存在VAR中;
find_package() 查找动态库文件;
add_library(common STATIC util.cpp) 生成静态库;add_library(common SHARED util.cpp) 生成动态库或共享库;
add_library(test_a STATIC ${source_list})
add_definitions 向C/c++编译器添加-D定义;例如:add_definitions(-DENABLE_DEBUG -DABC),参数之间用空格分割;如果你的代码中定义了#ifdef ENABLE_DEBUG #endif 这个代码就会生效;如果要添加其他的编译器开关,可以通过CMAKE_C_FLAGS变量和CMAKE_CXX_FLAGS变量设置;
exec_program(executable [directory in which to run] ...) 在CMakeLists.txt处理过程中执行命令,并不会在生成的makefile中执行;
file 指令,文件操作命令;
file(WRITE filename "message to write"...) WRITE将一则信息写入文件filename中,如果该文件存在,它会覆盖它;如果不存在,它会创建该文件;
file(APPEND filename "message to write"...) 如同WRITE,区别在于它将信息内容追加到文件末尾;
file(READ filename variable ...) 读取文件内容并存入变量中;
file(GLOB test_source_list "${work_home}/test/*.cpp")
include 指令,用来载入CMakeLists.txt文件,也用于载入预定义的cmake模块;
install 指令,用于安装模块;它可以用来安装很多内容,可以包括目标二进制、动态库、静态库以及文件、目录、脚本等;
- 控制指令:
(1)if指令,if ... else ... endif
(2)while指令,while(condition) ... endwhile(condition)
(3)forearch指令,forearch(loop_var arg1 arg2 ...) ... endforearch(loop_var)
- list 指令,用于创建;分隔的列表,常用子命令:APPEND,INSERT,FIND
list(APPEND include_list ${work_home}/include)
- get_filename_component 指令:获取文件路径的内容
get_filename_component(test ${origin_test} NAME)
- string 指令:用于处理字符串
string(REGEX_REPLACE "(.*).cpp$" "\\1" target ${test})
3. 预定义变量
- PROJECT_SOURCE_DIR 工程的根目录;
- PROJECT_BINARY_DIR 运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/build;
- PROJECT_NAME 返回通过project命令定义的项目名称;
- CMAKE_CURRENT_SOURCE_DIR 当前处理的CMakeLists.txt所在路径;
- CMAKE_CURRENT_BINARY_DIR target编译目录;
- CMAKE_CURRENT_LIST_DIR CMakeLists.txt的完整路径;
- CMAKE_CURRENT_LIST_LINE 当前所在的行;
- CMAKE_MODULE_PATH 定义自己的cmake模块所在的路径;
- EXECUTABLE_OUTPUT_PATH 重新定义目标二进制可执行文件的存放位置;
- LIBRARY_OUTPUT_PATH 重新定义目标链接库文件的存放位置;
- CMAKE_C_FLAGS 设置C编译选项;
- CMAKE_CXX_FLAGS 设置c++编译选项;
4. 简单例子
- hello-headers例子
https://github.com/ttroy50/cmake-examples/tree/master/01-basic/B-hello-headers - 静态链接库例子
https://github.com/ttroy50/cmake-examples/tree/master/01-basic/C-static-library - 动态链接库
https://github.com/ttroy50/cmake-examples/blob/master/01-basic/D-shared-library/CMakeLists.txt - install安装命令
https://github.com/ttroy50/cmake-examples/blob/master/01-basic/E-installing/CMakeLists.txt - 设置编译类型
https://github.com/ttroy50/cmake-examples/blob/master/01-basic/F-build-type/CMakeLists.txt - 设置编译参数
https://github.com/ttroy50/cmake-examples/blob/master/01-basic/G-compile-flags/CMakeLists.txt - 第三方库依赖
https://github.com/ttroy50/cmake-examples/blob/master/01-basic/H-third-party-library/CMakeLists.txt - 设置c++编译标准
https://github.com/ttroy50/cmake-examples/tree/master/01-basic/L-cpp-standard - 子项目
https://github.com/ttroy50/cmake-examples/tree/master/02-sub-projects - protobuf代码生成
https://github.com/ttroy50/cmake-examples/blob/master/03-code-generation/protobuf/CMakeLists.txt - 单元测试
https://github.com/ttroy50/cmake-examples/blob/master/05-unit-testing/boost/CMakeLists.txt - c/c++库管理
https://github.com/ttroy50/cmake-examples/tree/master/07-package-management
参考资料
- CMakeLists.txt 语法介绍与实例演练
https://blog.csdn.net/afei__/article/details/81201039 - 【使用CMake组织C++工程】2:CMake 常用命令和变量
https://elloop.github.io/tools/2016-04-10/learning-cmake-2-commands - CMakeFile命令之file
https://blog.csdn.net/fuyajun01/article/details/8880121 - CMakeList.txt相关例子git:https://github.com/ttroy50/cmake-examples