ENH: Simplified and moved link script implementation up from cmMakefileLibraryTargetGenerator to cmMakefileTargetGenerator and use for cmMakefileExecutableTargetGenerator too. This addresses bug #6192.
This commit is contained in:
parent
0a7bb41129
commit
59aa144516
|
@ -339,14 +339,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||
->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
|
||||
}
|
||||
|
||||
// Determine whether a link script will be used.
|
||||
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
|
||||
|
||||
// Construct the main link rule.
|
||||
std::vector<std::string> real_link_commands;
|
||||
std::string linkRuleVar = "CMAKE_";
|
||||
linkRuleVar += linkLanguage;
|
||||
linkRuleVar += "_LINK_EXECUTABLE";
|
||||
std::string linkRule =
|
||||
this->Makefile->GetRequiredDefinition(linkRuleVar.c_str());
|
||||
std::vector<std::string> commands1;
|
||||
cmSystemTools::ExpandListArgument(linkRule, commands1);
|
||||
cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
|
||||
if(this->Target->GetPropertyAsBool("ENABLE_EXPORTS"))
|
||||
{
|
||||
// If a separate rule for creating an import library is specified
|
||||
|
@ -357,37 +361,12 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||
if(const char* rule =
|
||||
this->Makefile->GetDefinition(implibRuleVar.c_str()))
|
||||
{
|
||||
cmSystemTools::ExpandListArgument(rule, commands1);
|
||||
cmSystemTools::ExpandListArgument(rule, real_link_commands);
|
||||
}
|
||||
}
|
||||
this->LocalGenerator->CreateCDCommand
|
||||
(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
|
||||
// Add a rule to create necessary symlinks for the library.
|
||||
if(targetOutPath != targetOutPathReal)
|
||||
{
|
||||
std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_executable ";
|
||||
symlink += targetOutPathReal;
|
||||
symlink += " ";
|
||||
symlink += targetOutPath;
|
||||
commands1.clear();
|
||||
commands1.push_back(symlink);
|
||||
this->LocalGenerator->CreateCDCommand(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
}
|
||||
|
||||
// Add the post-build rules when building but not when relinking.
|
||||
if(!relink)
|
||||
{
|
||||
this->LocalGenerator->
|
||||
AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
|
||||
}
|
||||
|
||||
// Expand the rule variables.
|
||||
{
|
||||
// Collect up flags to link in needed libraries.
|
||||
cmOStringStream linklibs;
|
||||
this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink);
|
||||
|
@ -397,11 +376,19 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||
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 += ")";
|
||||
|
@ -435,12 +422,55 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||
vars.LinkFlags = linkFlags.c_str();
|
||||
// Expand placeholders in the commands.
|
||||
this->LocalGenerator->TargetImplib = targetOutPathImport;
|
||||
for(std::vector<std::string>::iterator i = commands.begin();
|
||||
i != commands.end(); ++i)
|
||||
for(std::vector<std::string>::iterator i = real_link_commands.begin();
|
||||
i != real_link_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)
|
||||
{
|
||||
// Use a link script.
|
||||
const char* name = (relink? "relink.txt" : "link.txt");
|
||||
this->CreateLinkScript(name, real_link_commands, commands1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No link script. Just use the link rule directly.
|
||||
commands1 = real_link_commands;
|
||||
}
|
||||
this->LocalGenerator->CreateCDCommand
|
||||
(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
commands1.clear();
|
||||
|
||||
// Add a rule to create necessary symlinks for the library.
|
||||
if(targetOutPath != targetOutPathReal)
|
||||
{
|
||||
std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_executable ";
|
||||
symlink += targetOutPathReal;
|
||||
symlink += " ";
|
||||
symlink += targetOutPath;
|
||||
commands1.push_back(symlink);
|
||||
this->LocalGenerator->CreateCDCommand(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
commands1.clear();
|
||||
}
|
||||
|
||||
// Add the post-build rules when building but not when relinking.
|
||||
if(!relink)
|
||||
{
|
||||
this->LocalGenerator->
|
||||
AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
|
||||
}
|
||||
|
||||
// Write the build rule.
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream,
|
||||
|
|
|
@ -668,77 +668,16 @@ 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;
|
||||
if(relink)
|
||||
{
|
||||
linkScriptName += "/relink.txt";
|
||||
}
|
||||
else
|
||||
{
|
||||
linkScriptName += "/link.txt";
|
||||
}
|
||||
std::auto_ptr<cmGeneratedFileStream> lss(
|
||||
new cmGeneratedFileStream(linkScriptName.c_str()));
|
||||
linkScriptStream = lss;
|
||||
}
|
||||
|
||||
std::vector<std::string> link_script_commands;
|
||||
// Determine whether a link script will be used.
|
||||
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
|
||||
|
||||
// Construct the main link rule.
|
||||
std::vector<std::string> real_link_commands;
|
||||
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);
|
||||
}
|
||||
this->LocalGenerator->CreateCDCommand
|
||||
(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
|
||||
// Add a rule to create necessary symlinks for the library.
|
||||
if(targetOutPath != targetOutPathReal)
|
||||
{
|
||||
std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
|
||||
symlink += targetOutPathReal;
|
||||
symlink += " ";
|
||||
symlink += targetOutPathSO;
|
||||
symlink += " ";
|
||||
symlink += targetOutPath;
|
||||
commands1.clear();
|
||||
commands1.push_back(symlink);
|
||||
this->LocalGenerator->CreateCDCommand(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
}
|
||||
// Add the post-build rules when building but not when relinking.
|
||||
if(!relink)
|
||||
{
|
||||
this->LocalGenerator->
|
||||
AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
|
||||
}
|
||||
cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
|
||||
|
||||
// Expand the rule variables.
|
||||
{
|
||||
// Collect up flags to link in needed libraries.
|
||||
cmOStringStream linklibs;
|
||||
this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink);
|
||||
|
@ -834,38 +773,55 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
|||
vars.LanguageCompileFlags = langFlags.c_str();
|
||||
// Expand placeholders in the commands.
|
||||
this->LocalGenerator->TargetImplib = targetOutPathImport;
|
||||
if(useLinkScript)
|
||||
for(std::vector<std::string>::iterator i = real_link_commands.begin();
|
||||
i != real_link_commands.end(); ++i)
|
||||
{
|
||||
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->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)
|
||||
{
|
||||
// Do not write out empty commands or commands beginning in the
|
||||
// shell no-op ":".
|
||||
if(!cmd->empty() && (*cmd)[0] != ':')
|
||||
{
|
||||
(*linkScriptStream) << *cmd << "\n";
|
||||
}
|
||||
}
|
||||
// Use a link script.
|
||||
const char* name = (relink? "relink.txt" : "link.txt");
|
||||
this->CreateLinkScript(name, real_link_commands, commands1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No link script. Just use the link rule directly.
|
||||
commands1 = real_link_commands;
|
||||
}
|
||||
this->LocalGenerator->CreateCDCommand
|
||||
(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
commands1.clear();
|
||||
|
||||
// Add a rule to create necessary symlinks for the library.
|
||||
if(targetOutPath != targetOutPathReal)
|
||||
{
|
||||
std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
|
||||
symlink += targetOutPathReal;
|
||||
symlink += " ";
|
||||
symlink += targetOutPathSO;
|
||||
symlink += " ";
|
||||
symlink += targetOutPath;
|
||||
commands1.push_back(symlink);
|
||||
this->LocalGenerator->CreateCDCommand(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
commands1.clear();
|
||||
}
|
||||
// Add the post-build rules when building but not when relinking.
|
||||
if(!relink)
|
||||
{
|
||||
this->LocalGenerator->
|
||||
AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
|
||||
}
|
||||
|
||||
// Write the build rule.
|
||||
|
|
|
@ -1391,3 +1391,35 @@ cmMakefileTargetGenerator
|
|||
MultipleOutputPairsType::value_type p(depender, dependee);
|
||||
this->MultipleOutputPairs.insert(p);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmMakefileTargetGenerator
|
||||
::CreateLinkScript(const char* name,
|
||||
std::vector<std::string> const& link_commands,
|
||||
std::vector<std::string>& makefile_commands)
|
||||
{
|
||||
// Create the link script file.
|
||||
std::string linkScriptName = this->TargetBuildDirectoryFull;
|
||||
linkScriptName += "/";
|
||||
linkScriptName += name;
|
||||
cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
|
||||
for(std::vector<std::string>::const_iterator cmd = link_commands.begin();
|
||||
cmd != link_commands.end(); ++cmd)
|
||||
{
|
||||
// Do not write out empty commands or commands beginning in the
|
||||
// shell no-op ":".
|
||||
if(!cmd->empty() && (*cmd)[0] != ':')
|
||||
{
|
||||
linkScriptStream << *cmd << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Create the makefile command to invoke the link script.
|
||||
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)";
|
||||
makefile_commands.push_back(link_command);
|
||||
}
|
||||
|
|
|
@ -128,6 +128,12 @@ protected:
|
|||
makefile generators to register such pairs. */
|
||||
void AddMultipleOutputPair(const char* depender, const char* dependee);
|
||||
|
||||
/** Create a script to hold link rules and a command to invoke the
|
||||
script at build time. */
|
||||
void CreateLinkScript(const char* name,
|
||||
std::vector<std::string> const& link_commands,
|
||||
std::vector<std::string>& makefile_commands);
|
||||
|
||||
virtual void CloseFileStreams();
|
||||
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
|
||||
std::string& linkFlags);
|
||||
|
|
Loading…
Reference in New Issue