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

时间:2012-06-19 07:39:21

标签: cmake

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

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

如何让install命令跟踪相对路径?

我通过在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 个答案:

答案 0 :(得分:51)

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

install(DIRECTORY mydir/ DESTINATION dir/newname)

追踪' /'很重要。 如果没有它mydir将被安装到newname/mydir

来自CMake文档:

  

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

答案 1 :(得分:27)

使用:

INSTALL( DIRECTORY <directory> DESTINATION usr/myproject )

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

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

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

  1. 使用INSTALL( FILES .... DESTINATION usr/myproject)安装直接位于install/的文件,然后使用INSTALL( DIRECTORY .... DESTINATION usr/myproject)并手动列出要安装的目录。

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

    INSTALL( DIRECTORY ...)
  3. 注意:根据您安装的文件类型,其他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( ...)来安装库/可执行文件。

答案 2 :(得分:21)

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

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

完成。 ; - )

答案 3 :(得分:1)

由于不建议使用通配符,并且在 CMakeLists.txt 文件中运行循环很笨拙,因此 DIRECTORYpattern matching option 对我有用。

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

这采用了 src/ 中的整个文件夹结构,并在 <INSTALL_DIR>/include 中复制了它,只有头文件。