I am trying to copy one file ${PROJECT_SOURCE_DIR}/abc.h to another location {PROJECT_SOURCE_DIR}/src with the following command:
add_custom_command(
TARGET MyTarget
POST_BUILD
COMMAND -E copy ${PROJECT_SOURCE_DIR}/abc.h
$<"${PROJECT_SOURCE_DIR}/src":MyTarget>)
However, no matter how I try, it seems that the created VC Studio project will not perform the file copy. Any ideas? Thanks.
There are a couple of issues.
First, you want to execute cmake -E copy ... inside the custom command. To do this, you can provide the path to the CMake executable via the variable CMAKE_COMMAND.
Next, you don't need generator expressions in this case. You can just copy from "${PROJECT_SOURCE_DIR}/abc.h" to "${PROJECT_SOURCE_DIR}/src"
So, your final command should be more like:
add_custom_command(
TARGET MyTarget
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/abc.h"
"${PROJECT_SOURCE_DIR}/src")
As an aside, if the copied file is forming part of your build, you might be better to use cmake -E copy_if_different ... rather than just copy since this won't update the copied file's timestamp needlessly. (If the file is seen as "updated" all sources that #include it will be recompiled when a rebuild happens).
Related
I have a CMake project with next post_build command:
add_custom_command(TARGET ncd_json
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/ncd.json
$<TARGET_FILE_DIR:ncd_json>/ncd.json
COMMENT "Copy ncd.json into binaries folder"
)
ncd.json is copied every time target build. But I really need to copy this file only if it is changed, and even if target is already built and this is the main problem.
I think this question is not full duplicate of CMake copy if original file changed but supplements it.
Something like the following should do close to what you want:
add_custom_target(copyJson ALL
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/ncd.json
$<TARGET_FILE_DIR:ncd_json>/ncd.json
)
add_dependencies(copyJson ncd_json)
It will only copy the file if it is different and it will still copy if the target is already built. Note, however, that it won't copy if you ask only for the target itself to be built. The above relies on you building the default target to get the file copied. You could always combine the approach in your question with the above and it would probably be robust for the cases you want.
While writing question I found a good answer here
configure_file(input_file output_file COPYONLY)
or in my case
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ncd.json
${CMAKE_CURRENT_BINARY_DIR}/ncd.json
COPYONLY
)
But I still not sure if it copies ncd.json every time or not...
See also documentation.
We have two add_custom_command clauses, where one depends on the other:
The first command compiles an .osl source file into an .oso object file using the oslc compiler:
set (oslc ${PROJECT_SOURCE_DIR}/sandbox/bin/oslc)
add_custom_command (
OUTPUT "${oso_dir}/${oso_filename}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${oso_dir}"
COMMAND "${oslc}" -I"${osl_include_path}" -o "${oso_dir}/${oso_filename}" "${osl_src_abs}"
MAIN_DEPENDENCY ${osl_src_abs}
DEPENDS ${${headers}} ${osl_src_abs} "${oslc}"
)
Notice the dependency on ${oslc}: we explicitly depend on ${oslc} because we need to make sure it exists before we can execute this command.
The second command "builds" (really, deploys) the oslc compiler by copying it from somewhere else:
add_custom_command (
OUTPUT "${PROJECT_SOURCE_DIR}/sandbox/bin/oslc"
COMMAND ${CMAKE_COMMAND} -E copy ${OSL_COMPILER} ${PROJECT_SOURCE_DIR}/sandbox/bin/
)
While this setup works, it has the side effect that both commands are always executed (the second command followed by the first command) even when the .osl input file hasn't been modified.
It seems that this behavior is specific to Windows. It appears to work fine on Linux.
If the dependency to ${oslc} is removed from the first command, the second command is no longer executed at all, even when the oslc compiler is missing; but on the other hand, .osl files are now only recompiled when they have changed since the last build, as desired (as long as oslc is present).
Is there anything wrong with this setup? If not, what is the right way to combine both features: compiling .osl files only when they have changed since the last build, and "building" the oslc compiler (required by the first step) when it doesn't yet exist?
The actual CMake script is available on GitHub:
Entire CMakeLists.txt file
First add_custom_command clause
Second add_custom_command clause
A simple solution, at least for Windows, is to change the second command to
add_custom_command (
TARGET appleseed.shaders
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${OSL_COMPILER} ${PROJECT_SOURCE_DIR}/sandbox/bin/
)
(notice the PRE_BUILD keyword)
and to remove the explicit dependency to ${oslc} from the first command.
I am working on CMake for generating the visual studio files. I would like to add the xyz.dll in the same folder where abc.exe is residing.
I had read somewhere that when i manually copy the xyz.dll file into the same folder where abc.exe is residing then the problem would be solved. But every time it is not possible.. I want to write the CMake command so that it will find the xyz.dll file and copy into the same folder where the abc.exe is residing..
Following mentioned are the paths where the .exe and .dll file is residing in my PC.
${MyWorkSpace_ROOT_DIR}/algoCommon/pthread/dll/xyz.dll
${MyWorkSpace_ROOT_DIR}/xml/addAlgo/.../cmakeOut.VS12/Debug/abc.exe
abc is my Project and i would like to confirm whether the following mentioned is wrong or not.
add_custom_command(TARGET abc PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${MyWorkSpace_ROOT_DIR}/algoCommon/pthread/dll"
$<{MyWorkSpace_ROOT_DIR}/xml/addAlgo/.../cmakeOut.VS12/Debug/:abc>)
If this is wrong kindly correct me.
If it is correct then I would like to ask few doubts..
will this command automatically copies the xyz.dll files into the folder abc.exe is residing or something else is happening here??
As Tsyvarev already commented - the destination expression is invalid. In addition, your source line is incomplete (until you want to copy the whole folder which needs another command)
The right command would be
add_custom_command(TARGET abc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${MyWorkSpace_ROOT_DIR}/algoCommon/pthread/dll/xyz.dll"
$<TARGET_FILE_DIR:abc>)
in case you're building also the dll via cmake and you know the target name you could write
add_custom_command(TARGET abc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:xyz>
$<TARGET_FILE_DIR:abc>)
where xyz is the target name of the dll
you might also have a look on this one:
How to copy DLL files into the same folder as the executable using CMake?
An addition to the answer above, as I needed to copy not only the target .dlls, but also all of its dependencies.
As of CMake 3.21 there's a generator pattern that works specifically for .dll targets and takes all the dependencies as well. Do note, that this only works on DLL platforms as per the documentation. Use it like so:
find_package(foo CONFIG REQUIRED) # package generated by install(EXPORT)
add_executable(exe main.c)
target_link_libraries(exe PRIVATE foo::foo foo::bar)
add_custom_command(TARGET exe POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:exe> $<TARGET_FILE_DIR:exe>
COMMAND_EXPAND_LISTS
)
Link to the official CMake TARGET_RUNTIME_DLLS documentation:
https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_RUNTIME_DLLS
After my program is linked I need to perform some post-processing on it. I added a add_custom_command(TARGET ... and that worked fine. However, this extra custom command runs a script (that is not generated; it's checked into the codebase), and I want the target to be considered out of date if that script changes so it will be rebuilt properly.
The add_dependencies rule seems to only work between top-level elements, which this is not (it's just a script), and there's no DEPENDS element in this form of the add_custom_command that I can use.
How do I do this?
It's unfortunately a bit convoluted, but you can use add_custom_target to invoke CMake in script-processing mode via -P.
You need to use add_custom_target here since it will always execute, even if everything's up to date.
Having made this decision, we need to have the custom target execute commands which will check for a new version of your post-processing script file (let's call this "my_script" and assume it's in your root dir), and if it's changed cause your dependent target to go out of date.
This would comprise:
Compare a previous copy of "my_script" to the current "my_script" in the source tree. If the current "my_script" is different, or if the copy doesn't exist (i.e. this is the first run of CMake) then...
Copy "my_script" from the source tree to the build tree, and...
Touch a source file of the dependent target so that it goes out of date.
All of the commands required inside the CMake script can be achieved using execute_process to invoke cmake -E.
So the CMake script (called e.g. "copy_script.cmake") would be something like:
execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files
${OriginalScript} ${CopiedScript} RESULT_VARIABLE Result)
if(Result)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy
${OriginalScript} ${CopiedScript})
execute_process(COMMAND ${CMAKE_COMMAND} -E touch_nocreate ${FileToTouch})
endif()
The CMake script needs to have required variables passed in via the -D args before calling -P, so the calling CMakeLists.txt would have something like:
set(FileToTouch ${CMAKE_SOURCE_DIR}/src/main.cpp)
add_custom_target(CopyScript ALL ${CMAKE_COMMAND}
-DOriginalScript=${CMAKE_SOURCE_DIR}/my_script
-DCopiedScript=${CMAKE_BINARY_DIR}/my_script
-DFileToTouch=${FileToTouch}
-P ${CMAKE_SOURCE_DIR}/copy_script.cmake)
add_executable(MyExe ${FileToTouch})
This will cause a full rebuild of the executable, since it thinks a source file has been modified. If you only require to force relinking there may be a better way to achieve this.
In CMakeLists.txt have a library called "library.dll". I want to add a post build event to copy the resulting file to a different directory. The documentation says to use generator events, but it's not working:
add_custom_command(TARGET library.dll POST_BUILD COMMAND copy $<TARGET_FILE:library.dll> \"${SOME_DIR}/bin\")
I'm using CMake 2.8.3 to generate VC++ 2010 project files on Windows 7.
Try the following changes:
Add the VERBATIM option which ensures that all arguments to the command will be escaped properly.
Instead of using the Windows built-in copy command, invoke CMake in command mode which has a platform independent copy command built-in.
The modified command looks like this:
add_custom_command(TARGET library.dll POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:library.dll> ${SOME_DIR}/bin VERBATIM)