View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0009974CMakeCMakepublic2009-11-27 19:192016-06-10 14:31
ReporterSteve Wilson 
Assigned ToBrad King 
PrioritynormalSeverityfeatureReproducibilityN/A
StatusclosedResolutionmoved 
PlatformOSOS Version
Product VersionCMake-2-8 
Target VersionFixed in Version 
Summary0009974: CMake should support custom commands that can vary by configuration.
DescriptionThe 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.
TagsNo tags attached.
Attached Fileszip file icon CustomCommandsByConfiguration.zip [^] (11,670 bytes) 2009-11-27 19:19
patch file icon 0001-Per-config-add_custom_command.patch [^] (39,624 bytes) 2010-12-15 14:19 [Show Content]
patch file icon a14a8562+0001-Per-config-add_custom_command.patch [^] (39,620 bytes) 2010-12-15 14:26 [Show Content]

 Relationships
related to 0011209closedBrad King Support generator expression everywhere they make sense 
has duplicate 0012945closedBrad King CMake should support custom commands that can vary by configuration 
has duplicate 0006242closedBrad King ADD_CUSTOM_COMMAND needs CONFIGURATIONS keyword for Visual Studio post-builds 
has duplicate 0012438closedBrad King add_command _needs_ CONFIGURATION parameter for multi-target environments 
related to 0009465closedBrad King target names should resolve correctly in COMMAND statements 
related to 0012877closed Support generator expressions in OUTPUT 
related to 0013840closedKitware Robot Allow generator expressions anywhere 

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

Hello,

this is a feature which I also desperately miss.

Best,
Johannes
(0024183)
Brad King (manager)
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 (manager)
2010-12-15 14:26

Rebased on commit a14a8562 from master:

  a14a8562+0001-Per-config-add_custom_command.patch
(0024186)
Brad King (manager)
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 (manager)
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 (manager)
2012-01-02 15:56

Closing resolved issues that have not been updated in more than 4 months.
(0028884)
Brad King (manager)
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 (reporter)
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 (reporter)
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 (manager)
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 (reporter)
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 (manager)
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 (reporter)
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 (reporter)
2012-07-06 06:51

is there any update on this issue? will this be implemented into cmake in future revisions?
(0029929)
David Cole (manager)
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 (reporter)
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 (reporter)
2013-01-24 04:41
edited on: 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 (reporter)
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 (manager)
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 (reporter)
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 (reporter)
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 (reporter)
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 (administrator)
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.

 Issue History
Date Modified Username Field Change
2009-11-27 19:19 Steve Wilson New Issue
2009-11-27 19:19 Steve Wilson File Added: CustomCommandsByConfiguration.zip
2009-12-02 10:11 Johannes Brunen Note Added: 0018643
2010-12-15 07:17 David Cole Assigned To => Brad King
2010-12-15 07:17 David Cole Status new => assigned
2010-12-15 14:08 Brad King File Added: 0001-Per-config-add_custom_command.patch
2010-12-15 14:12 Brad King Note Added: 0024183
2010-12-15 14:19 Brad King File Deleted: 0001-Per-config-add_custom_command.patch
2010-12-15 14:19 Brad King File Added: 0001-Per-config-add_custom_command.patch
2010-12-15 14:26 Brad King File Added: a14a8562+0001-Per-config-add_custom_command.patch
2010-12-15 14:27 Brad King Note Added: 0024185
2010-12-15 14:28 Brad King Relationship added related to 0011209
2010-12-15 14:35 Brad King Note Added: 0024186
2011-07-29 18:07 Brad King Note Added: 0027126
2011-07-29 18:07 Brad King Status assigned => resolved
2011-07-29 18:07 Brad King Resolution open => suspended
2011-10-05 10:15 David Cole Relationship added child of 0009465
2011-10-05 10:15 David Cole Relationship deleted child of 0009465
2011-10-05 10:16 David Cole Relationship added related to 0009465
2012-01-02 15:56 David Cole Note Added: 0028115
2012-01-02 15:56 David Cole Status resolved => closed
2012-01-16 08:42 Brad King Relationship added related to 0012877
2012-02-08 09:00 Brad King Relationship added related to 0012945
2012-03-09 14:41 Brad King Relationship added has duplicate 0006242
2012-03-09 14:42 Brad King Relationship added related to 0012438
2012-03-09 14:44 Brad King Note Added: 0028884
2012-03-09 14:44 Brad King Status closed => feedback
2012-03-09 14:44 Brad King Resolution suspended => reopened
2012-03-09 14:44 Brad King Status feedback => backlog
2012-03-09 14:44 Brad King Relationship replaced has duplicate 0012438
2012-03-09 14:52 Brad King Relationship replaced has duplicate 0012945
2012-03-26 04:02 Mike Krus Note Added: 0028969
2012-03-26 04:04 Mike Krus Note Edited: 0028969
2012-03-29 08:18 Bjoern Thiel Note Added: 0028995
2012-03-29 10:35 David Cole Note Added: 0028996
2012-04-02 03:40 Bjoern Thiel Note Added: 0029032
2012-04-02 09:28 Brad King Note Added: 0029033
2012-04-03 05:08 chrislu Note Added: 0029063
2012-07-06 06:51 chrislu Note Added: 0029926
2012-07-06 10:21 David Cole Note Added: 0029929
2013-01-08 16:08 Brad King Relationship added related to 0013840
2013-01-23 13:48 void.pointer Note Added: 0032139
2013-01-24 04:41 Petr Kmoch Note Added: 0032144
2013-01-24 04:41 Petr Kmoch Note Edited: 0032144
2013-12-13 16:33 Bill MacDonald Note Added: 0034772
2013-12-18 16:18 Brad King Note Added: 0034810
2014-01-22 08:44 coordz Note Added: 0034986
2014-09-07 17:01 Yelmond Note Added: 0036739
2014-12-18 15:38 Davy Durham Note Added: 0037490
2016-06-10 14:27 Kitware Robot Note Added: 0041628
2016-06-10 14:27 Kitware Robot Status backlog => resolved
2016-06-10 14:27 Kitware Robot Resolution reopened => moved
2016-06-10 14:31 Kitware Robot Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team