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.

This commit is contained in:
Brad King 2006-06-15 16:17:11 -04:00
parent 6438bec4c9
commit 0bbcb49f65
12 changed files with 242 additions and 9 deletions

View File

@ -25,6 +25,7 @@ cmGlobalBorlandMakefileGenerator::cmGlobalBorlandMakefileGenerator()
this->FindMakeProgramFile = "CMakeBorlandFindMake.cmake"; this->FindMakeProgramFile = "CMakeBorlandFindMake.cmake";
this->ForceUnixPaths = false; this->ForceUnixPaths = false;
this->ToolSupportsColor = true; this->ToolSupportsColor = true;
this->UseLinkScript = false;
} }

View File

@ -36,6 +36,9 @@ cmGlobalGenerator::cmGlobalGenerator()
// By default do not try to support color. // By default do not try to support color.
this->ToolSupportsColor = false; this->ToolSupportsColor = false;
// By default do not use link scripts.
this->UseLinkScript = false;
} }
cmGlobalGenerator::~cmGlobalGenerator() cmGlobalGenerator::~cmGlobalGenerator()

View File

@ -152,6 +152,9 @@ public:
std::string ConvertToRelativePath(const std::vector<std::string>& local, std::string ConvertToRelativePath(const std::vector<std::string>& local,
const char* remote); 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. * Determine what program to use for building the project.
*/ */
@ -204,6 +207,7 @@ protected:
const cmCustomCommandLines* commandLines, const cmCustomCommandLines* commandLines,
std::vector<std::string> depends, bool depends_on_all = false); std::vector<std::string> depends, bool depends_on_all = false);
bool UseLinkScript;
bool ForceUnixPaths; bool ForceUnixPaths;
bool ToolSupportsColor; bool ToolSupportsColor;
cmStdString FindMakeProgramFile; cmStdString FindMakeProgramFile;

View File

@ -24,6 +24,7 @@ cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator()
this->FindMakeProgramFile = "CMakeMSYSFindMake.cmake"; this->FindMakeProgramFile = "CMakeMSYSFindMake.cmake";
this->ForceUnixPaths = true; this->ForceUnixPaths = true;
this->ToolSupportsColor = true; this->ToolSupportsColor = true;
this->UseLinkScript = false;
} }
std::string std::string

View File

@ -23,6 +23,7 @@ cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator()
this->FindMakeProgramFile = "CMakeMinGWFindMake.cmake"; this->FindMakeProgramFile = "CMakeMinGWFindMake.cmake";
this->ForceUnixPaths = true; this->ForceUnixPaths = true;
this->ToolSupportsColor = true; this->ToolSupportsColor = true;
this->UseLinkScript = true;
} }
void cmGlobalMinGWMakefileGenerator void cmGlobalMinGWMakefileGenerator

View File

@ -23,6 +23,7 @@ cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator()
this->FindMakeProgramFile = "CMakeNMakeFindMake.cmake"; this->FindMakeProgramFile = "CMakeNMakeFindMake.cmake";
this->ForceUnixPaths = false; this->ForceUnixPaths = false;
this->ToolSupportsColor = true; this->ToolSupportsColor = true;
this->UseLinkScript = false;
} }
void cmGlobalNMakeMakefileGenerator void cmGlobalNMakeMakefileGenerator

View File

@ -31,6 +31,7 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
this->ToolSupportsColor = true; this->ToolSupportsColor = true;
this->NumberOfSourceFiles = 0; this->NumberOfSourceFiles = 0;
this->NumberOfSourceFilesWritten = 0; this->NumberOfSourceFilesWritten = 0;
this->UseLinkScript = true;
} }
void cmGlobalUnixMakefileGenerator3 void cmGlobalUnixMakefileGenerator3

View File

@ -24,6 +24,8 @@
#include "cmTarget.h" #include "cmTarget.h"
#include "cmake.h" #include "cmake.h"
#include <memory> // auto_ptr
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteRuleFiles() void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
{ {
@ -376,9 +378,41 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
->AppendCustomCommands(commands, this->Target->GetPreLinkCommands()); ->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. // Construct the main link rule.
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar); std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
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); cmSystemTools::ExpandListArgument(linkRule, commands1);
}
this->LocalGenerator->CreateCDCommand this->LocalGenerator->CreateCDCommand
(commands1, (commands1,
this->Makefile->GetStartOutputDirectory(), this->Makefile->GetStartOutputDirectory(),
@ -418,11 +452,19 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string variableName; std::string variableName;
std::string variableNameExternal; std::string variableNameExternal;
this->WriteObjectsVariable(variableName, variableNameExternal); this->WriteObjectsVariable(variableName, variableNameExternal);
std::string buildObjs = "$("; std::string buildObjs;
if(useLinkScript)
{
this->WriteObjectsString(buildObjs);
}
else
{
buildObjs = "$(";
buildObjs += variableName; buildObjs += variableName;
buildObjs += ") $("; buildObjs += ") $(";
buildObjs += variableNameExternal; buildObjs += variableNameExternal;
buildObjs += ")"; buildObjs += ")";
}
std::string cleanObjs = "$("; std::string cleanObjs = "$(";
cleanObjs += variableName; cleanObjs += variableName;
cleanObjs += ")"; cleanObjs += ")";
@ -493,13 +535,35 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
vars.LanguageCompileFlags = langFlags.c_str(); vars.LanguageCompileFlags = langFlags.c_str();
// Expand placeholders in the commands. // Expand placeholders in the commands.
this->LocalGenerator->TargetImplib = targetOutPathImport; this->LocalGenerator->TargetImplib = targetOutPathImport;
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
{
for(std::vector<std::string>::iterator i = commands.begin(); for(std::vector<std::string>::iterator i = commands.begin();
i != commands.end(); ++i) i != commands.end(); ++i)
{ {
this->LocalGenerator->ExpandRuleVariables(*i, vars); this->LocalGenerator->ExpandRuleVariables(*i, vars);
} }
}
this->LocalGenerator->TargetImplib = ""; 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. // Write the build rule.
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
targetFullPathReal.c_str(), targetFullPathReal.c_str(),

View File

@ -808,6 +808,56 @@ cmMakefileTargetGenerator
*this->BuildFileStream << "\n" << "\n"; *this->BuildFileStream << "\n" << "\n";
} }
//----------------------------------------------------------------------------
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, void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
bool relink) bool relink)

View File

@ -91,6 +91,7 @@ protected:
// write out the variable that lists the objects for this target // write out the variable that lists the objects for this target
void WriteObjectsVariable(std::string& variableName, void WriteObjectsVariable(std::string& variableName,
std::string& variableNameExternal); std::string& variableNameExternal);
void WriteObjectsString(std::string& buildObjs);
// write the driver rule to build target outputs // write the driver rule to build target outputs
void WriteTargetDriverRule(const char* main_output, bool relink); void WriteTargetDriverRule(const char* main_output, bool relink);

View File

@ -32,6 +32,7 @@
#endif #endif
# include <cmsys/Directory.hxx> # include <cmsys/Directory.hxx>
#include <cmsys/Process.h>
// only build kdevelop generator on non-windows platforms // only build kdevelop generator on non-windows platforms
// when not bootstrapping cmake // when not bootstrapping cmake
@ -1178,6 +1179,12 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1; 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 #ifdef CMAKE_BUILD_WITH_CMAKE
// Internal CMake color makefile support. // Internal CMake color makefile support.
else if (args[1] == "cmake_echo_color") else if (args[1] == "cmake_echo_color")
@ -2643,3 +2650,101 @@ int cmake::ExecuteEchoColor(std::vector<std::string>&)
return 1; return 1;
} }
#endif #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;
}

View File

@ -323,6 +323,7 @@ protected:
void GenerateGraphViz(const char* fileName); void GenerateGraphViz(const char* fileName);
static int ExecuteEchoColor(std::vector<std::string>& args); static int ExecuteEchoColor(std::vector<std::string>& args);
static int ExecuteLinkScript(std::vector<std::string>& args);
cmVariableWatch* VariableWatch; cmVariableWatch* VariableWatch;