2012-06-19 31 views
25

我创建使用的文件列表:如何使用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 

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

我已经做手工在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() 

...但是这很烦人的事情。当然有更简单的方法?

(广东话看到安装文档任何东西,虽然...)

+1

简单有趣的是,他们难以做出简单的**'cp -r' **操作。 – ulidtko

回答

23

用途:

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. 在原来的岗位使用您的通配符的命令,然后确定哪些项目是文件,这些文件的目录,'move目录项到一个单独的列表,并分别喂名单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 ....)安装您的库/可执行文件

+0

@Fraser感谢编辑,我完全错过了错误的格式。 –

40

安装最简单的方法。一切从给定的目录是:

install(DIRECTORY mydir/ DESTINATION dir/newname) 

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

从cmake的文档:

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

+0

这是一个更简单的解决方案,通过globbing等谢谢。 –

+4

感谢“跟踪”/“很重要”。 – fechidal89

18

如果你有文件的列表,你可以简单地遍历它们,并使用get_filename_component()解压目录部分:

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

完成。 ;-)

+0

这是一个非常好的和简单的答案。除了解析文件列表并逐个安装它们之外,不需要执行其他技巧。 +1 – bartgol

+0

非常简单。 – Gallaecio