1#------------------------------------------------------------------------------
2# Function used to copy arbitrary files matching certain patterns.
3# Usage:
4# copy_files_recursive(<source-dir>
5#   DESTINATION <destination-dir>
6#   [LABEL "<label to use>"]
7#   [OUTPUT "<file generated to mark end of copying>"]
8#   [REGEX <regex> [EXCLUDE]]
9#   [DEPENDS [depends ...]]
10#   )
11#
12# One can specify multiple REGEX or REGEX <regex> EXCLUDE arguments.
13#------------------------------------------------------------------------------
14function(copy_files_recursive source-dir)
15  set (dest-dir)
16  set (patterns)
17  set (exclude-patterns)
18  set (output-file)
19  set (extra_depends)
20  set (label "Copying files")
21
22  set (doing "")
23  foreach (arg IN LISTS ARGN)
24    if (arg MATCHES "^(DESTINATION|REGEX|OUTPUT|LABEL|DEPENDS)$")
25      set (doing "${arg}")
26    elseif ("x${doing}" STREQUAL "xDESTINATION")
27      set (doing "")
28      set (dest-dir "${arg}")
29    elseif ("x${doing}" STREQUAL "xREGEX")
30      set (doing "SET")
31      list (APPEND patterns "${arg}")
32    elseif (("x${arg}" STREQUAL "xEXCLUDE") AND ("x${doing}" STREQUAL "xSET"))
33      set (doing "")
34      list (GET patterns -1 cur-pattern)
35      list (REMOVE_AT patterns -1)
36      list (APPEND exclude-patterns "${cur-pattern}")
37    elseif ("x${doing}" STREQUAL "xOUTPUT")
38      set (doing "")
39      set (output-file "${arg}")
40    elseif ("x${doing}" STREQUAL "xLABEL")
41      set (doing "")
42      set (label "${arg}")
43    elseif ("x${doing}" STREQUAL "xDEPENDS")
44      list(APPEND extra_depends "${arg}")
45    else()
46      message(AUTHOR_WARNING "Unknown argument [${arg}]")
47    endif()
48  endforeach()
49
50  file(GLOB_RECURSE _all_files RELATIVE "${source-dir}" "${source-dir}/*")
51  set(extra_args)
52  foreach(_item IN LISTS patterns)
53    # need to escape "\" since we're writing these out to a cmake file.
54    string(REPLACE "\\" "\\\\" _item "${_item}")
55    set(extra_args "${extra_args} REGEX \"${_item}\"")
56  endforeach()
57  foreach(_item IN LISTS exclude-patterns)
58    string(REPLACE "\\" "\\\\" _item "${_item}")
59    set(extra_args "${extra_args} REGEX \"${_item}\" EXCLUDE")
60  endforeach()
61  if(extra_args)
62    set(extra_args "FILES_MATCHING ${extra_args}")
63  endif()
64  set (copy-commands "file(COPY \${SRCDIR} DESTINATION \${OUTDIR} ${extra_args})")
65
66  # Let's now build a list of files matching the selection criteria
67  # so we can add dependencies on those.
68  set(all_files)
69  string(REPLACE ";" "|" match-regex "${patterns}")
70  string(REPLACE ";" "|" exclude-regex "${exclude-patterns}")
71  foreach (_file ${_all_files})
72    if (exclude-regex AND ("${_file}" MATCHES "${exclude-regex}"))
73      # skip
74    elseif ("${_file}" MATCHES "${match-regex}")
75      set (in-file "${source-dir}/${_file}")
76      list (APPEND all_files ${in-file})
77    endif()
78  endforeach()
79
80  get_filename_component(_name ${output-file} NAME)
81  set(CMAKE_CONFIGURABLE_FILE_CONTENT ${copy-commands})
82  configure_file(${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in
83    "${CMAKE_CURRENT_BINARY_DIR}/${_name}.cfr.cmake" @ONLY)
84  unset(CMAKE_CONFIGURABLE_FILE_CONTENT)
85
86  add_custom_command(OUTPUT ${output-file}
87    COMMAND ${CMAKE_COMMAND} -DOUTDIR=${dest-dir}
88                             -DSRCDIR=${source-dir}/
89                             -P ${CMAKE_CURRENT_BINARY_DIR}/${_name}.cfr.cmake
90    COMMAND ${CMAKE_COMMAND} -E touch ${output-file}
91    DEPENDS ${all_files}
92            "${CMAKE_CURRENT_BINARY_DIR}/${_name}.cfr.cmake"
93            ${extra_depends}
94    COMMENT ${label}
95    VERBATIM)
96endfunction()
97