Reputation: 764
I have the following project layout:
project/
├─ CMakeLists.txt
├─ main.cpp
╘═ my_lib/
├─ CMakeLists.txt
╞═ some_package1/
│ ├── header.hpp
│ └── impl.cpp
╘═ some_package2/
├── header.hpp
└── impl.cpp
my_lib
is added as a subdirectory by the CMakeLists.txt
from project
.
What I would like to have is a target in my_lib
CMakeLists.txt
which, when built, executes a command that copies all headers in my_lib
to a destination directory, while preserving directory structure. The destination directory would be defined by the project
CMakeLists.txt
.
Basically, if I could somehow get add_custom_command
to do this:
file(COPY ${CMAKE_SOURCE_DIR}/my_lib DESTINATION ${COPY_DEST_DIR} FILES_MATCHING PATTERN "*.hpp")
I would be extremely happy. But I haven't found a way to do that. This is very similar to an install target, except I need it done before anything gets even compiled.
I tried doing the following:
set(MY_LIB_HEADER_FILES
some_package1/header.hpp
some_package2/header.hpp
)
add_custom_target(copy_headers)
add_custom_command(
TARGET copy_headers
COMMAND ${CMAKE_COMMAND} -E copy "${MY_LIB_HEADER_FILES}" ${COPY_DEST_DIR}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/my_lib
)
But that doesn't preserve directory structure, which in just this example case would lead to one header being overwritten by the other. I haven't been able to find a workaround to that.
The only solution I can imagine is a hack in which I loop over every file in ${MY_LIB_HEADER_FILES}
, remove whatever follows the last forward slash, create that directory, and then copy the file over to it. But that really isn't something I want to resort to and come to think of it, I'm not even sure how I'd go about it considering it must be done in an add_custom_command
call.
Surely there is a solution, right?
Upvotes: 3
Views: 2098
Reputation: 1650
One of the ways to achieve this is to write a "CMake script" file that will contain your file(COPY ....)
command and to execute it within add_custom_command
. In brief, your code snippet would look like this:
#create script file during configure phase...
file(WRITE ${CMAKE_BINARY_DIR}/cp.cmake
"file(COPY ${CMAKE_SOURCE_DIR}/my_lib DESTINATION ${COPY_DEST_DIR} FILES_MATCHING PATTERN *.hpp)\n"
)
#execute the script during the build phase...
add_custom_command(
TARGET my_lib
POST_BUILD
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cp.cmake
)
file(WRITE ....
statement will create a new cmake script file within the root build folder named cp.cmake
.
Note 1:
The $
preceding variables CMAKE_SOURCE_DIR
and COPY_DEST_DIR
are not escaped, meaning that the cp.cmake
will contain their evaluated values.
Note 2:
It is assumed that your library creates a target named my_lib
and add_custom_command
is added as a POST_BUILD
event for that target.
In the end, here is the cmake documentation about add_custom_command, file command and running CMake in script mode
Upvotes: 3