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.
|
||||
this->LinkLanguage =
|
||||
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.
|
||||
this->UseImportLibrary =
|
||||
|
@ -194,6 +200,31 @@ cmComputeLinkInformation
|
|||
this->LibLinkSuffix =
|
||||
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.
|
||||
this->ComputeLinkTypeInfo();
|
||||
|
||||
|
@ -1227,3 +1258,105 @@ void cmComputeLinkInformation::DiagnoseCycle()
|
|||
}
|
||||
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();
|
||||
const char* GetLinkLanguage() const { return this->LinkLanguage; }
|
||||
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:
|
||||
void AddItem(std::string const& item, cmTarget* tgt);
|
||||
|
||||
|
@ -76,6 +82,10 @@ private:
|
|||
std::string LibLinkFlag;
|
||||
std::string LibLinkFileFlag;
|
||||
std::string LibLinkSuffix;
|
||||
std::string RuntimeFlag;
|
||||
std::string RuntimeSep;
|
||||
std::string RuntimeAlways;
|
||||
bool RuntimeUseChrpath;
|
||||
|
||||
// Link type adjustment.
|
||||
void ComputeLinkTypeInfo();
|
||||
|
|
|
@ -2105,11 +2105,12 @@ void cmGlobalXCodeGenerator
|
|||
}
|
||||
|
||||
// Compute the link library and directory information.
|
||||
cmComputeLinkInformation cli(cmtarget, configName);
|
||||
if(!cli.Compute())
|
||||
cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName);
|
||||
if(!pcli)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
cmComputeLinkInformation& cli = *pcli;
|
||||
|
||||
// Add dependencies directly on library files.
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
=========================================================================*/
|
||||
#include "cmInstallTargetGenerator.h"
|
||||
|
||||
#include "cmComputeLinkInformation.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
|
@ -283,7 +284,7 @@ cmInstallTargetGenerator
|
|||
|
||||
os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n";
|
||||
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->AddStripRule(os, indent.Next(), type, toDestDirPath);
|
||||
os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n";
|
||||
|
@ -487,7 +488,7 @@ cmInstallTargetGenerator
|
|||
void
|
||||
cmInstallTargetGenerator
|
||||
::AddChrpathPatchRule(std::ostream& os, Indent const& indent,
|
||||
std::string const& toDestDirPath)
|
||||
const char* config, std::string const& toDestDirPath)
|
||||
{
|
||||
if(this->ImportLibrary ||
|
||||
!(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
|
@ -497,40 +498,24 @@ cmInstallTargetGenerator
|
|||
return;
|
||||
}
|
||||
|
||||
if((this->Target->GetMakefile()->IsOn("CMAKE_USE_CHRPATH")==false)
|
||||
|| (this->Target->IsChrpathAvailable()==false))
|
||||
if(!this->Target->IsChrpathUsed())
|
||||
{
|
||||
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.
|
||||
std::string chrpathTool =
|
||||
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());
|
||||
}
|
||||
std::string chrpathTool = cli->GetChrpathTool();
|
||||
|
||||
// Write a rule to run chrpath to set the install-tree RPATH
|
||||
os << indent << "EXECUTE_PROCESS(COMMAND \"" << chrpathTool;
|
||||
|
|
|
@ -58,6 +58,7 @@ protected:
|
|||
const char* config,
|
||||
const std::string& toDestDirPath);
|
||||
void AddChrpathPatchRule(std::ostream& os, Indent const& indent,
|
||||
const char* config,
|
||||
std::string const& toDestDirPath);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool cmLocalGenerator::GetLinkerArgs(std::string& rpath,
|
||||
std::string& linkLibs,
|
||||
cmTarget& tgt,
|
||||
bool relink,
|
||||
unsigned int minRpathSize)
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
rpath = "";
|
||||
// collect all the flags needed for linking libraries
|
||||
linkLibs = "";
|
||||
|
||||
const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
|
||||
|
||||
cmComputeLinkInformation cli(&tgt, config);
|
||||
if(!cli.Compute())
|
||||
cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config);
|
||||
if(!pcli)
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
cmComputeLinkInformation& cli = *pcli;
|
||||
|
||||
// Collect library linking flags command line options.
|
||||
std::string linkLibs;
|
||||
|
||||
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 =
|
||||
this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
|
||||
std::string libPathTerminator =
|
||||
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.
|
||||
std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_";
|
||||
linkFlagsVar += linkLanguage;
|
||||
|
@ -1595,146 +1558,55 @@ bool cmLocalGenerator::GetLinkerArgs(std::string& rpath,
|
|||
linkLibs += " ";
|
||||
}
|
||||
|
||||
// Select whether to generate an rpath for the install tree or the
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Write the library flags to the build rule.
|
||||
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.
|
||||
std::string standardLibsVar = "CMAKE_";
|
||||
standardLibsVar += linkLanguage;
|
||||
standardLibsVar += cli.GetLinkLanguage();
|
||||
standardLibsVar += "_STANDARD_LIBRARIES";
|
||||
if(const char* stdLibs =
|
||||
this->Makefile->GetDefinition(standardLibsVar.c_str()))
|
||||
|
|
|
@ -248,13 +248,6 @@ public:
|
|||
*/
|
||||
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
|
||||
* in this directory. This is the value of the CMake variable
|
||||
|
|
|
@ -1570,11 +1570,12 @@ void cmLocalVisualStudio6Generator
|
|||
std::string& options)
|
||||
{
|
||||
// Compute the link information for this configuration.
|
||||
cmComputeLinkInformation cli(&target, configName);
|
||||
if(!cli.Compute())
|
||||
cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
|
||||
if(!pcli)
|
||||
{
|
||||
return;
|
||||
}
|
||||
cmComputeLinkInformation& cli = *pcli;
|
||||
typedef cmComputeLinkInformation::ItemVector ItemVector;
|
||||
ItemVector const& linkLibs = cli.GetItems();
|
||||
std::vector<std::string> const& linkDirs = cli.GetDirectories();
|
||||
|
|
|
@ -762,11 +762,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
targetNameImport, targetNamePDB, configName);
|
||||
|
||||
// Compute the link library and directory information.
|
||||
cmComputeLinkInformation cli(&target, configName);
|
||||
if(!cli.Compute())
|
||||
cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
|
||||
if(!pcli)
|
||||
{
|
||||
return;
|
||||
}
|
||||
cmComputeLinkInformation& cli = *pcli;
|
||||
const char* linkLanguage = cli.GetLinkLanguage();
|
||||
|
||||
// Compute the variable name to lookup standard libraries for this
|
||||
|
@ -831,11 +832,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
targetNameImport, targetNamePDB, configName);
|
||||
|
||||
// Compute the link library and directory information.
|
||||
cmComputeLinkInformation cli(&target, configName);
|
||||
if(!cli.Compute())
|
||||
cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
|
||||
if(!pcli)
|
||||
{
|
||||
return;
|
||||
}
|
||||
cmComputeLinkInformation& cli = *pcli;
|
||||
const char* linkLanguage = cli.GetLinkLanguage();
|
||||
|
||||
// Compute the variable name to lookup standard libraries for this
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "cmSourceFile.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmComputeLinkInformation.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <queue>
|
||||
|
@ -40,6 +41,17 @@ cmTarget::cmTarget()
|
|||
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)
|
||||
{
|
||||
|
@ -2531,12 +2543,6 @@ bool cmTarget::NeedRelinkBeforeInstall()
|
|||
return false;
|
||||
}
|
||||
|
||||
if(this->Makefile->IsOn("CMAKE_USE_CHRPATH")
|
||||
&& (this->IsChrpathAvailable()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If skipping all rpaths completely then no relinking is needed.
|
||||
if(this->Makefile->IsOn("CMAKE_SKIP_RPATH"))
|
||||
{
|
||||
|
@ -2549,6 +2555,12 @@ bool cmTarget::NeedRelinkBeforeInstall()
|
|||
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.
|
||||
if(const char* ll = this->GetLinkerLanguage(
|
||||
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
|
||||
// format is ELF) and if the separator is not empty
|
||||
if (this->Makefile->IsSet("CMAKE_CHRPATH")==false)
|
||||
// Enable use of "chrpath" if it is available, the user has turned
|
||||
// on the feature, and the rpath flag uses a separator.
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -3044,3 +3049,29 @@ cmTarget::GetImportedLinkLibraries(const char* config)
|
|||
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 cmSourceFile;
|
||||
class cmGlobalGenerator;
|
||||
class cmComputeLinkInformation;
|
||||
|
||||
/** \class cmTarget
|
||||
* \brief Represent a library or executable target loaded from a makefile.
|
||||
|
@ -35,6 +36,7 @@ class cmTarget
|
|||
{
|
||||
public:
|
||||
cmTarget();
|
||||
~cmTarget();
|
||||
enum TargetType { EXECUTABLE, STATIC_LIBRARY,
|
||||
SHARED_LIBRARY, MODULE_LIBRARY, UTILITY, GLOBAL_TARGET,
|
||||
INSTALL_FILES, INSTALL_PROGRAMS, INSTALL_DIRECTORY};
|
||||
|
@ -289,13 +291,15 @@ public:
|
|||
|
||||
bool HaveBuildTreeRPATH();
|
||||
bool HaveInstallTreeRPATH();
|
||||
|
||||
/// return true if chrpath might work for this target
|
||||
bool IsChrpathAvailable();
|
||||
|
||||
/** Return true if chrpath might work for this target */
|
||||
bool IsChrpathUsed();
|
||||
|
||||
std::string GetInstallNameDirForBuildTree(const char* config);
|
||||
std::string GetInstallNameDirForInstallTree(const char* config);
|
||||
|
||||
cmComputeLinkInformation* GetLinkInformation(const char* config);
|
||||
|
||||
// Get the properties
|
||||
cmPropertyMap &GetProperties() { return this->Properties; };
|
||||
|
||||
|
@ -462,6 +466,8 @@ private:
|
|||
ImportInfo const* GetImportInfo(const char* config);
|
||||
void ComputeImportInfo(std::string const& desired_config, ImportInfo& info);
|
||||
|
||||
std::map<cmStdString, cmComputeLinkInformation*> LinkInformation;
|
||||
|
||||
// The cmMakefile instance that owns this target. This should
|
||||
// always be set.
|
||||
cmMakefile* Makefile;
|
||||
|
|
Loading…
Reference in New Issue