我有一个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_directories
或target_link_libraries
包含库?如果包/库有一个.so
文件,我们可以简单地忽略该包/库的include_directories
吗?
编辑:如何知道是否应该使用include_directories
与target_link_libraries
包含库?
如何知道是否应该使用
include_directories
或target_link_libraries
包含库?
除非库是仅限标头的库,否则需要调用target_link_libraries
才能使用它。
如果Find*
脚本(由find_package()
调用调用)使用include目录设置变量(此信息可以从脚本的文档中获得),它假定将包含这些目录(通过include_directories
或target_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_DIRS
和package_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()
对此情况下的包含没有影响。