Re: [CMake] copy_if_different on build
On 2013-04-23 16:00, Skippy VonDrake wrote: Hmm... that is odd. I think there may be something else going on in your project that is not obvious from the above information. I wrote a quick example along the lines of what you show, and it worked fine for me. Actual CMakeLists.txt I used is attached. (The foo.c can contain any compiling code, and foo.cfg.in can contain anything or even be empty.) (Apparently a disadvantage of just using add_custom_target is that it always runs, regardless of the DEPENDS. Not that this should be a huge problem, though.) Have you tried naming the input/output like ${CMAKE_CURRENT_SOURCE_DIR}/name.in and ${CMAKE_CURRENT_BINARY_DIR}/name? (I didn't do that in the attached example because I was lazy (and the example may only work for in-source builds as a result), but that is how I would recommend naming the files in a real project.) The source of my problem was 'naming'. I did use the CMake 'SOURCE_DIR' variable but my file extensions were wrong and my path was off by one level! Everything works fine now. Ah, good to hear :-). Thanks for letting us know. I did notice an effect I didn't expect - when 'make clean' is run the 'output' is deleted. Hadn't thought about that... Well, yes, with the custom commend the output file is effectively a build artifact, so of course it is deleted by clean :-). -- Matthew -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] copy_if_different on build
Please keep this on list so that others may contribute/benefit. Thanks. On 2013-04-23 10:43, Skippy VonDrake wrote: Hmm... yes, I'm not sure if add_dependencies can be used to add a file dependency to a target (the documentation only talks about adding other targets as dependencies). Usually things like configured files are used as source files, i.e. as inputs to add_executable, etc. If for some reason that doesn't work, I believe you can make your executable Since this config file is not needed for the code to compile, I want to keep it separated from the sources list. CMake should be able to accomplish this task without adding the file to the sources. dependent on a custom target, which in turn depends on the output file from your custom command. IOW: add_custom_command(OUTPUT out DEPENDS in COMMAND stuff) add_executable(exe sources) add_custom_target(exe_config DEPENDS out) add_dependencies(exe exe_config) So with the example code above this would translate to?: add_executable (${TARGETNAME}main.cpp) add_custom_command(OUTPUT ${output} DEPENDS ${input} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${input} ${output}) add_custom_target(exe_config DEPENDS ${output}) add_dependencies(${TARGETNAME} exe_config) Which results in make error: make[2]: *** No rule to make target `../src/bin/config.cfg', needed by `src/CMakeFiles/exe_config'. Stop. If you only have one custom command, you can probably use add_custom_target to run the command instead, i.e.: add_custom_target(exe_config DEPENDS in COMMAND stuff) add_executable(exe sources) add_dependencies(exe exe_config) With example code this would be?: add_executable (${TARGETNAME}main.cpp) add_custom_target(exe_config DEPENDS ${input} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${input} ${output}) add_dependencies(${TARGETNAME} exe_config) This created the same make error above. Am I translating your suggestions into the example code erroneously, Matthew? Hmm... that is odd. I think there may be something else going on in your project that is not obvious from the above information. I wrote a quick example along the lines of what you show, and it worked fine for me. Actual CMakeLists.txt I used is attached. (The foo.c can contain any compiling code, and foo.cfg.in can contain anything or even be empty.) (Apparently a disadvantage of just using add_custom_target is that it always runs, regardless of the DEPENDS. Not that this should be a huge problem, though.) Have you tried naming the input/output like ${CMAKE_CURRENT_SOURCE_DIR}/name.in and ${CMAKE_CURRENT_BINARY_DIR}/name? (I didn't do that in the attached example because I was lazy (and the example may only work for in-source builds as a result), but that is how I would recommend naming the files in a real project.) (Incidentally, this tickles a ninja generator bug in CMake 2.8.11.) -- Matthew project(foo) cmake_minimum_required(VERSION 2.8) add_executable(foo foo.c) if(1) # Just to show doing it both ways add_custom_command( OUTPUT foo.cfg DEPENDS foo.cfg.in COMMAND ${CMAKE_COMMAND} -E copy foo.cfg.in foo.cfg ) add_custom_target(foo_config DEPENDS foo.cfg) else() add_custom_target(foo_config DEPENDS foo.cfg.in COMMAND ${CMAKE_COMMAND} -E copy_if_different foo.cfg.in foo.cfg ) endif() add_dependencies(foo foo_config) -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] copy_if_different on build
Hmm... that is odd. I think there may be something else going on in your project that is not obvious from the above information. I wrote a quick example along the lines of what you show, and it worked fine for me. Actual CMakeLists.txt I used is attached. (The foo.c can contain any compiling code, and foo.cfg.in can contain anything or even be empty.) (Apparently a disadvantage of just using add_custom_target is that it always runs, regardless of the DEPENDS. Not that this should be a huge problem, though.) Have you tried naming the input/output like ${CMAKE_CURRENT_SOURCE_DIR}/name.in and ${CMAKE_CURRENT_BINARY_DIR}/name? (I didn't do that in the attached example because I was lazy (and the example may only work for in-source builds as a result), but that is how I would recommend naming the files in a real project.) The source of my problem was 'naming'. I did use the CMake 'SOURCE_DIR' variable but my file extensions were wrong and my path was off by one level! Everything works fine now. (Incidentally, this tickles a ninja generator bug in CMake 2.8.11.) Don't know about that bug. I did notice an effect I didn't expect - when 'make clean' is run the 'output' is deleted. Hadn't thought about that... Thanks for your help and patience! -Skippy -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] copy_if_different on build
On 2013-04-17 12:41, Skippy VonDrake wrote: Thought I understood this - but alas my implementation is wrong. Here's my test case with a top-level cmake file and 3 subdirectories: 'src', 'bin' and 'outdir'. Top level CMakeLists.txt cmake_minimum_required (VERSION 2.8) project (copyFile) set (TARGETNAME fooCopy) set (TARGETDEST ${PROJECT_SOURCE_DIR}/bin) add_subdirectory (src) src/CMakeLists.txt add_executable (${TARGETNAME} main.cpp) set (input ${CMAKE_CURRENT_SOURCE_DIR}/bin/config.cfg) set (output ${CMAKE_CURRENT_SOURCE_DIR}/outdir/config.cfg) add_dependencies(${TARGETNAME} ${output}) add_custom_command( OUTPUT ${output} DEPENDS ${input} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${input} ${output} ) install (TARGETS ${TARGETNAME} DESTINATION ${TARGETDEST}) The config file (config.cfg) is just some text and cpp file is just a hello world example. Since the config file is not source included as a dependency in the add_executable command, I assume my problem is making the target properly depend on it? Specifically ${TARGETNAME} should depend on ${output}? Hmm... yes, I'm not sure if add_dependencies can be used to add a file dependency to a target (the documentation only talks about adding other targets as dependencies). Usually things like configured files are used as source files, i.e. as inputs to add_executable, etc. If for some reason that doesn't work, I believe you can make your executable dependent on a custom target, which in turn depends on the output file from your custom command. IOW: add_custom_command(OUTPUT out DEPENDS in COMMAND stuff) add_executable(exe sources) add_custom_target(exe_config DEPENDS out) add_dependencies(exe exe_config) If you only have one custom command, you can probably use add_custom_target to run the command instead, i.e.: add_custom_target(exe_config DEPENDS in COMMAND stuff) add_executable(exe sources) add_dependencies(exe exe_config) Hope that helps, -- Matthew -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] copy_if_different on build
believe what you want is: add_custom_command( OUTPUT ${output} DEPENDS ${input} COMMAND ${CMAKE_COMMAND} -E copy ${input} ${output} ...which is roughly equivalent to a Makefile rule like: output: input cp input output IOW, the file ${output} depends on the file ${input} (so the target will only run when ${input} is newer than ${output}), and will be created by copying ${input} to ${output} (using 'cmake -E' for portability). Don't forget to have an actual target depend on ${output} :-). (Probably you are using it as a source file for a library or executable, so there is no problem.) You may also want to use 'copy_if_different' instead of just 'copy', which won't change the time stamp of ${output} if the contents are the same as ${input}. On the plus side, this means that large targets depending on ${output} won't be needlessly rebuilt/relinked. On the down side, the copy_if_different will remain out of date, and as a result still think it needs to run after a successful build. Thought I understood this - but alas my implementation is wrong. Here's my test case with a top-level cmake file and 3 subdirectories: 'src', 'bin' and 'outdir'. Top level CMakeLists.txt cmake_minimum_required (VERSION 2.8) project (copyFile) set (TARGETNAME fooCopy) set (TARGETDEST ${PROJECT_SOURCE_DIR}/bin) add_subdirectory (src) src/CMakeLists.txt add_executable (${TARGETNAME}main.cpp) set (input ${CMAKE_CURRENT_SOURCE_DIR}/bin/config.cfg) set (output ${CMAKE_CURRENT_SOURCE_DIR}/outdir/config.cfg) add_dependencies(${TARGETNAME} ${output}) add_custom_command( OUTPUT ${output} DEPENDS ${input} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${input} ${output} ) install (TARGETS ${TARGETNAME} DESTINATION ${TARGETDEST}) The config file (config.cfg) is just some text and cpp file is just a hello world example. Since the config file is not source included as a dependency in the add_executable command, I assume my problem is making the target properly depend on it? Specifically ${TARGETNAME} should depend on ${output}? -Skippy -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] copy_if_different on build
On 2013-03-29 17:07, Skippy VonDrake wrote: I'll look closer at add_custom_command. I want the file to copy over if it has changed - at build time. Not cmake time. And not copy if it hasn't changed. But that may not be doable. Seems like every StackOverflow post I see has a different take on how to do this simple process. That's a little surprising... as you say, this shouldn't be complicated. I believe what you want is: add_custom_command( OUTPUT ${output} DEPENDS ${input} COMMAND ${CMAKE_COMMAND} -E copy ${input} ${output} ...which is roughly equivalent to a Makefile rule like: output: input cp input output IOW, the file ${output} depends on the file ${input} (so the target will only run when ${input} is newer than ${output}), and will be created by copying ${input} to ${output} (using 'cmake -E' for portability). Don't forget to have an actual target depend on ${output} :-). (Probably you are using it as a source file for a library or executable, so there is no problem.) You may also want to use 'copy_if_different' instead of just 'copy', which won't change the time stamp of ${output} if the contents are the same as ${input}. On the plus side, this means that large targets depending on ${output} won't be needlessly rebuilt/relinked. On the down side, the copy_if_different will remain out of date, and as a result still think it needs to run after a successful build. -- Matthew -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
[CMake] copy_if_different on build
I'm using: execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different some-file some-dest-dir) Should the file be copied when: the file has changed AND a build is executed? Or the file has changed AND CMakeLists.txt has changed AND a build is executed? Only the 2nd method (when the CMakeLists.txt file is touched) results in the changed file being copied. I'd expect the 1st method to also cause a file copy. If this assumption is wrong please tell me why. -Skippy -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] copy_if_different on build
On 2013-03-29 15:15, Skippy VonDrake wrote: I'm using: execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different some-file some-dest-dir) Should the file be copied when: the file has changed AND a build is executed? Or the file has changed AND CMakeLists.txt has changed AND a build is executed? Only the 2nd method (when the CMakeLists.txt file is touched) results in the changed file being copied. I'd expect the 1st method to also cause a file copy. If this assumption is wrong please tell me why. execute_process is a configure step. It does not create build rules and will ONLY execute when CMake is run. If you want to create a build rule, use add_custom_command or add_custom_target instead. Anyway, the above is silly; if you really only wanted the file copied at cmake time, you should instead use configure_file(... COPY_ONLY) :-) rather than unnecessarily invoking an extra process. -- Matthew -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] copy_if_different on build
I'm using: execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different some-file some-dest-dir) Should the file be copied when: the file has changed AND a build is executed? Or the file has changed AND CMakeLists.txt has changed AND a build is executed? Only the 2nd method (when the CMakeLists.txt file is touched) results in the changed file being copied. I'd expect the 1st method to also cause a file copy. If this assumption is wrong please tell me why. execute_process is a configure step. It does not create build rules and will ONLY execute when CMake is run. If you want to create a build rule, use add_custom_command or add_custom_target instead. Anyway, the above is silly; if you really only wanted the file copied at cmake time, you should instead use configure_file(... COPY_ONLY) :-) rather than unnecessarily invoking an extra process. I'll look closer at add_custom_command. I want the file to copy over if it has changed - at build time. Not cmake time. And not copy if it hasn't changed. But that may not be doable. Seems like every StackOverflow post I see has a different take on how to do this simple process. -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake