summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2006-06-15 20:17:11 (GMT)
committerBrad King <brad.king@kitware.com>2006-06-15 20:17:11 (GMT)
commit0bbcb49f65eb92daafc5ad87162f1ecedc3438dc (patch)
tree4889b6c00d1b1fb55a0e55c1ec17cb16edf0a4ab
parent6438bec4c9355960f47e4b853f27b548a55ec5e0 (diff)
downloadCMake-0bbcb49f65eb92daafc5ad87162f1ecedc3438dc.zip
CMake-0bbcb49f65eb92daafc5ad87162f1ecedc3438dc.tar.gz
CMake-0bbcb49f65eb92daafc5ad87162f1ecedc3438dc.tar.bz2
ENH: Added generation of link rules into script files executed by a cmake -E command in order to support longer link lines. This is needed only on platforms without response file support and that may have weak shells.
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx1
-rw-r--r--Source/cmGlobalGenerator.cxx3
-rw-r--r--Source/cmGlobalGenerator.h4
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.cxx1
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.cxx1
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx1
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx1
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx82
-rw-r--r--Source/cmMakefileTargetGenerator.cxx50
-rw-r--r--Source/cmMakefileTargetGenerator.h1
-rw-r--r--Source/cmake.cxx105
-rw-r--r--Source/cmake.h1
12 files changed, 242 insertions, 9 deletions
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 5018a8c..1ce506d 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -25,6 +25,7 @@ cmGlobalBorlandMakefileGenerator::cmGlobalBorlandMakefileGenerator()
this->FindMakeProgramFile = "CMakeBorlandFindMake.cmake";
this->ForceUnixPaths = false;
this->ToolSupportsColor = true;
+ this->UseLinkScript = false;
}
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 0feb91e..d840b8a 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -36,6 +36,9 @@ cmGlobalGenerator::cmGlobalGenerator()
// By default do not try to support color.
this->ToolSupportsColor = false;
+
+ // By default do not use link scripts.
+ this->UseLinkScript = false;
}
cmGlobalGenerator::~cmGlobalGenerator()
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index b60d497..7a05783 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -152,6 +152,9 @@ public:
std::string ConvertToRelativePath(const std::vector<std::string>& local,
const char* remote);
+ /** Get whether the generator should use a script for link commands. */
+ bool GetUseLinkScript() { return this->UseLinkScript; }
+
/*
* Determine what program to use for building the project.
*/
@@ -204,6 +207,7 @@ protected:
const cmCustomCommandLines* commandLines,
std::vector<std::string> depends, bool depends_on_all = false);
+ bool UseLinkScript;
bool ForceUnixPaths;
bool ToolSupportsColor;
cmStdString FindMakeProgramFile;
diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx
index 16c52cc..8ae0b08 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.cxx
+++ b/Source/cmGlobalMSYSMakefileGenerator.cxx
@@ -24,6 +24,7 @@ cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator()
this->FindMakeProgramFile = "CMakeMSYSFindMake.cmake";
this->ForceUnixPaths = true;
this->ToolSupportsColor = true;
+ this->UseLinkScript = false;
}
std::string
diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx
index 7e9ad82..f66134c 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.cxx
+++ b/Source/cmGlobalMinGWMakefileGenerator.cxx
@@ -23,6 +23,7 @@ cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator()
this->FindMakeProgramFile = "CMakeMinGWFindMake.cmake";
this->ForceUnixPaths = true;
this->ToolSupportsColor = true;
+ this->UseLinkScript = true;
}
void cmGlobalMinGWMakefileGenerator
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index bfb09db..35a2a86 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -23,6 +23,7 @@ cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator()
this->FindMakeProgramFile = "CMakeNMakeFindMake.cmake";
this->ForceUnixPaths = false;
this->ToolSupportsColor = true;
+ this->UseLinkScript = false;
}
void cmGlobalNMakeMakefileGenerator
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 387e7e0..82c87e2 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -31,6 +31,7 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
this->ToolSupportsColor = true;
this->NumberOfSourceFiles = 0;
this->NumberOfSourceFilesWritten = 0;
+ this->UseLinkScript = true;
}
void cmGlobalUnixMakefileGenerator3
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index a292605..c2de260 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -24,6 +24,8 @@
#include "cmTarget.h"
#include "cmake.h"
+#include <memory> // auto_ptr
+
//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
{
@@ -376,9 +378,41 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
}
+ // Open the link script if it will be used.
+ bool useLinkScript = false;
+ std::string linkScriptName;
+ std::auto_ptr<cmGeneratedFileStream> linkScriptStream;
+ if(this->GlobalGenerator->GetUseLinkScript() &&
+ (this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
+ this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
+ this->Target->GetType() == cmTarget::MODULE_LIBRARY))
+ {
+ useLinkScript = true;
+ linkScriptName = this->TargetBuildDirectoryFull;
+ linkScriptName += "/link.txt";
+ std::auto_ptr<cmGeneratedFileStream> lss(
+ new cmGeneratedFileStream(linkScriptName.c_str()));
+ linkScriptStream = lss;
+ }
+
+ std::vector<std::string> link_script_commands;
+
// Construct the main link rule.
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
- cmSystemTools::ExpandListArgument(linkRule, commands1);
+ if(useLinkScript)
+ {
+ cmSystemTools::ExpandListArgument(linkRule, link_script_commands);
+ std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
+ link_command += this->Convert(linkScriptName.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::SHELL);
+ link_command += " --verbose=$(VERBOSE)";
+ commands1.push_back(link_command);
+ }
+ else
+ {
+ cmSystemTools::ExpandListArgument(linkRule, commands1);
+ }
this->LocalGenerator->CreateCDCommand
(commands1,
this->Makefile->GetStartOutputDirectory(),
@@ -418,11 +452,19 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string variableName;
std::string variableNameExternal;
this->WriteObjectsVariable(variableName, variableNameExternal);
- std::string buildObjs = "$(";
- buildObjs += variableName;
- buildObjs += ") $(";
- buildObjs += variableNameExternal;
- buildObjs += ")";
+ std::string buildObjs;
+ if(useLinkScript)
+ {
+ this->WriteObjectsString(buildObjs);
+ }
+ else
+ {
+ buildObjs = "$(";
+ buildObjs += variableName;
+ buildObjs += ") $(";
+ buildObjs += variableNameExternal;
+ buildObjs += ")";
+ }
std::string cleanObjs = "$(";
cleanObjs += variableName;
cleanObjs += ")";
@@ -493,13 +535,35 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
vars.LanguageCompileFlags = langFlags.c_str();
// Expand placeholders in the commands.
this->LocalGenerator->TargetImplib = targetOutPathImport;
- for(std::vector<std::string>::iterator i = commands.begin();
- i != commands.end(); ++i)
+ if(useLinkScript)
+ {
+ for(std::vector<std::string>::iterator i = link_script_commands.begin();
+ i != link_script_commands.end(); ++i)
+ {
+ this->LocalGenerator->ExpandRuleVariables(*i, vars);
+ }
+ }
+ else
{
- this->LocalGenerator->ExpandRuleVariables(*i, vars);
+ for(std::vector<std::string>::iterator i = commands.begin();
+ i != commands.end(); ++i)
+ {
+ this->LocalGenerator->ExpandRuleVariables(*i, vars);
+ }
}
this->LocalGenerator->TargetImplib = "";
+ // Optionally convert the build rule to use a script to avoid long
+ // command lines in the make shell.
+ if(useLinkScript)
+ {
+ for(std::vector<std::string>::iterator cmd = link_script_commands.begin();
+ cmd != link_script_commands.end(); ++cmd)
+ {
+ (*linkScriptStream) << *cmd << "\n";
+ }
+ }
+
// Write the build rule.
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
targetFullPathReal.c_str(),
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 8973627..0f1a087 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -809,6 +809,56 @@ cmMakefileTargetGenerator
}
//----------------------------------------------------------------------------
+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)
+ {
+ if ( this->ExtraContent.find(i->c_str()) != this->ExtraContent.end() )
+ {
+ continue;
+ }
+ 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());
+ }
+ }
+ 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());
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
bool relink)
{
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index 35c702d..a624305 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -91,6 +91,7 @@ protected:
// write out the variable that lists the objects for this target
void WriteObjectsVariable(std::string& variableName,
std::string& variableNameExternal);
+ void WriteObjectsString(std::string& buildObjs);
// write the driver rule to build target outputs
void WriteTargetDriverRule(const char* main_output, bool relink);
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 550e0a6..44efd23 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -32,6 +32,7 @@
#endif
# include <cmsys/Directory.hxx>
+#include <cmsys/Process.h>
// only build kdevelop generator on non-windows platforms
// when not bootstrapping cmake
@@ -1178,6 +1179,12 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1;
}
+ // Internal CMake link script support.
+ else if (args[1] == "cmake_link_script" && args.size() >= 3)
+ {
+ return cmake::ExecuteLinkScript(args);
+ }
+
#ifdef CMAKE_BUILD_WITH_CMAKE
// Internal CMake color makefile support.
else if (args[1] == "cmake_echo_color")
@@ -2643,3 +2650,101 @@ int cmake::ExecuteEchoColor(std::vector<std::string>&)
return 1;
}
#endif
+
+//----------------------------------------------------------------------------
+int cmake::ExecuteLinkScript(std::vector<std::string>& args)
+{
+ // The arguments are
+ // argv[0] == <cmake-executable>
+ // argv[1] == cmake_link_script
+ // argv[2] == <link-script-name>
+ // argv[3] == --verbose=?
+ bool verbose = false;
+ if(args.size() >= 4)
+ {
+ if(args[3].find("--verbose=") == 0)
+ {
+ if(!cmSystemTools::IsOff(args[3].substr(10).c_str()))
+ {
+ verbose = true;
+ }
+ }
+ }
+
+ // Allocate a process instance.
+ cmsysProcess* cp = cmsysProcess_New();
+ if(!cp)
+ {
+ std::cerr << "Error allocating process instance in link script."
+ << std::endl;
+ return 1;
+ }
+
+ // Children should share stdout and stderr with this process.
+ cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
+ cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
+
+ // Run the command lines verbatim.
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_Verbatim, 1);
+
+ // Read command lines from the script.
+ std::ifstream fin(args[2].c_str());
+ if(!fin)
+ {
+ std::cerr << "Error opening link script \""
+ << args[2] << "\"" << std::endl;
+ return 1;
+ }
+
+ // Run one command at a time.
+ std::string command;
+ int result = 0;
+ while(result == 0 && cmSystemTools::GetLineFromStream(fin, command))
+ {
+ // Setup this command line.
+ const char* cmd[2] = {command.c_str(), 0};
+ cmsysProcess_SetCommand(cp, cmd);
+
+ // Report the command if verbose output is enabled.
+ if(verbose)
+ {
+ std::cout << command << std::endl;
+ }
+
+ // Run the command and wait for it to exit.
+ cmsysProcess_Execute(cp);
+ cmsysProcess_WaitForExit(cp, 0);
+
+ // Report failure if any.
+ switch(cmsysProcess_GetState(cp))
+ {
+ case cmsysProcess_State_Exited:
+ {
+ int value = cmsysProcess_GetExitValue(cp);
+ if(value != 0)
+ {
+ result = value;
+ }
+ }
+ break;
+ case cmsysProcess_State_Exception:
+ std::cerr << "Error running link command: "
+ << cmsysProcess_GetExceptionString(cp) << std::endl;
+ result = 1;
+ break;
+ case cmsysProcess_State_Error:
+ std::cerr << "Error running link command: "
+ << cmsysProcess_GetErrorString(cp) << std::endl;
+ result = 2;
+ break;
+ default:
+ break;
+ };
+ }
+
+ // Free the process instance.
+ cmsysProcess_Delete(cp);
+
+ // Return the final resulting return value.
+ return result;
+}
diff --git a/Source/cmake.h b/Source/cmake.h
index 71a7713..d63cf7e 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -323,6 +323,7 @@ protected:
void GenerateGraphViz(const char* fileName);
static int ExecuteEchoColor(std::vector<std::string>& args);
+ static int ExecuteLinkScript(std::vector<std::string>& args);
cmVariableWatch* VariableWatch;