Browse Source

Ninja Multi-Config: Fix crash on custom command config with no output

With generator expressions in a custom command's `OUTPUT` and
`BYPRODUCTS`, it is possible to have no outputs at all for a particular
configuration.  Generate no rule in this case.

Fixes: #21989
Brad King 4 years ago
parent
commit
6dd89529e8

+ 5 - 0
Source/cmLocalNinjaGenerator.cxx

@@ -582,6 +582,11 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
 
   auto ccgs = this->MakeCustomCommandGenerators(*cc, fileConfig);
   for (cmCustomCommandGenerator const& ccg : ccgs) {
+    if (ccg.GetOutputs().empty() && ccg.GetByproducts().empty()) {
+      // Generator expressions evaluate to no output for this config.
+      continue;
+    }
+
     cmNinjaDeps orderOnlyDeps;
 
     // A custom command may appear on multiple targets.  However, some build

+ 4 - 0
Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-debug-in-release-graph-ninja-stdout.txt

@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Release[\/]echo(\.exe)?
+\[3/3\] Generating echo_dbg_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Debug' 'echo_dbg_Debug\.txt'$

+ 4 - 0
Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-debug-ninja-stdout.txt

@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating echo_dbg_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_dbg_Debug\.txt'$

+ 2 - 0
Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbg-release-ninja-stdout.txt

@@ -0,0 +1,2 @@
+^\[1/2\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/2\] Linking C executable Release[\/]echo(\.exe)?$

+ 4 - 0
Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-debug-in-release-graph-ninja-stdout.txt

@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Release[\/]echo(\.exe)?
+\[3/3\] Generating echo_dbgx_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Debug' 'echo_dbgx_Debug\.txt' 'echo_dbgx_byproduct_Debug\.txt'$

+ 4 - 0
Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-debug-ninja-stdout.txt

@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating echo_dbgx_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_dbgx_Debug\.txt' 'echo_dbgx_byproduct_Debug\.txt'$

+ 5 - 0
Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_dbgx-release-ninja-stdout.txt

@@ -0,0 +1,5 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Release[\/]echo(\.exe)?
+\[3/3\] [^
+]*
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Release' 'echo_dbgx_byproduct_Release\.txt'$

+ 24 - 0
Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake

@@ -119,6 +119,30 @@ foreach(case
   add_custom_target(${case} DEPENDS ${case}_$<CONFIG>.txt)
 endforeach()
 
+# An OUTPUT in only one configuration.
+add_custom_command(
+  OUTPUT "$<$<CONFIG:Debug>:echo_dbg_Debug.txt>"
+  COMMAND echo $<CONFIG> "$<$<CONFIG:Debug>:echo_dbg_Debug.txt>"
+  )
+set_property(SOURCE ${CMAKE_CURRENT_BINARY_DIR}/echo_dbg_Debug.txt PROPERTY SYMBOLIC 1)
+add_custom_target(echo_dbg DEPENDS "$<$<CONFIG:Debug>:echo_dbg_Debug.txt>")
+
+# An OUTPUT in only one configuration with BYPRODUCTS in every configuration.
+add_custom_command(
+  OUTPUT "$<$<CONFIG:Debug>:echo_dbgx_Debug.txt>"
+  BYPRODUCTS echo_dbgx_byproduct_$<CONFIG>.txt
+  COMMAND echo $<CONFIG> "$<$<CONFIG:Debug>:echo_dbgx_Debug.txt>" echo_dbgx_byproduct_$<CONFIG>.txt
+  COMMAND_EXPAND_LISTS
+  )
+  set_property(SOURCE
+    ${CMAKE_CURRENT_BINARY_DIR}/echo_dbgx_Debug.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/echo_dbgx_byproduct_Debug.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/echo_dbgx_byproduct_Release.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/echo_dbgx_byproduct_MinSizeRel.txt
+    ${CMAKE_CURRENT_BINARY_DIR}/echo_dbgx_byproduct_RelWithDebInfo.txt
+    PROPERTY SYMBOLIC 1)
+add_custom_target(echo_dbgx DEPENDS "$<$<CONFIG:Debug>:echo_dbgx_Debug.txt>")
+
 add_custom_target(echo_target_raw
   BYPRODUCTS echo_target_raw_$<CONFIG>.txt
   COMMENT echo_target_raw

+ 14 - 0
Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake

@@ -323,6 +323,20 @@ run_ninja(CustomCommandOutputGenex echo_no_cross_byproduct_if-debug build-Debug.
 run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
 run_ninja(CustomCommandOutputGenex echo_no_cross_byproduct_if-debug-in-release-graph build-Release.ninja echo_no_cross_byproduct_if:Debug)
 run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# echo_dbg
+run_ninja(CustomCommandOutputGenex echo_dbg-debug build-Debug.ninja echo_dbg)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_dbg-release build-Release.ninja echo_dbg)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_dbg-debug-in-release-graph build-Release.ninja echo_dbg:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# echo_dbgx
+run_ninja(CustomCommandOutputGenex echo_dbgx-debug build-Debug.ninja echo_dbgx)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_dbgx-release build-Release.ninja echo_dbgx)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_dbgx-debug-in-release-graph build-Release.ninja echo_dbgx:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
 # echo_target_raw
 run_ninja(CustomCommandOutputGenex echo_target_raw-debug build-Debug.ninja echo_target_raw:Debug)
 run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)