summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/Platform/Windows-gcc.cmake11
-rw-r--r--Source/cmDocumentVariables.cxx29
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx106
-rw-r--r--Source/cmMakefileTargetGenerator.cxx107
-rw-r--r--Source/cmMakefileTargetGenerator.h2
5 files changed, 215 insertions, 40 deletions
diff --git a/Modules/Platform/Windows-gcc.cmake b/Modules/Platform/Windows-gcc.cmake
index 805b451..51857eb 100644
--- a/Modules/Platform/Windows-gcc.cmake
+++ b/Modules/Platform/Windows-gcc.cmake
@@ -53,3 +53,14 @@ IF(MSYS OR MINGW)
SET(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Wl,-Bdynamic")
ENDFOREACH(type)
ENDIF(MSYS OR MINGW)
+
+# Create archiving rules to support large object file lists for static
+# libraries.
+IF(MSYS OR MINGW)
+ SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
+ SET(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> r <TARGET> <LINK_FLAGS> <OBJECTS>")
+ SET(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
+ SET(CMAKE_CXX_ARCHIVE_CREATE ${CMAKE_C_ARCHIVE_CREATE})
+ SET(CMAKE_CXX_ARCHIVE_APPEND ${CMAKE_C_ARCHIVE_APPEND})
+ SET(CMAKE_CXX_ARCHIVE_FINISH ${CMAKE_C_ARCHIVE_FINISH})
+ENDIF(MSYS OR MINGW)
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 4c33014..bcc9e8c 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -944,7 +944,34 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"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.",
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 9ab4649..a81cfd6 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -668,12 +668,45 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
// 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 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string buildObjs;
if(useLinkScript)
{
- this->WriteObjectsString(buildObjs);
+ if(!useArchiveRules)
+ {
+ this->WriteObjectsString(buildObjs);
+ }
}
else
{
@@ -768,12 +804,64 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
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)
+ {
+ // 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();
{
- this->LocalGenerator->ExpandRuleVariables(*i, vars);
+ 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 = "";
}
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 0c550ef..3e8084c 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1200,49 +1200,96 @@ void
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();
}
//----------------------------------------------------------------------------
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index e997a0a..f645eab 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -107,6 +107,8 @@ protected:
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);