From 489b1c23b9a880da0012427b60cce7b6f5ddaa27 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 4 Mar 2014 13:25:42 -0500 Subject: [PATCH] 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 --- .../dev/link-libraries-response-files.rst | 5 ++++ Modules/Platform/Windows-GNU.cmake | 5 +++- .../cmMakefileExecutableTargetGenerator.cxx | 14 +++++++++- Source/cmMakefileLibraryTargetGenerator.cxx | 14 +++++++++- Source/cmMakefileTargetGenerator.cxx | 28 ++++++++++++++++++- Source/cmMakefileTargetGenerator.h | 1 + 6 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 Help/release/dev/link-libraries-response-files.rst diff --git a/Help/release/dev/link-libraries-response-files.rst b/Help/release/dev/link-libraries-response-files.rst new file mode 100644 index 000000000..cecf7f6ab --- /dev/null +++ b/Help/release/dev/link-libraries-response-files.rst @@ -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. diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index 2bb7a2076..5c5b36024 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -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() diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 6754525f3..180205427 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -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. diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index c639f3e58..39e00b231 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -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 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 diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 0f2b6e371..facbcc621 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1834,14 +1834,40 @@ cmMakefileTargetGenerator void cmMakefileTargetGenerator ::CreateLinkLibs(std::string& linkLibs, bool relink, + bool useResponseFile, std::vector& 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); + } } //---------------------------------------------------------------------------- diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index d47708d25..72dc6bc61 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -165,6 +165,7 @@ protected: /** Create list of flags for link libraries. */ void CreateLinkLibs(std::string& linkLibs, bool relink, + bool useResponseFile, std::vector& makefile_depends); /** Create lists of object files for linking and cleaning. */