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

标签 cmake build-system

我的 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 项目中处理的外部依赖项
  • 您正在处理的项目过于复杂,无法将它们添加为子目录,例如目标过多或其他原因。 (您的示例中似乎没有这样的项目。)
  • 您正在处理的项目:这些将被添加为 super 项目的子目录。

  • 在配置 super 项目之前,您需要在 #1 和 #2 组中配置、构建和安装项目:
  • 您可以在运行 super 项目的CMakeLists.txt 之前执行此操作,例如,来自 shell 脚本
  • 或者,正如您提到的,从 super 项目的 CMakeLists.txt 中, 使用 execute_process(${CMAKE_COMMAND} ...) .您可以使用适当的 find_package(... QUIET) 的结果有条件地执行此操作。命令。

  • 您需要决定是否属于第 3 组的项目,例如 engine将仅在将它们用作子目录的项目中使用,或者您打算将它们用作独立库,构建在它们自己的构建树中。

    另外,您提到:“我的库包括外部库的目录”。让我们涵盖所有可能的库 engine可以依赖于:
  • 比如说,LIB1LIB2engine 的私有(private)和公共(public)外部依赖项和他们的配置模块导出老派LIB1_*LIB2_*变量
  • LIB3LIB4engine 的私有(private)和公共(public)外部依赖项及其配置模块导出 LIB3LIB4导入库

  • 公共(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/

    相关文章:

    c++ - 使用纯CMake构建SFML时出现运行时错误

    c++ - 如何通过cmake使用-fPIC编译jsoncpp

    sublimetext - 如何配置 sublime 的构建系统来捕获此类错误输出中的文件和行?

    python - 设置远程 Sublime Text 构建系统

    haskell - 具有多个图书馆部分的 cabal

    android - Android.bp 和 Android.mk 之间的区别

    linux - fusebox watch 和热装不工作

    c++ - 编译 cpp 文件时出错 (ros)

    linux - 如何启用 vtk "direct"硬件渲染,X11/Ubuntu 11.04 x86-64?

    c++ - 如何在测试运行期间获取资源的目录路径?