46

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

file(GLOB_RECURSE DEPLOY_FILES "${PROJECT_SOURCE_DIR}/install/*")

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

install/junk
install/other/junk2
install/other/junk3

如果我使用:

install(FILES ${DEPLOY_FILES} DESTINATION "usr/myproject")

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

/usr/myproject/junk
/usr/myproject/junk2
/usr/myproject/junk3

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

我通过手动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()

...但这很烦人。肯定有更简单的方法吗?

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

4

4 回答 4

79

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

install(DIRECTORY mydir/ DESTINATION dir/newname)

尾随“/”很重要。 没有它mydir会被安装到newname/mydir.

从 CMake 文档中:

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

于 2014-05-20T17:25:57.167 回答
38

我假设你有一个文件列表,比如说INCLUDE_FILES。可能会选择分布在多个子目录中的文件,例如来自源树的头文件,而不是像其他答案中的单个子目录中的所有内容。

您可以遍历文件列表并用于get_filename_component()提取目录部分,然后在后续使用它install()来设置DESTINATION子目录:

foreach ( file ${INCLUDE_FILES} )
    get_filename_component( dir ${file} DIRECTORY )
    install( FILES ${file} DESTINATION include/${dir} )
endforeach()

完毕。;-)

编辑:如果您要以这种方式安装的所有文件都与特定文件模式匹配——例如“所有头文件”——那么brno 的答案比这个更有优势。

于 2014-09-19T12:29:55.683 回答
32

利用:

INSTALL( DIRECTORY <directory> DESTINATION usr/myproject )

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

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

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

  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 )
    

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

于 2012-06-19T08:17:31.387 回答
2

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

install(DIRECTORY src/ DESTINATION include FILES_MATCHING PATTERN "*.h")

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

于 2021-06-08T07:18:33.017 回答