1
0
Эх сурвалжийг харах

Merge topic 'ninja-per-target-rules'

a390de65 Ninja: Generate separate compile and link rules for each target
Brad King 10 жил өмнө
parent
commit
25d22be514

+ 31 - 1
Source/cmGlobalNinjaGenerator.cxx

@@ -21,6 +21,7 @@
 
 #include <algorithm>
 #include <assert.h>
+#include <ctype.h>
 
 const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja";
 const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja";
@@ -57,6 +58,28 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
   os << "# " << replace.substr(lpos) << "\n\n";
 }
 
+std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name)
+{
+  // Ninja rule names must match "[a-zA-Z0-9_.-]+".  Use ".xx" to encode
+  // "." and all invalid characters as hexadecimal.
+  std::string encoded;
+  for (std::string::const_iterator i = name.begin();
+       i != name.end(); ++i)
+    {
+    if (isalnum(*i) || *i == '_' || *i == '-')
+      {
+      encoded += *i;
+      }
+    else
+      {
+      char buf[16];
+      sprintf(buf, ".%02x", static_cast<unsigned int>(*i));
+      encoded += buf;
+      }
+    }
+  return encoded;
+}
+
 static bool IsIdentChar(char c)
 {
   return
@@ -120,7 +143,8 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
                                         const cmNinjaDeps& orderOnlyDeps,
                                         const cmNinjaVars& variables,
                                         const std::string& rspfile,
-                                        int cmdLineLimit)
+                                        int cmdLineLimit,
+                                        bool* usedResponseFile)
 {
   // Make sure there is a rule.
   if(rule.empty())
@@ -205,6 +229,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
   std::string buildstr = build;
   std::string assignments = variable_assignments.str();
   const std::string& args = arguments;
+  bool useResponseFile = false;
   if (cmdLineLimit > 0
       && args.size() + buildstr.size() + assignments.size()
                                                     > (size_t) cmdLineLimit) {
@@ -213,7 +238,12 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
     cmGlobalNinjaGenerator::WriteVariable(variable_assignments,
                                           "RSP_FILE", rspfile, "", 1);
     assignments += variable_assignments.str();
+    useResponseFile = true;
   }
+  if (usedResponseFile)
+    {
+    *usedResponseFile = useResponseFile;
+    }
 
   os << buildstr << args << assignments;
 }

+ 3 - 1
Source/cmGlobalNinjaGenerator.h

@@ -61,6 +61,7 @@ public:
   /// Write a divider in the given output stream @a os.
   static void WriteDivider(std::ostream& os);
 
+  static std::string EncodeRuleName(std::string const& name);
   static std::string EncodeIdent(const std::string &ident, std::ostream &vars);
   static std::string EncodeLiteral(const std::string &lit);
   std::string EncodePath(const std::string &path);
@@ -87,7 +88,8 @@ public:
                   const cmNinjaDeps& orderOnlyDeps,
                   const cmNinjaVars& variables,
                   const std::string& rspfile = std::string(),
-                  int cmdLineLimit = -1);
+                  int cmdLineLimit = -1,
+                  bool* usedResponseFile = 0);
 
   /**
    * Helper to write a build statement with the special 'phony' rule.

+ 7 - 6
Source/cmNinjaNormalTargetGenerator.cxx

@@ -94,8 +94,6 @@ void cmNinjaNormalTargetGenerator::Generate()
     }
   else
     {
-    this->WriteLinkRule(false); // write rule without rspfile support
-    this->WriteLinkRule(true);  // write rule with rspfile support
     this->WriteLinkStatement();
     }
 }
@@ -160,7 +158,9 @@ cmNinjaNormalTargetGenerator
   return this->TargetLinkLanguage
     + "_"
     + cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
-    + "_LINKER";
+    + "_LINKER__"
+    + cmGlobalNinjaGenerator::EncodeRuleName(this->GetTarget()->GetName())
+    ;
 }
 
 void
@@ -169,8 +169,6 @@ cmNinjaNormalTargetGenerator
 {
   cmTarget::TargetType targetType = this->GetTarget()->GetType();
   std::string ruleName = this->LanguageLinkerRule();
-  if (useResponseFile)
-    ruleName += "_RSP_FILE";
 
   // Select whether to use a response file for objects.
   std::string rspfile;
@@ -661,6 +659,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     }
 
   // Write the build statement for this target.
+  bool usedResponseFile = false;
   globalGen.WriteBuild(this->GetBuildFileStream(),
                         comment.str(),
                         this->LanguageLinkerRule(),
@@ -670,7 +669,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
                         orderOnlyDeps,
                         vars,
                         rspfile,
-                        commandLineLengthLimit);
+                        commandLineLengthLimit,
+                        &usedResponseFile);
+  this->WriteLinkRule(usedResponseFile);
 
   if (targetOutput != targetOutputReal && !target.IsFrameworkOnApple())
     {

+ 7 - 0
Source/cmNinjaTargetGenerator.cxx

@@ -97,6 +97,13 @@ std::string const& cmNinjaTargetGenerator::GetConfigName() const
   return this->LocalGenerator->GetConfigName();
 }
 
+std::string cmNinjaTargetGenerator::LanguageCompilerRule(
+  const std::string& lang) const
+{
+  return lang + "_COMPILER__" +
+    cmGlobalNinjaGenerator::EncodeRuleName(this->Target->GetName());
+}
+
 // TODO: Picked up from cmMakefileTargetGenerator.  Refactor it.
 const char* cmNinjaTargetGenerator::GetFeature(const std::string& feature)
 {

+ 1 - 2
Source/cmNinjaTargetGenerator.h

@@ -67,8 +67,7 @@ protected:
 
   std::string const& GetConfigName() const;
 
-  std::string LanguageCompilerRule(const std::string& lang) const
-  { return lang + "_COMPILER"; }
+  std::string LanguageCompilerRule(const std::string& lang) const;
 
   const char* GetFeature(const std::string& feature);
   bool GetFeatureAsBool(const std::string& feature);