【问题标题】:CMakeLists: Adding source files from Github with ExternalProjectCMakeLists:使用 ExternalProject 从 Github 添加源文件
【发布时间】:2020-05-04 13:04:38
【问题描述】:

我正在为 Beckhoff ADS 库编写一个小的 catkin 包装器。我想安装 AdsLib 文件夹中的文件,但不使用 Beckhoff 的 CMake 文件。

我只想复制文件以便将它们添加到我自己的 CMakeLists 中的库中。如果我手动复制文件,这工作正常。但我想直接使用来自 Github 源的最新文件进行构建。

我尝试了可以​​在 stackoverflow 上找到的所有可能组合,但不知何故无法使其发挥作用。

cmake_minimum_required(VERSION 2.8.3)
project(ads_catkin)

find_package(catkin_simple REQUIRED)
catkin_simple()

include(ExternalProject)


ExternalProject_Add(ads
    PREFIX ${CMAKE_BINARY_DIR}/ads
    GIT_REPOSITORY https://github.com/Beckhoff/ADS.git
    GIT_TAG master
    CONFIGURE_COMMAND ""
    #GIT_TAG 6b3a03009a757cf651fe44d8be7b6df698028f0e
    UPDATE_COMMAND ""
    BUILD_COMMAND ""
    INSTALL_COMMAND ""
)

ExternalProject_Get_Property(ads source_dir)

cs_add_library(${PROJECT_NAME}
    ${source_dir}/AdsLib/AdsDef.cpp
)
cs_install()
cs_export()

我第一次使用 catkin_tools 构建时,这给了我:

Errors     << ads_catkin:cmake /home/xxx/xxx_ws/logs/ads_catkin/build.cmake.000.log                                 
CMake Error at /home/xxx/xxx_ws/devel/share/catkin_simple/cmake/catkin_simple-extras.cmake:150 (add_library):
  Cannot find source file:

    /home/xxx/xxx/build/ads_catkin/ads/src/ads/AdsLib/AdsDef.cpp

  Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
  .hxx .in .txx
Call Stack (most recent call first):
  CMakeLists.txt:23 (cs_add_library)


CMake Error: CMake can not determine linker language for target: ads_catkin
CMake Error: Cannot determine link language for target "ads_catkin".

然后,我第二次在相同的代码上运行构建工具时,文件实际上被克隆了,但我最终得到了这个错误:

Errors     << ads_catkin:make /home/xxx/xxx_ws/logs/ads_catkin/build.make.000.log                                   
make[2]: *** No rule to make target 'CMakeFiles/ads_catkin.dir/build'.  Stop.
make[1]: *** [CMakeFiles/ads_catkin.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
Cloning into 'ads'...
Already on 'master'
make: *** [all] Error 2

顺便说一句:cs_add_library 是 add_library 和 target_link_libraries 的 catkin_simple 形式。

更新: 越来越近...将@Tsyvarev 中的解决方案改编为我的文件:

cmake_minimum_required(VERSION 2.8.3)
project(ads_catkin)

find_package(catkin_simple REQUIRED)
catkin_simple()

include(ExternalProject)


ExternalProject_Add(ads
    PREFIX ${CATKIN_DEVEL_PREFIX}/ads
    GIT_REPOSITORY https://github.com/Beckhoff/ADS.git
    GIT_TAG 6b3a03009a757cf651fe44d8be7b6df698028f0e
    #GIT_TAG master
    CONFIGURE_COMMAND ""
    UPDATE_COMMAND ""
    BUILD_COMMAND ""
    INSTALL_COMMAND ""
    BUILD_BYPRODUCTS 
        <SOURCE_DIR>/AdsLib/AdsDef.cpp
        <SOURCE_DIR>/AdsLib/AdsLib.cpp
        <SOURCE_DIR>/AdsLib/AmsConnection.cpp
        <SOURCE_DIR>/AdsLib/AmsPort.cpp
        <SOURCE_DIR>/AdsLib/AmsRouter.cpp
        <SOURCE_DIR>/AdsLib/Frame.cpp
        <SOURCE_DIR>/AdsLib/Log.cpp
        <SOURCE_DIR>/AdsLib/NotificationDispatcher.cpp
        <SOURCE_DIR>/AdsLib/Sockets.cpp
        <SOURCE_DIR>/AdsLib/AdsDef.h
        <SOURCE_DIR>/AdsLib/AdsLib.h
        <SOURCE_DIR>/AdsLib/AdsNotification.h
        <SOURCE_DIR>/AdsLib/AmsConnection.h
        <SOURCE_DIR>/AdsLib/AmsHeader.h
        <SOURCE_DIR>/AdsLib/AmsPort.h
        <SOURCE_DIR>/AdsLib/AmsRouter.h
        <SOURCE_DIR>/AdsLib/Frame.h
        <SOURCE_DIR>/AdsLib/Log.h
        <SOURCE_DIR>/AdsLib/NotificationDispatcher.h
        <SOURCE_DIR>/AdsLib/RingBuffer.h
        <SOURCE_DIR>/AdsLib/Router.h
        <SOURCE_DIR>/AdsLib/Semaphore.h
        <SOURCE_DIR>/AdsLib/Sockets.h
        <SOURCE_DIR>/AdsLib/wrap_endian.h
        <SOURCE_DIR>/AdsLib/wrap_socket.h
)

ExternalProject_Get_Property(ads SOURCE_DIR)


include_directories(
    ${SOURCE_DIR}/AdsLib
)

cs_add_library(AdsLib
    ${SOURCE_DIR}/AdsLib/AdsDef.cpp
    ${SOURCE_DIR}/AdsLib/AdsLib.cpp
    ${SOURCE_DIR}/AdsLib/AmsConnection.cpp
    ${SOURCE_DIR}/AdsLib/AmsPort.cpp
    ${SOURCE_DIR}/AdsLib/AmsRouter.cpp
    ${SOURCE_DIR}/AdsLib/Frame.cpp
    ${SOURCE_DIR}/AdsLib/Log.cpp
    ${SOURCE_DIR}/AdsLib/NotificationDispatcher.cpp
    ${SOURCE_DIR}/AdsLib/Sockets.cpp
)
add_dependencies(AdsLib ads)


cs_install()

install(DIRECTORY ${SOURCE_DIR}/AdsLib/
        DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
        PATTERN ".cpp" EXCLUDE   
)

cs_export()

我尝试将头文件包含在我的 AdsLib 库中。但我仍然收到错误:

In file included from /home/xxx/xxx_ws/src/xxx/nav_controller/src/controller.cpp:19:0:
/home/xxx/xxx_ws/src/xxx/nav_controller/include/nav_controller/controller.h:27:10: fatal error: AdsLib.h: No such file or directory
 #include "AdsLib.h"
          ^~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/nav_controller.dir/src/controller.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from /home/xxx/xxx_ws/src/xxx/nav_controller/src/test.cpp:22:0:
/home/xxx/xxx_ws/src/xxx/nav_controller/include/nav_controller/controller.h:27:10: fatal error: AdsLib.h: No such file or directory
 #include "AdsLib.h"
          ^~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/nav_controller.dir/src/test.cpp.o] Error 1
make[1]: *** [CMakeFiles/nav_controller.dir/all] Error 2
make: *** [all] Error 2

【问题讨论】:

  • 尚不清楚是什么原因导致了该问题。请在您的问题帖子中提供完整 CMake 日志,包括错误消息。如果您在帖子中包含 Minimal Reproducible Example 会很有帮助,因为您发布的 CMake 看起来并不完整...
  • @squareskittles 我扩展了这个例子,现在是完整的 CMakeLists.txt。我用catkin工具搭建。
  • @drescherjm 我看到了这个。第二个例子似乎与我正在做的相对应......
  • 谢谢,现在问题更清楚了。我认为this post 中的答案将有助于解决您的问题。本质上,ExternalProject_Add 运行 build 时间,因此当 CMake 运行时,它还无法访问外部项目的工件。

标签: c++ cmake catkin


【解决方案1】:

CMake 错误Cannot find source file 意味着一件简单的事情:没有任何东西告诉 CMake 给定的源文件是生成的,并且文件本身不存在。

由于文件是在ExternalProject_Add生成的,需要调整对应的target-level依赖:

add_dependency(ads_catkin ads)

此命令应该在创建相应目标的add_library()ExternalProject_Add 调用之后 发出。此命令告诉 CMake,只有在执行了外部项目的所有步骤之后才应该构建库。

您仍然需要告诉 CMake 源文件已生成。有两种方法可以做到这一点。

  1. 设置 GENERATED 属性:

    set_source_files_properties(${source_dir}/AdsLib/AdsDef.cpp PROPERTIES GENERATED TRUE)
    

    这会阻止 CMake 在配置阶段搜索文件。

  2. BYPRODUCTS 选项中为生成它的目标列出文件。对于ExternalProject_Add 命令创建的目标,这是通过该命令的附加选项来实现的

    BUILD_BYPRODUCTS <SOURCE_DIR>/AdsLib/AdsDef.cpp
    

    这也为源文件设置 GENERATED 属性,就像在第一种情况下一样。但 BYPRODUCTS 也让您的项目可供 Ninja 用户使用。

    (上面选项中的表达式&lt;SOURCE_DIR&gt;是一种特殊的方式来引用ExternalProject的源目录。它可以用于一些ExternalProject的选项,BUILD_BYPRODUCTS就是其中之一)。


从技术上讲,当 CMake 看到相应的 BYPRODUCTS 选项时,它应该足够聪明地添加目标级别的依赖项(add_dependency(ads_catkin ads) 的效果)自动。但是这个功能只针对3.16版本描述,不知道老版本是否有效。

【讨论】:

  • 谢谢!我试过了,但现在我的 catkin 库中仍然缺少头文件。我用我的新文件更新了帖子。
  • 看来安装不是问题。更多的是包含文件没有正确链接。我尝试添加 catkin_package(INCLUDE_DIRS ${SOURCE_DIR}/AdsLib),因为 cs_export 仅导出包含文件夹。但是即使我将它添加到 Cmake 文件的末尾,我也会收到一个错误,即外部项目中的文件不可用。
  • 这个答案是完全正确的。我想指出,还有一个鲜为人知的FetchContent CMake 模块,它在配置时检索外部项目或其他内容,而不是在构建时检索。如果您在使用项目中的文件之前声明并提供内容,这应该可以直接使用,无需管理依赖项。
  • @d-karl:使用FetchContent 模块已在问题的 cmets 中进行了讨论。提问者comments 认为旧版(
【解决方案2】:

最后,即使在@Tsyvarev 的帮助下,我也无法使用ExternalProject_Add 使其工作。部分解决方案是使用 cs_export(INCLUDE_DIRS ${ads}) 手动导出库,这不适用于 ExternalProject_Add,因为此时文件不可用。

最后,我在我的包中包含了DownloadProject module,它是 FetchContent 的前身。这是它应该做的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-01
    • 2023-03-19
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    相关资源
    最近更新 更多