从Target 角度看 CMake (二)为Target 设置专属include 与 library 目录

        为了更好地进行说明,我们先在此定义一个计算器开发项目,需求描述如下:

  1. 此项目需要开发一个库,能实现两个整数的加法;
  2. 此计算器要有一个c 语言例子程序,可以在WIndows 10、Ubuntu 20.04 以上版本运行;

        项目的目录结构如下:

.
|____CMakeLists.txt
|____module
| |____CMakeLists.txt
| |____calc.cpp
| |____calc.h
|____samples
  |____CMakeLists.txt
  |____calculator.cpp

        根目录下的CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(Calc)

add_subdirectory(module)

include_directories(module)

add_subdirectory(samples)

        module 目录下的CMakeLists.txt

add_library(calc calc.cpp)

        calc.h

int add(int a, int b);

        calc.cpp

#include "calc.h"

int add(int a, int b) {
    return a + b;
}

        calculator.cpp

#include <iostream>
#include "calc.h"

int main(int argc, char **argv) {
    std::cout << add(3,5) << std::endl;
    return 0;
}

        首先,我们通过 add_library() 与 add_executable() 创建两个Target,一个是可执行程序,另一个是库。

add_library(calc calc.cpp)
add_executable(calculator calculator.cpp)

        通过 target_link_libraries,可以把库加入到可执行文件中。注意,此命令除了指导编译器在连接可执行文件时的操作外,此处也隐式定义了从可执行程序到库两个Target 之间的依赖关系。

target_link_libraries(calculator calc)

        由于在编译calculator.cpp 的时候需要用到calc.h 所以需要把module 目录添加到calculator 的包含路径中去

include_directories(module)

        对于这样的小型项目这样做是完全没有问题的,只要通过 include_directories() 与 link_directories() 告诉编译系统在哪里找到编译时所需要的头文件与连接时需要的库文件就可以了。对于包含多个可执行文件与更多库的大项目则不同,并不是每一个Target都需要同样的头文件与库文件搜索路径。这时我们可以为每一个Target 指定不同的头文件与库文件的搜索路径。

target_include_directories

        编译时,编译器按照include_directories 中的设置寻找头文件。target_include_directories 设置仅仅用于此Target 的路径。以下是 include_directories 与 target_include_directories 的定义,以便对照说明:

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
  • AFTER | BEFORE 由于include_directories 是一个列表,AFTER | BEFORE 就是指新插入的目录是追加到列表的后面,还是插入到列表的前面。
  • SYSTEM 选项是指此处的目录是来自系统比如第三方库或标准库而非项目本身的容器中的代码。

        target_include_directories 特有的参数如下:

  • <target> 是指本条命令将要作用的 Target,而且不能是别名。

        当我们设置include_directories 的时候,它是对项目中的所有Target都起作用,无论Target之间是否有依赖关系。INTERFACE、PUBLIC、PRIVATE 这三个参数就是为了解决依赖问题而设立的。

  • PUBLIC 修饰的路径,除了加入到本Target 的编译搜索路径外,还会自动加入到所有依赖此Target的Target的编译搜索路径中。
  • PRIVATE 修饰的路径,只会加入到本Target 的编译搜索路径中,而不会自动加入到依赖本Target的 Target 的编译搜索路径中。
  • INTERFACE 后面的路径,只会加入到依赖本Target 的Target 中,而不会加入本Target 的编译搜索路径中。

综上,PUBLIC = PRIVATE + INTERFACE

target_link_libraries() 的运行机制与target_include_libraries 基本相同,这里列出基本定义,就不做详细分析。

link_directories([AFTER|BEFORE] directory1 [directory2 ...])

target_link_directories(<target> [BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

基于Target 的CMakeLists.txt

        更改后的根目录下的CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(Calculator)

add_subdirectory(module)
add_subdirectory(samples)

        去掉include_directories 后,文件显得更整齐。

        更改后的samples 目录下的CMakeLists.txt

add_executable(calculator calculator.cpp)
target_include_directories(calculator PRIVATE ${CMAKE_SOURCE_DIR}/module/)
target_link_libraries(calculator calc)

        由于calculator 是一个应用程序,不会再有其它程序依赖它的include 目录,因此使用PRIVATE 修饰。

Makefile 与 Visual Studio 在Release/Debug 配置上的不同

        CMake 可以生成四种类型的配置文件:

  • Release
  • Debug
  • RelWithDebInfo
  • MinSizeRel

        对于Visual Studio 编译器,在CMake 时可以生成四种配置,在编译(build)时选择不同的配置可以生成对应的文件。也可以通过命令行进行编译:

cmake --build . --config debug

        对于Unix Makefile 类型的编译器,需要在CMake 时指定CMAKE_BUILD_TYPE 来指定编译(build)类型,以生成对应类型的文件。此时 CMake --build . --config <cfg> 中的--config 会被忽略。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值