nemetroid
nemetroid

Reputation: 2159

Copy folder into subdirectory in CMake on Windows

I have a CMake project using Makefiles on Windows, with a folder structure that looks like this (the build takes place in build):

project
|- build
   |- ...
|- otherfolder
   |- stuff
   |- more stuff

As a build step (pre- or post doesn't matter), I want to make a copy of project into build (excluding the build folder), like so:

project
|- build
   |- ...
   |- project
      |- otherfolder
         |- stuff
         |- more stuff
|- otherfolder
   |- stuff
   |- more stuff

Other options might be acceptable as well, e.g. copying to a temporary directory outside the project root before moving it into place, but CMake seemingly has no builtin support for generating temporary directories.

Things I've tried: xcopy has support for excluding certain files and directories, but refuses to copy even if I explicitly exclude the build folder. cmake -E copy_directory does not (from what I'm able to find) support excluding certain directories.

CMake's file(COPY ... PATTERN build EXCLUDE ... copies successfully, but it runs at CMake configure time and I haven't been able to find a way to make it run at build time.

I might resort to using Python and shutil, but it would be nice if it could be done without additional dependencies, so I'd prefer a batch file solution.

Upvotes: 1

Views: 1828

Answers (1)

Tsyvarev
Tsyvarev

Reputation: 65888

There are several ways for doing selectable directory copiing.

  1. You can use cmake -P for execute cmake script at any time. E.g:

copy_to_build.cmake:

file(COPY . DESTINATION build PATTERN build EXCLUDE)

CMakeLists.txt:

add_custom_command(... COMMAND cmake -P copy_to_build.cmake)
  1. You can prepare list of subdirectories (and files) at configuration stage, and then copy every element of that list using xcopy. This approach uses fact, that everything outside of build directory is not changed. Here iteration is done on configuration stage (by CMake). I am not sure, whether "for" loop works under COMMAND of add_custom_command. If it works, you can use it for iterate over entries in the shell.

CMakeLists.txt:

# List of elements in source directory.
file(GLOB entries RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
# List of commands for pass to `add_custom_command` as is.
# `COMMAND` keyword is included into list.
set(copy_commands)
foreach(entry ${entries})
    list(APPEND copy_commands COMMAND xcopy /s /i
        ${CMAKE_CURRENT_SOURCE_DIR}/${entry} ${CMAKE_CURRENT_SOURCE_DIR}/build/${entry}
endforeach()

add_custom_command(... ${copy_commands})

Upvotes: 1

Related Questions