简体   繁体   English

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

[英]cmake - When to include include_directories in a CMakeLists.txt file

I have a C++ project in which I have the following line: 我有一个C ++项目,其中我有以下行:

#include <curl/curl.h>

I am using the CURL library to access IMU data from a sensor. 我正在使用CURL库从传感器访问IMU数据。 I prepared a CMakeLists.txt file that looks like this: 我准备了一个如下所示的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})

This works very well. 这非常有效。 However, if I remove the include_directories line and modify the add_executable line to just use my imu_data_access.cpp as source, the cmake does not throw an error and everything still works. 但是,如果我删除include_directories行并修改add_executable行只是使用我的imu_data_access.cpp作为源, cmake不会抛出错误,一切仍然有效。 I am assuming this is due to target_link_libraries line. 我假设这是由于target_link_libraries行。

How to know whether a library should be included using include_directories or target_link_libraries ? 如何知道是否应该使用include_directoriestarget_link_libraries包含库? If the package/library has a .so file can we simply ignore include_directories for that package/library? 如果包/库有.so文件,我们可以简单地忽略该包/库的include_directories吗?

Edit: How to know whether a library should be included using include_directories vs. target_link_libraries ? 编辑:如何知道是否应该使用include_directoriestarget_link_libraries包含库?

How to know whether a library should be included using include_directories or target_link_libraries ? 如何知道是否应该使用include_directoriestarget_link_libraries包含库?

Unless a library is a header-only library, call to target_link_libraries is required for use it. 除非库是仅限标头的库,否则需要调用target_link_libraries才能使用它。

If Find* script (called by find_package() call) sets variable with include directories (this information can be obtained from the script's documentation), it assumes that these directories will be included (via include_directories or target_include_directories ). 如果Find*脚本(由find_package()调用调用)使用include目录设置变量(此信息可以从脚本的文档中获得),则它假定将包含这些目录(通过include_directoriestarget_include_directories )。

Propagating include directories through the target_link_libraries occurred in case of IMPORTED target, usually named as <namespace>::<name> . IMPORTED目标的情况下,通过target_link_libraries传播include目录,通常命名为<namespace>::<name>


In your specific case include_directories have no effect only because given directory is searched by a compiler by default , this is usual when library is installed through package manager. 在您的特定情况下, include_directories不起作用,因为默认情况下编译器搜索给定目录,这通常是通过包管理器安装库时。 But find_package is intended to work even with non-system installations. find_package即使在非系统安装时也能工作。

I see a couple of things that may help you improve your code. 我看到了一些可以帮助您改进代码的事情。

Avoid overspecifying minimum version 避免过度指定最低版本

I generally like to make sure that my CMake scripts don't overspecify the version. 我通常希望确保我的CMake脚本不会过度指定版本。 It seems to me that in this script, anything more than version 3.1 would work. 在我看来,在这个脚本中,除了版本3.1之外的任何东西都可以工作。 So I'd be inclined to change that first line to this: 所以我倾向于改变第一行:

cmake_minimum_required(VERSION 3.1)

Handle packages consistently 始终如一地处理包裹

As you know, find_package() generally sets the package_INCLUDE_DIRS and package_LIBRARIES for the package. 如您所知, find_package()通常为包设置package_INCLUDE_DIRSpackage_LIBRARIES I find that consistently using such variables is much better for simplifying maintenance of the CMake script than trimming to the bare minimum. 我发现一直使用这些变量对于简化CMake脚本的维护比修剪到最低限度要好得多。 Therefore I'd not worry about whether they're required or not and do this: 因此我不担心他们是否需要并且这样做:

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})

Don't put system includes in sources 不要将系统包含在源中

Note that I have omitted this line: 请注意,我省略了这一行:

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

Not every library include file needs to be or should be listed as a source. 并非每个库都包含文件需要或应该作为源列出。 As a general rule, I only include my sources, and that's what I'd advice for your projects as well. 作为一般规则,我只包括我的来源,这也是我对你的项目的建议。

A good practice is to use target_include_directories() instead of include_directories() . 一个好的做法是使用target_include_directories()而不是include_directories() The benefit is that you can indicate the visibility of the include, for example if you configure a library with: 好处是您可以指示包含的可见性,例如,如果您使用以下内容配置库:

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

Then, if you link foo to an executable bar , then bar will have access to the foo_include directory, but not to private_include . 然后,如果将foo链接到可执行bar ,则bar将可以访问foo_include目录,但不能访问private_include Command include_directories() apply to the directory where the CMakeLists.txt contains the command, so it will apply to any library/executable declared in this directory and its sub-directories. 命令include_directories()适用于CMakeLists.txt包含命令的目录,因此它将应用于此目录及其子目录中声明的任何库/可执行文件。

For target_link_libraries() , then the behavior varies, because it can be a list of libraries, in which case there is no notion of include directories. 对于target_link_libraries() ,行为会有所不同,因为它可以是库列表,在这种情况下,没有包含目录的概念。 But it can be an IMPORTED library, where it can contain more information, such as include directories (for example, Boost and Qt do that). 但它可以是一个IMPORTED库,它可以包含更多信息,例如include目录(例如,Boost和Qt这样做)。

In the case of cURL, the documentation indicates that CURL_LIBRARIES contains the list of libraries. 对于cURL, 文档指出CURL_LIBRARIES包含库列表。 In your case, the cURL headers are probably found because by default CMake will search for headers in standard locations, so target_link_libraries() has no impact regarding the includes in this case. 在您的情况下,可能会找到cURL标头,因为默认情况下,CMake将在标准位置搜索标头,因此在这种情况下, target_link_libraries()对包含没有影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM