Issue
I've created a list of files using:
file(GLOB_RECURSE DEPLOY_FILES "${PROJECT_SOURCE_DIR}/install/*")
I want to install all of these files in /usr/myproject/
, but I want to maintain the file tree on the installed folder:
install/junk
install/other/junk2
install/other/junk3
If I use:
install(FILES ${DEPLOY_FILES} DESTINATION "usr/myproject")
All the files end up in /usr/myproject as:
/usr/myproject/junk
/usr/myproject/junk2
/usr/myproject/junk3
How can I make the install command keep track of relative paths?
I've worked around the issue by doing it manually in a for
loop:
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()
...but this is annoying to do. Surely there's an easier way?
(I can't see anything in the install documentation though...)
Solution
Use:
INSTALL( DIRECTORY <directory> DESTINATION usr/myproject )
(See here for details: http://www.cmake.org/cmake/help/v2.8.8/cmake.html#command:install)
INSTALL( DIRECTORY ... )
preserves the directory structure. But, if you use install
as <directory>
, you would end up with usr/myproject/install/....
which is not what you want.
There are two ways to do this:
Use
INSTALL( FILES .... DESTINATION usr/myproject)
to install the files that lie directly ininstall/
, then useINSTALL( DIRECTORY .... DESTINATION usr/myproject
) and manually list the directories to install.Use your globbing command in your original post, and then determine which entries are files, which are directories, move the directory entries to a separate list, feed the lists to
INSTALL( FILES ...)
andINSTALL( DIRECTORY ...)
, respectively.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 )
Note: Depending on the type of files you install, other INSTALL( ...)
commands might be more appropriate (for example, INSTALL( TARGETS .... )
to install your libraries/executables.
Answered By - Johannes S.