summaryrefslogtreecommitdiff
path: root/Source/cmLocalVisualStudio10Generator.cxx
diff options
context:
space:
mode:
authorFujii Hironori <fujii.hironori@gmail.com>2018-03-23 15:44:42 +0900
committerFujii Hironori <fujii.hironori@gmail.com>2018-04-23 13:31:28 +0900
commitf59c33a763ba1483129f0e721bc2394bb7442876 (patch)
tree3ff8c37758ffbe7faebe1e77ec9608e4d619775b /Source/cmLocalVisualStudio10Generator.cxx
parentd58d4daa6b2e36c6e2318e4d67271542dca79ee6 (diff)
downloadcmake-f59c33a763ba1483129f0e721bc2394bb7442876.tar.gz
VS: Generate a custom command only in the least dependent target
If a custom command is assigned to multiple targets, generate the build rule only in the least-dependent `.vcxproj` file. Otherwise MSBuild will run the command on the first build of a dependent target even if its dependencies already brought the command up to date (in order to populates its build log). Generate targets in least-to-most-dependent order, and assign a custom command to the least dependent target. Added cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst to call cmVisualStudio10TargetGenerator::Generate in least-dependent order. Moved SourcesVisited from cmVisualStudio10TargetGenerator to cmLocalVisualStudio10Generator to avoid attaching a custom command to multiple targets among the local generator. Fixes: #16767
Diffstat (limited to 'Source/cmLocalVisualStudio10Generator.cxx')
-rw-r--r--Source/cmLocalVisualStudio10Generator.cxx52
1 files changed, 39 insertions, 13 deletions
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index 2803d4a50e..5b6e781174 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -62,21 +62,47 @@ cmLocalVisualStudio10Generator::~cmLocalVisualStudio10Generator()
{
}
+void cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst(
+ cmGeneratorTarget* target, std::vector<cmGeneratorTarget*>& remaining)
+{
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return;
+ }
+ // Find this target in the list of remaining targets.
+ auto it = std::find(remaining.begin(), remaining.end(), target);
+ if (it == remaining.end()) {
+ // This target was already handled.
+ return;
+ }
+ // Remove this target from the list of remaining targets because
+ // we are handling it now.
+ *it = nullptr;
+ auto& deps = this->GlobalGenerator->GetTargetDirectDepends(target);
+ for (auto& d : deps) {
+ // FIXME: Revise CreateSingleVCProj so we do not have to drop `const` here.
+ auto dependee = const_cast<cmGeneratorTarget*>(&*d);
+ GenerateTargetsDepthFirst(dependee, remaining);
+ // Take the union of visited source files of custom commands
+ auto visited = GetSourcesVisited(dependee);
+ GetSourcesVisited(target).insert(visited.begin(), visited.end());
+ }
+ if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
+ ->TargetIsFortranOnly(target)) {
+ this->CreateSingleVCProj(target->GetName(), target);
+ } else {
+ cmVisualStudio10TargetGenerator tg(
+ target, static_cast<cmGlobalVisualStudio10Generator*>(
+ this->GetGlobalGenerator()));
+ tg.Generate();
+ }
+}
+
void cmLocalVisualStudio10Generator::Generate()
{
- const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets();
- for (cmGeneratorTarget* l : tgts) {
- if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- continue;
- }
- if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetIsFortranOnly(l)) {
- this->CreateSingleVCProj(l->GetName(), l);
- } else {
- cmVisualStudio10TargetGenerator tg(
- l, static_cast<cmGlobalVisualStudio10Generator*>(
- this->GetGlobalGenerator()));
- tg.Generate();
+ std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets();
+ for (auto& t : remaining) {
+ if (t) {
+ GenerateTargetsDepthFirst(t, remaining);
}
}
this->WriteStampFiles();