Преглед изворни кода

Merge topic 'vs-dedup-custom-commands'

f59c33a763 VS: Generate a custom command only in the least dependent target
d58d4daa6b cmVisualStudio10TargetGenerator: Use cmLocalVisualStudio10Generator

Acked-by: Kitware Robot <[email protected]>
Merge-request: !1889
Brad King пре 7 година
родитељ
комит
5a6c629289

+ 39 - 13
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();

+ 9 - 0
Source/cmLocalVisualStudio10Generator.h

@@ -33,10 +33,19 @@ public:
   void ReadAndStoreExternalGUID(const std::string& name,
                                 const char* path) override;
 
+  std::set<cmSourceFile const*>& GetSourcesVisited(cmGeneratorTarget* target)
+  {
+    return SourcesVisited[target];
+  };
+
 protected:
   const char* ReportErrorLabel() const override;
   bool CustomCommandUseLocal() const override { return true; }
 
 private:
+  void GenerateTargetsDepthFirst(cmGeneratorTarget* target,
+                                 std::vector<cmGeneratorTarget*>& remaining);
+
+  std::map<cmGeneratorTarget*, std::set<cmSourceFile const*>> SourcesVisited;
 };
 #endif

+ 6 - 4
Source/cmVisualStudio10TargetGenerator.cxx

@@ -8,7 +8,7 @@
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalVisualStudio10Generator.h"
-#include "cmLocalVisualStudio7Generator.h"
+#include "cmLocalVisualStudio10Generator.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
 #include "cmSystemTools.h"
@@ -204,7 +204,8 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
   , Name(target->GetName())
   , GUID(gg->GetGUID(this->Name))
   , GlobalGenerator(gg)
-  , LocalGenerator((cmLocalVisualStudio7Generator*)target->GetLocalGenerator())
+  , LocalGenerator(
+      (cmLocalVisualStudio10Generator*)target->GetLocalGenerator())
 {
   this->Makefile->GetConfigurations(this->Configurations);
   this->NsightTegra = gg->IsNsightTegra();
@@ -1177,7 +1178,6 @@ void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
 
 void cmVisualStudio10TargetGenerator::WriteCustomCommands()
 {
-  this->SourcesVisited.clear();
   this->CSharpCustomCommandNames.clear();
   std::vector<cmSourceFile const*> customCommands;
   this->GeneratorTarget->GetCustomCommands(customCommands, "");
@@ -1198,7 +1198,9 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommands()
 void cmVisualStudio10TargetGenerator::WriteCustomCommand(
   cmSourceFile const* sf)
 {
-  if (this->SourcesVisited.insert(sf).second) {
+  if (this->LocalGenerator->GetSourcesVisited(this->GeneratorTarget)
+        .insert(sf)
+        .second) {
     if (std::vector<cmSourceFile*> const* depends =
           this->GeneratorTarget->GetSourceDepends(sf)) {
       for (cmSourceFile const* di : *depends) {

+ 2 - 3
Source/cmVisualStudio10TargetGenerator.h

@@ -17,7 +17,7 @@ class cmCustomCommand;
 class cmGeneratedFileStream;
 class cmGeneratorTarget;
 class cmGlobalVisualStudio10Generator;
-class cmLocalVisualStudio7Generator;
+class cmLocalVisualStudio10Generator;
 class cmMakefile;
 class cmSourceFile;
 class cmSourceGroup;
@@ -208,8 +208,7 @@ private:
   bool TargetCompileAsWinRT;
   cmGlobalVisualStudio10Generator* const GlobalGenerator;
   cmGeneratedFileStream* BuildFileStream;
-  cmLocalVisualStudio7Generator* const LocalGenerator;
-  std::set<cmSourceFile const*> SourcesVisited;
+  cmLocalVisualStudio10Generator* const LocalGenerator;
   std::set<std::string> CSharpCustomCommandNames;
   bool IsMissingFiles;
   std::vector<std::string> AddedFiles;

+ 13 - 0
Tests/RunCMake/add_custom_command/AssigningMultipleTargets.cmake

@@ -0,0 +1,13 @@
+enable_language(CXX)
+
+add_custom_command(OUTPUT generated.cpp
+  MAIN_DEPENDENCY a.c
+  COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/generate-once.cmake ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp
+  VERBATIM)
+
+add_executable(exe1 ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp)
+add_executable(exe2 ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp)
+add_executable(exe3 ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp)
+
+add_dependencies(exe1 exe2)
+add_dependencies(exe3 exe1)

+ 7 - 0
Tests/RunCMake/add_custom_command/RunCMakeTest.cmake

@@ -14,3 +14,10 @@ run_cmake(TargetNotInDir)
 if(${RunCMake_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
   run_cmake(RemoveEmptyCommands)
 endif()
+
+run_cmake(AssigningMultipleTargets)
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AssigningMultipleTargets-build)
+set(RunCMake_TEST_NO_CLEAN 1)
+run_cmake_command(AssigningMultipleTargets-build ${CMAKE_COMMAND} --build .)
+unset(RunCMake_TEST_BINARY_DIR)
+unset(RunCMake_TEST_NO_CLEAN)

+ 3 - 0
Tests/RunCMake/add_custom_command/a.c

@@ -0,0 +1,3 @@
+void a()
+{
+}

+ 8 - 0
Tests/RunCMake/add_custom_command/generate-once.cmake

@@ -0,0 +1,8 @@
+if (${CMAKE_ARGC} LESS 4)
+  message(FATAL_ERROR "Too few arguments")
+endif()
+set(output "${CMAKE_ARGV3}")
+if(EXISTS ${output})
+  message(FATAL_ERROR "${output} already exists")
+endif()
+file(WRITE ${output} "int main() { return 0; }\n")