[cmake-commits] king committed cmDocumentVariables.cxx 1.12 1.13 cmMakefileLibraryTargetGenerator.cxx 1.51 1.52 cmMakefileTargetGenerator.cxx 1.87 1.88 cmMakefileTargetGenerator.h 1.19 1.20

cmake-commits at cmake.org cmake-commits at cmake.org
Tue Jan 29 20:46:27 EST 2008


Update of /cvsroot/CMake/CMake/Source
In directory public:/mounts/ram/cvs-serv7659/Source

Modified Files:
	cmDocumentVariables.cxx cmMakefileLibraryTargetGenerator.cxx 
	cmMakefileTargetGenerator.cxx cmMakefileTargetGenerator.h 
Log Message:
ENH: Added build rule variables CMAKE_<LANG>_ARCHIVE_CREATE, CMAKE_<LANG>_ARCHIVE_APPEND, and CMAKE_<LANG>_ARCHIVE_FINISH to support creation of static archive libraries out of a large number of objects.  See bug #6284.


Index: cmMakefileLibraryTargetGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefileLibraryTargetGenerator.cxx,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- cmMakefileLibraryTargetGenerator.cxx	28 Jan 2008 18:05:58 -0000	1.51
+++ cmMakefileLibraryTargetGenerator.cxx	30 Jan 2008 01:46:25 -0000	1.52
@@ -668,12 +668,45 @@
   // Determine whether a link script will be used.
   bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
 
-  // Construct the main link rule.
-  std::vector<std::string> real_link_commands;
-  std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
-  cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
+  // For static libraries there might be archiving rules.
+  std::vector<std::string> archiveCreateCommands;
+  std::vector<std::string> archiveAppendCommands;
+  std::vector<std::string> archiveFinishCommands;
+  std::string::size_type archiveCommandLimit = std::string::npos;
+  if(useLinkScript && this->Target->GetType() == cmTarget::STATIC_LIBRARY)
+    {
+    std::string arCreateVar = "CMAKE_";
+    arCreateVar += linkLanguage;
+    arCreateVar += "_ARCHIVE_CREATE";
+    if(const char* rule = this->Makefile->GetDefinition(arCreateVar.c_str()))
+      {
+      cmSystemTools::ExpandListArgument(rule, archiveCreateCommands);
+      }
+    std::string arAppendVar = "CMAKE_";
+    arAppendVar += linkLanguage;
+    arAppendVar += "_ARCHIVE_APPEND";
+    if(const char* rule = this->Makefile->GetDefinition(arAppendVar.c_str()))
+      {
+      cmSystemTools::ExpandListArgument(rule, archiveAppendCommands);
+      }
+    std::string arFinishVar = "CMAKE_";
+    arFinishVar += linkLanguage;
+    arFinishVar += "_ARCHIVE_FINISH";
+    if(const char* rule = this->Makefile->GetDefinition(arFinishVar.c_str()))
+      {
+      cmSystemTools::ExpandListArgument(rule, archiveFinishCommands);
+      }
+
+    // Limit the length of individual object lists to less than the
+    // 32K command line length limit on Windows.  We could make this a
+    // platform file variable but this should work everywhere.
+    archiveCommandLimit = 30000;
+    }
+  bool useArchiveRules =
+    !archiveCreateCommands.empty() && !archiveAppendCommands.empty();
 
   // Expand the rule variables.
+  std::vector<std::string> real_link_commands;
   {
   // Collect up flags to link in needed libraries.
   cmOStringStream linklibs;
@@ -687,7 +720,10 @@
   std::string buildObjs;
   if(useLinkScript)
     {
-    this->WriteObjectsString(buildObjs);
+    if(!useArchiveRules)
+      {
+      this->WriteObjectsString(buildObjs);
+      }
     }
   else
     {
@@ -768,12 +804,64 @@
                                linkLanguage, langFlags);
     }
   vars.LanguageCompileFlags = langFlags.c_str();
-  // Expand placeholders in the commands.
+
+  // Construct the main link rule and expand placeholders.
   this->LocalGenerator->TargetImplib = targetOutPathImport;
-  for(std::vector<std::string>::iterator i = real_link_commands.begin();
-      i != real_link_commands.end(); ++i)
+  if(useArchiveRules)
     {
-    this->LocalGenerator->ExpandRuleVariables(*i, vars);
+    // Construct the individual object list strings.
+    std::vector<std::string> object_strings;
+    this->WriteObjectsStrings(object_strings, archiveCommandLimit);
+
+    // Create the archive with the first set of objects.
+    std::vector<std::string>::iterator osi = object_strings.begin();
+    {
+    vars.Objects = osi->c_str();
+    for(std::vector<std::string>::const_iterator
+          i = archiveCreateCommands.begin();
+        i != archiveCreateCommands.end(); ++i)
+      {
+      std::string cmd = *i;
+      this->LocalGenerator->ExpandRuleVariables(cmd, vars);
+      real_link_commands.push_back(cmd);
+      }
+    }
+    // Append to the archive with the other object sets.
+    for(++osi; osi != object_strings.end(); ++osi)
+      {
+      vars.Objects = osi->c_str();
+      for(std::vector<std::string>::const_iterator
+            i = archiveAppendCommands.begin();
+          i != archiveAppendCommands.end(); ++i)
+        {
+        std::string cmd = *i;
+        this->LocalGenerator->ExpandRuleVariables(cmd, vars);
+        real_link_commands.push_back(cmd);
+        }
+      }
+    // Finish the archive.
+    vars.Objects = "";
+    for(std::vector<std::string>::const_iterator
+          i = archiveFinishCommands.begin();
+        i != archiveFinishCommands.end(); ++i)
+      {
+      std::string cmd = *i;
+      this->LocalGenerator->ExpandRuleVariables(cmd, vars);
+      real_link_commands.push_back(cmd);
+      }
+    }
+  else
+    {
+    // Get the set of commands.
+    std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
+    cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
+
+    // Expand placeholders.
+    for(std::vector<std::string>::iterator i = real_link_commands.begin();
+        i != real_link_commands.end(); ++i)
+      {
+      this->LocalGenerator->ExpandRuleVariables(*i, vars);
+      }
     }
   this->LocalGenerator->TargetImplib = "";
   }

Index: cmDocumentVariables.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmDocumentVariables.cxx,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- cmDocumentVariables.cxx	23 Jan 2008 20:22:38 -0000	1.12
+++ cmDocumentVariables.cxx	30 Jan 2008 01:46:25 -0000	1.13
@@ -944,7 +944,34 @@
      "This is a rule variable that tells CMake how "
      "to create a static library for the language <LANG>.",false,
      "Variables for Languages");
-  
+
+  cm->DefineProperty
+    ("CMAKE_<LANG>_ARCHIVE_CREATE", cmProperty::VARIABLE,
+     "Rule variable to create a new static archive.",
+     "This is a rule variable that tells CMake how to create a static "
+     "archive.  It is used in place of CMAKE_<LANG>_CREATE_STATIC_LIBRARY "
+     "on some platforms in order to support large object counts.  "
+     "See also CMAKE_<LANG>_ARCHIVE_APPEND and CMAKE_<LANG>_ARCHIVE_FINISH.",
+     false, "Variables for Languages");
+
+  cm->DefineProperty
+    ("CMAKE_<LANG>_ARCHIVE_APPEND", cmProperty::VARIABLE,
+     "Rule variable to append to a static archive.",
+     "This is a rule variable that tells CMake how to append to a static "
+     "archive.  It is used in place of CMAKE_<LANG>_CREATE_STATIC_LIBRARY "
+     "on some platforms in order to support large object counts.  "
+     "See also CMAKE_<LANG>_ARCHIVE_CREATE and CMAKE_<LANG>_ARCHIVE_FINISH.",
+     false, "Variables for Languages");
+
+  cm->DefineProperty
+    ("CMAKE_<LANG>_ARCHIVE_FINISH", cmProperty::VARIABLE,
+     "Rule variable to finish an existing static archive.",
+     "This is a rule variable that tells CMake how to finish a static "
+     "archive.  It is used in place of CMAKE_<LANG>_CREATE_STATIC_LIBRARY "
+     "on some platforms in order to support large object counts.  "
+     "See also CMAKE_<LANG>_ARCHIVE_CREATE and CMAKE_<LANG>_ARCHIVE_APPEND.",
+     false, "Variables for Languages");
+
   cm->DefineProperty
     ("CMAKE_<LANG>_IGNORE_EXTENSIONS", cmProperty::VARIABLE,
      "File extensions that should be ignored by the build.",

Index: cmMakefileTargetGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefileTargetGenerator.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- cmMakefileTargetGenerator.h	30 Dec 2007 21:11:38 -0000	1.19
+++ cmMakefileTargetGenerator.h	30 Jan 2008 01:46:25 -0000	1.20
@@ -107,6 +107,8 @@
   void WriteObjectsVariable(std::string& variableName,
                             std::string& variableNameExternal);
   void WriteObjectsString(std::string& buildObjs);
+  void WriteObjectsStrings(std::vector<std::string>& objStrings,
+                           std::string::size_type limit = std::string::npos);
 
   // write the driver rule to build target outputs
   void WriteTargetDriverRule(const char* main_output, bool relink);

Index: cmMakefileTargetGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefileTargetGenerator.cxx,v
retrieving revision 1.87
retrieving revision 1.88
diff -u -d -r1.87 -r1.88
--- cmMakefileTargetGenerator.cxx	28 Jan 2008 13:38:36 -0000	1.87
+++ cmMakefileTargetGenerator.cxx	30 Jan 2008 01:46:25 -0000	1.88
@@ -1200,49 +1200,96 @@
 cmMakefileTargetGenerator
 ::WriteObjectsString(std::string& buildObjs)
 {
-  std::string object;
-  const char* no_quoted =
-    this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
-  const char* space = "";
-  for(std::vector<std::string>::const_iterator i = this->Objects.begin();
-      i != this->Objects.end(); ++i)
+  std::vector<std::string> objStrings;
+  this->WriteObjectsStrings(objStrings);
+  buildObjs = objStrings[0];
+}
+
+//----------------------------------------------------------------------------
+class cmMakefileTargetGeneratorObjectStrings
+{
+public:
+  cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
+                                         cmMakefile* mf,
+                                         cmLocalUnixMakefileGenerator3* lg,
+                                         std::string::size_type limit):
+    Strings(strings), Makefile(mf), LocalGenerator(lg), LengthLimit(limit)
     {
-    if ( this->ExtraContent.find(i->c_str()) != this->ExtraContent.end() )
+    this->NoQuotes = mf->IsOn("CMAKE_NO_QUOTED_OBJECTS");
+    this->Space = "";
+    }
+  void Feed(std::string const& obj)
+    {
+    // Construct the name of the next object.
+    if(this->NoQuotes)
       {
-      continue;
+      this->NextObject =
+        this->LocalGenerator->Convert(obj.c_str(),
+                                      cmLocalGenerator::START_OUTPUT,
+                                      cmLocalGenerator::SHELL);
       }
-    buildObjs += space;
-    space = " ";
-    if(no_quoted)
+    else
       {
-      buildObjs +=
-        this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
-                      cmLocalGenerator::SHELL);
+      this->NextObject =
+        this->LocalGenerator->ConvertToQuotedOutputPath(obj.c_str());
       }
-    else
+
+    // Roll over to next string if the limit will be exceeded.
+    if(this->LengthLimit != std::string::npos &&
+       (this->CurrentString.length() + 1 + this->NextObject.length()
+        > this->LengthLimit))
       {
-      buildObjs +=
-        this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
+      this->Strings.push_back(this->CurrentString);
+      this->CurrentString = "";
+      this->Space = "";
       }
+
+    // Separate from previous object.
+    this->CurrentString += this->Space;
+    this->Space = " ";
+
+    // Append this object.
+    this->CurrentString += this->NextObject;
+    }
+  void Done()
+    {
+    this->Strings.push_back(this->CurrentString);
+    }
+private:
+  std::vector<std::string>& Strings;
+  cmMakefile* Makefile;
+  cmLocalUnixMakefileGenerator3* LocalGenerator;
+  std::string::size_type LengthLimit;
+  bool NoQuotes;
+  std::string CurrentString;
+  std::string NextObject;
+  const char* Space;
+};
+
+//----------------------------------------------------------------------------
+void
+cmMakefileTargetGenerator
+::WriteObjectsStrings(std::vector<std::string>& objStrings,
+                      std::string::size_type limit)
+{
+  cmMakefileTargetGeneratorObjectStrings
+    helper(objStrings, this->Makefile, this->LocalGenerator, limit);
+  for(std::vector<std::string>::const_iterator i = this->Objects.begin();
+      i != this->Objects.end(); ++i)
+    {
+    if ( this->ExtraContent.find(i->c_str()) != this->ExtraContent.end() )
+      {
+      continue;
+      }
+    helper.Feed(*i);
     }
   for(std::vector<std::string>::const_iterator i =
         this->ExternalObjects.begin();
       i != this->ExternalObjects.end(); ++i)
     {
-    buildObjs += space;
-    space = " ";
-    if(no_quoted)
-      {
-      buildObjs +=
-        this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
-                      cmLocalGenerator::SHELL);
-      }
-    else
-      {
-      buildObjs +=
-        this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
-      }
+    helper.Feed(*i);
     }
+  helper.Done();
 }
 
 //----------------------------------------------------------------------------



More information about the Cmake-commits mailing list