CMake:将 add_subproject 与使用 Include 的库一起使用以错误的相对路径结束

CMake: Using add_subproject with a library using Include ends up in wrong relative path

全球CMakeLists.txt

这个 CMakeLists.txt 使用 MOC 编译了一些 C++ 文件 (Qt5/...),在任何方面都不是 'special'。

有问题的代码是这样的:

add_subdirectory(third-party/libwebrtc)
include_directories(third-party/libwebrtc)
target_link_libraries(${PROJECT_NAME} libwebrtc)

libwebrtc CMakeLists.txt

cmake_minimum_required(VERSION 3.3)
project(libwebrtc)

# Allow the use of IN_LIST operand
cmake_policy(SET CMP0057 NEW)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
    ${CMAKE_SOURCE_DIR}/CMakeModules)

find_package(Git REQUIRED)

include(FindLibraries)
include(Version)
include(Options)
include(TargetOsAndCpu)
...

完整的 libwebrtc 源 -> https://github.com/cloudwebrtc/libwebrtc-build/blob/dev/CMakeLists.txt

'cmake ..'

出错

如果我 运行 mkdir build; cd build; cmake .. 我可以看到 CMake 在顶级项目中搜索 include(),而不是像我预期的那样在其子目录中搜索。

joachim@thinkpad-x1:[~/projects/client/build]: cmake ..
-- CMAKE_SYSTEM_INFO_FILE: 
-- CMAKE_SYSTEM_NAME:      
-- CMAKE_SYSTEM_PROCESSOR: 
-- CMAKE_SYSTEM:           
-- CMAKE_C_COMPILER:       /usr/bin/clang
-- CMAKE_CXX_COMPILER:     /usr/bin/clang++
CMake Error at sources/third-party/libwebrtc/CMakeLists.txt:13 (include):
  include could not find load file:

    FindLibraries


CMake Error at sources/third-party/libwebrtc/CMakeLists.txt:14 (include):
  include could not find load file:

    Version

问题(原创)

除了通过从 CMakeModules 目录复制包含将库集成到我的基础项目之外,我还能做些什么吗?

谢谢,下面已经回答了,还是留在这里吧。

关于依赖关系的问题

add_subdirectory 调用正确构建了 libwebrtc,但是我的 include_directories 调用,来自顶层 CMakeLists.txt 的调用(不是 libwebrtc 库),想要包含的文件是仅在完成构建后可用:

include_directories(
  ${CMAKE_CURRENT_BINARY_DIR}/sources/third-party/libwebrtc/include/webrtc
  ${CMAKE_CURRENT_BINARY_DIR}/sources/third-party/libwebrtc/include/webrtc/third_party/libyuv/include/
  ${CMAKE_CURRENT_BINARY_DIR}/sources/third-party/libwebrtc/webrtc/src/third_party/abseil-cpp
)

如何让cmake依赖库的完整构建,然后再构建主程序?通常一个人使用 add_custom_command(..) 但由于我们使用 add_subdirectory(..) 我们不能也使用 add_custom_command(..).

我解决这个问题的方法是在 libwebrtc/CMakeLists.txt 和 ExternalProject_Add(libwebrtcx ...) 中将库重命名为 project(libwebrtcx) 并添加一个 add_dependencies(${PROJECT_NAME} libwebrtcx) 但是没有那个 hack 可以完成吗?

错误CMAKE_SOURCE_DIR

我认为错误似乎在此处

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
    ${CMAKE_SOURCE_DIR}/CMakeModules)

CMAKE_SOURCE_DIR 将是您的 主源目录的路径。将其更改为

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
    ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules)

作为外部依赖使用

另一个想法是自己构建项目并将其作为外部依赖项在您的项目中使用。

find_package(LibWebRTC REQUIRED)
include(${LIBWEBRTC_USE_FILE})

target_link_libraries(my-app ${LIBWEBRTC_LIBRARIES})

所以我基本上是这样做的:

libwebrtc项目结构

  • 将文件夹重命名为 libwebrtcx
  • 重命名项目

    project(libwebrtcx)
    
  • 修改了CMAKE_MODULE_PATH

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
    -    ${CMAKE_SOURCE_DIR}/CMakeModules)
    +    ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules)
    

libwebrtc CMakeLists.txt

替换了所有这些:

  • CMAKE_SOURCE_DIR 与 CMAKE_CURRENT_SOURCE_DIR 和
  • CMAKE_BINARY_DIR 使用 CMAKE_CURRENT_BINARY_DIR 并使用

我的项目CMakeLists.txt

add_dependencies(${PROJECT_NAME} libwebrtcx)
add_subdirectory(third-party/libwebrtcx)
include_directories(
  ${CMAKE_BINARY_DIR}/sources/third-party/libwebrtcx/include/webrtc
  ${CMAKE_BINARY_DIR}/sources/third-party/libwebrtcx/include/webrtc/third_party/libyuv/include/
  ${CMAKE_BINARY_DIR}/sources/third-party/libwebrtcx/webrtc/src/third_party/abseil-cpp
)

add_library(libwebrtc STATIC IMPORTED)
set_property(TARGET libwebrtc PROPERTY IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/sources/third-party/libwebrtcx/webrtc/src/out/Release/obj/libwebrtc.a")
target_link_libraries(${PROJECT_NAME} libwebrtc)

摘要

有了这个,由于 add_dependencies 调用,我得到了库 libwebrtcx 在实际使用之前构建。但是对于链接器,我需要原始的 'libwebrtc' 名称,所以我基本上引入了另一个依赖项,称为 libwebrtc.

我想知道是否也可以用更好的方式做到这一点?!