我试图使用cmake来安装" Skeltrack"进入共享库。这是我的项目分支:https://github.com/birgersp/Skeltrack/tree/cmake
根据我的理解,target_include_directories
使包能够保存"它需要的头文件的位置,因此使用我的库的应用程序不必包含此目录以供库运行。这是对的吗?
似乎如果我的库需要一些标题,我需要在我的应用程序中包含这些标题,即使我在我的库中使用target_include_directories
...
图书馆的CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(Skeltrack)
# Set output folders
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
# Find source files
file(GLOB SOURCES src/*.c)
# Include header files
include_directories(include)
# Create shared library
add_library(${PROJECT_NAME} STATIC ${SOURCES})
# Include Glib library
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(Glib REQUIRED)
target_link_libraries(${PROJECT_NAME} ${Glib_LIBRARIES})
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${Glib_INCLUDE_DIRS})
# Install library
install(TARGETS ${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME})
# Install library headers
file(GLOB HEADERS include/*.h)
install(FILES ${HEADERS} DESTINATION include/${PROJECT_NAME})
我的应用程序的CMakeListst.txt
cmake_minimum_required(VERSION 2.4.0)
project(skeltrack-test)
# Find source files
file(GLOB SOURCES src/*.cpp)
# Create executable
add_executable(${PROJECT_NAME} ${SOURCES})
# Find and link Skeltrack library
find_library(SKELTRACK Skeltrack PATH_SUFFIXES Skeltrack)
target_link_libraries(${PROJECT_NAME} ${SKELTRACK})
# Find and include Skeltrack library headers
find_path(SKELTRACK_INCDLUDE_DIRS skeltrack.h PATH_SUFFIXES Skeltrack)
target_include_directories(${PROJECT_NAME} PUBLIC ${SKELTRACK_INCDLUDE_DIRS})
输出:
[ 50%] Building CXX object CMakeFiles/skeltrack-test.dir/src/main.o
In file included from /usr/local/include/Skeltrack/skeltrack-skeleton.h:26:0,
from /usr/local/include/Skeltrack/skeltrack.h:26,
from /home/birger/Workspace/skeltrack-test/src/main.cpp:2:
/usr/local/include/Skeltrack/skeltrack-joint.h:26:18: fatal error: glib.h: No such file or directory
compilation terminated.
CMakeFiles/skeltrack-test.dir/build.make:62: recipe for target 'CMakeFiles/skeltrack-test.dir/src/main.o' failed
make[2]: *** [CMakeFiles/skeltrack-test.dir/src/main.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/skeltrack-test.dir/all' failed
make[1]: *** [CMakeFiles/skeltrack-test.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
似乎我需要在我的应用程序中包含Glib头目录,才能使库运行?如何避免两次包含标题?
答案 0 :(得分:2)
让我们查看target_include_directories
的手册,以便更好地了解它的工作原理:
target_include_directories(<target> [SYSTEM] [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
指定编译给定目标时要使用的包含目录。该 named必须由诸如之类的命令创建 add_executable()或add_library(),不得是IMPORTED目标。
[...]
需要
INTERFACE
,PUBLIC
和PRIVATE
关键字来指定 以下参数的范围。PRIVATE
和PUBLIC
件商品会 填充INCLUDE_DIRECTORIES
属性。PUBLIC
和INTERFACE
项将填充INTERFACE_INCLUDE_DIRECTORIES
的财产。以下参数指定include 目录。
秘诀在于INTERFACE_INCLUDE_DIRECTORIES
目标属性:
使用
target_link_libraries()
指定目标依赖项时, CMake将从所有目标依赖项中读取此属性 确定消费者的构建属性。
因此,总结一下:当链接到目标时,CMake将继承该目标的INTERFACE_INCLUDE_DIRECTORIES
属性中的所有包含目录。
为此,您需要确保两件事:首先,您的项目必须链接到CMake目标(因为没有目标意味着没有目标属性),并且其INTERFACE_INCLUDE_DIRECTORIES
目标属性必须正确公开包含目录。
现在让我们来看看你在做什么:
find_library(SKELTRACK Skeltrack PATH_SUFFIXES Skeltrack)
target_link_libraries(${PROJECT_NAME} ${SKELTRACK})
嗯......那看起来不像是目标。 find_library
找到文件,而不是目标。实际上,检查${SKELTRACK}
的值将显示它指向文件名。支票if(TARGET ${SKELTRACK})
将失败。
这是因为用于处理依赖关系的机制早于接口目标属性系统。它仅依赖于文件路径,因此需要您手动将所有相关选项传递给下游程序。
不幸的是,你无法免费获得更舒适的行为。有人必须在应用程序的构建环境中为Skeltrack创建目标,并相应地填充其目标属性。这需要CMake代码。通常依赖者有责任提供该代码(尽管没有什么可以阻止你自己编写代码;编写和维护它只是有点痛苦)。
CMake提供a convenient mechanism为您的软件包自动生成此类代码。不幸的是,Skeltrack的构建系统必须这样做,以便您的应用程序可以从中受益。
由于您已经分叉了项目,为什么不在其构建系统中添加对此项目的支持并打开拉取请求?