MantisBT - CMake
View Issue Details
0015112CMakeCMakepublic2014-08-26 17:352015-03-02 08:57
Javier Martinez 
Brad King 
normalminoralways
closedfixed 
WindowsWindowsWin7-64
CMake 3.0.1 
CMake 3.1CMake 3.1 
0015112: add_custom_command: Clarify documented relationship of multiple COMMANDs
CMake generates incorrect commands in a custom build step causing builds to fail. The attached example exposes two issues:
- CMake inserts spaces around the statement in parenthesis which changes the variable value. In the attached example the CONF variable value is "Release " instead of "Release"
  Expected: if '$(Configuration)'=='Release-Internal' set (CONF=Release)
  Actual: if '$(Configuration)'=='Release-Internal' set ( CONF=Release )
  Workaround: if there's no else clause the w/a is to not use parenthesis

- If the content of a variable is used at the beginning of a command CMake will wrap it in additional percent (%) characters making the command invalid.
  Expected: %CMDLINE%
  Actual: %%CMDLINE%%
  Workaround: use conditional expressions to avoid the variable be at the beginning, for example ECHO "Running command" && %CMDLINE%
cmake_minimum_required(VERSION 3.0)

add_custom_target(Test
)

add_custom_command(
    TARGET Test
    PRE_BUILD
    COMMAND set CONF=$(Configuration)
    COMMAND if '$(Configuration)'=='Release-Internal' set (CONF=Release)
    COMMAND set BUNDLE_FOLDER=Prebuilt/Windows/%CONF%/$(PlatformArchitecture)
    COMMAND set CMDLINE=7z.exe x -y %BUNDLE_FOLDER%/bundle.7z -o%BUNDLE_FOLDER%
    COMMAND echo %CMDLINE%
    COMMAND %CMDLINE%
    COMMENT "Extracting Bundle (failed)"
)

add_custom_command(
    TARGET Test
    POST_BUILD
    COMMAND set CONF=$(Configuration)
    COMMAND if '$(Configuration)'=='Release-Internal' set CONF=Release
    COMMAND set BUNDLE_FOLDER=Prebuilt/Windows/%CONF%/$(PlatformArchitecture)
    COMMAND set CMDLINE=7z.exe x -y %BUNDLE_FOLDER%/bundle.7z -o%BUNDLE_FOLDER%
    COMMAND echo %CMDLINE% && %CMDLINE%
    COMMENT "Extracting Bundle (succeed)"
)
Command line to reproduce: cmake.exe CMakeLists.txt -G"Visual Studio 12" -B"CMakeOutput"
No tags attached.
txt CMakeLists.txt (902) 2014-08-26 17:35
https://public.kitware.com/Bug/file/5235/CMakeLists.txt
Issue History
2014-08-26 17:35Javier MartinezNew Issue
2014-08-26 17:35Javier MartinezFile Added: CMakeLists.txt
2014-08-27 07:51David ColeNote Added: 0036679
2014-08-27 07:58David ColeSummaryIncorrect commands generated on bustom build step for Visual Studio => Incorrect commands generated on custom build step for Visual Studio
2014-08-27 09:34Brad KingNote Added: 0036682
2014-08-28 17:01Javier MartinezNote Added: 0036689
2014-09-02 15:15Brad KingSummaryIncorrect commands generated on custom build step for Visual Studio => add_custom_command: Clarify documented relationship of multiple COMMANDs
2014-09-02 15:15Brad KingNote Added: 0036702
2014-09-04 09:44Brad KingAssigned To => Brad King
2014-09-04 09:44Brad KingStatusnew => resolved
2014-09-04 09:44Brad KingResolutionopen => fixed
2014-09-04 09:44Brad KingFixed in Version => CMake 3.1
2014-09-04 09:44Brad KingTarget Version => CMake 3.1
2014-09-08 14:06Javier MartinezNote Added: 0036748
2014-09-08 14:06Javier MartinezStatusresolved => feedback
2014-09-08 14:06Javier MartinezResolutionfixed => reopened
2014-09-08 14:16Brad KingNote Added: 0036749
2014-09-08 14:17Brad KingStatusfeedback => assigned
2014-09-08 14:17Brad KingResolutionreopened => open
2014-09-11 13:03Brad KingStatusassigned => resolved
2014-09-11 13:03Brad KingResolutionopen => fixed
2015-03-02 08:57Robert MaynardNote Added: 0038114
2015-03-02 08:57Robert MaynardStatusresolved => closed

Notes
(0036679)
David Cole   
2014-08-27 07:51   
One workaround would be to write this all into a batch file, and use "COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/script.bat arg1 arg2"

Another workaround would be to use:
call %CMDLINE%

instead of just
%CMDLINE%

It's a legitimate bug report (but I didn't confirm it myself), but there are multiple ways to work around the issue.
(0036682)
Brad King   
2014-08-27 09:34   
The add_custom_command COMMAND option expects full command lines rather than batch script fragments. After each command the generated script contains code to abort execution on failure. The only way to get a custom batch file is to generate it yourself.

It looks like you're trying to get per-configuration behavior. You can use file(GENERATE) to get a config-specific script generated with generator expressions like $<CONFIG>.
(0036689)
Javier Martinez   
2014-08-28 17:01   
> The add_custom_command COMMAND option expects full command lines rather than batch script fragments.
The documentation (http://www.cmake.org/cmake/help/v3.0/command/add_custom_command.html?highlight=add_custom_command [^]) doesn't make any mention of that but it does show support for multiple COMMANDs. What constitutes a 'full command line' anyways?

The notes have pretty good alternatives and thank you for providing them but I still feel the add_custom_command parser can be fixed to handle the corner cases described here. At the very least fix the documentation to list the parser limitations.
(0036702)
Brad King   
2014-09-02 15:15   
Here is a documentation update:

 Help: Clarify add_custom_command multiple command behavior
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=412926d0 [^]
(0036748)
Javier Martinez   
2014-09-08 14:06   
Sorry to reopen the issue. I was on Vacation all of last week and couldn't provide feedback until today. The change is correct but it's only clear to me after reading the thread. Perhaps you should consider adding to the documentation that to execute complete shell scripts they need to be in their own file and use a COMMAND instruction to launch them.
(0036749)
Brad King   
2014-09-08 14:16   
Help: Suggest in add_custom_command how to create a script
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1fdf4ff0 [^]
(0038114)
Robert Maynard   
2015-03-02 08:57   
Closing resolved issues that have not been updated in more than 4 months.