我使用以下方法创建了一个文件列表:
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()
......但这很烦人。当然有一种更简单的方法吗?
(虽然我在安装文档中看不到任何内容......)
答案 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/....
,这不是您想要的。
有两种方法可以做到这一点:
使用INSTALL( FILES .... DESTINATION usr/myproject)
安装直接位于install/
的文件,然后使用INSTALL( DIRECTORY .... DESTINATION usr/myproject
)并手动列出要安装的目录。
在原始帖子中使用globbing命令,然后确定哪些条目是文件,哪些是目录,将目录条目移动到单独的列表,将列表提供给INSTALL( FILES ...)
和{{1}分别。
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( ...)
来安装库/可执行文件。
答案 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
文件中运行循环很笨拙,因此 DIRECTORY
的 pattern matching option 对我有用。
install(DIRECTORY src/ DESTINATION include FILES_MATCHING PATTERN "*.h")
这采用了 src/
中的整个文件夹结构,并在 <INSTALL_DIR>/include
中复制了它,只有头文件。