[CMake] Copy a input file from src folder to EXECUTABLE_OUTPUT_PATH

Michael Hertling mhertling at online.de
Tue Dec 13 16:21:10 EST 2011


On 12/12/2011 04:36 PM, Michael Wild wrote:
> On 12/12/2011 04:29 PM, Totte Karlsson wrote:
>>>
>>> At build time:
>>>
>>
>>> ADD_CUSTOM_COMMAND(TARGET OneOfYourExecutables
>>>      COMMAND ${CMAKE_COMMAND} -E copy_if_different
>>>          <path>/<to>/input.txt $<TARGET_FILE_DIR:OneOfYourExecutables>)
>>> ADD_CUSTOM_COMMAND(TARGET AnotherExecutable
>>>      COMMAND ${CMAKE_COMMAND} -E copy_if_different
>>>          <path>/<to>/input.txt $<TARGET_FILE_DIR:AnotherExecutable>)
>>>
>>> Personally, I'd prefer the latter as it's clean and quite flexible.
>>
>> I decided to use
>> ADD_CUSTOM_COMMAND(
>> TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E
>> copy_if_different
>>         "P:/mtkLib/Examples/${PROJECT_NAME}/ball.mtk"
>> $<TARGET_FILE_DIR:${PROJECT_NAME}>
>> )
>>
>> It works fine. But I have a few more questions:
>> 1) How can I get rid of the absolute path in the expression for the
>> source file?
> 
> Use the ${PROJECT_SOURCE_DIR} variable. It points to the directory
> containing the CMakeLists.txt file with the last project() call.
> 
>> 2) when doing make clean, the file in the target file dir is not
>> deleted. How to add it to 'clean'?
> 
> See the ADDITIONAL_MAKE_CLEAN_FILES directory property. However, this is
> going to be somewhat tricky since you are using $<TARGET_FILE_DIR:...>
> in your custom command, and AFAIK the set_directory_property command is
> not aware of this notation. Do you really need ball.mtk to be in the
> same directory as your output file?

If one comes to the conclusion that it's worth the effort, one
could also record any additional files to clean at build time
and use a custom target to trigger the built-in clean target
as well as to remove the recorded files:

# CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(P C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
FILE(WRITE ${CMAKE_BINARY_DIR}/f.c "void f(void){}\n")
ADD_LIBRARY(f SHARED f.c)
ADD_CUSTOM_COMMAND(TARGET f POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E touch $<TARGET_FILE_DIR:f>/f.dat
    COMMAND ${CMAKE_COMMAND}
        -DF=$<TARGET_FILE_DIR:f>/f.dat
        -DL=${CMAKE_BINARY_DIR}/files.dat
        -P ${CMAKE_SOURCE_DIR}/record.cmake)
FILE(WRITE ${CMAKE_BINARY_DIR}/g.c "void g(void){}\n")
ADD_LIBRARY(g SHARED g.c)
ADD_CUSTOM_COMMAND(TARGET g POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E touch $<TARGET_FILE_DIR:g>/g.dat
    COMMAND ${CMAKE_COMMAND}
        -DF=$<TARGET_FILE_DIR:g>/g.dat
        -DL=${CMAKE_BINARY_DIR}/files.dat
        -P ${CMAKE_SOURCE_DIR}/record.cmake)
FILE(WRITE ${CMAKE_BINARY_DIR}/h.c "void h(void){}\n")
ADD_LIBRARY(h SHARED h.c)
ADD_CUSTOM_COMMAND(TARGET h POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E touch $<TARGET_FILE_DIR:h>/h.dat
    COMMAND ${CMAKE_COMMAND}
        -DF=$<TARGET_FILE_DIR:h>/h.dat
        -DL=${CMAKE_BINARY_DIR}/files.dat
        -P ${CMAKE_SOURCE_DIR}/record.cmake)
ADD_CUSTOM_TARGET(totalclean
    COMMAND ${CMAKE_COMMAND}
        --build ${CMAKE_BINARY_DIR}
        --config $<CONFIGURATION>
        --target clean
    COMMAND ${CMAKE_COMMAND}
        -DL=${CMAKE_BINARY_DIR}/files.dat
        -P ${CMAKE_SOURCE_DIR}/remove.cmake)

# record.cmake:
IF(EXISTS "${L}")
    FILE(STRINGS "${L}" FILES)
ENDIF()
LIST(APPEND FILES "${F}")
LIST(REMOVE_DUPLICATES FILES)
STRING(REGEX REPLACE ";" "\n" FILES "${FILES}")
FILE(WRITE "${L}" "${FILES}\n")

# remove.cmake:
IF(EXISTS "${L}")
    FILE(STRINGS "${L}" FILES)
    FILE(REMOVE ${FILES})
    FILE(REMOVE "${L}")
ENDIF()

The downside is that one cannot use the well-known "clean" target
anymore to purge the files but must trigger "totalclean" instead.

Regards,

Michael


More information about the CMake mailing list