【问题标题】:How to install subdirectories to different locations with CMake?如何使用 CMake 将子目录安装到不同的位置?
【发布时间】:2015-07-29 02:27:07
【问题描述】:

我有几个 CMake 项目,它们定义了自己的安装逻辑。现在,我想添加一个全局 CMakeLists.txt,它使用 add_subdirectory() 添加这些项目,以便一次构建和安装所有项目。如何从外部为他们每个人提供不同的${CMAKE_INSTALL_PREFIX}

我尝试的是更改调用之间的安装前缀以添加子目录,但它们是在实际调用 make install 时安装的,当时,安装前缀已设置为最后分配的值。

【问题讨论】:

  • 如果您的项目具有不同的安装逻辑,则不应在单个全局项目中使用add_subdirectory 构建它们。相反,全局项目可以通过 execute_processExternalProject_Add 使用 CMake 调用来安装它们。
  • @Tsyvarev 你能举个例子说明一下吗?我认为使用execute_process 意味着我不能再在这些子目录之间指定依赖目标,对吧?而且,命令输出只有在完整的命令完成后才能显示,这有点烦人。

标签: installation cmake


【解决方案1】:

如果您的子项目需要相同的变量具有不同的值(在全局范围内),您无法在单个全局项目中使用 add_subdirectory 构建它们。

相反,全局项目可以通过execute_processExternalProject_Add 调用cmake 来安装它们。有时,可以使用install(SCRIPT) 命令。


使用execute_process 安装 使子项目在configuration 阶段立即可用。

当子项目有一些打包机制时可以使用它(参见CMake tutorials about packaging),因此全局对象可以执行find_package(<subproject-name>)并以最简单的方式与子项目中定义的库链接(使用变量,外部填充)。

# Configure subproject into <subproject-build-dir>
execute_process(COMMAND ${CMAKE_COMMAND} -D<var>=<value> <subproject-source-dir> 
    WORKING_DIRECTORY <subproject-build-dir>)
# Build and install subproject
execute_process(COMMAND ${CMAKE_COMMAND} --build <subproject-build-dir> --target install)
# Extract variables, related to subproject for link with it.
find_package(<subproject-name>)

# Create target in global project and link with subproject
include_directories(${<subproject-name>_INCLUDE_DIRS})
link_directories(${<subproject-name>_LIBRARY_DIRS})
add_executable(global_program main.cpp)
target_link_libraries(global_program ${<subproject-name>_LIBRARIES})

使用ExternalProject_add安装将目标分配给子项目,该子项目将安装在build阶段。在这种情况下也可以与子项目链接,但需要手动填充变量。

# Configure, build and install subproject
ExternalProject_Add(<subproject_target>
    SOURCE_DIR <subproject-source-dir>
    CMAKE_CACHE_ARGS -D<var>=<value>
    BINARY_DIR <subproject-build-dir>
    INSTALL_DIR <CMAKE_INSTALL_PREFIX-for-subproject>
    )

# Create target in global project and link with subproject
include_directories(<subproject-include-files-location>)
link_directories(<subproject-libraries-location>)
add_executable(global_program main.cpp)
target_link_libraries(global_program <subproject-libraries-name>)
# Make sure that subproject will be built before executable.
add_dependencies(global_program <subproject_target>)

使用install(SCRIPT)安装会在install 阶段执行脚本。当全局项目和子项目之间没有构建依赖关系时,可以使用这种方法。

subproject_install.cmake:

# Configure subproject into <subproject-build-dir>
execute_process(COMMAND ${CMAKE_COMMAND} -D<var>=<value> <subproject-source-dir> 
    WORKING_DIRECTORY <subproject-build-dir>)
# Build and install subproject
execute_process(COMMAND ${CMAKE_COMMAND} --build <subproject-build-dir> --target install)

CMakeLists.txt:

install(SCRIPT subproject_install.cmake)

【讨论】:

  • 感谢您的全面回答。我想使用 CMake 生成 makefile 或项目文件,我可以在更改代码后再次使用它们来构建整个项目。使用execute_process() 时,子目录将在配置时构建,因此我必须在更改源代码后重新运行 CMake。即使有一种在构建时执行第二个execute_process() 调用的方法,我也会回到依赖库的问题,这些依赖库需要在配置依赖目标之前安装。你知道如何解决这个问题吗?
  • 如果您可以修改子项目,最好将其修复为使用通用安装逻辑,这样您就可以使用add_subdirectory。我的回答中描述的直接安装子项目意味着您将其视为持久性。
  • 我意识到我在这里作为评论发布的问题与这个问题并不严格相关,所以我created a new post for it。如果你能去看看就好了。
  • @ruslo:这只是一个模式,而不是完整的代码。当然,真正的应用程序需要执行错误检查。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-30
  • 2023-01-25
  • 1970-01-01
  • 2017-01-14
  • 1970-01-01
  • 2014-12-22
相关资源
最近更新 更多