似乎CMake ExternalProject 始终假定为根目录
外部项目的源目录。但是如果不是这样的话
案子?

考虑以下示例:

外部项目使用以下目录布局:

libfoo.git                 <--- ExternalProject assumes this as source dir.
├── ...
└── libfoo                 <--- However, the actual source directory is this!
    ├── CMakeLists.txt
    └──  ...

在依赖项目中,libfoo的配置如下:
ExternalProject_Add( libfoo
    PREFIX            "${CMAKE_CURRENT_BINARY_DIR}/EP_libfoo"
    GIT_REPOSITORY    "<link to remote which hosts libfoo.git>"
    GIT_TAG           "<some hash>"
)

然后,构建失败,并显示以下错误消息:
$ cmake -H/path/to/source-dir -B/path/to/build-dir
...
$ cmake --build /path/to/build-dir/ --target all
...
CMake Error: The source directory "/path/to/build-dir/EP_libfoo/src/libfoo" does not appear to contain CMakeLists.txt.
...
$

因此,正如以上目录布局所指出的那样,CMake认为
外部项目是
/path/to/build-dir/EP_libfoo/src/libfoo

实际上,当
/path/to/build-dir/EP_libfoo/src/libfoo/libfoo

我尝试解决此问题:
  • 不幸的是,更改了SOURCE_DIR的参数ExternalProject确实
    不起作用,因为此变量的值用作位置
    libfoo的git存储库克隆到其中。这将导致无法打破的递归依赖 hell 。
  • 更改libfoo的目录布局以符合ExternalProject
    显然,这会起作用,但可能不适用于其他(只读)
    第三方图书馆。
  • 滥用ExternalProject的更新/补丁步骤,例如通过指定
    set( EP_LIBFOO_DIR "${CMAKE_CURRENT_BINARY_DIR}/EP_libfoo" )
    
    ExternalProject_Add( libfoo
        PREFIX            "${EP_LIBFOO_DIR}"
        GIT_REPOSITORY    "<link to remote which hosts libfoo.git>"
        GIT_TAG           "<some hash>"
    
        # Copy the content of `<...>/libfoo/libfoo` into `<...>/libfoo`.
        # Note to self: using symlinks instead copying is too platform-specific.
        PATCH_COMMAND     ${CMAKE_COMMAND} -E copy_directory "${EP_LIBFOO_DIR}/src/libfoo/libfoo" "${EP_LIBFOO_DIR}/src/libfoo"
    )
    

    这是可行的,但是它很扎实,并且很容易在其他外部项目中失败。
  • solution to another problem上构建:添加一个临时项
    CMake假定的位置中的CMakeLists.txt。这个临时文件
    然后包括实际的CMakeLists.txt:
    set( EP_LIBFOO_DIR "${CMAKE_CURRENT_BINARY_DIR}/EP_libfoo" )
    set( GENERATED_DIR "${CMAKE_BINARY_DIR}/generated" )
    
    file( MAKE_DIRECTORY ${GENERATED_DIR} )
    file( WRITE ${GENERATED_DIR}/CMakeLists.txt
        "cmake_minimum_required( VERSION 3.0 )\n"
        "add_subdirectory( libfoo )\n"
    )
    
    ExternalProject_Add( libfoo
        PREFIX            "${EP_LIBFOO_DIR}"
        GIT_REPOSITORY    "<link to remote which hosts libfoo.git>"
        GIT_TAG           "<some hash>"
    
        # Copy the
        UPDATE_COMMAND    ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/generated/CMakeLists.txt ${EP_LIBFOO_DIR}/src/libfoo
    )
    

    这也很好,并且比以前的解决方案感觉更好。

  • 但是,是否存在更优雅的方法呢?

    最佳答案

    我已经提交a merge request来向SOURCE_SUBDIR添加ExternalProject_Add选项,以解决此用例。希望它将在CMake 3.7中可用。 (您也可以将ExternalProject*.cmake本地复制到您自己的项目中,以立即利用该功能。)

    10-06 03:10