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:
parent
bb52f45ebb
commit
ffac622a85
|
@ -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");
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue