Windows: Use response files to specify link libraries for GNU tools

Work around the command-line-length limit by using an @linklibs.rsp
response file to pass the flags for link libraries.  This allows
very long lists of libraries to be used in addition to the existing
support for passing object files via response file.

Suggested-by: Peter Keuschnigg <peter.keuschnigg@pmu.ac.at>
This commit is contained in:
Brad King 2014-03-04 13:25:42 -05:00
parent 745caae6dd
commit 489b1c23b9
6 changed files with 63 additions and 4 deletions

View File

@ -0,0 +1,5 @@
link-libraries-response-files
-----------------------------
* The Makefile generators learned to use response files with GNU tools
on Windows to pass library directories and names to the linker.

View File

@ -87,6 +87,7 @@ macro(__windows_compiler_gnu lang)
set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "")
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS ${__WINDOWS_GNU_LD_RESPONSE})
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES ${__WINDOWS_GNU_LD_RESPONSE})
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1)
# We prefer "@" for response files but it is not supported by gcc 3.
@ -103,7 +104,9 @@ macro(__windows_compiler_gnu lang)
endif()
# The GNU 3.x compilers do not support response files (only linkers).
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 0)
elseif(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS)
# Link libraries are generated only for the front-end.
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
else()
# Use "@" to pass the response file to the front-end.
set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "@")
endif()

View File

@ -318,6 +318,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
}
}
// Select whether to use a response file for libraries.
bool useResponseFileForLibs = false;
{
std::string responseVar = "CMAKE_";
responseVar += linkLanguage;
responseVar += "_USE_RESPONSE_FILE_FOR_LIBRARIES";
if(this->Makefile->IsOn(responseVar.c_str()))
{
useResponseFileForLibs = true;
}
}
// Expand the rule variables.
{
// Set path conversion for link script shells.
@ -325,7 +337,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Collect up flags to link in needed libraries.
std::string linkLibs;
this->CreateLinkLibs(linkLibs, relink, depends);
this->CreateLinkLibs(linkLibs, relink, useResponseFileForLibs, depends);
// Construct object file lists that may be needed to expand the
// rule.

View File

@ -485,6 +485,18 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
}
}
// Select whether to use a response file for libraries.
bool useResponseFileForLibs = false;
{
std::string responseVar = "CMAKE_";
responseVar += linkLanguage;
responseVar += "_USE_RESPONSE_FILE_FOR_LIBRARIES";
if(this->Makefile->IsOn(responseVar.c_str()))
{
useResponseFileForLibs = true;
}
}
// For static libraries there might be archiving rules.
bool haveStaticLibraryRule = false;
std::vector<std::string> archiveCreateCommands;
@ -546,7 +558,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string linkLibs;
if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
{
this->CreateLinkLibs(linkLibs, relink, depends);
this->CreateLinkLibs(linkLibs, relink, useResponseFileForLibs, depends);
}
// Construct object file lists that may be needed to expand the

View File

@ -1834,14 +1834,40 @@ cmMakefileTargetGenerator
void
cmMakefileTargetGenerator
::CreateLinkLibs(std::string& linkLibs, bool relink,
bool useResponseFile,
std::vector<std::string>& makefile_depends)
{
std::string frameworkPath;
std::string linkPath;
this->LocalGenerator
->OutputLinkLibraries(linkLibs, frameworkPath, linkPath,
*this->GeneratorTarget, relink, false);
*this->GeneratorTarget, relink,
useResponseFile);
linkLibs = frameworkPath + linkPath + linkLibs;
if(useResponseFile)
{
// Lookup the response file reference flag.
std::string responseFlagVar = "CMAKE_";
responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName);
responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
const char* responseFlag =
this->Makefile->GetDefinition(responseFlagVar.c_str());
if(!responseFlag)
{
responseFlag = "@";
}
// Create this response file.
std::string link_rsp =
this->CreateResponseFile("linklibs.rsp", linkLibs, makefile_depends);
// Reference the response file.
linkLibs = responseFlag;
linkLibs += this->Convert(link_rsp.c_str(),
cmLocalGenerator::NONE,
cmLocalGenerator::SHELL);
}
}
//----------------------------------------------------------------------------

View File

@ -165,6 +165,7 @@ protected:
/** Create list of flags for link libraries. */
void CreateLinkLibs(std::string& linkLibs, bool relink,
bool useResponseFile,
std::vector<std::string>& makefile_depends);
/** Create lists of object files for linking and cleaning. */