我有一个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
了解是否应包含库?
答案 0 :(得分:5)
如何使用
了解是否应包含库include_directories
或target_link_libraries
?
除非库是仅限标题的库,否则需要调用target_link_libraries
才能使用它。
如果Find*
脚本(由find_package()
调用调用)设置包含目录的变量(此信息可以从脚本的文档中获取),则假定将包含这些目录(通过include_directories
或target_include_directories
)。
在 IMPORTED 目标的情况下,通过target_link_libraries
传播包含目录,通常命名为<namespace>::<name>
。
在您的特定情况下,include_directories
无效只是因为默认情况下编译器搜索给定目录,这通常是通过包管理器安装库时。但find_package
即使在非系统安装时也可以使用。
答案 1 :(得分:2)
我看到了一些可以帮助您改进代码的事情。
我通常希望确保我的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)
并非每个库包含文件都需要或应该作为源列出。作为一般规则,我只包含我的来源,这也是我为您的项目提供的建议。
答案 2 :(得分:2)
一个好的做法是使用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()
在这种情况下对包含没有影响。