diff options
-rw-r--r-- | Modules/CMakeFindBinUtils.cmake | 10 | ||||
-rw-r--r-- | Source/cmInstallTargetGenerator.cxx | 55 | ||||
-rw-r--r-- | Source/cmInstallTargetGenerator.h | 3 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 29 | ||||
-rw-r--r-- | Source/cmLocalGenerator.h | 11 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 45 | ||||
-rw-r--r-- | Source/cmTarget.h | 3 |
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); |