CMake ExternalProject:如何指定根CMakeLists.txt的相对路径?

时间:2015-05-04 10:42:18

标签: git build cmake build-process build-automation

似乎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

我试图解决这个问题:

  1. 不幸的是,更改SOURCE_DIR的参数ExternalProject 不起作用,因为此变量的值用作位置 将libfoo的git存储库克隆到其中。这导致递归依赖地狱无法破解。

  2. 更改libfoo的目录布局以符合ExternalProject。 显然,这可行,但它可能不适用于其他(只读) 第三方图书馆。

  3. 滥用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"
    )
    

    这很有效,但很容易因其他外部项目而失败。

  4. solution to another problem上构建:添加一个临时的 {CM}假设的位置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
    )
    

    这也很有效,感觉比之前的解决方案更好。

  5. 但是,更优雅是否存在同样的效果?

6 个答案:

答案 0 :(得分:10)

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

答案 1 :(得分:2)

您只需手动覆盖 cmake 命令蚂蚁设置路径到 CMakeLists.txt 即可。例如

ExternalProject_Add(libfoo
   PREFIX            "${EP_LIBFOO_DIR}"
   GIT_REPOSITORY    "<link to remote which hosts libfoo.git>" 
   GIT_TAG           "<some hash>"
   CONFIGURE_COMMAND ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} "${EP_LIBFOO_DIR}/src/libfoo/libfoo")

答案 2 :(得分:1)

您可以使用

SOURCE_DIR /path/to/build-dir/EP_libfoo/src/libfoo/libfoo  

ExternalProject_Add调用。这指定了实际的源目录。

答案 3 :(得分:0)

我一直在努力解决我正在进行的项目中的同一问题,这是我能够提出的解决方案。它导致不使用ExternalProject进行git处理,但结果却产生了相同的行为。

的CMakeLists.txt

include(ExternalProject)
set(libfoo_prefix ${CMAKE_HOME_DIRECTORY}/libfoo)

# during generation remove any previous repo and clone.
file(REMOVE_RECURSE ${libfoo_prefix})
execute_process(
    COMMAND git clone <link to remote which hosts libfoo.git>
    WORKING_DIRECTORY ${CMAKE_HOME_DIRECTORY})

# Add the external project.
ExternalProject_Add(libfoo
    PREFIX ${libfoo_prefix}
    SOURCE_DIR ${libfoo_prefix}/libfoo)
# As part of the pre-build step update the git repo.
add_custom_command(
    TARGET libfoo
    PRE_BUILD
    COMMAND ${CMAKE_COMMAND} -P GitPull.cmake)

GitPull.cmake

execute_process(
    COMMAND git pull origin master
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIRECTORY}/libfoo)

答案 4 :(得分:0)

这是一个简单的解决方案

MainPage

基本上你把它分成两部分。第一个是获取源代码,第二个是获取软件。我手动创建了标题的链接,因此kdevelop的解析器不必解析整个项目。

答案 5 :(得分:0)

对于那些仍在寻找答案的人:尝试指定CONFIGURE_COMMAND

ExternalProject_Add(libfoo 
    GIT_REPOSITORY "<link to remote which hosts libfoo.git>" 
    GIT_TAG "<some hash>"
    SOURCE_DIR "where to put the source"
    CONFIGURE_COMMAND
        "${CMAKE_COMMAND}"
        "-HPathToDirectoryWhereTheCMakeListsAre"
        "-BWhereToBuild"
    BUILD_COMMAND
        "${CMAKE_COMMAND}" --build "Path to the directory where you are building (specified with -B flag in CONFIGURE_COMMAND)"
)