帮助
cmake --help-command-list
cmake --help-command <--->
cmake -E
cmake -G <generator-name>
cmake -D <var>:<type>=<value> -D <var>=<value>
常用方法
string相关方法
# 正则匹配 ${variable} 按^(.*)_OUTPUT_(.*)$匹配到 output_variable 变量
string(REGEX MATCH "^(.*)_OUTPUT_(.*)$" output_variable "${variable}")
# 将文件名转成全路径,从输入中匹配出字符串,并放入取代表达式中,最后放入变量中
# string(REGEX REPLACE <regular_expression> <replace_expression>
# <output variable> <input> [<input>...])
string(REGEX REPLACE "([^;]+)" "${PROJECT_SOURCE_DIR}/src/\\1" SRC_LIST "${SRC_LIST}")
list相关方法
# 向变量最后添加一项
list(APPEND argument_list "-D${output_variable}=${${output_variable}}")
file相关方法
# 查找src目录下所有头文件并保存到SRC_FILES变量里,通常与install一起用
file(GLOB HEADER_FILES "src/*.h")
# 递归查找
file(GLOB_RECURSE SRC_FILES "src/hello*")
# 写文件
file(WRITE "version.h" "#define VERSION \"version: ${PROJECT_VERSION}\"\n")
# 创建目录
file(MAKE_DIRECTORY ${xmlDir})
常用命令
add_compile_definitions VS add_definitions
if(BUILD_SHARED_LIBS)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions(JSON_DLL_BUILD)
else()
add_definitions(-DJSON_DLL_BUILD)
endif()
endif()
add_compile_options VS CMAKE_<LANG>_FLAGS
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options($<$<CONFIG:Debug>:/WX>)
else()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ")
endif()
install
# 安装目标
install(TARGETS ${TARGET_NAME}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
# 安装目录
install(DIRECTORY ${SRC_DIR}
DESTINATION ${DST_DIR})
# 安装文件
install(FILES ${FILES_LIST}
DESTINATION ${DST_DIR})
find_package
Find<LibName>.cmake或<LibName>Config.cmake或<小写package-name>-config.cmake
<LibName>_FOUND、<LibName>_INCLUDE_DIR、<LibName>_LIBRARY
LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/modules)
find_package(<LibName> REQUIRED)
常用模板
添加外部工程
set(PACKAGE dtype)
set(argument_list)
get_cmake_property(variables VARIABLES)
foreach(variable ${variables})
string(REGEX MATCH "^(.*)_OUTPUT_(.*)$" output_variable "${variable}")
if(output_variable)
list(APPEND argument_list "-D${output_variable}=${${output_variable}}")
unset(output_variable)
unset(${variable})
endif()
endforeach()
# print argument_list
foreach(arg ${argument_list})
message("${arg} - ${${arg}}")
endforeach()
ExternalProject_Add(${PACKAGE}
SOURCE_DIR ${PROJECT_SOURCE_DIR}/package/${PACKAGE}
CMAKE_ARGS "${argument_list}"
)
工程和目标属性
设置和获取属性
# 设置全局和工程属性
# eg: set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# eg: set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "test")
set_property
# 获取工程属性
# eg: get_property
get_property
# 设置目标属性
set_target_properties(<目标> PROPERTIES <属性名> <属性值>)
# 获取目标属性
get_target_properties(<属性值> <目标> <属性名>)
属性盘点
DEFINE_SYMBOL
# 属性设置了编译一个共享库中的源文件时才会被定义的预处理器符号名。
# 如果这个值没有被设置的话,那么它会被设置为默认值target_EXPORTS
VERSION
# 设置库的版本,linux下生成的库版本在文件名后面
# windows下无效果
SOVERSION
# 设置库的版本,linux下生成的库的soname版本在文件名后面
# windows下无效果
OUTPUT_NAME
OUTPUT_NAME_<CONFIG>
# 设置库和执行体的输出名称,若若没指定就是target的名称
# OUTPUT_NAME_<CONFIG>可以是OUTPUT_NAME_DEBUG
COMPILE_DEFINITIONS
# 设置宏定义,如:值为"GTEST_LINKED_AS_SHARED_LIBRARY=1"
DEBUG_POSTFIX
# 设置debug配置下目标名后缀,如“d”
FRAMEWORK
# 生成framework,如TRUE
IMPORTED_LOCATION
# 设置本地导入库的全路径,常用于安卓,如../libswscale-3.so
外部工程
外部工程和设置目标目录
# ExternalProject_Add必须先include(ExternalProject)
include(ExternalProject)
ExternalProject_Add
# 为目标设置目录时必须先打开用户目录属性
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
SET_PROPERTY(TARGET ${MODULE} PROPERTY FOLDER "modules")
ExternalProject_Add
常用
# 指定相关文件生成存放文件目录前缀
PREFIX
# 指定源码目录,必须存在CMakeLists.txt
SOURCE_DIR
# 新的cmake工程参数
CMAKE_ARGS
# 待说明
INSTALL_DIR
下载
# 下载命令,比如git clone <git-url> -b <分支>
DOWNLOAD_COMMAND
# 指定目录
DOWNLOAD_DIR
# 如果是下载文件,指定文件名
DOWNLOAD_NAME
# 是否报告进度,1
DOWNLOAD_NO_PROGRESS
git
# git url
GIT_REPOSITORY
# git tag
GIT_TAG
ExternalProject_Get_Property
形式:ExternalProject_Get_Property(<name> [prop1 [prop2 [...]]])
# 获取外部工程gtest的source_dir和binary_dir属性,并将结果存放在这两个变量中
ExternalProject_Get_Property(gtest source_dir binary_dir)
内部模块
CMakeDependentOption.cmake
# 包含模块
include(CMakeDependentOption)
# 根据BUILD_GMOCK判断,给INSTALL_GMOCK赋值,若为真,为前面的值,否则为后面的值
option(BUILD_GMOCK "Builds the googlemock subproject" ON)
cmake_dependent_option(INSTALL_GMOCK "Enable installation of googlemock." ON "BUILD_GMOCK" OFF)
GNUInstallDirs.cmake
# 包含模块
include(GNUInstallDirs)
注意点
列表变量和列表变量字符串
# 正则匹配的时候要注意
set(CPP_LIST
InitLib.cpp
print.cpp
StringUtil.h
StringUtil.cpp
DllibUtil.h
DllibUtil.cpp
)
message(${CPP_LIST})
message("${CPP_LIST}")
# 结果:
# InitLib.cppprint.cppStringUtil.hStringUtil.cppDllibUtil.hDllibUtil.cpp
# InitLib.cpp;print.cpp;StringUtil.h;StringUtil.cpp;DllibUtil.h;DllibUtil.cpp
关于rpath目录
- CMAKE_INSTALL_RPATH 指定rpath目录
- CMAKE_BUILD_WITH_INSTALL_RPATH 启动指定rpath目录
- CMAKE_SKIP_RPATH 构建和安装的时候是否加自认为的rpath
- CMAKE_SKIP_BUILD_RAPTH 构建时候是否加自认为的rpath
- CMAKE_SKIP_INSTALL_RPATH 安装时候是否加自认为的rpath
- CMAKE_INSTALL_RPATH_USE_LINK_PATH
- CMAKE_MACOSX_RPATH
if(NOT CMAKE_HOST_WIN32)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
if(CMAKE_HOST_APPLE)
cmake_policy(SET CMP0068 OLD)
set(CMAKE_INSTALL_RPATH "@executable_path")
elseif(CMAKE_HOST_UNIX)
set(CMAKE_INSTALL_RPATH "$ORIGIN")
else()
message("rpath not support")
endif()
endif()
多个rpath用;隔开:如set(CMAKE_INSTALL_RPATH "@executable_path;/usr/local/lib")
/*
其他参考
if(UNIX)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
if(NOT APPLE)
set(CMAKE_INSTALL_RPATH "$ORIGIN")
else()
cmake_policy(SET CMP0068 OLD)
set(CMAKE_MACOSX_RPATH ON)
set(CMAKE_INSTALL_RPATH "@executable_path")
endif()
endif()
*/
关于常用编译参数
# 设置 警告 - 异常 - 运行类型信息(dynamic_cast)
if(MSVC)
add_definitions(/W4 /EHsc /GR)
else()
add_definitions(/Wall -fexceptions -frtti)
endif()
关于sysroot
set(SYSROOT_PATH /home/admin/tx2-rootfs)
set(CMAKE_SYSROOT "${SYSROOT_PATH}")
关于调试
if(CMAKE_HOST_APPLE)
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym")
elseif(CMAKE_HOST_UNIX AND CMAKE_BUILD_TYPE STREQUAL Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
endif()
关于验证编译器编译标志
# 验证c编译器flag
# -std=c90 -std=c90 -std=c11 -std=gnu90 -std=gnu99 -std=gnu11
include(CheckCCompilerFlag)
CHECK_C_COMPILER_FLAG("-std=gnu99" B1)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
# 验证c++编译器flag
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" B1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
检查头文件是否包含
# include的作用是将cmake的Modules下的CheckIncludeFil.cmake包含进来
# CMAKE_REQUIRED_INCLUDES 指定包含路径
include(CheckIncludeFile)
set (CMAKE_REQUIRED_INCLUDES ${PROJECT_SOURCE_DIR}/include)
CHECK_INCLUDE_FILE(InitLib/InitLib.h INITLIB_H_FOUND)
IF(INITLIB_H_FOUND)
MESSAGE("found InitLib.h")
ENDIF(INITLIB_H_FOUND)
自动添加源文件
# 从当前CMakeLists.txt中遍历源文件
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} DIR_SRCS)
foreach(DIR_SRC ${DIR_SRCS})
message("${DIR_SRC}")
endforeach()
add_library(<库名> SHARED ${DIR_SRCS})
关于将源文件分组到工程
set(INC_LIST
InitLib.h
)
set(CPP_LIST
InitLib.cpp
print.cpp
StringUtil.h
StringUtil.cpp
DllibUtil.h
DllibUtil.cpp
)
string(REGEX REPLACE "([^;]+)" "${PROJECT_SOURCE_DIR}/include/${LIBRARY}/\\1" INC_LIST "${INC_LIST}")
string(REGEX REPLACE "([^;]+)" "${PROJECT_SOURCE_DIR}/code/${LIBRARY}/\\1" CPP_LIST "${CPP_LIST}")
foreach(file ${INC_LIST} ${CPP_LIST})
string(REGEX REPLACE "^${PROJECT_SOURCE_DIR}/(.*)/.*$" "\\1" groupname ${file})
if(WIN32)
string(REGEX REPLACE "/" "\\\\" groupname ${groupname})
endif()
source_group(${groupname} FILES ${file})
unset(groupname)
endforeach()
自定义命令
# ---> post script
#add_custom_command(TARGET ${TARGET_NAME}_lib POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_OUTPUT_INCLUDE_DIR}/${TARGET_NAME}
# COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/inc/FreeImage.h ${PROJECT_OUTPUT_INCLUDE_DIR}/${TARGET_NAME})
日志
macro(logmessage msg)
message("[${CMAKE_CURRENT_LIST_FILE}-${CMAKE_CURRENT_LIST_LINE}] ${msg}")
endmacro()
不同配置链接不同库和链接框架
# windows下debug配置链接baseutild.lib库,release配置链接baseutil.lib库
target_link_libraries(<目标名> debug baseutild optimized baseutil)
# 默认参数不是debug和optimized,而是general
# debug是针对debug配置或者DEBUG_CONFIGURATIONS属性加入的配置
# optimized是针对debug参数对应的其他所有配置
# general是针对所有配置生效
# 比如多配置有如下Debug;Release;MinSizeRel;RelWithDebInfo
# 其中Debug和MinSizeRel设置为DEBUG_CONFIGURATIONS
set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS "Debug;MinSizeRel")
target_link_libraries(<目标名> debug baseutild optimized baseutil)
# 那么只有debug和MinSizeRel是链接baseutild.lib,其他链接baseutil.lib
# 链接framework
target_link_libraries(<目标名> "-framework frame1" "-framework frame2")
参考:[CMake] TARGET_LINK_LIBRARIES debug optimized visual studio 2010
安卓下本地导入库
add_library(swscale SHARED IMPORTED)
set_target_properties(swscale PROPERTIES IMPORTED_LOCATION ../libswscale-3.so)
问题
VERSION not allowed unless CMP0048 is set to NEW ,cmake最小版本太多,比如最小2.8
使用参数
# 指定生成工具
cmake -G "Visual Studio 12 2013 Win64" ..
cmake -DCMAKE_BUILD_TYPE=Debug -G "Unix Makefiles" ..
cmake -G "Xcode" ..
# 列出缓存的变量中的非高级的变量。
cmake -LAH
-L[A][H]: 列出缓存的变量中的非高级的变量。
# 关闭警告输出,cmake输出更清爽
cmake -Wno-dev
不同系统
CMAKE_OSX_DEPLOYMENT_TARGET 10.9
CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym
配套工具
cpack
# 设置打包名称,输出目录,会产生一个PACKAGE目标,通过make package生成目标,vs增加一个package项目
set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME}_${PROJECT_VERSION})
set(CPACK_GENERATOR "TGZ")
set(CPACK_OUTPUT_FILE_PREFIX ${PROJECT_SOURCE_DIR})
include(CPack)
ctest
参考
主要变量
CMAKE_ARGC | 3 | cmake解释*.cmake脚本文件传入参数的个数 |
CMAKE_ARGV0 CMAKE_ARGV1 | cmake | 各个参数值 |
CMAKE_AR | /usr/bin/ar | linux下 |
CMAKE_MAKE_PROGRAM | C:/Program Files (x86)/MSBuild/12.0/bin/MSBuild.exe /usr/bin/make | CMAKE_BUILD_TOOL |
CMAKE_COMMAND | C:/Program Files/CMake/bin/cmake.exe /usr/bin/cmake | cmake程序完整路径 |
CMAKE_CTEST_COMMAND | C:/Program Files/CMake/bin/ctest.exe /usr/bin/ctest |