Pintu
Pintu

Reputation: 369

CMake copy files using copy_if_different recursively

I am new to CMake. I have got my project compiling. I have a structure like this

PROJECT

The question is how do I copy all static files ie. from test and example folder and place them in a different folder outside the binary structure recursively?

My main CMakeLists.txt file:

PROJECT(copythefiles)

SET(CMAKE_CURRENT_BINARY_DIR ".")

add_subdirectory(/src/test /lib/test) # I am specifying the location where the files are to be generated
add_subdirectory(/src/example /lib/example)

ADD_CUSTOM_TARGET( a ALL COMMAND ${CMAKE_COMMAND} -E echo "\{X}" > ${CMAKE_CURRENT_BINARY_DIR}/lib/test/libtest.a )

ADD_CUSTOM_COMMAND(TARGET a POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
        ${CMAKE_CURRENT_BINARY_DIR}/lib/test/libtest.a
        ${CMAKE_CURRENT_BINARY_DIR}/lib/libtest.a )

This copies the files. But I have around 20 projects and I would like to do it recursively.

Thanks :)

Upvotes: 2

Views: 9962

Answers (1)

Fraser
Fraser

Reputation: 78428

It's normal to have your top-level CMakeLists.txt file in the root of your project. If you move your CMakeLists.txt out of "/build" to the root, then you should be able to call add_subdirectory without having to specify the binary path for each case.

Assuming you move the CMakeLists file, then you can insert this before the add_subdirectory calls:

function(MoveLib TheTarget)
  add_custom_command(TARGET ${TheTarget} POST_BUILD
                     COMMAND ${CMAKE_COMMAND} -E
                         copy $<TARGET_FILE:${TheTarget}> ${CMAKE_SOURCE_DIR}/lib)
endfunction()

execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/lib)

This then allows you to add e.g. MoveLib(my_test) inside the libraries' CMakeLists.txt files, where my_test is the name of the library concerned.


A copy of all libraries will then end up in "/lib". If you're not really wanting copies, then you should have a look at the ARCHIVE_OUTPUT_DIRECTORY property. If you simply add

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)

then all your static libraries will end up in "/lib". There are a couple of things to watch for here though.

Shared libraries aren't covered by ARCHIVE_OUTPUT_DIRECTORY. The details for shared libs are in the docs for ARCHIVE_OUTPUT_DIRECTORY though.

Also, some generators (e.g. MSVC) append a per-configuration subdirectory to the specified directory, so you'd end up with "/lib/Debug", "/lib/Release", etc. You can circumvent this by setting the configuration-specific versions of CMAKE_ARCHIVE_OUTPUT_DIRECTORY to all point to ${CMAKE_SOURCE_DIR}/lib:

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/lib)

Upvotes: 3

Related Questions