CMake:使用 ExternalProject_Add 的不同 lib 路径的最佳实践

CMake: Best practices for differing lib paths with ExternalProject_Add

我有一个小项目,其 CMakeLists.txt 看起来像这样:

include(ExternalProject)
ExternalProject_Add(gainput_project
  PREFIX gainput
  GIT_REPOSITORY https://github.com/jkuhlmann/gainput.git
  GIT_TAG e21b15f0bc3dd3f1a745fe89a966a2457e940142
  INSTALL_COMMAND ""
)
ExternalProject_Get_Property(gainput_project SOURCE_DIR)
ExternalProject_Get_Property(gainput_project BINARY_DIR)
set(GAINPUT_SOURCE_DIR "${SOURCE_DIR}")
set(GAINPUT_BINARY_DIR "${BINARY_DIR}")

add_executable(demo main.cpp)
add_dependencies(demo gainput_project)

target_include_directories(demo PUBLIC
  SYSTEM ${GAINPUT_SOURCE_DIR}/lib/include
)

# TODO: this is bad
if(WIN32)
  target_link_libraries(demo PUBLIC
    debug ${GAINPUT_BINARY_DIR}/lib/Debug/gainput-d.lib
    optimized ${GAINPUT_BINARY_DIR}/lib/Release/gainput.lib
  )
else()
  target_link_libraries(demo PUBLIC
    debug ${GAINPUT_BINARY_DIR}/lib/gainput-d.so
    optimized ${GAINPUT_BINARY_DIR}/lib/gainput.so
  )
endif()

显然,对 target_link_libraries 的调用并不理想;它们非常重复,我正在明确编写构建系统应该已经知道的路径和文件名。 处理来自外部项目的不同输出目录和文件名的最佳方法是什么?

有没有办法查询外部项目以获得实际输出目录? (例如通过 ExternalProject_Get_Property?)我可以使用一些神奇的生成器表达式吗? (ExternalProject_Get_Property(gainput_project RUNTIME_OUTPUT_DIRECTORY) 无效。)

似乎 find_library 可以, 除了 输出库在配置时不存在,因此失败。

也许我应该将外部项目的 INSTALL_DIR 设置为我控制并始终使用的某个硬编码目录? (它还会得到 Windows 上的 DebugRelease 子目录吗?)

FetchContent 模块是否能让我更好地访问包含项目的输出?我在那里的文档中没有看到任何明显的内容。

Idk,我已经尝试了很多想法,但到目前为止没有任何效果。我觉得我可能缺少一些基本的东西——这是我第一次使用 ExternalProject。有什么建议吗?

正如@Tsyvarev 所建议的,我通过从 ExternalProject 切换到 FetchContent 然后使用生成器表达式查找输出文件来解决这个问题:

include(FetchContent)
FetchContent_Declare(gainput
  PREFIX gainput
  GIT_REPOSITORY https://github.com/jkuhlmann/gainput.git
  GIT_TAG e21b15f0bc3dd3f1a745fe89a966a2457e940142
  INSTALL_COMMAND ""
)
FetchContent_MakeAvailable(gainput)

add_executable(demo main.cpp)
add_dependencies(demo gainput)

target_include_directories(demo PUBLIC
  SYSTEM ${gainput_SOURCE_DIR}/lib/include
)

target_link_libraries(demo PUBLIC
  $<TARGET_LINKER_FILE:gainput>
)