cmake - 何时在CMakeLists.txt文件中包含include_directories

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cmake - 何时在CMakeLists.txt文件中包含include_directories相关的知识,希望对你有一定的参考价值。

我有一个C ++项目,其中我有以下行:

#include <curl/curl.h>

我正在使用CURL库从传感器访问IMU数据。我准备了一个CMakeLists.txt文件,如下所示:

cmake_minimum_required(VERSION 3.5.1)
project(imu_data_access_cmake_test)
set(CMAKE_CXX_STANDARD 11)
find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIRS})
set(SOURCES imu_data_access.cpp ${CURL_INCLUDE_DIRS}/curl/curl.h)
add_executable(imu_data_access_cmake_test ${SOURCES})
#add_executable(imu_data_access_cmake_test imu_data_access.cpp)
target_link_libraries(imu_data_access_cmake_test ${CURL_LIBRARIES})

这非常有效。但是,如果我删除include_directories线并修改add_executable线只是使用我的imu_data_access.cpp作为源,cmake不会抛出错误,一切仍然有效。我假设这是由于target_link_libraries线。

如何知道是否应该使用include_directoriestarget_link_libraries包含库?如果包/库有一个.so文件,我们可以简单地忽略该包/库的include_directories吗?

编辑:如何知道是否应该使用include_directoriestarget_link_libraries包含库?

答案

如何知道是否应该使用include_directoriestarget_link_libraries包含库?

除非库是仅限标头的库,否则需要调用target_link_libraries才能使用它。

如果Find*脚本(由find_package()调用调用)使用include目录设置变量(此信息可以从脚本的文档中获得),它假定将包含这些目录(通过include_directoriestarget_include_directories)。

在IMPORTED目标的情况下,通过target_link_libraries传播包含目录,通常命名为<namespace>::<name>


在您的特定情况下,include_directories无效只是因为默认情况下编译器搜索给定目录,这通常是通过包管理器安装库时。但find_package即使在非系统安装中也能工作。

另一答案

我看到了一些可以帮助您改进代码的事情。

避免过度指定最低版本

我通常希望确保我的CMake脚本不会过度指定版本。在我看来,在这个脚本中,除了版本3.1之外的任何东西都可以工作。所以我倾向于改变第一行:

cmake_minimum_required(VERSION 3.1)

始终如一地处理包裹

如你所知,find_package()通常为包裹设置package_INCLUDE_DIRSpackage_LIBRARIES。我发现一直使用这些变量对于简化CMake脚本的维护比修剪到最低限度要好得多。因此我不担心他们是否需要并且这样做:

find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIRS})
add_executable(imu_data_access_cmake_test imu_data_access.cpp)
target_link_libraries(imu_data_access_cmake_test ${CURL_LIBRARIES})

不要将系统包含在源中

请注意,我省略了这一行:

set(SOURCES imu_data_access.cpp ${CURL_INCLUDE_DIRS}/curl/curl.h)

并非每个库都包含文件需要或应该作为源列出。作为一般规则,我只包括我的来源,这也是我对你的项目的建议。

另一答案

一个好的做法是使用target_include_directories()而不是include_directories()。好处是您可以指示包含的可见性,例如,如果您使用以下内容配置库:

add_library(foo foo.cpp)
target_include_directories(foo PUBLIC foo_include)
target_include_directories(foo PRIVATE private_include)

然后,如果您将foo链接到可执行文件bar,那么bar将可以访问foo_include目录,但不能访问private_include。命令include_directories()适用于CMakeLists.txt包含命令的目录,因此它将应用于此目录及其子目录中声明的任何库/可执行文件。

对于target_link_libraries(),行为会有所不同,因为它可以是一个库列表,在这种情况下,没有包含目录的概念。但它可以是一个IMPORTED库,它可以包含更多信息,例如include目录(例如,Boost和Qt那样做)。

在cURL的情况下,documentation表示CURL_LIBRARIES包含库列表。在您的情况下,可能会找到cURL标头,因为默认情况下,CMake将在标准位置搜索标头,因此target_link_libraries()对此情况下的包含没有影响。

以上是关于cmake - 何时在CMakeLists.txt文件中包含include_directories的主要内容,如果未能解决你的问题,请参考以下文章

从父 CMakeLists.txt 覆盖 CMake 中的默认选项(...)值

CMakeLists.txt

cmake 多级CMakeLists.txt调用

CMake 从 CMakeLists.txt 脚本中获取缓存变量列表

CMake 配置 CMakeLists.txt

将 CMake 选项从命令行移动到*** CMakeLists.txt