CMake定义头文件路径、链接库路径及链接选项:PRIVATE,INTERFACE,PUBLIC

文章目录

    一、CMake常用变量
    二、自定义头文件、链接库路径的方法
        自定义头文件路径
        自定义链接库路径
        另一种实现的命令
        两种命令的区别介绍
            测试工程目录结构:
            调用关系:
            关键字用法说明:

一、CMake常用变量

在 CMake 中,有许多常见的变量可用于配置和管理构建过程。以下是一些常见的变量,包括当前源码路径:

    CMAKE_SOURCE_DIR:当前 CMakeLists.txt 所在的源码目录的根路径。
    CMAKE_BINARY_DIR:构建目录的根路径,即构建生成的可执行文件、库和其他构建输出的存放位置。
    CMAKE_CURRENT_SOURCE_DIR:当前处理的 CMakeLists.txt 所在的源码目录的路径。
    CMAKE_CURRENT_BINARY_DIR:当前处理的 CMakeLists.txt 所在的构建目录的路径。
    CMAKE_CURRENT_LIST_DIR:当前处理的 CMakeLists.txt 所在的路径(源码目录或构建目录)。
    CMAKE_CURRENT_LIST_LINE:当前正在处理的 CMakeLists.txt 的行号。
    CMAKE_MODULE_PATH:一个用于指定额外的 CMake 模块(.cmake 文件)的搜索路径的列表。
    CMAKE_INCLUDE_CURRENT_DIR:如果设置为 ON,则在构建过程中自动将当前处理的 CMakeLists.txt 所在的目录添加到包含路径中。
    CMAKE_LIBRARY_OUTPUT_DIRECTORY:库文件的输出目录。
    CMAKE_RUNTIME_OUTPUT_DIRECTORY:可执行文件的输出目录。

以上是一些常用的 CMake 变量,其中包含了当前源码路径相关的变量。您可以在 CMakeLists.txt 文件中使用这些变量来设置路径、配置目录结构以及管理构建过程中的输出位置。
二、自定义头文件、链接库路径的方法
自定义头文件路径

可以使用 include_directories 命令来指定自定义的头文件路径。该命令会将指定的路径添加到编译器的头文件搜索路径中。

include_directories(path/to/include/dir)

    1

你可以多次调用 include_directories 命令,以添加多个头文件路径。
自定义链接库路径

可以使用 link_directories 命令来指定自定义的链接库路径。该命令会将指定的路径添加到链接器的库搜索路径中。

link_directories(path/to/library/dir)

    1

你可以多次调用 link_directories 命令,以添加多个链接库路径。

需要注意的是,尽量避免在 CMake 中使用 include_directories 和 link_directories 命令来处理第三方库的头文件和链接库路径。更好的做法是使用 find_package 命令或编写 Find 模块来查找和链接第三方库,这样可以更好地管理依赖关系和跨平台兼容性。
另一种实现的命令

另外,对于特定的库,你还可以使用 target_include_directories 命令和 target_link_directories 命令,将自定义的头文件路径和链接库路径应用于特定的目标。

target_include_directories(target_name PUBLIC path/to/include/dir)
target_link_directories(target_name PUBLIC path/to/library/dir)

    1
    2

这样可以确保自定义路径只应用于特定的目标,并使得相关路径不会泄漏到其他目标中。

通过以上方式,你可以在 CMake 中自定义头文件路径和链接库路径,以满足项目的需求。
两种命令的区别介绍

target_include_directories() 的功能完全可以使用 include_directories() 实现。但是我还是建议使用 target_include_directories()。为什么?保持清晰!

include_directories(header-dir) 是一个全局包含,向下传递。什么意思呢?就是说如果某个目录的 CMakeLists.txt 中使用了该指令,其下所有的子目录默认也包含了header-dir 目录。

上述例子中,如果在顶层的 cmake-test/CMakeLists.txt 中加入:

include_directories(hello-world)
include_directories(hello-world/hello)
include_directories(hello-world/world)

    1
    2
    3

那么整个工程的源文件在编译时都会增加:

-I hello-world -I hello-world/hello -I hello-world/world ...

    1

各级子目录中无需使用 target_include_directories() 或者 include_directories()了。如果此时查看详细的编译过程(make VERBOSE=1)就会发现编译过程是一大坨,很不舒服。

当然了,在最终子目录的 CMakeLists.txt 文件中,使用 include_directories() 和 target_include_directories() 的效果是相同的。

而使用 target_include/link_directories() 每一个目录都是一个模块,目录内部应将对外和对内的头文件进行区分,由模块的调用者决定模块是否被传递(PRIVATE,INTERFACE,PUBLIC)。
测试工程目录结构:

cmake-test/                 工程主目录,main.c 调用 libhello-world.so
├── CMakeLists.txt
├── hello-world             生成 libhello-world.so,调用 libhello.so 和 libworld.so
│   ├── CMakeLists.txt
│   ├── hello               生成 libhello.so
│   │   ├── CMakeLists.txt
│   │   ├── hello.c
│   │   └── hello.h         libhello.so 对外的头文件
│   ├── hello_world.c
│   ├── hello_world.h       libhello-world.so 对外的头文件
│   └── world               生成 libworld.so
│       ├── CMakeLists.txt
│       ├── world.c
│       └── world.h         libworld.so 对外的头文件
└── main.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

调用关系:

                                ├────libhello.so
可执行文件────libhello-world.so
                                ├────libworld.so

    1
    2
    3

关键字用法说明:

PRIVATE:私有的。生成 libhello-world.so时,只在 hello_world.c 中包含了 hello.h,libhello-world.so 对外的头文件——hello_world.h 中不包含 hello.h。而且 main.c 不会调用 hello.c 中的函数,或者说 main.c 不知道 hello.c 的存在,那么在 hello-world/CMakeLists.txt 中应该写入:

target_link_libraries(hello-world PRIVATE hello)
target_include_directories(hello-world PRIVATE hello)

    1
    2

INTERFACE:接口。生成 libhello-world.so 时,只在libhello-world.so 对外的头文件——hello_world.h 中包含 了 hello.h, hello_world.c 中不包含 hello.h,即 libhello-world.so 不使用 libhello.so 提供的功能,只使用 hello.h 中的某些信息,比如结构体。但是 main.c 需要使用 libhello.so 中的功能。那么在 hello-world/CMakeLists.txt 中应该写入:

target_link_libraries(hello-world INTERFACE hello)
target_include_directories(hello-world INTERFACE hello)

    1
    2

PUBLIC:公开的。PUBLIC = PRIVATE + INTERFACE。生成 libhello-world.so 时,在 hello_world.c 和 hello_world.h 中都包含了 hello.h。并且 main.c 中也需要使用 libhello.so 提供的功能。那么在 hello-world/CMakeLists.txt 中应该写入:

target_link_libraries(hello-world PUBLIC hello)
target_include_directories(hello-world PUBLIC hello)

    1
    2

实际上,这三个关键字指定的是目标文件依赖项的使用范围(scope)或者一种传递(propagate)。官方说明

可执行文件依赖 libhello-world.so, libhello-world.so 依赖 libhello.so 和 libworld.so。

        main.c 不使用 libhello.so 的任何功能,因此 libhello-world.so 不需要将其依赖 libhello.so 传递给 main.c,hello-world/CMakeLists.txt 中使用 PRIVATE 关键字;
        main.c 使用 libhello.so 的功能,但是libhello-world.so 不使用,hello-world/CMakeLists.txt 中使用 INTERFACE 关键字;
        main.c 和 libhello-world.so 都使用 libhello.so 的功能,hello-world/CMakeLists.txt 中使用 PUBLIC 关键字;

补充阅读:
CMake的链接选项:PRIVATE,INTERFACE,PUBLIC

参考链接:
https://zhuanlan.zhihu.com/p/631823872
https://zhuanlan.zhihu.com/p/82244559
仅作学习记录
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.youkuaiyun.com/All_In_gzx_cc/article/details/132403228

CMake是一个跨平台的自动化构建系统,使用CMakeLists.txt文件来指定如何构建项目的各种设置。设置头文件路径是构建过程中的一个常见需求,以下是几种在CMake中设置头文件路径的方法: 1. 使用`include_directories()`命令: 这是最常用的方法之一。`include_directories()`命令用于向编译器添加头文件搜索路径。你可以指定绝对路径或相对路径。例如: ```cmake include_directories("/path/to/headers") include_directories("relative/path/to/headers") ``` 这些路径会被添加到编译器的头文件搜索列表中,适用于所有的目标(target)。 2. 使用`target_include_directories()`命令: 如果你希望只对特定的目标(target)添加头文件路径,可以使用`target_include_directories()`。这可以确保头文件路径只对指定的目标有效。例如: ```cmake target_include_directories(my_target PRIVATE "/path/to/headers") ``` 其中`my_target`是你的目标名称,`PRIVATE`表示该头文件路径只对目标本身可见。 3. 使用`link_directories()`命令: `link_directories()`命令用于添加库文件的搜索路径。虽然它不是直接添加头文件路径的命令,但它在链接阶段可能需要头文件路径对应的库文件,因此间接影响头文件的查找。使用方法如下: ```cmake link_directories("/path/to/libs") ``` 4. 使用`target_link_directories()`命令: 类似于`link_directories()`,但`target_link_directories()`可以指定特定的目标(target)链接库的搜索路径。例如: ```cmake target_link_directories(my_target PRIVATE "/path/to/libs") ``` 5. 设置环境变量: 虽然不推荐,但你可以通过设置环境变量`CMAKE_INCLUDE_PATH`和`CMAKE_LIBRARY_PATH`来添加头文件和库文件的路径。这会影响CMake找到头文件和库文件的方式。 请注意,设置头文件路径时,应确保路径的正确性以及根据项目需求选择正确的命令和作用域(如`PRIVATE`, `PUBLIC`, `INTERFACE`)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值