From f54117c6b1d24be6fde850099cdbe81f886ebe0f Mon Sep 17 00:00:00 2001 From: Tyler Yankee Date: Sun, 25 Oct 2026 19:31:05 -0400 Subject: [PATCH] Ninja: Evaluate generator expressions in CODEGEN outputs Codegen is supported for Ninja Multi-Config, so CODEGEN should support generator expressions. --- Help/command/add_custom_command.rst | 4 ++++ Source/cmGlobalNinjaGenerator.cxx | 4 +++- Tests/RunCMake/Codegen/RunCMakeTest.cmake | 10 ++++++++++ Tests/RunCMake/Codegen/per-config-build-check.cmake | 11 +++++++++++ Tests/RunCMake/Codegen/per-config.cmake | 11 +++++++++++ 5 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/Codegen/per-config-build-check.cmake create mode 100644 Tests/RunCMake/Codegen/per-config.cmake diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 75b66e999b..ec9e51e848 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -264,6 +264,10 @@ Generating Files It can only be set on the first call to ``add_custom_command(OUTPUT...)`` for the output files. + .. versionchanged:: 4.5 + Arguments to ``OUTPUT`` may use + :manual:`generator expressions `. + ``IMPLICIT_DEPENDS`` Request scanning of implicit dependencies of an input file. The language given specifies the programming language whose diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 46e5d23df8..9cc1eaae2a 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -23,6 +23,7 @@ #include "cmsys/String.h" #include "cmCustomCommand.h" +#include "cmCustomCommandGenerator.h" #include "cmCxxModuleMapper.h" #include "cmDiagnostics.h" #include "cmDyndepCollation.h" @@ -1713,7 +1714,8 @@ void cmGlobalNinjaGenerator::AppendCodegenOutputs( for (cmSourceFile const* sf : customCommandSources) { cmCustomCommand const* cc = sf->GetCustomCommand(); if (cc->GetCodegen()) { - std::vector const& outputs = cc->GetOutputs(); + cmCustomCommandGenerator ccg(*cc, config, target->GetLocalGenerator()); + std::vector const& outputs = ccg.GetOutputs(); std::transform(outputs.begin(), outputs.end(), std::back_inserter(deps), this->MapToNinjaPath()); } diff --git a/Tests/RunCMake/Codegen/RunCMakeTest.cmake b/Tests/RunCMake/Codegen/RunCMakeTest.cmake index a159f88fb1..cec1dc7610 100644 --- a/Tests/RunCMake/Codegen/RunCMakeTest.cmake +++ b/Tests/RunCMake/Codegen/RunCMakeTest.cmake @@ -28,6 +28,16 @@ run_codegen("add-custom-command-depends") run_codegen("byproducts") run_codegen("add-dependencies-not-all") +# Outputs that differ per configuration +block() + if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release") + else() + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + endif() + run_codegen("per-config") +endblock() + # Error handling run_cmake("implicit-depends") run_cmake("implicit-depends-append-codegen") diff --git a/Tests/RunCMake/Codegen/per-config-build-check.cmake b/Tests/RunCMake/Codegen/per-config-build-check.cmake new file mode 100644 index 0000000000..6989e0d1a9 --- /dev/null +++ b/Tests/RunCMake/Codegen/per-config-build-check.cmake @@ -0,0 +1,11 @@ +set(filename "${RunCMake_TEST_BINARY_DIR}/Debug/generated.h") +if (NOT EXISTS "${filename}") + set(RunCMake_TEST_FAILED "expected file NOT created:\n ${filename}") + return() +endif() + +set(filename "${RunCMake_TEST_BINARY_DIR}/Release/generated.h") +if (EXISTS "${filename}") + set(RunCMake_TEST_FAILED "unexpected file created:\n ${filename}") + return() +endif() diff --git a/Tests/RunCMake/Codegen/per-config.cmake b/Tests/RunCMake/Codegen/per-config.cmake new file mode 100644 index 0000000000..1b59731d42 --- /dev/null +++ b/Tests/RunCMake/Codegen/per-config.cmake @@ -0,0 +1,11 @@ +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$/generated.h + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/generated.h.in + ${CMAKE_CURRENT_BINARY_DIR}/$/generated.h + CODEGEN +) + +add_custom_target(h_creator ALL + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/$/generated.h +)