CMake使用特点

帮助

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档案

cmake3.3

CMake中文文档 - 幕布

cmake 常用变量、常用环境变量、常用语法总结

主要变量

CMAKE_ARGC3cmake解释*.cmake脚本文件传入参数的个数
CMAKE_ARGV0 CMAKE_ARGV1cmake各个参数值
CMAKE_AR/usr/bin/arlinux下
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

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值