MantisBT - CMake
View Issue Details
0009974CMakeCMakepublic2009-11-27 19:192016-06-10 14:31
Steve Wilson 
Brad King 
normalfeatureN/A
closedmoved 
CMake-2-8 
 
0009974: CMake should support custom commands that can vary by configuration.
The current CMake 2.8.0 system does not allow custom commands created with add_custom_command() to do different things based on the build configuration.

I propose adding a new keyword to the add_custom_command CMake directive called CONFIG:

add_custom_command(OUTPUT output1 [output2 ...]
   COMMAND command1 [ARGS] [args1...]
   [COMMAND command2 [ARGS] [args2...] ...]
   [MAIN_DEPENDENCY depend]
   [DEPENDS [depends...]]
   [IMPLICIT_DEPENDS <lang1> depend1 ...]
   [WORKING_DIRECTORY dir]
   [COMMENT comment] [VERBATIM] [APPEND]
   [CONFIG Debug | MinSizeRel | Release | RelWithDebInfo | ...])

add_custom_command(TARGET target
   PRE_BUILD | PRE_LINK | POST_BUILD
   COMMAND command1 [ARGS] [args1...]
   [COMMAND command2 [ARGS] [args2...] ...]
   [WORKING_DIRECTORY dir]
   [COMMENT comment] [VERBATIM]
   [CONFIG Debug | MinSizeRel | Release | RelWithDebInfo | ...])

The CONFIG option specifies that the custom command(s) should run only when the given build configuration is active. This option allows custom commands to have configuration specific behavior.

When the CONFIG option is not present, add_custom_command command behaves as before.

I have uploaded patches that implement this feature. These patches were created on 11-27-09 against the current CMake CVS head branch sources.

A similar addition could be made for add_custom_target although I have not taken the time to add an implementation.
No tags attached.
related to 0011209closed Brad King Support generator expression everywhere they make sense 
has duplicate 0012945closed Brad King CMake should support custom commands that can vary by configuration 
has duplicate 0006242closed Brad King ADD_CUSTOM_COMMAND needs CONFIGURATIONS keyword for Visual Studio post-builds 
has duplicate 0012438closed Brad King add_command _needs_ CONFIGURATION parameter for multi-target environments 
related to 0009465closed Brad King target names should resolve correctly in COMMAND statements 
related to 0012877closed  Support generator expressions in OUTPUT 
related to 0013840closed Kitware Robot Allow generator expressions anywhere 
zip CustomCommandsByConfiguration.zip (11,670) 2009-11-27 19:19
https://public.kitware.com/Bug/file/2695/CustomCommandsByConfiguration.zip
patch 0001-Per-config-add_custom_command.patch (39,624) 2010-12-15 14:19
https://public.kitware.com/Bug/file/3575/0001-Per-config-add_custom_command.patch
patch a14a8562+0001-Per-config-add_custom_command.patch (39,620) 2010-12-15 14:26
https://public.kitware.com/Bug/file/3576/a14a8562%2B0001-Per-config-add_custom_command.patch
Issue History
2009-11-27 19:19Steve WilsonNew Issue
2009-11-27 19:19Steve WilsonFile Added: CustomCommandsByConfiguration.zip
2009-12-02 10:11Johannes BrunenNote Added: 0018643
2010-12-15 07:17David ColeAssigned To => Brad King
2010-12-15 07:17David ColeStatusnew => assigned
2010-12-15 14:08Brad KingFile Added: 0001-Per-config-add_custom_command.patch
2010-12-15 14:12Brad KingNote Added: 0024183
2010-12-15 14:19Brad KingFile Deleted: 0001-Per-config-add_custom_command.patch
2010-12-15 14:19Brad KingFile Added: 0001-Per-config-add_custom_command.patch
2010-12-15 14:26Brad KingFile Added: a14a8562+0001-Per-config-add_custom_command.patch
2010-12-15 14:27Brad KingNote Added: 0024185
2010-12-15 14:28Brad KingRelationship addedrelated to 0011209
2010-12-15 14:35Brad KingNote Added: 0024186
2011-07-29 18:07Brad KingNote Added: 0027126
2011-07-29 18:07Brad KingStatusassigned => resolved
2011-07-29 18:07Brad KingResolutionopen => suspended
2011-10-05 10:15David ColeRelationship addedchild of 0009465
2011-10-05 10:15David ColeRelationship deletedchild of 0009465
2011-10-05 10:16David ColeRelationship addedrelated to 0009465
2012-01-02 15:56David ColeNote Added: 0028115
2012-01-02 15:56David ColeStatusresolved => closed
2012-01-16 08:42Brad KingRelationship addedrelated to 0012877
2012-02-08 09:00Brad KingRelationship addedrelated to 0012945
2012-03-09 14:41Brad KingRelationship addedhas duplicate 0006242
2012-03-09 14:42Brad KingRelationship addedrelated to 0012438
2012-03-09 14:44Brad KingNote Added: 0028884
2012-03-09 14:44Brad KingStatusclosed => feedback
2012-03-09 14:44Brad KingResolutionsuspended => reopened
2012-03-09 14:44Brad KingStatusfeedback => backlog
2012-03-09 14:44Brad KingRelationship replacedhas duplicate 0012438
2012-03-09 14:52Brad KingRelationship replacedhas duplicate 0012945
2012-03-26 04:02Mike KrusNote Added: 0028969
2012-03-26 04:04Mike KrusNote Edited: 0028969bug_revision_view_page.php?bugnote_id=28969#r579
2012-03-29 08:18Bjoern ThielNote Added: 0028995
2012-03-29 10:35David ColeNote Added: 0028996
2012-04-02 03:40Bjoern ThielNote Added: 0029032
2012-04-02 09:28Brad KingNote Added: 0029033
2012-04-03 05:08chrisluNote Added: 0029063
2012-07-06 06:51chrisluNote Added: 0029926
2012-07-06 10:21David ColeNote Added: 0029929
2013-01-08 16:08Brad KingRelationship addedrelated to 0013840
2013-01-23 13:48void.pointerNote Added: 0032139
2013-01-24 04:41Petr KmochNote Added: 0032144
2013-01-24 04:41Petr KmochNote Edited: 0032144bug_revision_view_page.php?bugnote_id=32144#r1010
2013-12-13 16:33Bill MacDonaldNote Added: 0034772
2013-12-18 16:18Brad KingNote Added: 0034810
2014-01-22 08:44coordzNote Added: 0034986
2014-09-07 17:01YelmondNote Added: 0036739
2014-12-18 15:38Davy DurhamNote Added: 0037490
2016-06-10 14:27Kitware RobotNote Added: 0041628
2016-06-10 14:27Kitware RobotStatusbacklog => resolved
2016-06-10 14:27Kitware RobotResolutionreopened => moved
2016-06-10 14:31Kitware RobotStatusresolved => closed

Notes
(0018643)
Johannes Brunen   
2009-12-02 10:11   
Hello,

this is a feature which I also desperately miss.

Best,
Johannes
(0024183)
Brad King   
2010-12-15 14:12   
I converted the patch to a commit based on 8e7a630f (KWSys Nightly Date Stamp, 2009-11-26):

  0001-Per-config-add_custom_command.patch
(0024185)
Brad King   
2010-12-15 14:26   
Rebased on commit a14a8562 from master:

  a14a8562+0001-Per-config-add_custom_command.patch
(0024186)
Brad King   
2010-12-15 14:35   
Unfortunately I didn't know about this patch until today. During the last week I've been working on some custom command implementation refactoring which conflicts with this patch.

I'm working on a feature I've wanted to do for a long time that has also been requested in issue 0011209. It will allow code like this:

 add_executable(myexe ...)
 add_custom_command(OUTPUT ...
   COMMAND echo $<TARGET_FILE:myexe> $<CONFIGURATION>
   ...)

The $<> syntax is a "generator expression" that gets replaced on a per-config basis. See CMake 2.8's add_test documentation for all current generator expressions. I'm basically adding support to add_custom_command for them.

This kind of feature removes IMO most of the need for per-config custom commands. However, I'm not against integrating the patch from this issue and resolving the conflicts. Do you have an example use case that is not covered by generator expressions? Also, please propose a new test under Tests/ to cover the proposed feature.
(0027126)
Brad King   
2011-07-29 18:07   
The generator expression support described in 0011209 has been released.

I'm resolving this as "suspended" pending proposed use cases not handled by generator expressions as requested in 0009974:0024186. Furthermore, the patch will have to be rebased on master.
(0028115)
David Cole   
2012-01-02 15:56   
Closing resolved issues that have not been updated in more than 4 months.
(0028884)
Brad King   
2012-03-09 14:44   
Re-opening as the central issue for discussion of this feature (since it is the only one with a proposed patch).
(0028969)
Mike Krus   
2012-03-26 04:02   
(edited on: 2012-03-26 04:04)
+1 for this feature. The $<> "generator expressions" only apply to parameters of the command, so you cannot for example have per configuration output files. Adding a CONFIG command would let you do that

Alternative would be to have per-config depend rules for add_dependencies() but that is not currently possible I believe

(0028995)
Bjoern Thiel   
2012-03-29 08:18   
I'd really like to see this feature as it can help you to bring 3'rd party dlls into the build directory using VS e.g. for debugging or running tests.
(0028996)
David Cole   
2012-03-29 10:35   
You can already have per-configuration output files, if you limit yourself to specifying them in a directory named with ${CMAKE_CFG_INTDIR}.

For example, the ActiViz project does this successfully to copy either the Debug or Release dlls of VTK into its own build tree.

Sample code:

  set(dstFile "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/output.txt")
  set(srcFile "${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_CFG_INTDIR}/input.txt")
  ADD_CUSTOM_COMMAND(
    OUTPUT "${dstFile}"
    DEPENDS "${srcFile}"
    COMMAND ${CMAKE_COMMAND} -E copy "${srcFile}" "${dstFile}"
  )

(assumes differing input.txt in Debug and Release subdirs of the current source dir... yielding differing output.txt next to the libs/exes after a build)


I understand that this feature would be desirable to go beyond these limitations, but simply copying files into the right place is 100% possible with current CMake without any patches. It has been even since version 2.4.something, anyway.

Check out the ActiViz code for real world code that works with Visual Studio, specifically the CMakeLists file and the BuildExamples script:

  http://public.kitware.com/gitweb?p=activizdotnet.git;a=blob;f=CMakeLists.txt;h=6434ba79884f8b59626352851373d1a909126ff1;hb=7a9a569b8bfa4b3183efc30e817d1bb701fd99b6 [^]

  http://public.kitware.com/gitweb?p=activizdotnet.git;a=blob;f=BuildExamples.cmake;h=d19ea17ef9b9986b5a0eaebca35a1915a100955b;hb=7a9a569b8bfa4b3183efc30e817d1bb701fd99b6 [^]
(0029032)
Bjoern Thiel   
2012-04-02 03:40   
Right. And in combination with ${CMAKE_BUILD_TYPE} one can work with nmake in parallel as well. But for differing names (zlib1.dll and zlibd1.dll) unfortunately I got stuck.
(0029033)
Brad King   
2012-04-02 09:28   
A commonly proposed use case for this feature is to copy a per-config .dll dependency into an executable's directory using a post-build command. Here is how to do that with generator expressions:

add_library(z SHARED IMPORTED)
set_target_properties(z PROPERTIES
  IMPORTED_CONFIGURATIONS "Release;Debug"
  IMPORTED_LOCATION_RELEASE "c:/path/to/zlib1.dll"
  IMPORTED_LOCATION_DEBUG "c:/path/to/zlib1d.dll"
  IMPORTED_IMPLIB_RELEASE "c:/path/to/zlib.lib"
  IMPORTED_IMPLIB_DEBUG "c:/path/to/zlibd.lib"
  )

add_executable(foo foo.c)
target_link_libraries(foo z)
add_custom_command(TARGET foo POST_BUILD COMMAND
  ${CMAKE_COMMAND} -E copy $<TARGET_FILE:z> $<TARGET_FILE_DIR:foo>/$<TARGET_FILE_NAME:z>
  
)
(0029063)
chrislu   
2012-04-03 05:08   
here is my very ugly solution using "if EXIST" to distinguish the debug and release dll version. i really wish for this feature to solve such ugly solutions:

macro(scm_link_libraries)
    set(in_platform ${ARGV0})
    set(in_libraries ${ARGV})

    list(REMOVE_AT in_libraries 0)

    # first to the actual target_link_libraries
    if (in_platform MATCHES ALL)
        target_link_libraries(${PROJECT_NAME} ${in_libraries})
    else (in_platform MATCHES ALL)
        if (${in_platform})
            target_link_libraries(${PROJECT_NAME} ${in_libraries})
        endif (${in_platform})
    endif (in_platform MATCHES ALL)

    get_target_property(target_type ${PROJECT_NAME} TYPE)
    if (target_type MATCHES EXECUTABLE)
        if (in_platform MATCHES ALL OR in_platform MATCHES WIN32)
            get_directory_property(link_dirs LINK_DIRECTORIES)
            list(REMOVE_ITEM in_libraries debug optimized general)
            list(REMOVE_ITEM link_dirs ${SCHISM_LIBRARY_DIR})
            set(conf_list release debug)

            foreach(conf ${conf_list})
                foreach(link_lib ${in_libraries})
                    set(link_lib_dll ${link_lib}.dll)
                    foreach(ldir ${link_dirs})
                        set(dll_path ${ldir}/${conf}/${link_lib_dll})
                        if (EXISTS ${dll_path})
                            # make if fail for the wrong configuration
                            string(REPLACE /${conf}/ "/$<CONFIGURATION>/" dll_path ${dll_path})
                            add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
                                               COMMAND if EXIST ${dll_path} ${CMAKE_COMMAND} -E echo "copying ${link_lib_dll} to ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIGURATION>/"
                                               COMMAND if EXIST ${dll_path} ${CMAKE_COMMAND} -E copy_if_different ${dll_path} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIGURATION>/)
                        endif (EXISTS ${dll_path})
                    endforeach(ldir)
                endforeach(link_lib)
            endforeach(conf)
        endif (in_platform MATCHES ALL OR in_platform MATCHES WIN32)
    endif (target_type MATCHES EXECUTABLE)
endmacro(scm_link_libraries)

macro(scm_copy_shared_libraries)
    set(in_platform ${ARGV0})
    set(in_libraries ${ARGV})

    list(REMOVE_AT in_libraries 0)

    if (${in_platform} OR in_platform MATCHES ALL)
        foreach(shlib ${in_libraries})
            #message(${shlib})
            #message(${in_platform})
            #file(GLOB_RECURSE scm_glob_dlls ${GLOBAL_EXT_DIR}/lib/$<CONFIGURATION>/ ${shlib})
            #message(${scm_glob_dlls})
            set(scm_copy_dlls ${GLOBAL_EXT_DIR}/lib/$<CONFIGURATION>/${shlib})
            set(scm_copy_path ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIGURATION>/)
            string(REPLACE "/" "\\" scm_copy_dlls ${scm_copy_dlls})
            string(REPLACE "/" "\\" scm_copy_path ${scm_copy_path})
            add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
                               COMMAND if EXIST ${scm_copy_dlls} ${CMAKE_COMMAND} -E echo "copying ${shlib} to ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIGURATION>/"
                               COMMAND if EXIST ${scm_copy_dlls} ${CMAKE_COMMAND} -E copy_if_different ${scm_copy_dlls} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIGURATION>/)

        endforeach(shlib)

    # set(scm_copy_dlls ${SCHISM_LIBRARY_DIR}/$<CONFIGURATION>/*.dll)
    # set(scm_copy_path ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIGURATION>/)
    # string(REPLACE "/" "\\" scm_copy_dlls ${scm_copy_dlls})
    # string(REPLACE "/" "\\" scm_copy_path ${scm_copy_path})
#
# add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
# COMMAND if EXIST ${dll_path} ${CMAKE_COMMAND} -E echo "copying ${link_lib_dll} to ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIGURATION>/"
# COMMAND if EXIST ${dll_path} ${CMAKE_COMMAND} -E copy_if_different ${dll_path} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIGURATION>/)

    endif (${in_platform} OR in_platform MATCHES ALL)

endmacro(scm_copy_shared_libraries)
(0029926)
chrislu   
2012-07-06 06:51   
is there any update on this issue? will this be implemented into cmake in future revisions?
(0029929)
David Cole   
2012-07-06 10:21   
No updates beyond the notes already posted here.

We already have per-configuration add_test calls. Eventually, we will probably also have per-configuration add_custom_command calls. But to the best of my knowledge nobody is actively working on it, or has a specific timing in mind.
(0032139)
void.pointer   
2013-01-23 13:48   
A few months back I offered to take this up but I've been so busy with work and other things I don't think I'll ever be able to work on this. Hoping someone can pick this up and add in the patch file already provided.

The workaround I use for this right now involves creating 1 custom target per configuration, but all of them run in every configuration. For example:

copy_dlls_debug
copy_dlls_relwithdebinfo
copy_dlls_release
copy_dlls_minsizerel

When I build "Debug" in visual studio, all 4 will execute. Any chance of getting this worked on soon?
(0032144)
Petr Kmoch   
2013-01-24 04:41   
Re: void.pointer's note, using such per-configuration custom targets can be combined with 0013587 (which is already marged to master) to turn off those targets for the unwanted configurations.

(0034772)
Bill MacDonald   
2013-12-13 16:33   
Can I ask for this to be considered again. We have a large project with many targets, each of which needs post processing tools chained to the linking (i.e not run every time but run only when the linker runs), and applied only to the release builds. (context: our software has security requirements and we must apply anti-debug tools to the release binaries. Obviously, you don't want anti-debug measures in your debug builds).

I might be able to use the above workaround, but given the number of targets and variants we are producing, it's going to make for a very heavy, very unwieldy solution file in VS and XCode.
(0034810)
Brad King   
2013-12-18 16:18   
Re 0009974:0034772: The patch proposed here is now 3 years old and would need to be rebased and updated before it could be considered again.

In your use case you may be able to use a generator expression like $<CONFIGURATION> or $<CONFIG:Debug> to pass a parameter to your postprocessing tool (or a wrapper) to tell it whether to actually do anything.
(0034986)
coordz   
2014-01-22 08:44   
I'm trying to use the workaround proposed by Brad and use generators. Sadly, this gets me close but not all the way. It has also got very complex and unclear. Please, please take this bug off the backlog, dust off the patch and slip it in ASAP.
(0036739)
Yelmond   
2014-09-07 17:01   
Seconded! My main use case is that I have a per-build command for a specific configuration (Release) and I have NO commands for all other configurations. It would be nice to avoid adding any command for the other configurations - something the generator expressions solution doesn't support.

My current workaround is something like this:
add_custom_command(
    TARGET target
    PRE_BUILD
    COMMAND if 1==$<CONFIG:Rlease> command arg1 arg2
    COMMENT "Running pre-build event." )

But the suggested CONFIG parameter to add_custom_command() would be a lot more elegant.
(0037490)
Davy Durham   
2014-12-18 15:38   
I also second this feature: I'd like to compress the final binary, but only in some release configurations. I can probably get away with passing the configuration to the script, but that makes less sense (IMO) than having a conditional as part of cmake's feature since the script now has to be aware of build configuration issues.
(0041628)
Kitware Robot   
2016-06-10 14:27   
Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.