我的 CMake 构建系统有问题。有CMakeLists.txt
定义运行时或库或使用 ExternalProjects_Add()
的文件下载和构建外部代码。由于依赖关系,这些项目必须相互找到。现在我想要一个 CMakeLists.txt
在一次构建所有这些的顶层。为了找到一个项目,是必须安装的。但是在 CMake 的配置时已经完成了查找项目。
repository
├─project
│ ├─game (Depends on engine, uses EngineConfig.cmake once installed)
│ │ ├─CMakeLists.txt
│ │ ├─include
│ │ ├─src
│ │ └─textures
│ ├─engine (Depends on boost, uses built-in FindBoost.cmake)
│ │ ├─CMakeLists.txt
│ │ ├─include
│ │ └─src
│ ├─boost (Not the source code, just an ExternalProject_Add call)
│ : └─CMakeLists.txt
│
├─build
│ ├─game
│ ├─engine
│ ├─boost (Source will be downloaded and built here)
│ : ├─download
│ ├─source
│ :
│
├─install
│ ├─game
│ │ ├─bin
│ │ └─textures
│ ├─engine
│ │ ├─include
│ │ │ └─engine
│ │ │ ├─EngineConfig.cmake (Needed to find the library)
│ │ │ :
│ │ │
│ │ └─lib
│ ├─boost (Layout is up to the external library)
│ : └─ ...
│
└─CMakeLists.txt (Calls add_subdirectory for all inside the project folder)
为每个项目运行一个 CMake 进程:使用
execute_process(${CMAKE_COMMAND} ...)
,我可以在配置时一个接一个地配置和构建每个项目。但是,这意味着我总是必须在编辑代码后运行 CMake,并且无法从我为其生成项目文件的 IDE 中进行编译。链接到 CMake 目标:为所有外部库运行 CMake 过程是可以的,因为我不处理它们。我自己的库可以通过调用
target_link_libraries()
来使用与他们的目标名称。然而,链接是不够的。我的库包括外部库的目录。这些也必须对使用项目可用。如何在我的 CMake 项目中使用需要首先安装的库?
最佳答案
您可以将项目分为三组:
在配置 super 项目之前,您需要在 #1 和 #2 组中配置、构建和安装项目:
CMakeLists.txt
之前执行此操作,例如,来自 shell 脚本 CMakeLists.txt
中, 使用 execute_process(${CMAKE_COMMAND} ...)
.您可以使用适当的 find_package(... QUIET)
的结果有条件地执行此操作。命令。 您需要决定是否属于第 3 组的项目,例如
engine
将仅在将它们用作子目录的项目中使用,或者您打算将它们用作独立库,构建在它们自己的构建树中。另外,您提到:“我的库包括外部库的目录”。让我们涵盖所有可能的库
engine
可以依赖于:LIB1
和 LIB2
是 engine
的私有(private)和公共(public)外部依赖项和他们的配置模块导出老派LIB1_*
和 LIB2_*
变量 LIB3
和 LIB4
是 engine
的私有(private)和公共(public)外部依赖项及其配置模块导出 LIB3
和 LIB4
导入库 公共(public)和私有(private)依赖是指在
engine
的接口(interface)上是否使用特定库。 .现在,如果
engine
仅用作子目录,然后是 engine/CMakeLists.txt
的相关部分是:add_library(engine ...)
target_include_directories(engine
PRIVATE
${LIB1_INCLUDE_DIRS}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
${LIB2_INCLUDE_DIRS})
target_compiled_definitions(engine
PRIVATE ${LIB1_DEFINITIONS}
PUBLIC ${LIB2_DEFINITIONS})
target_link_libraries(engine
PRIVATE LIB3
PUBLIC LIB4)
在
repository/CMakeLists.txt
:add_subdirectory(engine)
add_subdirectory(game)
在
game/CMakeLists.txt
:add_executable(game ...)
target_link_libraries(game engine)
引擎及其公共(public)依赖项的包含目录将正确转发到
game
.如果
engine
也将在自己的构建树中构建(在另一个项目中)您需要将导出代码添加到 engine/CMakeLists.txt
也可能是调用 find_package
的自定义配置模块(或 find_dependency
)用于其依赖项。见 How to use CMake to find and link to a library using install-export and find_package?详情。该答案中未讨论的一个问题是在库的配置模块中查找库的依赖项:引用的 SO 答案只是安装
<lib>-targets.cmake
脚本,由 install(EXPORT ...)
生成命令,作为配置模块:install(EXPORT engine-targets
FILE engine-config.cmake
DESTINATION lib/cmake/engine)
此解决方案适用于
engine
没有进一步的依赖关系。如果是这样,则需要在配置模块的开头找到它们,该模块应手动编写。engine/engine-config.cmake:
include(CMakeFindDependencyMacro)
find_dependency(some-dep-of-engine)
include(${CMAKE_CURRENT_LIST_DIR}/engine-targets.cmake)
在
engine/CMakeLists.txt
:install(EXPORT engine-targets
FILE engine-targets.cmake
DESTINATION lib/cmake/engine)
install(FILES engine-config.cmake
DESTINATION lib/cmake/engine)
注意:
CMakeFindDependencyMacro
已在 CMake 3.0 中引入。使用较旧的 CMake,您可以使用 find_package
而不是 find_dependency
(QUIET 和 REQUIRED 选项的处理不会转发给依赖项)。
关于cmake - 如何在我的 CMake 项目中使用需要首先安装的库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31755870/