Merge topic 'ninja-target-deps'
1296a0ea
Ninja: Fix inter-target order-only dependencies of custom commands
This commit is contained in:
commit
e297e0455e
|
@ -493,6 +493,8 @@ void cmGlobalNinjaGenerator::Generate()
|
|||
this->OpenBuildFileStream();
|
||||
this->OpenRulesFileStream();
|
||||
|
||||
this->TargetDependsClosures.clear();
|
||||
|
||||
this->InitOutputPathPrefix();
|
||||
this->TargetAll = this->NinjaOutputPath("all");
|
||||
this->CMakeCacheFile = this->NinjaOutputPath("CMakeCache.txt");
|
||||
|
@ -905,6 +907,42 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
|
|||
}
|
||||
}
|
||||
|
||||
void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
|
||||
cmGeneratorTarget const* target, cmNinjaDeps& outputs)
|
||||
{
|
||||
TargetDependsClosureMap::iterator i =
|
||||
this->TargetDependsClosures.find(target);
|
||||
if (i == this->TargetDependsClosures.end()) {
|
||||
TargetDependsClosureMap::value_type e(
|
||||
target, std::set<cmGeneratorTarget const*>());
|
||||
i = this->TargetDependsClosures.insert(e).first;
|
||||
this->ComputeTargetDependsClosure(target, i->second);
|
||||
}
|
||||
std::set<cmGeneratorTarget const*> const& targets = i->second;
|
||||
cmNinjaDeps outs;
|
||||
for (std::set<cmGeneratorTarget const*>::const_iterator ti = targets.begin();
|
||||
ti != targets.end(); ++ti) {
|
||||
this->AppendTargetOutputs(*ti, outs);
|
||||
}
|
||||
std::sort(outs.begin(), outs.end());
|
||||
outputs.insert(outputs.end(), outs.begin(), outs.end());
|
||||
}
|
||||
|
||||
void cmGlobalNinjaGenerator::ComputeTargetDependsClosure(
|
||||
cmGeneratorTarget const* target, std::set<cmGeneratorTarget const*>& depends)
|
||||
{
|
||||
cmTargetDependSet const& targetDeps = this->GetTargetDirectDepends(target);
|
||||
for (cmTargetDependSet::const_iterator i = targetDeps.begin();
|
||||
i != targetDeps.end(); ++i) {
|
||||
if ((*i)->GetType() == cmState::INTERFACE_LIBRARY) {
|
||||
continue;
|
||||
}
|
||||
if (depends.insert(*i).second) {
|
||||
this->ComputeTargetDependsClosure(*i, depends);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
|
||||
cmGeneratorTarget* target)
|
||||
{
|
||||
|
|
|
@ -301,6 +301,8 @@ public:
|
|||
cmNinjaDeps& outputs);
|
||||
void AppendTargetDepends(cmGeneratorTarget const* target,
|
||||
cmNinjaDeps& outputs);
|
||||
void AppendTargetDependsClosure(cmGeneratorTarget const* target,
|
||||
cmNinjaDeps& outputs);
|
||||
void AddDependencyToAll(cmGeneratorTarget* target);
|
||||
void AddDependencyToAll(const std::string& input);
|
||||
|
||||
|
@ -361,6 +363,10 @@ private:
|
|||
void WriteTargetClean(std::ostream& os);
|
||||
void WriteTargetHelp(std::ostream& os);
|
||||
|
||||
void ComputeTargetDependsClosure(
|
||||
cmGeneratorTarget const* target,
|
||||
std::set<cmGeneratorTarget const*>& depends);
|
||||
|
||||
std::string ninjaCmd() const;
|
||||
|
||||
/// The file containing the build statement. (the relationship of the
|
||||
|
@ -410,6 +416,11 @@ private:
|
|||
typedef std::map<std::string, cmGeneratorTarget*> TargetAliasMap;
|
||||
TargetAliasMap TargetAliases;
|
||||
|
||||
typedef std::map<cmGeneratorTarget const*,
|
||||
std::set<cmGeneratorTarget const*> >
|
||||
TargetDependsClosureMap;
|
||||
TargetDependsClosureMap TargetDependsClosures;
|
||||
|
||||
std::string NinjaCommand;
|
||||
std::string NinjaVersion;
|
||||
|
||||
|
|
|
@ -450,13 +450,14 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
|
|||
std::set<cmGeneratorTarget*>::iterator j = i->second.begin();
|
||||
assert(j != i->second.end());
|
||||
std::vector<std::string> ccTargetDeps;
|
||||
this->AppendTargetDepends(*j, ccTargetDeps);
|
||||
this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j,
|
||||
ccTargetDeps);
|
||||
std::sort(ccTargetDeps.begin(), ccTargetDeps.end());
|
||||
++j;
|
||||
|
||||
for (; j != i->second.end(); ++j) {
|
||||
std::vector<std::string> jDeps, depsIntersection;
|
||||
this->AppendTargetDepends(*j, jDeps);
|
||||
this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps);
|
||||
std::sort(jDeps.begin(), jDeps.end());
|
||||
std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(),
|
||||
jDeps.begin(), jDeps.end(),
|
||||
|
|
|
@ -4,3 +4,17 @@ run_cmake(NoArguments)
|
|||
run_cmake(BadTargetName)
|
||||
run_cmake(ByproductsNoCommand)
|
||||
run_cmake(UsesTerminalNoCommand)
|
||||
|
||||
function(run_TargetOrder)
|
||||
# Use a single build tree for a few tests without cleaning.
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TargetOrder-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
run_cmake(TargetOrder)
|
||||
if(RunCMake_GENERATOR STREQUAL "Ninja")
|
||||
set(build_flags -j 1 -v)
|
||||
endif()
|
||||
run_cmake_command(TargetOrder-build ${CMAKE_COMMAND} --build . -- ${build_flags})
|
||||
endfunction()
|
||||
run_TargetOrder()
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# Add a target that requires step1 to run first but enforces
|
||||
# it only by target-level ordering dependency.
|
||||
add_custom_command(
|
||||
OUTPUT step2.txt
|
||||
COMMAND ${CMAKE_COMMAND} -E copy step1.txt step2.txt
|
||||
)
|
||||
add_custom_target(step2 DEPENDS step2.txt)
|
||||
add_dependencies(step2 step1)
|
||||
|
||||
# Add a target that requires step1 and step2 to work,
|
||||
# only depends on step1 transitively through step2, but
|
||||
# also gets a copy of step2's custom command.
|
||||
# The Ninja generator in particular must be careful with
|
||||
# this case because it needs to compute the proper set of
|
||||
# target ordering dependencies for the step2 custom command
|
||||
# even though it appears in both the step2 and step3
|
||||
# targets due to dependency propagation.
|
||||
add_custom_command(
|
||||
OUTPUT step3.txt
|
||||
COMMAND ${CMAKE_COMMAND} -E copy step1.txt step3-1.txt
|
||||
COMMAND ${CMAKE_COMMAND} -E copy step2.txt step3.txt
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/step2.txt
|
||||
)
|
||||
add_custom_target(step3 ALL DEPENDS step3.txt)
|
||||
add_dependencies(step3 step2)
|
||||
|
||||
# We want this target to always run first. Add it last so
|
||||
# that serial builds require dependencies to order it first.
|
||||
add_custom_target(step1
|
||||
COMMAND ${CMAKE_COMMAND} -E touch step1.txt
|
||||
)
|
Loading…
Reference in New Issue