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:
parent
6438bec4c9
commit
0bbcb49f65
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
105
Source/cmake.cxx
105
Source/cmake.cxx
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue