文章目录
1. 常用命令
命令行:
cmake [<options>] -S <path-to-source> -B <path-to-build>
使用作为构建树 作为源代码树。指定的路径可以是绝对路径,也可以是相对于当前工作目录的路径。源树必须包含一个 CMakeLists.txt文件。如果构建树尚不存在,则会自动创建。例如:
$ cmake -S src -B build
平台选择
默认目标平台名称(架构)是主机的名称,并在 CMAKE_VS_PLATFORM_NAME_DEFAULT 多变的。
这 CMAKE_GENERATOR_PLATFORM 变量可以设置,也许通过 cmake(1) -A选项,以指定目标平台名称(架构)。例如:
cmake -G "Visual Studio 15 2017" -A Win32
cmake -G "Visual Studio 15 2017" -A x64
cmake -G "Visual Studio 15 2017" -A ARM
cmake -G "Visual Studio 15 2017" -A ARM64
cmake -G "Visual Studio 16 2019" -A Win32
cmake -G "Visual Studio 16 2019" -A x64
cmake -G "Visual Studio 16 2019" -A ARM
cmake -G "Visual Studio 16 2019" -A ARM64
1.1configure_file
将文件复制到另一个位置并修改其内容。
configure_file(<input> <output>
[NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
FILE_PERMISSIONS <permissions>...]
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
将<input>文件复制到<output>文件,并替换作为输入文件内容@VAR@或${VAR}在输入文件内容中引用的变量值。每个变量引用将替换为该变量的当前值,如果未定义该变量,则为空字符串。
例子1
考虑包含foo.h.in文件的源树:
#cmakedefine FOO_ENABLE
#cmakedefine FOO_STRING "@FOO_STRING@"
相邻项CMakeLists.txt可用于配置标头:configure_file
option(FOO_ENABLE "Enable Foo" ON)
if(FOO_ENABLE)
set(FOO_STRING "foo")
endif()
configure_file(foo.h.in foo.h @ONLY)
这将foo.h在与该源目录相对应的构建目录中创建一个。如果FOO_ENABLE启用该选项,则配置的文件将包含:
#define FOO_ENABLE
#define FOO_STRING "foo"
否则它将包含:
/* #undef FOO_ENABLE */
/* #undef FOO_STRING */
然后可以使用 include_directories() 命令将输出目录指定为包含目录:
include_directories(${CMAKE_CURRENT_BINARY_DIR})
因此来源可能包括标头。#include <foo.h>
例子2
set(src "${CMAKE_CURRENT_SOURCE_DIR}/../../../DCPS/Messenger")
set(dst ${CMAKE_CURRENT_BINARY_DIR})
set(all_targets ${publisher} ${subscriber} ${messenger})
foreach(file
Messenger.idl subscriber.cpp publisher.cpp Writer.cpp Writer.h Args.h
DataReaderListener.cpp DataReaderListener.h)
configure_file(${src}/${file} ${dst}/${file} COPYONLY)
endforeach()
1.1 find_program, find_package
find_program(<VAR>名称1 [path1 path2 ...])
该命令用于查找程序。创建名为的缓存条目以存储此命令的结果。如果找到程序,则结果存储在变量中,除非清除变量,否则将不会重复搜索。如果未找到任何结果,则结果将为-NOTFOUND。
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[NO_POLICY_SCOPE])
查找一个外部项目,并加载其设置。
1.2 add_custom_target
cmake编译后想执行一些特定的shell命令: 主要是用ADD_CUSTOM_TARGET
和EXECUTE_PROCESS
来实现
添加没有输出的目标,因此将始终对其进行构建。
add_custom_target(Name [ALL] [command1 [args1...]]
[COMMAND command2 [args2...] ...]
[DEPENDS depend depend depend ... ]
[BYPRODUCTS [files...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[JOB_POOL job_pool]
[VERBATIM] [USES_TERMINAL]
[COMMAND_EXPAND_LISTS]
[SOURCES src1 [src2...]])
添加具有给定名称的目标,该目标将执行给定命令。目标没有输出文件, 即使命令尝试使用目标名称创建文件,也始终将其视为已过期。使用add_custom_command()命令生成具有依赖性的文件。默认情况下,任何内容都不取决于自定义目标。使用add_dependencies() 命令添加与其他目标之间的依赖关系。
选项包括:
ALL
指示应将此目标添加到默认的构建目标,以便每次都将运行该目标(不能调用该命令ALL)。
VERBATIM
对于构建工具,将正确转义命令的所有自变量,以使调用的命令不变地接收每个自变量。请注意,CMake语言处理器仍在使用一级转义符,add_custom_target甚至没有看到参数。VERBATIM建议使用,因为它可以使行为正确。VERBATIM未指定when的行为是特定于平台的,因为没有保护特定于工具的特殊字符。
COMMAND_EXPAND_LISTS
3.8版中的新功能。
COMMAND参数中的列表将被扩展,包括使用 generator expressions,从而 可以适当扩展COMMAND诸如之类的参数 。 C C " − I {CC} "-I CC"−I<JOIN:$<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>,;-I>" foo.cc
在COMMAND选项后的参数可以使用“生成器表达式”,它的语法是"$<…>"。这些表达式会在构建系统生成期间,以及构建配置的专有信息的产生期间被评估。合法的表达式是:
$<CONFIGURATION> = 配置名称
$<TARGET_FILE:tgt> = 主要的二进制文件(.exe, .so.1.2, .a)
$<TARGET_LINKER_FILE:tgt> = 用于链接的文件(.a, .lib, .so)
$<TARGET_SONAME_FILE:tgt> = 带有.so.的文件(.so.3)
其中,"tgt"是目标的名称。目标文件表达式TARGET_FILE生成了一个完整的路径,但是它的_DIR和_NAME版本可以生成目录以及文件名部分:
$<TARGET_FILE_DIR:tgt>/$<TARGET_FILE_NAME:tgt>
$<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>
$<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>
1.3 函数function
开始记录功能,以供以后作为命令调用。
不区分大小写,强烈建议保留函数定义中选择的大小写。通常,函数使用全小写的名称。
在新版本3.18:该cmake_language(CALL …)命令也可以用来调用函数。
function(<name> [<arg1> ...])
<commands>
endfunction()
foo()
Foo()
FOO()
cmake_language(CALL foo)
1.4 参数解析:cmake_parse_arguments
该命令用于宏或函数。它处理提供给该宏或函数的参数,并定义一组保存相应选项值的变量
cmake_parse_arguments(<prefix> <options> <one_value_keywords>
<multi_value_keywords> <args>...)
cmake_parse_arguments(PARSE_ARGV <N> <prefix> <options>
<one_value_keywords> <multi_value_keywords>)
示例1:
function(opendds_target_idl_sources target)
set(oneValueArgs SCOPE SKIP_TAO_IDL)
set(multiValueArgs TAO_IDL_FLAGS DDS_IDL_FLAGS IDL_FILES)
cmake_parse_arguments(_arg "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
每个参数都会加一个前缀:_arg
示例2:
macro(my_install)
set(options OPTIONAL FAST)
set(oneValueArgs DESTINATION RENAME)
set(multiValueArgs TARGETS CONFIGURATIONS)
cmake_parse_arguments(MY_INSTALL “
o
p
t
i
o
n
s
"
"
{options}" "
options""{oneValueArgs}”
“${multiValueArgs}” ${ARGN} )
# ...
假设my_install()被这样调用:
my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub CONFIGURATIONS)
后调用宏将已经设置或未定义以下变量:cmake_parse_arguments
MY_INSTALL_OPTIONAL = TRUE
MY_INSTALL_FAST = FALSE # was not used in call to my_install
MY_INSTALL_DESTINATION = "bin"
MY_INSTALL_RENAME <UNDEFINED> # was not used
MY_INSTALL_TARGETS = "foo;bar"
MY_INSTALL_CONFIGURATIONS <UNDEFINED> # was not used
MY_INSTALL_UNPARSED_ARGUMENTS = "blub" # nothing expected after "OPTIONAL"
MY_INSTALL_KEYWORDS_MISSING_VALUES = "CONFIGURATIONS"
# No value for "CONFIGURATIONS" given
1.5 project
project(<PROJECT-NAME> [<language-name>...])
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[DESCRIPTION <project-description-string>]
[HOMEPAGE_URL <url-string>]
[LANGUAGES <language-name>...])
设置工程名,语言,版本号,描述等。
语言: C, CXX (i.e. C++), CUDA, OBJC (i.e. Objective-C), OBJCXX, Fortran, ISPC, and ASM. 默认为C,C++.
New in version 3.8: Added CUDA support.
New in version 3.16: Added OBJC and OBJCXX support.
New in version 3.18: Added ISPC support.
2.变量
-
set
set( … [PARENT_SCOPE]) #将普通变量,缓存变量或环境变量设置为给定值。
如果PARENT_SCOPE给出了该选项,则将在当前作用域上方的作用域中设置变量。每个新目录或函数都会创建一个新作用域。
引用变量:${}set(ENV{} []) #设置环境变量,随后的调用$ENV{}将返回此新值
-
set_target_properties
set_target_properties(target1 target2 …
PROPERTIES prop1 value1
prop2 value2 …)
在目标上设置属性。该命令的语法是列出要更改的所有目标,然后提供下一步要设置的值。#设置目标名称 OUTPUT_NAME
set_target_properties(${messenger}
PROPERTIES OUTPUT_NAME messenger
) -
target_sources
target_sources(
<INTERFACE|PUBLIC|PRIVATE> [items1…]
[<INTERFACE|PUBLIC|PRIVATE> [items2…] …])
指定在构建目标和/或其依赖项时要使用的源。命名必须由诸如以下命令创建 add_executable() 或者 add_library() 或者 add_custom_target()并且不能是别名目标。
必须使用INTERFACE,PUBLIC和PRIVATE关键字来指定其后各项的范围。
- CMAKE_BINARY_DIR
到构建树顶层的路径。
这是当前CMake构建树顶层的完整路径。对于源代码内部版本,这将与 CMAKE_SOURCE_DIR。
在-P脚本模式下运行时,CMake设置变量 CMAKE_BINARY_DIR, CMAKE_SOURCE_DIR, CMAKE_CURRENT_BINARY_DIR 和 CMAKE_CURRENT_SOURCE_DIR 到当前工作目录。
- CMAKE_PREFIX_PATH
这是CMake环境变量。它的初始值来自调用过程环境。多个值用;分隔。
可以将环境变量设置为目录列表,这些目录指定要由安装程序搜索的安装前缀。 CMAKE_PREFIX_PATHfind_package(), find_program(), find_library(), find_file(), 和 find_path()命令。每个命令将添加相应的子目录(例如bin,lib或include),作为其自己的文档中指定。
3. select_library_configurations
select_library_configurations(basename)
该宏将库基本名称作为参数,并将根据找到和设置的内容为basename_LIBRARY,basename_LIBRARIES,basename_LIBRARY_DEBUG和basename_LIBRARY_RELEASE选择合适的值。如果仅定义了basename_LIBRARY_RELEASE,则将basename_LIBRARY设置为发布值,并将basename_LIBRARY_DEBUG设置为basename_LIBRARY_DEBUG-NOTFOUND。如果仅定义了basename_LIBRARY_DEBUG,则basename_LIBRARY将采用调试值,并且basename_LIBRARY_RELEASE将设置为basename_LIBRARY_RELEASE-NOTFOUND。
4. 链接不同版本的库
target_link_libraries(${target} debug debug.lib optimized release.lib)
使用限制,每个库都要声明是debug 还是optimized ,不然会出错
set(3rd_libs
messenger
demo
)
##----------------find libs--------------------------------------------
foreach(_cfg RELEASE DEBUG)
set(_sfx ${_suffix_${_cfg}})
foreach(_lib ${3rd_libs})
find_library(${_lib}_LIBRARY_${_cfg}
${_lib}${_sfx}
HINTS ${SJDDS_LIB_DIR} "${PROJECT_SOURCE_DIR}/lib"
)
endforeach()
endforeach()
macro(_ADD_3rd_LIB target 3rdlib)
set(_debug_lib "${${3rdlib}_LIBRARY_DEBUG}")
set(_release_lib "${${3rdlib}_LIBRARY_RELEASE}")
message("## _debug_lib = ${_debug_lib}")
message("## _release_lib = ${_release_lib}")
if ((EXISTS "${_debug_lib}" OR EXISTS "${_release_lib}"))
if (EXISTS "${_debug_lib}")
target_link_libraries(${target} debug "${_debug_lib}")
endif()
if (EXISTS "${_release_lib}")
target_link_libraries(${target} optimized "${_release_lib}")
endif()
endif()
endmacro()