Cmake仅链接标头库(工作示例)我需要说明
我正在学习如何使用 external -project 仅下载header libaries并链接到我的可执行文件。
我的工作流程如下:
- 我使用EndenalProject下载标头库EIGEN:
cmake -dget_libs = on -dbuild_shared_libs = on -dbuild_my_projects = off -g -g “ Visual Studio 17 2022” -A X64 ..&& CMAKE-建造。 -Config版本
- 然后第二次运行相同的cmakelists,但是这次我禁用外部专用项目并编译链接特征的可执行文件:
cmake -dget_libs = off -dbuild_shared_libs = off -dbuild_my_projects = on -g“ Visual Studio 17 2022” -A x64 ..&& CMAKE-建造。 -Config版本
Question
为什么我需要使用这两个命令,因为在target_include_directories中
命令i指定与Indunce Indulce_directories
中相同的路径?
在下面的代码中,我需要两个命令include_directories
和target_include_directories
。 我认为仅使用target_include_directories
,但是没有include_directories
它将无法使用。
if (BUILD_MY_PROJECTS)
add_executable(my_exe main.cpp)
include_directories("${CMAKE_BINARY_DIR}/install/eigen/") #add directory of the header-only library without this the next line wort work
target_include_directories(my_exe INTERFACE "${CMAKE_BINARY_DIR}/install/eigen/")# link exe to exectable
endif ()
我的完整cmakelists.txt如下:
project(superbuild LANGUAGES CXX)
cmake_minimum_required(VERSION 3.19)
########################################################################
# EIGEN
########################################################################
SET(GET_LIBS "" CACHE STRING "Set option to download dependencies")
if (GET_LIBS)
message(AUTHOR_WARNING ${GET_LIBS})
ExternalProject_Add(eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG 3.4.0
CMAKE_ARGS
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/install/eigen #this does nothing...
SOURCE_DIR "${CMAKE_BINARY_DIR}/install/eigen" #install in my local build dir
#SOURCE_DIR ${CMAKE_INSTALL_PREFIX}
BUILD_COMMAND "" #do not build
INSTALL_COMMAND "" #do not install
)
endif ()
###############################################################################
#EXECUTABLES
###############################################################################
if (BUILD_MY_PROJECTS)
add_executable(my_exe main.cpp)
include_directories("${CMAKE_BINARY_DIR}/install/eigen/") #add directory of the header-only library without this the next line wort work
target_include_directories(my_exe INTERFACE "${CMAKE_BINARY_DIR}/install/eigen/")# link exe to exectable
endif ()
I am learning how to use ExternalProject to download header only libaries and link to my executable.
My workflow is following:
- I download header library Eigen using ExtenalProject:
cmake -DGET_LIBS=ON -DBUILD_SHARED_LIBS=ON -DBUILD_MY_PROJECTS=OFF -G
"Visual Studio 17 2022" -A x64 .. && cmake --build . --config Release
- Then I run the same CMakeLists a second time, but this time I disable ExternalProject and compile the executable that links the Eigen:
cmake -DGET_LIBS=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_MY_PROJECTS=ON
-G "Visual Studio 17 2022" -A x64 .. && cmake --build . --config Release
Question
Why I need to use both of these commands since in target_include_directories
command I specify the same path as in include_directories
?
In the code below I need two commands include_directories
and target_include_directories
.
I thought that it would be enough to use only target_include_directories
, but without include_directories
it wont work.
if (BUILD_MY_PROJECTS)
add_executable(my_exe main.cpp)
include_directories("${CMAKE_BINARY_DIR}/install/eigen/") #add directory of the header-only library without this the next line wort work
target_include_directories(my_exe INTERFACE "${CMAKE_BINARY_DIR}/install/eigen/")# link exe to exectable
endif ()
My full CMakeLists.txt is following:
project(superbuild LANGUAGES CXX)
cmake_minimum_required(VERSION 3.19)
########################################################################
# EIGEN
########################################################################
SET(GET_LIBS "" CACHE STRING "Set option to download dependencies")
if (GET_LIBS)
message(AUTHOR_WARNING ${GET_LIBS})
ExternalProject_Add(eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG 3.4.0
CMAKE_ARGS
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/install/eigen #this does nothing...
SOURCE_DIR "${CMAKE_BINARY_DIR}/install/eigen" #install in my local build dir
#SOURCE_DIR ${CMAKE_INSTALL_PREFIX}
BUILD_COMMAND "" #do not build
INSTALL_COMMAND "" #do not install
)
endif ()
###############################################################################
#EXECUTABLES
###############################################################################
if (BUILD_MY_PROJECTS)
add_executable(my_exe main.cpp)
include_directories("${CMAKE_BINARY_DIR}/install/eigen/") #add directory of the header-only library without this the next line wort work
target_include_directories(my_exe INTERFACE "${CMAKE_BINARY_DIR}/install/eigen/")# link exe to exectable
endif ()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
tl; dr 切勿使用
include_directories
。曾经。了解属性可见性如何在CMAKE中起作用。在您提供的代码中,
include_directories
隐含地设置include_directories
在您的my_exe
target上的属性。然后,第二行设置Interface_include_directories
属性。include_directories
是构建目标时必须传递给编译器的包括目录的列表。Interface_include_directories
是一个包括目录的列表,当构建链接到此的目标时,必须将其传递给编译器。对于可执行文件而言,这并没有多大意义,就是写:
这只会填充
include_directories
而无需触摸接口_
版本。如果您愿意,则可以编写public
,而不是private
或接口
。根据定义,public
只是其他两个。但这并不是一个很好的依赖性管理策略...挖掘项目的源肠道是无法扩展的。在不编辑构建文件的情况下,尝试不同版本的特征也很难。
我只会写:
使用适当的软件包管理器,例如VCPKG或CONAN在系统上没有可用时处理eigen。
Tl;dr never use
include_directories
. Ever. Learn how property visibility works in CMake instead.In the code you supplied,
include_directories
is implicitly setting theINCLUDE_DIRECTORIES
property on yourmy_exe
target. Then the second line sets theINTERFACE_INCLUDE_DIRECTORIES
property.INCLUDE_DIRECTORIES
is a list of include directories that must be passed to the compiler when building the target.INTERFACE_INCLUDE_DIRECTORIES
is a list of include directories that must be passed to the compiler when building targets that link to this one. This doesn't make much sense for an executableSlightly better would be to write:
This will just populate
INCLUDE_DIRECTORIES
without touching theINTERFACE_
version. If you wanted both you could writePUBLIC
instead ofPRIVATE
orINTERFACE
. By definition,PUBLIC
is just both of the others.But this isn't a great dependency management strategy anyway... digging into the source tree guts of a project isn't scalable. It's also difficult to try different versions of Eigen without editing your build files.
I would just write:
Use a proper package manager like vcpkg or Conan to handle downloading Eigen when it isn't available on the system.