summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/CMakeFindBinUtils.cmake10
-rw-r--r--Source/cmInstallTargetGenerator.cxx55
-rw-r--r--Source/cmInstallTargetGenerator.h3
-rw-r--r--Source/cmLocalGenerator.cxx29
-rw-r--r--Source/cmLocalGenerator.h11
-rw-r--r--Source/cmTarget.cxx45
-rw-r--r--Source/cmTarget.h3
7 files changed, 150 insertions, 6 deletions
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index 2cb7696..43f76f7 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -75,3 +75,13 @@ IF(APPLE)
MARK_AS_ADVANCED(CMAKE_INSTALL_NAME_TOOL)
ENDIF(APPLE)
+IF(UNIX AND NOT APPLE AND NOT WIN32)
+ # on ELF platforms there might be chrpath, which works similar to install_name_tool
+ OPTION(CMAKE_USE_CHRPATH "Enable this to use chrpath if available" OFF)
+
+ FIND_PROGRAM(CMAKE_CHRPATH chrpath PATHS ${_CMAKE_TOOLCHAIN_LOCATION} NO_DEFAULT_PATH)
+ FIND_PROGRAM(CMAKE_CHRPATH chrpath)
+
+ MARK_AS_ADVANCED(CMAKE_CHRPATH)
+ENDIF(UNIX AND NOT APPLE AND NOT WIN32)
+
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index abe9348..9998d0d 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -305,6 +305,7 @@ cmInstallTargetGenerator
os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n";
this->AddInstallNamePatchRule(os, indent.Next(), config, 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";
@@ -506,6 +507,60 @@ cmInstallTargetGenerator
//----------------------------------------------------------------------------
void
+cmInstallTargetGenerator
+::AddChrpathPatchRule(std::ostream& os, Indent const& indent,
+ const char* config, std::string const& toDestDirPath)
+{
+ if(this->ImportLibrary ||
+ !(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
+ this->Target->GetType() == cmTarget::MODULE_LIBRARY ||
+ this->Target->GetType() == cmTarget::EXECUTABLE))
+ {
+ return;
+ }
+
+ if((this->Target->GetMakefile()->IsOn("CMAKE_USE_CHRPATH")==false)
+ || (this->Target->IsChrpathAvailable()==false))
+ {
+ 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)
+ {
+ 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
+ os << indent << "EXECUTE_PROCESS(COMMAND \"" << chrpathTool;
+ os << "\" -r \"" << newRpath << "\" \"" << toDestDirPath << "\")\n";
+}
+
+//----------------------------------------------------------------------------
+void
cmInstallTargetGenerator::AddStripRule(std::ostream& os,
Indent const& indent,
cmTarget::TargetType type,
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index d03ea3d..3fdd5bf 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -54,6 +54,9 @@ protected:
void AddInstallNamePatchRule(std::ostream& os, Indent const& indent,
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,
cmTarget::TargetType type,
const std::string& toDestDirPath);
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 6c081b9..bf91751 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1479,7 +1479,8 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
bool cmLocalGenerator::GetLinkerArgs(std::string& rpath,
std::string& linkLibs,
cmTarget& tgt,
- bool relink)
+ bool relink,
+ int minRpathSize)
{
rpath = "";
// collect all the flags needed for linking libraries
@@ -1656,6 +1657,18 @@ bool cmLocalGenerator::GetLinkerArgs(std::string& rpath,
}
}
}
+
+ if (rpath.size()<minRpathSize)
+ {
+ if (rpath.size()==0)
+ {
+ rpath += runtimeFlag;
+ }
+ while (rpath.size() < minRpathSize)
+ {
+ rpath += runtimeSep;
+ }
+ }
return true;
}
@@ -1670,7 +1683,19 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
{
std::string rpath;
std::string linkLibs;
- if (!this->GetLinkerArgs(rpath, linkLibs, tgt, relink))
+ 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=installRpath.size();
+ }
+
+ if (!this->GetLinkerArgs(rpath, linkLibs, tgt, relink, minBuildRpathSize))
{
return;
}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 9f24f3f..1015251 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -242,6 +242,13 @@ 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, int minRpathSize);
+
+ bool IsChrpathAvailable(const cmTarget& target);
+
protected:
/** Construct a comment for a custom command. */
@@ -258,10 +265,6 @@ protected:
///! put all the libraries for a target on into the given stream
virtual void OutputLinkLibraries(std::ostream&, cmTarget&, bool relink);
- ///! Determine the arguments for the linker call
- bool GetLinkerArgs(std::string& rpath, std::string& linkLibs,
- cmTarget& tgt, bool relink);
-
// Expand rule variables in CMake of the type found in language rules
void ExpandRuleVariables(std::string& string,
const RuleVariables& replaceValues);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 2f4bb67..daca41f 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -2242,6 +2242,12 @@ 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"))
{
@@ -2518,3 +2524,42 @@ void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
}
}
}
+
+bool cmTarget::IsChrpathAvailable()
+{
+ //only return true if the flag is "-Wl,rpath," amd 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 runTimeFlagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
+ runTimeFlagVar += linkLanguage;
+ runTimeFlagVar += "_FLAG";
+ std::string runTimeFlagSepVar = runTimeFlagVar + "_SEP";
+
+ std::string runtimeSep =
+ this->Makefile->GetSafeDefinition(runTimeFlagSepVar.c_str());
+
+ if (runtimeSep.size()<=0)
+ {
+ return 0;
+ }
+
+ std::string runtimeFlag =
+ this->Makefile->GetSafeDefinition(runTimeFlagVar.c_str());
+
+ if (runtimeFlag!="-Wl,-rpath,")
+ {
+ return false;
+ }
+
+ return true;
+}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 44e0a05..879693a 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -277,6 +277,9 @@ public:
bool HaveBuildTreeRPATH();
bool HaveInstallTreeRPATH();
+
+ /// return true if chrpath might work for this target
+ bool IsChrpathAvailable();
std::string GetInstallNameDirForBuildTree(const char* config);
std::string GetInstallNameDirForInstallTree(const char* config);