• CMake教程系列-04-编译相关函数


    1.引入

    编译过程与链接过程需要向编译器及链接器传入不同的参数,而这些参数分为以下几类:

    • 编译选项(包括宏定义)
    • 头文件路径
    • 链接库文件名称
    • 链接库查找路径

    2.target_compile_options

    此函数向目标添加编译选项,

    • 其原型为:
    target_compile_options(<target> [BEFORE]
      <INTERFACE|PUBLIC|PRIVATE> [items1...]
      [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
    
    
    • 1
    • 2
    • 3
    • 4
    • eg:
    target_compile_options(sample PUBLIC /arch=avx2 /Wall)
    
    • 1

    需要注意的是,如果要设置c / c++ 标准,不仅可以使用该函数添加 -std=STANDARD,还可以且更推荐设置以下两个cmake预设宏的值:

    • 直接填标准号的数字即可,cmake会自动设置标准相关的选项。
    CMAKE_C_STANDARD
    CMAKE_CXX_STANDARD
    
    • 1
    • 2

    2.target_compile_definitions

    此函数专门向目标添加预设宏声明及定义。

    • 当然,你也可使用上面的函数完成这个操作,毕竟最后都是要变成命令行中的参数不是?
    • 不过专业的人干专业的事情,建议使用此函数添加宏定义。其原型为:
    target_compile_definitions(<target>
      <INTERFACE|PUBLIC|PRIVATE> [items1...]
      [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
    
    • 1
    • 2
    • 3
    • eg:
    target_compile_definitions(sample PRIVATE BUILD_DLL PUBLIC "-DPI=3.14159")
    
    • 1

    3.target_compile_features

    此函数专门向目标设置c / c++版本。当然,你仍然可以选择第一个函数中的两种做法。

    • 其原型为:
    target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...])
    
    • 1
    • 例如:
    target_compile_features(sample PUBLIC cxx_std_17)
    
    • 1

    4.target_precompile_headers

    该函数向目标添加了预编译头文件。

    • 就是使用Visual Studio 创建新工程后自动创建的pch.h这种文件。
    • 其原型为:
    target_precompile_headers(<target>
      <INTERFACE|PUBLIC|PRIVATE> [header1...]
      [<INTERFACE|PUBLIC|PRIVATE> [header2...] ...])
    
    • 1
    • 2
    • 3
    • eg:
    target_precompile_headers(sample PRIVATE pch.hpp)
    
    • 1

    5.target_include_directories

    该函数声明了编译目标时查找使用头文件的路径。

    • 其原型为:
    target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
      <INTERFACE|PUBLIC|PRIVATE> [items1...]
      [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
    
    • 1
    • 2
    • 3
    • eg:
    target_include_directories(sample PUBLIC public/include/sample PRIVATE sample)
    
    • 1

    6.target_link_libraries

    该函数声明了链接时需要参与的依赖库名称或target。其名称可包含完整路径。

    • 其原型为:
    target_link_libraries(<target>
      <INTERFACE|PUBLIC|PRIVATE> [items1...]
      [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
    
    • 1
    • 2
    • 3
    • eg:
    target_link_libraries(sample PUBLIC CURL::curl glib m)
    
    • 1

    注意:由于一个target中包含多个属性,一般情况下包含了头文件路径。

    • 所以使用target作为参数传入此函数时,无需调用 target_include_directories 再次声明添加头文件路径。

    7.target_link_directories

    该函数声明了链接时,查找依赖库的路径。

    • 其原型为:
    target_link_directories(<target> [BEFORE]
      <INTERFACE|PUBLIC|PRIVATE> [items1...]
      [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
    
    • 1
    • 2
    • 3
    • eg:
    target_link_directories(sample PUBLIC third_party/libs/x86/rel)
    
    • 1

    8.target_link_options

    该函数声明了添加额外的链接选项。

    • 其原型为:
    target_link_options(<target> [BEFORE]
      <INTERFACE|PUBLIC|PRIVATE> [items1...]
      [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
    
    • 1
    • 2
    • 3
    • eg:
    target_link_options(sample PUBLIC /shared)
    
    • 1

    9.target_sources

    该函数声明了向target添加源文件。

    • 其原型为:
    target_sources(<target>
      <INTERFACE|PUBLIC|PRIVATE> [items1...]
      [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
    
    • 1
    • 2
    • 3
    • eg:
    target_sources(sample PRIVATE decode.cxx)
    
    • 1

    注:不要认为这个函数完全无用,可以被 add_library / add_executable 替代。在某些情况下,此函数还是非常好用的。

    • eg:
      我需要提供一个仅包含源代码的库给下游使用,而不是编译好二进制提供给下游。此时,我们需要使用 add_library(sample INTERFACE) 并使用此函数添加源码文件来链接至 sample ,并通过cmake导出此target。如此一来,下游只需要使用 target 族函数便可以不通过其他额外代码使用我提供的源码文件。

    10.target族函数注意事项

    当需要使用cmake export关键字导出声明的target并附带其中的 PUBLIC 属性时,我们必须 将PUBLIC / PRIVATE / INTERFACE 关键字向这类 target 族函数补齐。且如果一个 target 族函数声明了这三个关键字其中之一,该 target 所属的其他 target 族函数均应当声明关键字。且对于包含路径的值,我们需要声明此值的使用范围:

    • 编译/链接时使用。必须使用绝对路径。
    • 导出以向下游提供。必须使用相对路径。

    所以,我们通常情况下使用以下方式:

    target_include_directories(sample PRIVATE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/header/include> PUBLIC $<INSTALL_INTERFACE:include>)
    
    • 1

    11.完整示例

    cmake_minimum_required(VERSION 3.0)
    project(sample CXX)
    set(CMAKE_CXX_STANDARD 11)
    
    add_library(sample sample.cpp)
    target_include_directories(sample PRIVATE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/header/include> PUBLIC $<INSTALL_INTERFACE:include>)
    target_compile_options(sample PUBLIC /Wall)
    target_compile_definitions(sample PRIVATE BUILD_DLL INTERFACE USE_DLL)
    target_link_libraries(sample PRIVATE thread m)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    L61.linux命令每日一练 -- 第九章 Linux进程管理命令 -- renice和nohup
    一只程序猿很黄很暴力的日记
    【Proteus仿真】【Arduino单片机】数码管显示
    进程(1)——什么是进程?【linux】
    基于H5 网页的打豆豆小游戏的设计与实现
    IPO解读丨高处不胜寒,澜沧古茶低头取暖?
    全同态加密知识体系整理
    JUC系列(九) CAS 与锁的理解
    劫持TLS绕过canary pwn89
    Hadoop3教程(十六):MapReduce中的OutputFormat
  • 原文地址:https://blog.csdn.net/u011436427/article/details/125467985