ENH: Add cmTarget::GetLinkInformation method to allow several places in the generators to share link information while only computing it once per configuration for a target. Use it to simplify the chrpath feature.

This commit is contained in:
Brad King 2008-01-29 15:07:33 -05:00
parent bb52f45ebb
commit ffac622a85
11 changed files with 305 additions and 270 deletions

View File

@ -168,6 +168,12 @@ cmComputeLinkInformation
// Get the language used for linking this target. // Get the language used for linking this target.
this->LinkLanguage = this->LinkLanguage =
this->Target->GetLinkerLanguage(this->GlobalGenerator); this->Target->GetLinkerLanguage(this->GlobalGenerator);
if(!this->LinkLanguage)
{
// The Compute method will do nothing, so skip the rest of the
// initialization.
return;
}
// Check whether we should use an import library for linking a target. // Check whether we should use an import library for linking a target.
this->UseImportLibrary = this->UseImportLibrary =
@ -194,6 +200,31 @@ cmComputeLinkInformation
this->LibLinkSuffix = this->LibLinkSuffix =
this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"); this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
// Get options needed to specify RPATHs.
this->RuntimeUseChrpath = false;
if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
{
std::string rtVar = "CMAKE_";
if(this->Target->GetType() == cmTarget::EXECUTABLE)
{
rtVar += "EXECUTABLE";
}
else
{
rtVar += "SHARED_LIBRARY";
}
rtVar += "_RUNTIME_";
rtVar += this->LinkLanguage;
rtVar += "_FLAG";
std::string rtSepVar = rtVar + "_SEP";
this->RuntimeFlag = this->Makefile->GetSafeDefinition(rtVar.c_str());
this->RuntimeSep = this->Makefile->GetSafeDefinition(rtSepVar.c_str());
this->RuntimeAlways =
(this->Makefile->
GetSafeDefinition("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH"));
this->RuntimeUseChrpath = this->Target->IsChrpathUsed();
}
// Get link type information. // Get link type information.
this->ComputeLinkTypeInfo(); this->ComputeLinkTypeInfo();
@ -1227,3 +1258,105 @@ void cmComputeLinkInformation::DiagnoseCycle()
} }
cmSystemTools::Message(e.str().c_str()); cmSystemTools::Message(e.str().c_str());
} }
//----------------------------------------------------------------------------
void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
bool for_install)
{
// Select whether to generate runtime search directories.
bool outputRuntime =
!this->Makefile->IsOn("CMAKE_SKIP_RPATH") && !this->RuntimeFlag.empty();
// Select whether to generate an rpath for the install tree or the
// build tree.
bool linking_for_install =
(for_install ||
this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"));
bool use_install_rpath =
(outputRuntime && this->Target->HaveInstallTreeRPATH() &&
linking_for_install);
bool use_build_rpath =
(outputRuntime && this->Target->HaveBuildTreeRPATH() &&
!linking_for_install);
bool use_link_rpath =
outputRuntime && linking_for_install &&
this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
// Construct the RPATH.
if(use_install_rpath)
{
const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH");
cmSystemTools::ExpandListArgument(install_rpath, runtimeDirs);
}
if(use_build_rpath || use_link_rpath)
{
std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath();
for(std::vector<std::string>::const_iterator ri = rdirs.begin();
ri != rdirs.end(); ++ri)
{
// Put this directory in the rpath if using build-tree rpath
// support or if using the link path as an rpath.
if(use_build_rpath)
{
runtimeDirs.push_back(*ri);
}
else if(use_link_rpath)
{
// Do not add any path inside the source or build tree.
const char* topSourceDir = this->Makefile->GetHomeDirectory();
const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
if(!cmSystemTools::ComparePath(ri->c_str(), topSourceDir) &&
!cmSystemTools::ComparePath(ri->c_str(), topBinaryDir) &&
!cmSystemTools::IsSubDirectory(ri->c_str(), topSourceDir) &&
!cmSystemTools::IsSubDirectory(ri->c_str(), topBinaryDir))
{
runtimeDirs.push_back(*ri);
}
}
}
}
// Add runtime paths required by the platform to always be
// present. This is done even when skipping rpath support.
cmSystemTools::ExpandListArgument(this->RuntimeAlways.c_str(), runtimeDirs);
}
//----------------------------------------------------------------------------
std::string cmComputeLinkInformation::GetRPathString(bool for_install)
{
// Get the directories to use.
std::vector<std::string> runtimeDirs;
this->GetRPath(runtimeDirs, for_install);
// Concatenate the paths.
std::string rpath;
const char* sep = "";
for(std::vector<std::string>::const_iterator ri = runtimeDirs.begin();
ri != runtimeDirs.end(); ++ri)
{
// Separate from previous path.
rpath += sep;
sep = this->GetRuntimeSep().c_str();
// Add this path.
rpath += *ri;
}
return rpath;
}
//----------------------------------------------------------------------------
std::string cmComputeLinkInformation::GetChrpathString()
{
if(!this->RuntimeUseChrpath)
{
return "";
}
return this->GetRPathString(true);
}
//----------------------------------------------------------------------------
std::string cmComputeLinkInformation::GetChrpathTool()
{
return this->Makefile->GetSafeDefinition("CMAKE_CHRPATH");
}

View File

@ -50,6 +50,12 @@ public:
std::vector<std::string> const& GetFrameworkPaths(); std::vector<std::string> const& GetFrameworkPaths();
const char* GetLinkLanguage() const { return this->LinkLanguage; } const char* GetLinkLanguage() const { return this->LinkLanguage; }
std::vector<std::string> const& GetRuntimeSearchPath(); std::vector<std::string> const& GetRuntimeSearchPath();
std::string const& GetRuntimeFlag() const { return this->RuntimeFlag; }
std::string const& GetRuntimeSep() const { return this->RuntimeSep; }
void GetRPath(std::vector<std::string>& runtimeDirs, bool for_install);
std::string GetRPathString(bool for_install);
std::string GetChrpathString();
std::string GetChrpathTool();
private: private:
void AddItem(std::string const& item, cmTarget* tgt); void AddItem(std::string const& item, cmTarget* tgt);
@ -76,6 +82,10 @@ private:
std::string LibLinkFlag; std::string LibLinkFlag;
std::string LibLinkFileFlag; std::string LibLinkFileFlag;
std::string LibLinkSuffix; std::string LibLinkSuffix;
std::string RuntimeFlag;
std::string RuntimeSep;
std::string RuntimeAlways;
bool RuntimeUseChrpath;
// Link type adjustment. // Link type adjustment.
void ComputeLinkTypeInfo(); void ComputeLinkTypeInfo();

View File

@ -2105,11 +2105,12 @@ void cmGlobalXCodeGenerator
} }
// Compute the link library and directory information. // Compute the link library and directory information.
cmComputeLinkInformation cli(cmtarget, configName); cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName);
if(!cli.Compute()) if(!pcli)
{ {
continue; continue;
} }
cmComputeLinkInformation& cli = *pcli;
// Add dependencies directly on library files. // Add dependencies directly on library files.
{ {

View File

@ -16,6 +16,7 @@
=========================================================================*/ =========================================================================*/
#include "cmInstallTargetGenerator.h" #include "cmInstallTargetGenerator.h"
#include "cmComputeLinkInformation.h"
#include "cmGlobalGenerator.h" #include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmMakefile.h" #include "cmMakefile.h"
@ -283,7 +284,7 @@ cmInstallTargetGenerator
os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n"; os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n";
this->AddInstallNamePatchRule(os, indent.Next(), config, toDestDirPath); this->AddInstallNamePatchRule(os, indent.Next(), config, toDestDirPath);
this->AddChrpathPatchRule(os, indent.Next(), toDestDirPath); this->AddChrpathPatchRule(os, indent.Next(), config, toDestDirPath);
this->AddRanlibRule(os, indent.Next(), type, toDestDirPath); this->AddRanlibRule(os, indent.Next(), type, toDestDirPath);
this->AddStripRule(os, indent.Next(), type, toDestDirPath); this->AddStripRule(os, indent.Next(), type, toDestDirPath);
os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n"; os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n";
@ -487,7 +488,7 @@ cmInstallTargetGenerator
void void
cmInstallTargetGenerator cmInstallTargetGenerator
::AddChrpathPatchRule(std::ostream& os, Indent const& indent, ::AddChrpathPatchRule(std::ostream& os, Indent const& indent,
std::string const& toDestDirPath) const char* config, std::string const& toDestDirPath)
{ {
if(this->ImportLibrary || if(this->ImportLibrary ||
!(this->Target->GetType() == cmTarget::SHARED_LIBRARY || !(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
@ -497,40 +498,24 @@ cmInstallTargetGenerator
return; return;
} }
if((this->Target->GetMakefile()->IsOn("CMAKE_USE_CHRPATH")==false) if(!this->Target->IsChrpathUsed())
|| (this->Target->IsChrpathAvailable()==false))
{ {
return; return;
} }
// Get the link information for this target.
// It can provide the RPATH.
cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
if(!cli)
{
return;
}
// Get the install RPATH from the link information.
std::string newRpath = cli->GetChrpathString();
// Fix the RPATH in installed ELF binaries using chrpath. // Fix the RPATH in installed ELF binaries using chrpath.
std::string chrpathTool = std::string chrpathTool = cli->GetChrpathTool();
this->Target->GetMakefile()->GetSafeDefinition("CMAKE_CHRPATH");
std::string installRpath;
std::string dummy;
this->Target->GetMakefile()->GetLocalGenerator()->GetLinkerArgs(
installRpath, dummy, *this->Target, true, 0);
const char* linkLanguage = this->Target->GetLinkerLanguage(this->Target->
GetMakefile()->GetLocalGenerator()->GetGlobalGenerator());
if (linkLanguage==0)
{
return;
}
std::string runTimeFlagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
runTimeFlagVar += linkLanguage;
runTimeFlagVar += "_FLAG";
std::string runtimeFlag =
this->Target->GetMakefile()->GetSafeDefinition(runTimeFlagVar.c_str());
const char* newRpath=installRpath.c_str();
if (strstr(installRpath.c_str(), runtimeFlag.c_str())==installRpath.c_str())
{
newRpath = installRpath.c_str()+strlen(runtimeFlag.c_str());
}
// Write a rule to run chrpath to set the install-tree RPATH // Write a rule to run chrpath to set the install-tree RPATH
os << indent << "EXECUTE_PROCESS(COMMAND \"" << chrpathTool; os << indent << "EXECUTE_PROCESS(COMMAND \"" << chrpathTool;

View File

@ -58,6 +58,7 @@ protected:
const char* config, const char* config,
const std::string& toDestDirPath); const std::string& toDestDirPath);
void AddChrpathPatchRule(std::ostream& os, Indent const& indent, void AddChrpathPatchRule(std::ostream& os, Indent const& indent,
const char* config,
std::string const& toDestDirPath); std::string const& toDestDirPath);
void AddStripRule(std::ostream& os, Indent const& indent, void AddStripRule(std::ostream& os, Indent const& indent,

View File

@ -1483,70 +1483,33 @@ std::string cmLocalGenerator::ConvertToLinkReference(std::string const& lib)
return this->Convert(lib.c_str(), START_OUTPUT, SHELL); return this->Convert(lib.c_str(), START_OUTPUT, SHELL);
} }
bool cmLocalGenerator::GetLinkerArgs(std::string& rpath, /**
std::string& linkLibs, * Output the linking rules on a command line. For executables,
cmTarget& tgt, * targetLibrary should be a NULL pointer. For libraries, it should point
bool relink, * to the name of the library. This will not link a library against itself.
unsigned int minRpathSize) */
void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
cmTarget& tgt,
bool relink)
{ {
rpath = "";
// collect all the flags needed for linking libraries
linkLibs = "";
const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config);
cmComputeLinkInformation cli(&tgt, config); if(!pcli)
if(!cli.Compute())
{ {
return false; return;
} }
cmComputeLinkInformation& cli = *pcli;
// Collect library linking flags command line options.
std::string linkLibs;
const char* linkLanguage = cli.GetLinkLanguage(); const char* linkLanguage = cli.GetLinkLanguage();
// Embed runtime search paths if possible and if required.
bool outputRuntime = !this->Makefile->IsOn("CMAKE_SKIP_RPATH");
// Lookup rpath specification flags.
std::string runtimeFlag;
std::string runtimeSep;
if(tgt.GetType() != cmTarget::STATIC_LIBRARY)
{
std::string runTimeFlagVar = "CMAKE_";
if(tgt.GetType() == cmTarget::EXECUTABLE)
{
runTimeFlagVar += "EXECUTABLE";
}
else
{
runTimeFlagVar += "SHARED_LIBRARY";
}
runTimeFlagVar += "_RUNTIME_";
runTimeFlagVar += linkLanguage;
runTimeFlagVar += "_FLAG";
std::string runTimeFlagSepVar = runTimeFlagVar + "_SEP";
runtimeFlag = this->Makefile->GetSafeDefinition(runTimeFlagVar.c_str());
runtimeSep = this->Makefile->GetSafeDefinition(runTimeFlagSepVar.c_str());
}
// concatenate all paths or no?
bool runtimeConcatenate = !runtimeSep.empty();
const char* runtimeAlways =
this->Makefile->GetDefinition("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH");
// Turn off rpath support if no flag is available to specify it.
if(runtimeFlag.empty())
{
outputRuntime = false;
runtimeAlways = 0;
}
std::string libPathFlag = std::string libPathFlag =
this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG"); this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
std::string libPathTerminator = std::string libPathTerminator =
this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR"); this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR");
std::string libLinkFlag =
this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG");
// Flags to link an executable to shared libraries. // Flags to link an executable to shared libraries.
std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_"; std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_";
linkFlagsVar += linkLanguage; linkFlagsVar += linkLanguage;
@ -1595,146 +1558,55 @@ bool cmLocalGenerator::GetLinkerArgs(std::string& rpath,
linkLibs += " "; linkLibs += " ";
} }
// Select whether to generate an rpath for the install tree or the // Write the library flags to the build rule.
// build tree.
bool linking_for_install =
relink || tgt.GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
bool use_install_rpath =
outputRuntime && tgt.HaveInstallTreeRPATH() && linking_for_install;
bool use_build_rpath =
outputRuntime && tgt.HaveBuildTreeRPATH() && !linking_for_install;
bool use_link_rpath =
outputRuntime && linking_for_install &&
tgt.GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
// Construct the RPATH.
std::vector<std::string> runtimeDirs;
if(use_install_rpath)
{
const char* install_rpath = tgt.GetProperty("INSTALL_RPATH");
cmSystemTools::ExpandListArgument(install_rpath, runtimeDirs);
}
if(use_build_rpath || use_link_rpath)
{
std::vector<std::string> const& rdirs = cli.GetRuntimeSearchPath();
for(std::vector<std::string>::const_iterator ri = rdirs.begin();
ri != rdirs.end(); ++ri)
{
// Put this directory in the rpath if using build-tree rpath
// support or if using the link path as an rpath.
if(use_build_rpath)
{
runtimeDirs.push_back(*ri);
}
else if(use_link_rpath)
{
// Do not add any path inside the source or build tree.
const char* topSourceDir = this->Makefile->GetHomeDirectory();
const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
if(!cmSystemTools::ComparePath(ri->c_str(), topSourceDir) &&
!cmSystemTools::ComparePath(ri->c_str(), topBinaryDir) &&
!cmSystemTools::IsSubDirectory(ri->c_str(), topSourceDir) &&
!cmSystemTools::IsSubDirectory(ri->c_str(), topBinaryDir))
{
runtimeDirs.push_back(*ri);
}
}
}
}
if(runtimeAlways)
{
// Add runtime paths required by the platform to always be
// present. This is done even when skipping rpath support.
cmSystemTools::ExpandListArgument(runtimeAlways, runtimeDirs);
}
// Convert the runtime directory names for use in the build file.
for(std::vector<std::string>::iterator ri = runtimeDirs.begin();
ri != runtimeDirs.end(); ++ri)
{
*ri = this->Convert(ri->c_str(), FULL, SHELL, false);
}
if(!runtimeDirs.empty())
{
// For the runtime search directories, do a "-Wl,-rpath,a:b:c" or
// a "-R a -R b -R c" type link line
rpath += runtimeFlag;
std::vector<std::string>::iterator itr = runtimeDirs.begin();
rpath += *itr;
++itr;
for( ; itr != runtimeDirs.end(); ++itr )
{
if(runtimeConcatenate)
{
rpath += runtimeSep;
rpath += *itr;
}
else
{
rpath += " ";
rpath += runtimeFlag;
rpath += *itr;
}
}
}
while (rpath.size() < minRpathSize)
{
if (rpath.size()==0)
{
rpath += runtimeFlag;
}
rpath += runtimeSep;
}
return true;
}
/**
* Output the linking rules on a command line. For executables,
* targetLibrary should be a NULL pointer. For libraries, it should point
* to the name of the library. This will not link a library against itself.
*/
void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
cmTarget& tgt,
bool relink)
{
std::string rpath;
std::string linkLibs;
unsigned int minBuildRpathSize = 0;
if ((relink==false)
&& this->Makefile->IsOn("CMAKE_USE_CHRPATH")
&& (tgt.IsChrpathAvailable()))
{
std::string installRpath;
std::string dummy;
this->GetLinkerArgs(installRpath, dummy, tgt, true, 0);
minBuildRpathSize = static_cast<unsigned int>(installRpath.size());
}
if (!this->GetLinkerArgs(rpath, linkLibs, tgt, relink, minBuildRpathSize))
{
return;
}
const char* linkLanguage =
tgt.GetLinkerLanguage(this->GetGlobalGenerator());
if(!linkLanguage)
{
cmSystemTools::
Error("CMake can not determine linker language for target:",
tgt.GetName());
return;
}
fout << linkLibs; fout << linkLibs;
fout << rpath << " ";
// Get the RPATH entries.
std::vector<std::string> runtimeDirs;
cli.GetRPath(runtimeDirs, relink);
// Check what kind of rpath flags to use.
if(cli.GetRuntimeSep().empty())
{
// Each rpath entry gets its own option ("-R a -R b -R c")
std::string rpath;
for(std::vector<std::string>::iterator ri = runtimeDirs.begin();
ri != runtimeDirs.end(); ++ri)
{
rpath += cli.GetRuntimeFlag();
rpath += this->Convert(ri->c_str(), FULL, SHELL, false);
rpath += " ";
}
fout << rpath;
}
else
{
// All rpath entries are combined ("-Wl,-rpath,a:b:c").
std::string rpath = cli.GetRPathString(relink);
// If not relinking, make sure the rpath string is long enough to
// support a subsequent chrpath on installation.
if(!relink)
{
std::string::size_type minLength = cli.GetChrpathString().size();
while(rpath.size() < minLength)
{
rpath += cli.GetRuntimeSep();
}
}
// Store the rpath option in the stream.
if(!rpath.empty())
{
fout << cli.GetRuntimeFlag();
fout << this->EscapeForShell(rpath.c_str(), true);
fout << " ";
}
}
// Add standard libraries for this language. // Add standard libraries for this language.
std::string standardLibsVar = "CMAKE_"; std::string standardLibsVar = "CMAKE_";
standardLibsVar += linkLanguage; standardLibsVar += cli.GetLinkLanguage();
standardLibsVar += "_STANDARD_LIBRARIES"; standardLibsVar += "_STANDARD_LIBRARIES";
if(const char* stdLibs = if(const char* stdLibs =
this->Makefile->GetDefinition(standardLibsVar.c_str())) this->Makefile->GetDefinition(standardLibsVar.c_str()))

View File

@ -248,13 +248,6 @@ public:
*/ */
virtual std::string GetTargetDirectory(cmTarget const& target) const; virtual std::string GetTargetDirectory(cmTarget const& target) const;
///! Determine the arguments for the linker call, used also by
/// cmInstallTargetGenerator
bool GetLinkerArgs(std::string& rpath, std::string& linkLibs,
cmTarget& tgt, bool relink, unsigned int minRpathSize);
bool IsChrpathAvailable(const cmTarget& target);
/** /**
* Get the level of backwards compatibility requested by the project * Get the level of backwards compatibility requested by the project
* in this directory. This is the value of the CMake variable * in this directory. This is the value of the CMake variable

View File

@ -1570,11 +1570,12 @@ void cmLocalVisualStudio6Generator
std::string& options) std::string& options)
{ {
// Compute the link information for this configuration. // Compute the link information for this configuration.
cmComputeLinkInformation cli(&target, configName); cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
if(!cli.Compute()) if(!pcli)
{ {
return; return;
} }
cmComputeLinkInformation& cli = *pcli;
typedef cmComputeLinkInformation::ItemVector ItemVector; typedef cmComputeLinkInformation::ItemVector ItemVector;
ItemVector const& linkLibs = cli.GetItems(); ItemVector const& linkLibs = cli.GetItems();
std::vector<std::string> const& linkDirs = cli.GetDirectories(); std::vector<std::string> const& linkDirs = cli.GetDirectories();

View File

@ -762,11 +762,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
targetNameImport, targetNamePDB, configName); targetNameImport, targetNamePDB, configName);
// Compute the link library and directory information. // Compute the link library and directory information.
cmComputeLinkInformation cli(&target, configName); cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
if(!cli.Compute()) if(!pcli)
{ {
return; return;
} }
cmComputeLinkInformation& cli = *pcli;
const char* linkLanguage = cli.GetLinkLanguage(); const char* linkLanguage = cli.GetLinkLanguage();
// Compute the variable name to lookup standard libraries for this // Compute the variable name to lookup standard libraries for this
@ -831,11 +832,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
targetNameImport, targetNamePDB, configName); targetNameImport, targetNamePDB, configName);
// Compute the link library and directory information. // Compute the link library and directory information.
cmComputeLinkInformation cli(&target, configName); cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
if(!cli.Compute()) if(!pcli)
{ {
return; return;
} }
cmComputeLinkInformation& cli = *pcli;
const char* linkLanguage = cli.GetLinkLanguage(); const char* linkLanguage = cli.GetLinkLanguage();
// Compute the variable name to lookup standard libraries for this // Compute the variable name to lookup standard libraries for this

View File

@ -20,6 +20,7 @@
#include "cmSourceFile.h" #include "cmSourceFile.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h" #include "cmGlobalGenerator.h"
#include "cmComputeLinkInformation.h"
#include <map> #include <map>
#include <set> #include <set>
#include <queue> #include <queue>
@ -40,6 +41,17 @@ cmTarget::cmTarget()
this->IsImportedTarget = false; this->IsImportedTarget = false;
} }
//----------------------------------------------------------------------------
cmTarget::~cmTarget()
{
for(std::map<cmStdString, cmComputeLinkInformation*>::iterator
i = this->LinkInformation.begin();
i != this->LinkInformation.end(); ++i)
{
delete i->second;
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::DefineProperties(cmake *cm) void cmTarget::DefineProperties(cmake *cm)
{ {
@ -2531,12 +2543,6 @@ bool cmTarget::NeedRelinkBeforeInstall()
return false; return false;
} }
if(this->Makefile->IsOn("CMAKE_USE_CHRPATH")
&& (this->IsChrpathAvailable()))
{
return false;
}
// If skipping all rpaths completely then no relinking is needed. // If skipping all rpaths completely then no relinking is needed.
if(this->Makefile->IsOn("CMAKE_SKIP_RPATH")) if(this->Makefile->IsOn("CMAKE_SKIP_RPATH"))
{ {
@ -2549,6 +2555,12 @@ bool cmTarget::NeedRelinkBeforeInstall()
return false; return false;
} }
// If chrpath is going to be used no relinking is needed.
if(this->IsChrpathUsed())
{
return false;
}
// Check for rpath support on this platform. // Check for rpath support on this platform.
if(const char* ll = this->GetLinkerLanguage( if(const char* ll = this->GetLinkerLanguage(
this->Makefile->GetLocalGenerator()->GetGlobalGenerator())) this->Makefile->GetLocalGenerator()->GetGlobalGenerator()))
@ -2809,35 +2821,28 @@ void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
} }
} }
bool cmTarget::IsChrpathAvailable() //----------------------------------------------------------------------------
bool cmTarget::IsChrpathUsed()
{ {
//only return true if chrpath has been found (happens only if the executable // Enable use of "chrpath" if it is available, the user has turned
// format is ELF) and if the separator is not empty // on the feature, and the rpath flag uses a separator.
if (this->Makefile->IsSet("CMAKE_CHRPATH")==false) if(const char* ll = this->GetLinkerLanguage(
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()))
{ {
return false; std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
sepVar += ll;
sepVar += "_FLAG_SEP";
const char* sep = this->Makefile->GetDefinition(sepVar.c_str());
if(sep && *sep)
{
if(this->Makefile->IsSet("CMAKE_CHRPATH") &&
this->Makefile->IsOn("CMAKE_USE_CHRPATH"))
{
return true;
}
}
} }
return false;
const char* linkLanguage = this->GetLinkerLanguage(this->Makefile->
GetLocalGenerator()->GetGlobalGenerator());
if (linkLanguage==0)
{
return false;
}
std::string runTimeFlagSepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
runTimeFlagSepVar += linkLanguage;
runTimeFlagSepVar += "_FLAG_SEP";
std::string runtimeSep =
this->Makefile->GetSafeDefinition(runTimeFlagSepVar.c_str());
if (runtimeSep.size()<=0)
{
return 0;
}
return true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -3044,3 +3049,29 @@ cmTarget::GetImportedLinkLibraries(const char* config)
return 0; return 0;
} }
} }
//----------------------------------------------------------------------------
cmComputeLinkInformation*
cmTarget::GetLinkInformation(const char* config)
{
// Lookup any existing information for this configuration.
std::map<cmStdString, cmComputeLinkInformation*>::iterator
i = this->LinkInformation.find(config?config:"");
if(i == this->LinkInformation.end())
{
// Compute information for this configuration.
cmComputeLinkInformation* info =
new cmComputeLinkInformation(this, config);
if(!info || !info->Compute())
{
delete info;
info = 0;
}
// Store the information for this configuration.
std::map<cmStdString, cmComputeLinkInformation*>::value_type
entry(config?config:"", info);
i = this->LinkInformation.insert(entry).first;
}
return i->second;
}

View File

@ -24,6 +24,7 @@ class cmake;
class cmMakefile; class cmMakefile;
class cmSourceFile; class cmSourceFile;
class cmGlobalGenerator; class cmGlobalGenerator;
class cmComputeLinkInformation;
/** \class cmTarget /** \class cmTarget
* \brief Represent a library or executable target loaded from a makefile. * \brief Represent a library or executable target loaded from a makefile.
@ -35,6 +36,7 @@ class cmTarget
{ {
public: public:
cmTarget(); cmTarget();
~cmTarget();
enum TargetType { EXECUTABLE, STATIC_LIBRARY, enum TargetType { EXECUTABLE, STATIC_LIBRARY,
SHARED_LIBRARY, MODULE_LIBRARY, UTILITY, GLOBAL_TARGET, SHARED_LIBRARY, MODULE_LIBRARY, UTILITY, GLOBAL_TARGET,
INSTALL_FILES, INSTALL_PROGRAMS, INSTALL_DIRECTORY}; INSTALL_FILES, INSTALL_PROGRAMS, INSTALL_DIRECTORY};
@ -289,13 +291,15 @@ public:
bool HaveBuildTreeRPATH(); bool HaveBuildTreeRPATH();
bool HaveInstallTreeRPATH(); bool HaveInstallTreeRPATH();
/// return true if chrpath might work for this target /** Return true if chrpath might work for this target */
bool IsChrpathAvailable(); bool IsChrpathUsed();
std::string GetInstallNameDirForBuildTree(const char* config); std::string GetInstallNameDirForBuildTree(const char* config);
std::string GetInstallNameDirForInstallTree(const char* config); std::string GetInstallNameDirForInstallTree(const char* config);
cmComputeLinkInformation* GetLinkInformation(const char* config);
// Get the properties // Get the properties
cmPropertyMap &GetProperties() { return this->Properties; }; cmPropertyMap &GetProperties() { return this->Properties; };
@ -462,6 +466,8 @@ private:
ImportInfo const* GetImportInfo(const char* config); ImportInfo const* GetImportInfo(const char* config);
void ComputeImportInfo(std::string const& desired_config, ImportInfo& info); void ComputeImportInfo(std::string const& desired_config, ImportInfo& info);
std::map<cmStdString, cmComputeLinkInformation*> LinkInformation;
// The cmMakefile instance that owns this target. This should // The cmMakefile instance that owns this target. This should
// always be set. // always be set.
cmMakefile* Makefile; cmMakefile* Makefile;