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->ForceUnixPaths = false;
|
||||
this->ToolSupportsColor = true;
|
||||
this->UseLinkScript = false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -24,6 +24,7 @@ cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator()
|
|||
this->FindMakeProgramFile = "CMakeMSYSFindMake.cmake";
|
||||
this->ForceUnixPaths = true;
|
||||
this->ToolSupportsColor = true;
|
||||
this->UseLinkScript = false;
|
||||
}
|
||||
|
||||
std::string
|
||||
|
|
|
@ -23,6 +23,7 @@ cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator()
|
|||
this->FindMakeProgramFile = "CMakeMinGWFindMake.cmake";
|
||||
this->ForceUnixPaths = true;
|
||||
this->ToolSupportsColor = true;
|
||||
this->UseLinkScript = true;
|
||||
}
|
||||
|
||||
void cmGlobalMinGWMakefileGenerator
|
||||
|
|
|
@ -23,6 +23,7 @@ cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator()
|
|||
this->FindMakeProgramFile = "CMakeNMakeFindMake.cmake";
|
||||
this->ForceUnixPaths = false;
|
||||
this->ToolSupportsColor = true;
|
||||
this->UseLinkScript = false;
|
||||
}
|
||||
|
||||
void cmGlobalNMakeMakefileGenerator
|
||||
|
|
|
@ -31,6 +31,7 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
|
|||
this->ToolSupportsColor = true;
|
||||
this->NumberOfSourceFiles = 0;
|
||||
this->NumberOfSourceFilesWritten = 0;
|
||||
this->UseLinkScript = true;
|
||||
}
|
||||
|
||||
void cmGlobalUnixMakefileGenerator3
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
this->LocalGenerator->ExpandRuleVariables(*i, vars);
|
||||
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();
|
||||
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(),
|
||||
|
|
|
@ -808,6 +808,56 @@ cmMakefileTargetGenerator
|
|||
*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,
|
||||
bool relink)
|
||||
|
|
|
@ -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);
|
||||
|
|
105
Source/cmake.cxx
105
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue