summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2008-01-29 20:07:33 (GMT)
committerBrad King <brad.king@kitware.com>2008-01-29 20:07:33 (GMT)
commitffac622a858cca4dc661caa896d961da666430cc (patch)
tree3c52af43de45021dbfc5afc7f64f3ce17701a78f
parentbb52f45ebb6b1c80f8f7b8e2b841202118ed9d06 (diff)
downloadCMake-ffac622a858cca4dc661caa896d961da666430cc.zip
CMake-ffac622a858cca4dc661caa896d961da666430cc.tar.gz
CMake-ffac622a858cca4dc661caa896d961da666430cc.tar.bz2
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.
-rw-r--r--Source/cmComputeLinkInformation.cxx133
-rw-r--r--Source/cmComputeLinkInformation.h10
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx5
-rw-r--r--Source/cmInstallTargetGenerator.cxx39
-rw-r--r--Source/cmInstallTargetGenerator.h1
-rw-r--r--Source/cmLocalGenerator.cxx220
-rw-r--r--Source/cmLocalGenerator.h7
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx5
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx10
-rw-r--r--Source/cmTarget.cxx95
-rw-r--r--Source/cmTarget.h12
11 files changed, 286 insertions, 251 deletions
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index b614de8..190ffb8 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -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");
+}
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 993ad0f..96af2e4 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -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();
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index f1a2b71..ed1af64 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -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.
{
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 2cbb31e..4f6539a 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -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;
}
- // 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)
+ // Get the link information for this target.
+ // It can provide the RPATH.
+ cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
+ if(!cli)
{
return;
}
- std::string runTimeFlagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
- runTimeFlagVar += linkLanguage;
- runTimeFlagVar += "_FLAG";
-
- std::string runtimeFlag =
- this->Target->GetMakefile()->GetSafeDefinition(runTimeFlagVar.c_str());
+ // Get the install RPATH from the link information.
+ std::string newRpath = cli->GetChrpathString();
- 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());
- }
+ // Fix the RPATH in installed ELF binaries using chrpath.
+ std::string chrpathTool = cli->GetChrpathTool();
// Write a rule to run chrpath to set the install-tree RPATH
os << indent << "EXECUTE_PROCESS(COMMAND \"" << chrpathTool;
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index 01d36bb..64ad784 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -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,
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 4812572..493d26e 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -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;
- }
-
- 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());
+ return;
}
- // concatenate all paths or no?
- bool runtimeConcatenate = !runtimeSep.empty();
+ cmComputeLinkInformation& cli = *pcli;
- const char* runtimeAlways =
- this->Makefile->GetDefinition("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH");
+ // Collect library linking flags command line options.
+ std::string linkLibs;
- // Turn off rpath support if no flag is available to specify it.
- if(runtimeFlag.empty())
- {
- outputRuntime = false;
- runtimeAlways = 0;
- }
+ const char* linkLanguage = cli.GetLinkLanguage();
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");
+ // Write the library flags to the build rule.
+ fout << linkLibs;
- // Construct the RPATH.
+ // Get the RPATH entries.
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)
+ cli.GetRPath(runtimeDirs, relink);
+
+ // Check what kind of rpath flags to use.
+ if(cli.GetRuntimeSep().empty())
{
- std::vector<std::string> const& rdirs = cli.GetRuntimeSearchPath();
- for(std::vector<std::string>::const_iterator ri = rdirs.begin();
- ri != rdirs.end(); ++ri)
+ // 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)
{
- // 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);
- }
- }
+ rpath += cli.GetRuntimeFlag();
+ rpath += this->Convert(ri->c_str(), FULL, SHELL, false);
+ rpath += " ";
}
+ fout << rpath;
}
- 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)
+ else
{
- *ri = this->Convert(ri->c_str(), FULL, SHELL, false);
- }
+ // All rpath entries are combined ("-Wl,-rpath,a:b:c").
+ std::string rpath = cli.GetRPathString(relink);
- 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 not relinking, make sure the rpath string is long enough to
+ // support a subsequent chrpath on installation.
+ if(!relink)
{
- if(runtimeConcatenate)
+ std::string::size_type minLength = cli.GetChrpathString().size();
+ while(rpath.size() < minLength)
{
- rpath += runtimeSep;
- rpath += *itr;
- }
- else
- {
- rpath += " ";
- rpath += runtimeFlag;
- rpath += *itr;
+ rpath += cli.GetRuntimeSep();
}
}
- }
- while (rpath.size() < minRpathSize)
- {
- if (rpath.size()==0)
+ // Store the rpath option in the stream.
+ if(!rpath.empty())
{
- rpath += runtimeFlag;
+ fout << cli.GetRuntimeFlag();
+ fout << this->EscapeForShell(rpath.c_str(), true);
+ fout << " ";
}
-
- 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 << rpath << " ";
-
// 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()))
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index f334163..d899747 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -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
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 258d027..c657a0e 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -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();
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index b368f7c..5922884 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -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
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index a6bf5d2..3691c47 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -20,6 +20,7 @@
#include "cmSourceFile.h"
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
+#include "cmComputeLinkInformation.h"
#include <map>
#include <set>
#include <queue>
@@ -41,6 +42,17 @@ cmTarget::cmTarget()
}
//----------------------------------------------------------------------------
+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)
{
cm->DefineProperty
@@ -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)
- {
- 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)
+ // 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 0;
+ 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 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;
+}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index c1de1a3..202190a 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -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;