如何使用CMake安装文件层次结构?

Dou*_*oug 33 cmake

我使用以下方法创建了一个文件列表:

file(GLOB_RECURSE DEPLOY_FILES "${PROJECT_SOURCE_DIR}/install/*")
Run Code Online (Sandbox Code Playgroud)

我想安装所有这些文件/usr/myproject/,但我想在已安装的文件夹上维护文件树:

install/junk
install/other/junk2
install/other/junk3
Run Code Online (Sandbox Code Playgroud)

如果我使用:

install(FILES ${DEPLOY_FILES} DESTINATION "usr/myproject")
Run Code Online (Sandbox Code Playgroud)

所有文件最终都在/ usr/myproject中:

/usr/myproject/junk
/usr/myproject/junk2
/usr/myproject/junk3
Run Code Online (Sandbox Code Playgroud)

如何使安装命令跟踪相对路径?

我通过在for循环中手动执行来解决这个问题:

set(BASE "${PROJECT_SOURCE_DIR}/install")
foreach(ITEM ${DEPLOY_FILES})
  get_filename_component(ITEM_PATH ${ITEM} PATH)
  string(REPLACE ${BASE} "" ITEM_PATH ${ITEM_PATH})
  install(FILES ${ITEM} DESTINATION "usr/myproject${ITEM_PATH}")
endforeach()
Run Code Online (Sandbox Code Playgroud)

......但这很烦人.当然有一种更简单的方法吗?

(虽然我在安装文档中看不到任何内容...)

mar*_*cin 58

从给定目录安装所有内容的最简单方法是:

install(DIRECTORY mydir/ DESTINATION dir/newname)
Run Code Online (Sandbox Code Playgroud)

尾随'/'很重要. 没有它将mydir安装到newname/mydir.

从CMake文档:

每个目录名的最后一个组件都附加到目标目录,但可以使用尾部斜杠来避免这种情况,因为它会将最后一个组件留空.

  • 感谢"尾随'/'很重要." (7认同)

Joh*_* S. 27

使用:

INSTALL( DIRECTORY <directory> DESTINATION usr/myproject )
Run Code Online (Sandbox Code Playgroud)

(详见此处:http://www.cmake.org/cmake/help/v2.8.8/cmake.html#command:install)

INSTALL( DIRECTORY ... )保留目录结构.但是,如果你使用installas <directory>,你最终会usr/myproject/install/....得到的不是你想要的.

有两种方法可以做到这一点:

  1. 使用INSTALL( FILES .... DESTINATION usr/myproject)安装直接躺在文件install/,然后使用INSTALL( DIRECTORY .... DESTINATION usr/myproject),手工列出的目录进行安装.

  2. 在原始帖子中使用globbing命令,然后确定哪些条目是文件,哪些是目录,将目录条目移动到单独的列表,分别将列表提供给INSTALL( FILES ...)INSTALL( DIRECTORY ...).

    file(GLOB DEPLOY_FILES_AND_DIRS "${PROJECT_SOURCE_DIR}/install/*")
    foreach(ITEM ${DEPLOY_FILES_AND_DIRS})
       IF( IS_DIRECTORY "${ITEM}" )
          LIST( APPEND DIRS_TO_DEPLOY "${ITEM}" )
       ELSE()
          LIST( APPEND FILES_TO_DEPLOY "${ITEM}" )
       ENDIF()
    endforeach()
    INSTALL( FILES ${FILES_TO_DEPLOY} DESTINATION usr/myproject )
    INSTALL( DIRECTORY ${DIRS_TO_DEPLOY} DESTINATION usr/myproject )
    
    Run Code Online (Sandbox Code Playgroud)

注意:根据您安装的文件类型,其他INSTALL( ...)命令可能更合适(例如,INSTALL( TARGETS .... )安装库/可执行文件).


Dev*_*lar 24

如果你有一个文件列表(可能是分布在许多子目录上的文件选择,而不是像其他答案那样的完整子目录),你可以循环它们并INCLUDE_FILES用来提取目录部分:

foreach ( file ${INCLUDE_FILES} )
    get_filename_component( dir ${file} DIRECTORY )
    install( FILES ${file} DESTINATION include/${dir} )
endforeach()
Run Code Online (Sandbox Code Playgroud)

完成.;-)

  • 这是一个非常好的和简单的答案。除了解析文件列表并一次安装一个之外,无需做任何其他技巧。+1 (2认同)
  • 非常简单。 (2认同)

小智 6

由于不建议使用通配符,并且在CMakeLists.txt文件中运行循环很笨重,因此模式匹配选项DIRECTORY我来说很有效。

install(DIRECTORY src/ DESTINATION include FILES_MATCHING PATTERN "*.h")
Run Code Online (Sandbox Code Playgroud)

这将整个文件夹结构放入其中,src/并仅在头文件中复制它<INSTALL_DIR>/include