cmake使用

可见性修饰符和目标

cmake中有三种可见性修饰符:PRIVATEPUBLICINTERFACE

这些修饰符随着命令一起使用,如target_include_directoriestarget_link_libraries
这些修饰符是在目标targets的上下文中指定的

目标targets是指在cmake中某种类型的输出:

  • 可执行目标add_executable生成二进制可执行文件
  • 库目标add_library生成库文件
  • 自定义目标add_custom_target通过脚本生成任意文件

接口目标是库目标的一个特殊情况,定义如下:

add_library(my_interface_lib INTERFACE)
target_include_directories(my_interface_lib INTERFACE include/)

里my_interface_lib不会立即生成任何文件,但后面可能有依赖它的具体目标
INTERFACE库可以被看作是构建依赖关系的一种便利机制

target_include_directories(test PRIVATE "${CMAKE_BINARY_DIR}")
表示目标test将使用指定的包含目录
但若后面有其他目标链接到test,则不会依赖于该目录
即源文件和依赖关系只传递给当前目标

target_include_directories(test PUBLIC "${CMAKE_BINARY_DIR}")
表示目标test将使用指定的包含目录
且若后面有其他目标链接到test,也会依赖该包含目录
即源文件和依赖关系传递给当前目标及依赖它的目标

target_include_directories(test INTERFACE "${CMAKE_BINARY_DIR}")
表示目标test本身不需要该包含目录
但若后面有其他目标链接到test,则会依赖于该包含目录
即源文件和依赖关系不传递给当前目标,但会传递给依赖它的目标

cmake中可以用子目录指定独立的模块及其自定义构建流程
可以由一个主cmake配置触发多个目录的构建,最后再链接到主程序
如下目录结构

test
  MathFunc
    mysqrt.hpp
    mysqrt.cpp
    MathFunc.hpp
    MathFunc.cpp
    CMakeLists.txt
  test.cpp
  CMakeLists.txt

库文件的使用

需要找到库文件和对应的头文件

  1. 添加库文件
target_link_libraries()
  1. 添加头文件的两种方法
    INCLUDE_DIRECTORIES全局性引入
    target_include_directories可以为当前目标文件指定头文件路径

  2. 使用更现代化的方法来包含库文件
    如链接MathFunc库的目标文件都需要包含MathFunc目录作为头文件路径
    若在MathFunc/CMakeLists.txt中添加

target_include_directories(
  MathFunc
  INTERFACE
  ${CMAKE_CURRENT_SOURCE_DIR}
)

指定了INTERFACE修饰,则项目的CMakeLists.txt可以不使用EXTRA_INCLUDE变量
只要链接MathFunc库,就会自动包含库所在目录的头文件
注意:静态库被不同程序引用,内存在会存在静态库函数的多份拷贝

生成可执行文件

add_executabe()

若有多个源文件,用空格隔开,可以用${PROJECT_NAME}引用项目名

用一个变量来表示多个源文件

set(SRC_LIST a.cpp b.cpp c.cpp)

引用变量的方式${}

添加编译时间戳

string(TIMESTAMP COMPILE_TIME %Y%m%d-%H%M%S)

Config.h.in中添加#define TIMESTAMP @COMPILE_TIME@

指定C++标准

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_executable命令之前添加,GCC6.1开始,默认为C++14

将库文件设置为可选项

  1. 经典方法
    提供用户可选项option(USE_MATHFUNC "description" ON)
    将库的构建和链接添加条件
if(USE_MATHFUNC)
  add_subdirectory(MathFunc)
  list(APPEND EXTRA_LIBS MathFunc)
  list(APPEND EXTRA_INCLUDES ${PROJECT_SOURCE_DIR}/MathFunc)
endif()

target_link_libraries(
  ${PROJECT_NAME}
  PUBLIC
  ${EXTRA_LIBS}
)
target_include_directories(
  ${PROJECT_NAME}
  PUBLIC
  ${PROJECT_BINARY_DIR}
  ${EXTRA_INCLUDES}
)

变量EXTRA_LIBS保存需要链接到可执行程序的可选库
变量EXTRA_INCLUDES保存可选的头文件的搜索路径

  1. 现代方法
    修改源代码
#ifdef USE_MATHFUNC
  #include"MathFunc.hpp"
#endif

#ifdef USE_MATHFUNC
  const double val= mysqrt(inputVal);
#else
  const double val= std::sqrt(inputVal);
#endif

由于是引用的cmake中的变量,需要在Config.h.in中添加

#cmakedefine USE_MATHFUNC

也可以在构建时指定变量值

cmake -DUSE_MATHFUNC=OFF ..
cmake --build .

安装规则

install(
  TARGETS target1 [target2 ...]
  [RUNTIME DESTINATION dir]
  [LIBRARY DESTINATION dir]
  [ARCHIVE DESTINATION dir]
  [INCLUDES DESTINATION [dir ...]]
  [PRIVATE_HEADER DESTINATION dir]
  [PUBLIC_HEADER DESTINATION dir]
)

在C++项目中使用cmake中的变量

cmake通过config.h.in提供的机制,允许在cpp文件中使用CMakeLists.txt中的变量

编写文件Config.h.in

#pragma once
#define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define AUTHOR_NAME "@AUTHOR_NAME@"

在CMakeLists.txt中配置

cmake_minimum_required(VERSION 3.10)
project(tuto)

set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 0)
set(AUTHOR_NAME "Jith")

configure_file(Config.h.in Config.h)

add_executable(tuto tuto.cpp)

# include the dir where the generated header file is located
target_include_directories(tuto PRIVATE "${CMAKE_BINARY_DIR}")

Config.h会自动写入到build目录
需要将该目录添加到搜索头文件的路径列表,也可以修改为写到其它目录
${CMAKE_BINARY_DIR}表示当前工程的二进制路径,存放编译生成,即build目录

cmake会在变量占位被填充后生成头文件,这些动态生成的头文件需要被包含到项目中
示例中Config.h文件被放置在${CMAKE_BINARY_DIR}目录中,所以只需要指定该路径即可

posted @ 2024-11-06 15:23  sgqmax  阅读(6)  评论(0编辑  收藏  举报