mirror of
https://github.com/Kitware/CMake.git
synced 2026-11-06 05:16:58 +00:00
Makefile, Ninja: Fix no-op codegen builds with no CODEGEN
Ninja: Since commit2d85779126(Ninja: Account for explicit target dependencies via CODEGEN, 2026-09-15, v4.5.0-rc1~162^2), a directory's codegen phony depends on the full build of every add_dependencies target (which caused their non-CODEGEN commands to run). Instead, depend only on those targets' CODEGEN outputs, and follow their own codegen dependencies in turn. Makefiles: Since commit197cb419d1(add_custom_command: Add CODEGEN support, 2024-05-27, v3.31.0-rc1~394^2), a target's `<target>/codegen` rule used to depend on `<dep>/all` for every add_dependencies target, which fully built them. Instead, depend on `<dep>/codegen`, except when the target has CODEGEN commands of its own, in which case it should still depend on `<dep>/all` as the commands may need the dependency's outputs. Shape up the prior `no-codegen` test case, which wasn't verifying much of anything. Fixes: #28205
This commit is contained in:
1 parent
17de9500e8
commit
902ec85438
9 files changed
+79
-24
No files matched your search
@@ -254,7 +254,11 @@ Generating Files
|
||||
is set to ``NEW``.
|
||||
|
||||
Like ``all``, the ``codegen`` target exists per directory and skips
|
||||
targets and directories marked ``EXCLUDE_FROM_ALL``.
|
||||
targets and directories marked ``EXCLUDE_FROM_ALL``. It follows
|
||||
:command:`add_dependencies`: the dependencies' ``CODEGEN`` commands are
|
||||
also run, but their other commands are not, unless the depending target
|
||||
has ``CODEGEN`` commands of its own, in which case the dependencies are
|
||||
built in full first.
|
||||
|
||||
This keyword cannot be used with ``APPEND`` (see policy :policy:`CMP0175`).
|
||||
It can only be set on the first call to ``add_custom_command(OUTPUT...)``
|
||||
|
||||
@@ -1704,17 +1704,34 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
|
||||
outputs.insert(outs.begin(), outs.end());
|
||||
}
|
||||
|
||||
void cmGlobalNinjaGenerator::AppendCodegenOutputs(
|
||||
cmGeneratorTarget const* target, cmNinjaDeps& deps,
|
||||
std::string const& config)
|
||||
{
|
||||
std::vector<cmSourceFile const*> customCommandSources;
|
||||
target->GetCustomCommands(customCommandSources, config);
|
||||
for (cmSourceFile const* sf : customCommandSources) {
|
||||
cmCustomCommand const* cc = sf->GetCustomCommand();
|
||||
if (cc->GetCodegen()) {
|
||||
std::vector<std::string> const& outputs = cc->GetOutputs();
|
||||
std::transform(outputs.begin(), outputs.end(), std::back_inserter(deps),
|
||||
this->MapToNinjaPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalNinjaGenerator::AppendCodegenTargetDepends(
|
||||
cmGeneratorTarget const* target, cmNinjaDeps& deps,
|
||||
std::string const& config) const
|
||||
std::string const& config, std::set<cmGeneratorTarget const*>& visited)
|
||||
{
|
||||
std::set<std::string> const& codegenDeps = target->Target->GetCodegenDeps();
|
||||
for (cmTargetDepend const& targetDep :
|
||||
this->GetTargetDirectDepends(target)) {
|
||||
if (targetDep->IsInBuildSystem() &&
|
||||
codegenDeps.count(targetDep->GetName())) {
|
||||
this->AppendTargetOutputs(targetDep, deps, config,
|
||||
DependOnTargetArtifact);
|
||||
codegenDeps.count(targetDep->GetName()) &&
|
||||
visited.insert(targetDep).second) {
|
||||
this->AppendCodegenOutputs(targetDep, deps, config);
|
||||
this->AppendCodegenTargetDepends(targetDep, deps, config, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1884,25 +1901,18 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
|
||||
build.Outputs.front() =
|
||||
this->BuildAlias(buildDirCodegenTarget, config);
|
||||
|
||||
std::set<cmGeneratorTarget const*> visited;
|
||||
|
||||
for (DirectoryTarget::Target const& t : dt.Targets) {
|
||||
if (this->IsExcludedFromAllInConfig(t, config)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this->AppendCodegenTargetDepends(t.GT, build.ExplicitDeps, config);
|
||||
|
||||
std::vector<cmSourceFile const*> customCommandSources;
|
||||
t.GT->GetCustomCommands(customCommandSources, config);
|
||||
for (cmSourceFile const* sf : customCommandSources) {
|
||||
cmCustomCommand const* cc = sf->GetCustomCommand();
|
||||
if (cc->GetCodegen()) {
|
||||
auto const& outputs = cc->GetOutputs();
|
||||
|
||||
std::transform(outputs.begin(), outputs.end(),
|
||||
std::back_inserter(build.ExplicitDeps),
|
||||
this->MapToNinjaPath());
|
||||
}
|
||||
if (visited.insert(t.GT).second) {
|
||||
this->AppendCodegenOutputs(t.GT, build.ExplicitDeps, config);
|
||||
}
|
||||
this->AppendCodegenTargetDepends(t.GT, build.ExplicitDeps, config,
|
||||
visited);
|
||||
}
|
||||
|
||||
for (DirectoryTarget::Dir const& d : dt.Children) {
|
||||
|
||||
@@ -526,9 +526,11 @@ private:
|
||||
void CloseRulesFileStream();
|
||||
void CleanMetaData();
|
||||
|
||||
void AppendCodegenOutputs(cmGeneratorTarget const* target, cmNinjaDeps& deps,
|
||||
std::string const& config);
|
||||
void AppendCodegenTargetDepends(cmGeneratorTarget const* target,
|
||||
cmNinjaDeps& deps,
|
||||
std::string const& config) const;
|
||||
cmNinjaDeps& deps, std::string const& config,
|
||||
std::set<cmGeneratorTarget const*>& visited);
|
||||
|
||||
/// Write the common disclaimer text at the top of each build file.
|
||||
void WriteDisclaimer(std::ostream& os) const;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include "cmCustomCommand.h"
|
||||
#include "cmDuration.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
@@ -23,6 +24,7 @@
|
||||
#include "cmMakefileTargetGenerator.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmOutputConverter.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmState.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
@@ -1000,6 +1002,19 @@ void cmGlobalUnixMakefileGenerator3::AppendCodegenTargetDepends(
|
||||
std::set<std::string> const& codegen_depends =
|
||||
target->Target->GetCodegenDeps();
|
||||
|
||||
bool hasCodegenCommands = false;
|
||||
{
|
||||
std::vector<cmSourceFile const*> customCommands;
|
||||
cmLocalUnixMakefileGenerator3* lg3 =
|
||||
static_cast<cmLocalUnixMakefileGenerator3*>(target->GetLocalGenerator());
|
||||
target->GetCustomCommands(customCommands, lg3->GetConfigName());
|
||||
hasCodegenCommands =
|
||||
std::any_of(customCommands.begin(), customCommands.end(),
|
||||
[](cmSourceFile const* sf) {
|
||||
return sf->GetCustomCommand()->GetCodegen();
|
||||
});
|
||||
}
|
||||
|
||||
for (cmTargetDepend const& i : this->GetTargetDirectDepends(target)) {
|
||||
// Create the target-level dependency.
|
||||
cmGeneratorTarget const* dep = i;
|
||||
@@ -1009,10 +1024,12 @@ void cmGlobalUnixMakefileGenerator3::AppendCodegenTargetDepends(
|
||||
if (codegen_depends.find(dep->GetName()) != codegen_depends.end()) {
|
||||
cmLocalUnixMakefileGenerator3* lg3 =
|
||||
static_cast<cmLocalUnixMakefileGenerator3*>(dep->GetLocalGenerator());
|
||||
std::string tgtName = cmStrCat(
|
||||
lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep)),
|
||||
"/all");
|
||||
depends.push_back(tgtName);
|
||||
std::string const tgtDir =
|
||||
lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep));
|
||||
depends.push_back(cmStrCat(tgtDir, "/codegen"));
|
||||
if (hasCodegenCommands) {
|
||||
depends.push_back(cmStrCat(tgtDir, "/all"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ endfunction()
|
||||
|
||||
# Builds codegen target when there are no custom commands marked codegen
|
||||
run_codegen("no-codegen")
|
||||
run_codegen("no-codegen-2")
|
||||
|
||||
# We don't want codegen to drive parts of the project that are EXCLUDE_FROM_ALL
|
||||
run_codegen("exclude-from-all")
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Verify generated.h was NOT created
|
||||
set(unexpected "${RunCMake_TEST_BINARY_DIR}/generated.h")
|
||||
if(EXISTS "${unexpected}")
|
||||
set(RunCMake_TEST_FAILED "unexpected file created:\n ${unexpected}")
|
||||
endif()
|
||||
@@ -0,0 +1,14 @@
|
||||
add_executable(main
|
||||
main.c
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT generated.h
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/generated.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/generated.h
|
||||
# no CODEGEN
|
||||
)
|
||||
|
||||
add_custom_target(h_creator DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/generated.h)
|
||||
|
||||
add_dependencies(main h_creator)
|
||||
File renamed without changes.
@@ -4,3 +4,5 @@ add_custom_command(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/generated.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/generated.hpp
|
||||
)
|
||||
|
||||
add_custom_target(hpp_creator ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/generated.hpp)
|
||||
Reference in new issue
Block a user