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());
|
->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine whether a link script will be used.
|
||||||
|
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
|
||||||
|
|
||||||
// Construct the main link rule.
|
// Construct the main link rule.
|
||||||
|
std::vector<std::string> real_link_commands;
|
||||||
std::string linkRuleVar = "CMAKE_";
|
std::string linkRuleVar = "CMAKE_";
|
||||||
linkRuleVar += linkLanguage;
|
linkRuleVar += linkLanguage;
|
||||||
linkRuleVar += "_LINK_EXECUTABLE";
|
linkRuleVar += "_LINK_EXECUTABLE";
|
||||||
std::string linkRule =
|
std::string linkRule =
|
||||||
this->Makefile->GetRequiredDefinition(linkRuleVar.c_str());
|
this->Makefile->GetRequiredDefinition(linkRuleVar.c_str());
|
||||||
std::vector<std::string> commands1;
|
std::vector<std::string> commands1;
|
||||||
cmSystemTools::ExpandListArgument(linkRule, commands1);
|
cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
|
||||||
if(this->Target->GetPropertyAsBool("ENABLE_EXPORTS"))
|
if(this->Target->GetPropertyAsBool("ENABLE_EXPORTS"))
|
||||||
{
|
{
|
||||||
// If a separate rule for creating an import library is specified
|
// If a separate rule for creating an import library is specified
|
||||||
|
@ -357,37 +361,12 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
||||||
if(const char* rule =
|
if(const char* rule =
|
||||||
this->Makefile->GetDefinition(implibRuleVar.c_str()))
|
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.
|
// Collect up flags to link in needed libraries.
|
||||||
cmOStringStream linklibs;
|
cmOStringStream linklibs;
|
||||||
this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink);
|
this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink);
|
||||||
|
@ -397,11 +376,19 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
||||||
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;
|
||||||
buildObjs += variableName;
|
if(useLinkScript)
|
||||||
buildObjs += ") $(";
|
{
|
||||||
buildObjs += variableNameExternal;
|
this->WriteObjectsString(buildObjs);
|
||||||
buildObjs += ")";
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buildObjs = "$(";
|
||||||
|
buildObjs += variableName;
|
||||||
|
buildObjs += ") $(";
|
||||||
|
buildObjs += variableNameExternal;
|
||||||
|
buildObjs += ")";
|
||||||
|
}
|
||||||
std::string cleanObjs = "$(";
|
std::string cleanObjs = "$(";
|
||||||
cleanObjs += variableName;
|
cleanObjs += variableName;
|
||||||
cleanObjs += ")";
|
cleanObjs += ")";
|
||||||
|
@ -435,12 +422,55 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
||||||
vars.LinkFlags = linkFlags.c_str();
|
vars.LinkFlags = linkFlags.c_str();
|
||||||
// Expand placeholders in the commands.
|
// Expand placeholders in the commands.
|
||||||
this->LocalGenerator->TargetImplib = targetOutPathImport;
|
this->LocalGenerator->TargetImplib = targetOutPathImport;
|
||||||
for(std::vector<std::string>::iterator i = commands.begin();
|
for(std::vector<std::string>::iterator i = real_link_commands.begin();
|
||||||
i != commands.end(); ++i)
|
i != real_link_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)
|
||||||
|
{
|
||||||
|
// 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.
|
// Write the build rule.
|
||||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream,
|
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream,
|
||||||
|
|
|
@ -668,77 +668,16 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
||||||
->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
|
->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the link script if it will be used.
|
// Determine whether a link script will be used.
|
||||||
bool useLinkScript = false;
|
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
|
||||||
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;
|
|
||||||
|
|
||||||
// Construct the main link rule.
|
// Construct the main link rule.
|
||||||
|
std::vector<std::string> real_link_commands;
|
||||||
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
|
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
|
||||||
if(useLinkScript)
|
cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
|
||||||
{
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Expand the rule variables.
|
||||||
|
{
|
||||||
// Collect up flags to link in needed libraries.
|
// Collect up flags to link in needed libraries.
|
||||||
cmOStringStream linklibs;
|
cmOStringStream linklibs;
|
||||||
this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink);
|
this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink);
|
||||||
|
@ -834,38 +773,55 @@ 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 = real_link_commands.begin();
|
||||||
|
i != real_link_commands.end(); ++i)
|
||||||
{
|
{
|
||||||
for(std::vector<std::string>::iterator i = link_script_commands.begin();
|
this->LocalGenerator->ExpandRuleVariables(*i, vars);
|
||||||
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 = "";
|
this->LocalGenerator->TargetImplib = "";
|
||||||
|
}
|
||||||
|
|
||||||
// Optionally convert the build rule to use a script to avoid long
|
// Optionally convert the build rule to use a script to avoid long
|
||||||
// command lines in the make shell.
|
// command lines in the make shell.
|
||||||
if(useLinkScript)
|
if(useLinkScript)
|
||||||
{
|
{
|
||||||
for(std::vector<std::string>::iterator cmd = link_script_commands.begin();
|
// Use a link script.
|
||||||
cmd != link_script_commands.end(); ++cmd)
|
const char* name = (relink? "relink.txt" : "link.txt");
|
||||||
{
|
this->CreateLinkScript(name, real_link_commands, commands1);
|
||||||
// Do not write out empty commands or commands beginning in the
|
}
|
||||||
// shell no-op ":".
|
else
|
||||||
if(!cmd->empty() && (*cmd)[0] != ':')
|
{
|
||||||
{
|
// No link script. Just use the link rule directly.
|
||||||
(*linkScriptStream) << *cmd << "\n";
|
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.
|
// Write the build rule.
|
||||||
|
|
|
@ -1391,3 +1391,35 @@ cmMakefileTargetGenerator
|
||||||
MultipleOutputPairsType::value_type p(depender, dependee);
|
MultipleOutputPairsType::value_type p(depender, dependee);
|
||||||
this->MultipleOutputPairs.insert(p);
|
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. */
|
makefile generators to register such pairs. */
|
||||||
void AddMultipleOutputPair(const char* depender, const char* dependee);
|
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();
|
virtual void CloseFileStreams();
|
||||||
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
|
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
|
||||||
std::string& linkFlags);
|
std::string& linkFlags);
|
||||||
|
|
Loading…
Reference in New Issue