CMAKE使用记录

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_TARGETEXECUTE_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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baibingql

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值