cmake 进阶用法

1,899 阅读2分钟

[TOC]

cmake

指定cmake的版本

cmake_minimum_required(VERSION major.minor[.patch[.tweak]]
                       [FATAL_ERROR])
cmake_minimum_required(VERSION 3.0)

变量

# 设置变量
set(<variable> <value>... [PARENT_SCOPE])
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
## 环境变量
set(ENV{<variable>} <value>...)

# 使用变量
${var}

打印日志

message([STATUS|WARNING|SEND_ERROR|FATAL_ERROR] "info")

生成对象

# 静态库|动态库
add_library(<name> [SHARED|STATIC] <SOURCE_FILES>)
# 可执行文件
add_executable(<name> <files>)

源文件

#按照自己指定的伪正则进行匹配查找【不建议使用】
file(GLOB_RECURSE <variable>  [<globbing-expressions>...])
# 只能查找本目录下所有的c/cxx/cpp结尾的文件
aux_source_directory(<dir> <variable>)

添加头文件

target_include_directories(<target> [SYSTEM] [BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
  
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

编译参数

# 预编译
target_compile_definitions(<target>
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
  
add_definitions(-DFOO -DBAR ...)
set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -MD")

# 编译
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-\\#pragma-messages")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11");
target_compile_options(<target> [BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

# 这个方法什么参数都可以加
add_compile_options(-Wno-#pragma-messages)

链接参数

target_link_libraries(<target>
                      <PRIVATE|PUBLIC|INTERFACE> <item>...
                     [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

set(CMAKE_SHARED_LINKER_FLAGS "-z defs")
set(CMAKE_STATIC_LINKER_FLAGS "x")

编译依赖

# 执行target 需要先执行target-dependency
add_dependencies(<target 目标> [<target-dependency> 依赖项]...)

创建目标项

# 创建的目标为可执行文件
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               source1 [source2 ...])
# 创建的目标为库
add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            source1 [source2 ...])
# 创建一个普通的目标
add_custom_target(Name [ALL] [command1 [args1...]]
                  [COMMAND command2 [args2...] ...]
                  [DEPENDS depend depend depend ... ]
                  [BYPRODUCTS [files...]]
                  [WORKING_DIRECTORY dir]
                  [COMMENT comment]
                  [VERBATIM] [USES_TERMINAL]
                  [SOURCES src1 [src2...]])

以上为简单的可以编译的具体的方式

如果需要编写逻辑条件的话,则需要CMAKE的具体语法规则了

查看我的另一篇文章:CMake 分享

还有几个点要说明一下:

进阶

通过文件来生成文件

通过 *.h.in 来生成具体的文件

configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])

*.h.in 的写法,主要是做字符串替换,如果需要使用生成的文件则需要添加到编译路径上面即可

#define TUTORIAL_VARSION_MAJOR @TUTORIAL_VARSION_MAJOR@
#define TUTORIAL_VERSION_MAJOR @TUTORIAL_VERSION_MAJOR@
// ${VAR} 这样的必须要用 #cmakedefine 才会替换
#define TUTORIAL_VERSION_MINOR ${TUTORIAL_VERSION_MINOR}
// 如果加了 @ONLY 则这里不会进行替换
#cmakedefine TEST_VAR ${TEST_VAR}
// 这里可以证明,宏名必须和需要替换的名称一致,否则有问题
#cmakedefine TTT @TEST_VAR@
// 如果是define 则宏名和替换的名称可以不一致
#define TTTDefine @TEST_VAR@

find_* 的用法

*.cmake 供 find_package 进行查找

命名规则:Find<package>.cmake

find_path (
          <VAR>
          name | NAMES name1 [name2 ...]
          [HINTS path1 [path2 ... ENV var]]
          [PATHS path1 [path2 ... ENV var]]
          [PATH_SUFFIXES suffix1 [suffix2 ...]]
          [DOC "cache documentation string"]
          [NO_DEFAULT_PATH]
          [NO_CMAKE_ENVIRONMENT_PATH]
          [NO_CMAKE_PATH]
          [NO_SYSTEM_ENVIRONMENT_PATH]
          [NO_CMAKE_SYSTEM_PATH]
          [CMAKE_FIND_ROOT_PATH_BOTH |
           ONLY_CMAKE_FIND_ROOT_PATH |
           NO_CMAKE_FIND_ROOT_PATH]
         )

find_library (
          <VAR>
          name | NAMES name1 [name2 ...] [NAMES_PER_DIR]
          [HINTS path1 [path2 ... ENV var]]
          [PATHS path1 [path2 ... ENV var]]
          [PATH_SUFFIXES suffix1 [suffix2 ...]]
          [DOC "cache documentation string"]
          [NO_DEFAULT_PATH]
          [NO_CMAKE_ENVIRONMENT_PATH]
          [NO_CMAKE_PATH]
          [NO_SYSTEM_ENVIRONMENT_PATH]
          [NO_CMAKE_SYSTEM_PATH]
          [CMAKE_FIND_ROOT_PATH_BOTH |
           ONLY_CMAKE_FIND_ROOT_PATH |
           NO_CMAKE_FIND_ROOT_PATH]
         )

查找包

通过 set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 来指定查找路径

find_package(<package> [version] [EXACT] [QUIET] [MODULE]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [NO_POLICY_SCOPE])       

FAQ:

如何传递一个list 给到function

functionName("${listName}")即可,注意双引号

使用execute_process() 会产生换行符,怎么办?

可以使用 exec_program 来进行替换,或者你需要使用 string(REGEX REPLACE "\n$" "" GIT_CURRENT_TIME "${GIT_CURRENT_TIME}") 来替换后面的换行符

如何多行注释 cmake

#[==[
多行注释
#]==]

file(READ)读取文件的时候,会出现换行,怎么破?

file(STRINGS) 使用这个来进行读取,然后foreach循环读取每一行即可

以上所有测试,可以去我的github上面进行查看具体的例子使用 :地址