Browse Source

ENH: Makefile performance improvements

Ken Martin 19 năm trước cách đây
mục cha
commit
3023eb7ccb

+ 1 - 1
Modules/CMakeDetermineCCompiler.cmake

@@ -91,7 +91,7 @@ ENDIF(NOT CMAKE_COMPILER_IS_GNUCC_RUN)
 
 # configure variables set in this file for fast reload later on
 CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeCCompiler.cmake.in 
-               ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCCompiler.cmake IMMEDIATE)
+               "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCCompiler.cmake" IMMEDIATE)
 MARK_AS_ADVANCED(CMAKE_AR)
 
 SET(CMAKE_C_COMPILER_ENV_VAR "CC")

+ 6 - 6
Modules/Platform/Windows-cl.cmake

@@ -1,7 +1,7 @@
 # try to load any previously computed information for C on this platform
-INCLUDE( ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCPlatform.cmake OPTIONAL)
+INCLUDE( ${CMAKE_PLATFORM_ROOT_BIN}/CMakeCPlatform.cmake OPTIONAL)
 # try to load any previously computed information for CXX on this platform
-INCLUDE( ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCXXPlatform.cmake OPTIONAL)
+INCLUDE( ${CMAKE_PLATFORM_ROOT_BIN}/CMakeCXXPlatform.cmake OPTIONAL)
 
 SET(CMAKE_LIBRARY_PATH_FLAG "-LIBPATH:")
 SET(CMAKE_LINK_LIBRARY_FLAG "")
@@ -273,14 +273,14 @@ SET (CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO_INIT ${CMAKE_EXE_LINKER_FLAGS_RELW
 
 
 # save computed information for this platform
-IF(NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCPlatform.cmake")
+IF(NOT EXISTS "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCPlatform.cmake")
   CONFIGURE_FILE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake.in 
     ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCPlatform.cmake IMMEDIATE)
-ENDIF(NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCPlatform.cmake")
+ENDIF(NOT EXISTS "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCPlatform.cmake")
 
-IF(NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCXXPlatform.cmake")
+IF(NOT EXISTS "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCXXPlatform.cmake")
   CONFIGURE_FILE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake.in 
                ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCXXPlatform.cmake IMMEDIATE)
-ENDIF(NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCXXPlatform.cmake")
+ENDIF(NOT EXISTS "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCXXPlatform.cmake")
 
 INCLUDE(Platform/WindowsPaths)

+ 4 - 25
Source/cmGlobalGenerator.cxx

@@ -169,42 +169,21 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
   // files from the parent cmake bin dir, into the try compile bin dir
   if(this->ConfiguredFilesPath.size())
     {
-    std::string src = this->ConfiguredFilesPath;
-    src += "/CMakeSystem.cmake";
-    std::string dst = rootBin;
-    dst += "/CMakeSystem.cmake";
-    cmSystemTools::CopyFileIfDifferent(src.c_str(), dst.c_str());
     for(std::vector<std::string>::const_iterator l = languages.begin();
         l != languages.end(); ++l)
       {
       if(*l == "NONE")
         {
         this->SetLanguageEnabled("NONE", mf);
-        continue;
+        break;
         }
-      const char* lang = l->c_str();
-      std::string src2 = this->ConfiguredFilesPath;
-      src2 += "/CMake";
-      src2 += lang;
-      src2 += "Compiler.cmake";
-      std::string dst2 = rootBin;
-      dst2 += "/CMake";
-      dst2 += lang;
-      dst2 += "Compiler.cmake";
-      cmSystemTools::CopyFileIfDifferent(src2.c_str(), dst2.c_str()); 
-      src2 = this->ConfiguredFilesPath;
-      src2 += "/CMake";
-      src2 += lang;
-      src2 += "Platform.cmake";
-      dst2 = rootBin;
-      dst2 += "/CMake";
-      dst2 += lang;
-      dst2 += "Platform.cmake";
-      cmSystemTools::CopyFileIfDifferent(src2.c_str(), dst2.c_str());
       }
     rootBin = this->ConfiguredFilesPath;
     }
 
+  // set the dir for parent files so they can be used by modules
+  mf->AddDefinition("CMAKE_PLATFORM_ROOT_BIN",rootBin.c_str());  
+                    
   // find and make sure CMAKE_MAKE_PROGRAM is defined
   this->FindMakeProgram(mf);
 

+ 181 - 91
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -501,6 +501,66 @@ cmGlobalUnixMakefileGenerator3
   this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", false, true);
 }
 
+
+std::string cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(const char* makeProgram,
+  const char *projectName, const char* additionalOptions, const char *targetName,
+  const char* config, bool ignoreErrors)
+{
+  // Project name and config are not used yet.
+  (void)projectName;
+  (void)config;
+
+  std::string makeCommand = cmSystemTools::ConvertToUnixOutputPath(makeProgram);
+
+  // Since we have full control over the invocation of nmake, let us
+  // make it quiet.
+  if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
+    {
+    makeCommand += " /NOLOGO ";
+    }
+  if ( ignoreErrors )
+    {
+    makeCommand += " -i";
+    }
+  if ( additionalOptions )
+    {
+    makeCommand += " ";
+    makeCommand += additionalOptions;
+    }
+  if ( targetName && strlen(targetName))
+    {
+    cmLocalUnixMakefileGenerator3 *lg;
+    if (this->LocalGenerators.size())
+      {
+      lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
+      }
+    else
+      {
+      lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->CreateLocalGenerator());
+      // set the Start directories
+      lg->GetMakefile()->SetStartDirectory
+        (this->CMakeInstance->GetStartDirectory());
+      lg->GetMakefile()->SetStartOutputDirectory
+        (this->CMakeInstance->GetStartOutputDirectory());
+      lg->GetMakefile()->MakeStartDirectoriesCurrent();
+      }
+    
+    makeCommand += "\"";
+    std::string tname = targetName;
+    tname += "/fast";
+    tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
+                        cmLocalGenerator::SHELL);
+    tname = lg->ConvertToMakeTarget(tname.c_str());
+    makeCommand += tname.c_str();
+    makeCommand += "\"";
+    if (!this->LocalGenerators.size())
+      {
+      delete lg;
+      }
+    }
+  return makeCommand;
+}
+
 //----------------------------------------------------------------------------
 void
 cmGlobalUnixMakefileGenerator3
@@ -550,8 +610,35 @@ cmGlobalUnixMakefileGenerator3
                             "Build rule for target.",
                             t->second.GetName(), depends, commands,
                             true);
+          
+          // Add a fast rule to build the target
+          std::string localName = lg->GetRelativeTargetDirectory(t->second);
+          std::string makefileName;
+          makefileName = localName;
+          makefileName += "/build.make";          
+          depends.clear();
+          commands.clear();
+          std::string makeTargetName = localName;
+          makeTargetName += "/build";
+          localName = t->second.GetName();
+          localName += "/fast";
+          commands.push_back(lg->GetRecursiveMakeCall
+                             (makefileName.c_str(), makeTargetName.c_str()));
+          lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
+                            localName.c_str(), depends, commands, true);
           }
         }
+      else
+        {
+        // Add a fast rule to build the target
+        depends.clear();
+        commands.clear();
+        std::string localName = t->second.GetName();
+        depends.push_back(localName);
+        localName += "/fast";
+        lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
+                          localName.c_str(), depends, commands, true);        
+        }
       }
     }
 }
@@ -578,117 +665,120 @@ cmGlobalUnixMakefileGenerator3
   cmTargets& targets = lg->GetMakefile()->GetTargets();
   for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
     {
-    if (((t->second.GetType() == cmTarget::EXECUTABLE) ||
-         (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
-         (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
-         (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
-         (t->second.GetType() == cmTarget::UTILITY)) &&
-        t->second.GetName() &&
-        strlen(t->second.GetName()))  
+    if (t->second.GetName() && strlen(t->second.GetName()))
       {
-      bool needRequiresStep = 
-        this->NeedRequiresStep(lg,t->second.GetName());
+      std::string makefileName;
       // Add a rule to build the target by name.
       localName = lg->GetRelativeTargetDirectory(t->second);
-      std::string makefileName = localName;
+      makefileName = localName;
       makefileName += "/build.make";
       
-      lg->WriteDivider(ruleFileStream);
-      ruleFileStream
-        << "# Target rules for target "
-        << localName << "\n\n";
-      
-      commands.clear();
-      if (t->second.GetType() != cmTarget::UTILITY)
+      if (((t->second.GetType() == cmTarget::EXECUTABLE) ||
+           (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
+           (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
+           (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
+           (t->second.GetType() == cmTarget::UTILITY)))  
         {
-        makeTargetName = localName;
-        makeTargetName += "/depend";
-        commands.push_back(lg->GetRecursiveMakeCall
-                           (makefileName.c_str(),makeTargetName.c_str()));
+        bool needRequiresStep = 
+          this->NeedRequiresStep(lg,t->second.GetName());
         
-        // add requires if we need it for this generator
-        if (needRequiresStep)
+        lg->WriteDivider(ruleFileStream);
+        ruleFileStream
+          << "# Target rules for target "
+          << localName << "\n\n";
+      
+        commands.clear();
+        if (t->second.GetType() != cmTarget::UTILITY)
           {
           makeTargetName = localName;
-          makeTargetName += "/requires";
+          makeTargetName += "/depend";
           commands.push_back(lg->GetRecursiveMakeCall
                              (makefileName.c_str(),makeTargetName.c_str()));
+          
+          // add requires if we need it for this generator
+          if (needRequiresStep)
+            {
+            makeTargetName = localName;
+            makeTargetName += "/requires";
+            commands.push_back(lg->GetRecursiveMakeCall
+                               (makefileName.c_str(),makeTargetName.c_str()));
+            }
           }
-        }
-      makeTargetName = localName;
-      makeTargetName += "/build";
-      commands.push_back(lg->GetRecursiveMakeCall
-                         (makefileName.c_str(),makeTargetName.c_str()));
-
-      // Write the rule.
-      localName += "/all";
-      depends.clear();
-      this->AppendGlobalTargetDepends(depends,t->second);
-      lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
-                        localName.c_str(), depends, commands, true);
-
-      // add the all/all dependency
-      if (!exclude && t->second.IsInAll())
-        {
-        depends.clear();
-        depends.push_back(localName);
-        commands.clear();
-        lg->WriteMakeRule(ruleFileStream, "Include target in all.",
-                          "all", depends, commands, true);
-        }
-
-      // Write the rule.
-      commands.clear();
-      commands.push_back(lg->GetRecursiveMakeCall
-                         ("CMakeFiles/Makefile2",localName.c_str()));
-      depends.clear();
-      depends.push_back("cmake_check_build_system");
-      localName = lg->GetRelativeTargetDirectory(t->second);
-      localName += "/rule";
-      lg->WriteMakeRule(ruleFileStream, 
-                        "Build rule for subdir invocation for target.",
-                        localName.c_str(), depends, commands, true);
-
-      // Add a target with the canonical name (no prefix, suffix or path).
-      commands.clear();
-      depends.clear();
-      depends.push_back(localName);
-      lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
-                        t->second.GetName(), depends, commands, true);
-
-      // Add rules to prepare the target for installation.
-      if(t->second.NeedRelinkBeforeInstall())
-        {
-        localName = lg->GetRelativeTargetDirectory(t->second);
-        localName += "/preinstall";
+        makeTargetName = localName;
+        makeTargetName += "/build";
+        commands.push_back(lg->GetRecursiveMakeCall
+                           (makefileName.c_str(),makeTargetName.c_str()));
+        
+        // Write the rule.
+        localName += "/all";
         depends.clear();
+        this->AppendGlobalTargetDepends(depends,t->second);
+        lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
+                          localName.c_str(), depends, commands, true);
+        
+        // add the all/all dependency
+        if (!exclude && t->second.IsInAll())
+          {
+          depends.clear();
+          depends.push_back(localName);
+          commands.clear();
+          lg->WriteMakeRule(ruleFileStream, "Include target in all.",
+                            "all", depends, commands, true);
+          }
+        
+        // Write the rule.
         commands.clear();
         commands.push_back(lg->GetRecursiveMakeCall
-                           (makefileName.c_str(), localName.c_str()));
-        this->AppendGlobalTargetDepends(depends,t->second);
-        lg->WriteMakeRule(ruleFileStream, "Pre-install relink rule for target.",
+                           ("CMakeFiles/Makefile2",localName.c_str()));
+        depends.clear();
+        depends.push_back("cmake_check_build_system");
+        localName = lg->GetRelativeTargetDirectory(t->second);
+        localName += "/rule";
+        lg->WriteMakeRule(ruleFileStream, 
+                          "Build rule for subdir invocation for target.",
                           localName.c_str(), depends, commands, true);
+        
+        // Add a target with the canonical name (no prefix, suffix or path).
+        commands.clear();
         depends.clear();
         depends.push_back(localName);
+        lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
+                          t->second.GetName(), depends, commands, true);
+        
+        // Add rules to prepare the target for installation.
+        if(t->second.NeedRelinkBeforeInstall())
+          {
+          localName = lg->GetRelativeTargetDirectory(t->second);
+          localName += "/preinstall";
+          depends.clear();
+          commands.clear();
+          commands.push_back(lg->GetRecursiveMakeCall
+                             (makefileName.c_str(), localName.c_str()));
+          this->AppendGlobalTargetDepends(depends,t->second);
+          lg->WriteMakeRule(ruleFileStream, "Pre-install relink rule for target.",
+                            localName.c_str(), depends, commands, true);
+          depends.clear();
+          depends.push_back(localName);
+          commands.clear();
+          lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
+                            "preinstall", depends, commands, true);
+          }
+        
+        // add the clean rule
+        localName = lg->GetRelativeTargetDirectory(t->second);
+        makeTargetName = localName;
+        makeTargetName += "/clean";
+        depends.clear();
+        commands.clear();
+        commands.push_back(lg->GetRecursiveMakeCall
+                           (makefileName.c_str(), makeTargetName.c_str()));
+        lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
+                          makeTargetName.c_str(), depends, commands, true);
         commands.clear();
-        lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
-                          "preinstall", depends, commands, true);
+        depends.push_back(makeTargetName);
+        lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
+                          "clean", depends, commands, true);
         }
-
-      // add the clean rule
-      localName = lg->GetRelativeTargetDirectory(t->second);
-      makeTargetName = localName;
-      makeTargetName += "/clean";
-      depends.clear();
-      commands.clear();
-      commands.push_back(lg->GetRecursiveMakeCall
-                         (makefileName.c_str(), makeTargetName.c_str()));
-      lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
-                        makeTargetName.c_str(), depends, commands, true);
-      commands.clear();
-      depends.push_back(makeTargetName);
-      lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
-                        "clean", depends, commands, true);
       }
     }
 }

+ 9 - 0
Source/cmGlobalUnixMakefileGenerator3.h

@@ -113,6 +113,15 @@ public:
   /** Get the command to use for a non-symbolic target file that has
       no rule.  This is used for multiple output dependencies.  */
   std::string GetEmptyCommandHack() { return this->EmptyCommandsHack; }
+
+
+  // change the build command for speed
+  virtual std::string GenerateBuildCommand
+  (const char* makeProgram,
+   const char *projectName, const char* additionalOptions, 
+   const char *targetName,
+   const char* config, bool ignoreErrors);
+
 protected:
   void WriteMainMakefile2();
   void WriteMainCMakefile();

+ 5 - 0
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -1418,6 +1418,11 @@ void cmLocalUnixMakefileGenerator3
                                 this->Makefile->GetStartOutputDirectory());
   this->WriteMakeRule(ruleFileStream, "The main clean target", "clean",
                       depends, commands, true);
+  commands.clear();
+  depends.clear();
+  depends.push_back("clean");
+  this->WriteMakeRule(ruleFileStream, "The main clean target", "clean/fast",
+                      depends, commands, true);
 
   // Write the preinstall rule.
   dir = this->Makefile->GetStartOutputDirectory();