如何使用我的CMake项目中需要首先安装的库? [英] How to use libraries within my CMake project that need to be installed first?

查看:239
本文介绍了如何使用我的CMake项目中需要首先安装的库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的CMake构建系统有问题。有 CMakeLists.txt 定义运行时或库的文件或使用 ExternalProjects_Add()下载和构建外部代码。因为依赖,这些项目必须找到对方。现在我想在顶层创建一个 CMakeLists.txt ,同时构建所有这些。为了找到一个项目,必须安装。但是在CMake的配置时已经找到了项目。

I have a problem with my CMake build system. There are CMakeLists.txt files defining runtimes or libraries or using ExternalProjects_Add() to download and build external code. Because of dependencies, those projects have to find each other. Now I want to have a CMakeLists.txt at the top level that builds all those at once. In order to find a project, is must be installed. But finding projects is already done at configuration time in 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)

使用 execute_process($ {CMAKE_COMMAND} ...),我可以在配置时配置和构建每个项目。但是,这意味着我总是在编辑代码后运行CMake,并且无法从IDE中编译生成的项目文件。

Run a CMake process for every project: Using execute_process(${CMAKE_COMMAND} ...), I can configure and build each project after another at configure time. However, this means I always have to run CMake after editing the code and cannot compile from within the IDE I generated project files for.

链接到CMake目标: 为所有外部库运行一个CMake进程是可以的,因为我不工作他们。我可以通过使用它们的目标名称调用 target_link_libraries()来使用我自己的库。然而,连接是不够的。我的库包括外部库的目录。

Linking to CMake targets: Running a CMake process for all external libraries is okay since I don't work on them. My own libraries could be used by calling target_link_libraries() with their target names. However, linking isn't enough. My libraries include directories of external libraries. Those must be made available to the using project, as well.

如何在我的CMake项目中使用需要首先安装的库?

How can I use libraries within my CMake project that need to be installed first?

推荐答案

您可以将您的项目分为三组:

You can classify your projects into three groups:



  1. 您正在处理的项目,但太复杂,无法将其添加为子目录,例如目标太多或其他原因。 (您的示例中似乎没有这样的项目。)

  2. 正在处理的项目:这些项目将添加为超级项目的子目录。

在配置超级项目之前,您需要在组#1和#2中配置,构建和安装项目:

You need to configure, build and install the project in groups #1 and #2 before configuring the super-project:


  • 您可以在运行超级项目的 CMakeLists.txt 之前执行此操作,例如,脚本

  • 或者,如您所述,从超级项目的 CMakeLists.txt 中,使用 execute_process $ {CMAKE_COMMAND} ...)。您可以使用适当的 find_package(... QUIET)命令的结果有条件地执行此操作。

  • You can do it before running the super-project's CMakeLists.txt, for example, from a shell-script
  • Or, as you mentioned, from within the super-project's CMakeLists.txt, using execute_process(${CMAKE_COMMAND} ...). You can do it conditionally using the result of an appropriate find_package(... QUIET) command.

您需要决定组#3中的项目,如 engine 是否将仅用于使用它们作为子目录的项目,或者您打算将它们用作

You need to decide if projects in group #3, like engine will be used solely in projects that uses them as subdirectories or you intend to use them as standalone libraries, built in their own build trees.

此外,您还提到:我的库包含外部库的目录。让我们覆盖所有这样的可能的库引擎可以依赖于:

Also, you mentioned that: "My libraries include directories of external libraries". Let's cover all such possible libraries the engine can be dependent on:


  • LIB1 LIB2 引擎的私有和公共外部依赖性及其配置模块导出旧版 LIB1 _ * LIB2 _ * 变量

  • LIB3 LIB4 引擎的私有和公共外部依赖及其配置模块导出 LIB3 LIB4 导入的

  • say, LIB1 and LIB2 are private and public external dependencies of engine and their config-modules export old-school LIB1_* and LIB2_* variables
  • LIB3 and LIB4 are private and public external dependencies of engine and their config-modules export the LIB3 and LIB4 imported libraries

通过公共和私有依赖我是指在 engine

By public and private dependencies I mean whether the particular library is used or not used on the interface of engine.

现在,如果引擎仅用作子目录, engine / CMakeLists.txt 是:

Now, if engine is to be used only as a subdirectory then the relevant section of engine/CMakeLists.txt is:

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)

引擎及其公共依赖关系的include dirs将正确转发到 game

The include dirs of both of the engine and of its public dependencies will be correctly forwarded to game.

如果引擎也将在自己的构建树(在另一个项目中)中构建,您需要将导出代码添加到引擎/ CMakeLists.txt ,也许一个自定义的配置模块调用 find_package (或 find_dependency )为其依赖。请参阅如何使用CMake查找并使用install-export和find_package链接到库?。在该答案中没有讨论的一个问题是在库的配置模块中找到库的依赖性:

If engine will also be built in its own build tree (in another project) you need to add the exporting code to engine/CMakeLists.txt and maybe a custom config-module that calls find_package (or find_dependency) for its dependencies. See How to use CMake to find and link to a library using install-export and find_package? for details. One issue not discussed in that answer is finding the dependencies of a library in the library's config module:

引用的SO回答只是安装 install(EXPORT ...)命令生成的脚本作为config-module:

The referenced SO answer simply installs the <lib>-targets.cmake script, generated by the install(EXPORT ...) command, as the config-module:

install(EXPORT engine-targets
    FILE engine-config.cmake
    DESTINATION lib/cmake/engine)

engine 没有进一步的依赖性时,此解决方案很好。如果是,它们需要在config模块的开头找到,应该手动编写。

This solution is fine when engine has no further dependencies. If it does, they need to be found at the beginning of the config module, which should be written manually.

engine / engine-config。 cmake:

include(CMakeFindDependencyMacro)
find_dependency(some-dep-of-engine)
include(${CMAKE_CURRENT_LIST_DIR}/engine-targets.cmake)

code> engine / CMakeLists.txt

and in engine/CMakeLists.txt:

install(EXPORT engine-targets
    FILE engine-config.cmake
    DESTINATION lib/cmake/engine)
install(FILES engine-config.cmake
    DESTINATION lib/cmake/engine)

注意:CMake 3.0中引入了 CMakeFindDependencyMacro 对于较早的CMake,您可以使用 find_package 而不是 find_dependency (处理QUIET和REQUIRED选项不会转发依赖)。

Note: The CMakeFindDependencyMacro has been introduced in CMake 3.0. With an older CMake you can use find_package instead of find_dependency (handling of QUIET and REQUIRED options will not be forwarded to the dependency).

这篇关于如何使用我的CMake项目中需要首先安装的库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆