summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Modules/CMakeFindBinUtils.cmake13
-rw-r--r--Source/cmComputeLinkInformation.cxx6
-rw-r--r--Source/cmComputeLinkInformation.h1
-rw-r--r--Source/cmFileCommand.cxx32
-rw-r--r--Source/cmFileCommand.h1
-rw-r--r--Source/cmInstallTargetGenerator.cxx7
-rw-r--r--Source/cmSystemTools.cxx83
-rw-r--r--Source/cmSystemTools.h5
-rw-r--r--Source/cmTarget.cxx14
-rw-r--r--Source/cmTarget.h2
10 files changed, 133 insertions, 31 deletions
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index 60d7dae7e8..9d76e75e95 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -74,16 +74,3 @@ IF(APPLE)
MARK_AS_ADVANCED(CMAKE_INSTALL_NAME_TOOL)
ENDIF(APPLE)
-
-# if we are on an ELF system, search for chrpath
-# according to the binutils mailing list chrpath has problems when cross compiling
-# i.e. if the target has different endianness than the host
-IF("${CMAKE_EXECUTABLE_FORMAT}" STREQUAL "ELF" AND NOT CMAKE_CROSSCOMPILING)
- # 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 CMAKE_USE_CHRPATH)
-ENDIF("${CMAKE_EXECUTABLE_FORMAT}" STREQUAL "ELF" AND NOT CMAKE_CROSSCOMPILING)
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index cd671d9cbe..554d8dedd3 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -1476,9 +1476,3 @@ std::string cmComputeLinkInformation::GetChrpathString()
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 c0f8b5c215..df22d53a3c 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -58,7 +58,6 @@ public:
void GetRPath(std::vector<std::string>& runtimeDirs, bool for_install);
std::string GetRPathString(bool for_install);
std::string GetChrpathString();
- std::string GetChrpathTool();
std::set<cmTarget*> const& GetSharedLibrariesLinked();
std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; }
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index ec61a59db6..01281355de 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -112,6 +112,10 @@ bool cmFileCommand
{
return this->HandleInstallCommand(args);
}
+ else if ( subCommand == "CHRPATH" )
+ {
+ return this->HandleChrpathCommand(args);
+ }
else if ( subCommand == "RELATIVE_PATH" )
{
return this->HandleRelativePathCommand(args);
@@ -1327,6 +1331,34 @@ bool cmFileCommand::HandleInstallDestination(cmFileInstaller& installer,
}
//----------------------------------------------------------------------------
+bool cmFileCommand::HandleChrpathCommand(std::vector<std::string> const& args)
+{
+ if(args.size() != 3)
+ {
+ this->SetError("CHRPATH must be given a file and a new rpath.");
+ return false;
+ }
+ if(!cmSystemTools::FileExists(args[1].c_str(), true))
+ {
+ this->SetError("CHRPATH given file that does not exist.");
+ return false;
+ }
+ std::string emsg;
+ if(cmSystemTools::ChangeRPath(args[1], args[2], &emsg))
+ {
+ return true;
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "CHRPATH could not write new RPATH to the file: "
+ << emsg;
+ this->SetError(e.str().c_str());
+ return false;
+ }
+}
+
+//----------------------------------------------------------------------------
bool cmFileCommand::HandleInstallCommand(std::vector<std::string> const& args)
{
if ( args.size() < 6 )
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 18f4c8f990..85bdc32484 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -171,6 +171,7 @@ protected:
bool HandleRelativePathCommand(std::vector<std::string> const& args);
bool HandleCMakePathCommand(std::vector<std::string> const& args,
bool nativePath);
+ bool HandleChrpathCommand(std::vector<std::string> const& args);
// file(INSTALL ...) related functions
bool HandleInstallCommand(std::vector<std::string> const& args);
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index c8e00d5dc0..c2d606ee16 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -576,12 +576,9 @@ cmInstallTargetGenerator
// 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 = cli->GetChrpathTool();
-
// Write a rule to run chrpath to set the install-tree RPATH
- os << indent << "EXECUTE_PROCESS(COMMAND \"" << chrpathTool;
- os << "\" -r \"" << newRpath << "\" \"" << toDestDirPath << "\")\n";
+ os << indent
+ << "FILE(CHRPATH \"" << toDestDirPath << "\" \"" << newRpath << "\")\n";
}
//----------------------------------------------------------------------------
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index aa4d1c2bfa..1842317e92 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -2195,3 +2195,86 @@ bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
}
return false;
}
+
+//----------------------------------------------------------------------------
+bool cmSystemTools::ChangeRPath(std::string const& file,
+ std::string const& newRPath,
+ std::string* emsg)
+{
+#if defined(CMAKE_USE_ELF_PARSER)
+ unsigned long rpathPosition = 0;
+ unsigned long rpathSize = 0;
+ {
+ cmELF elf(file.c_str());
+ if(cmELF::StringEntry const* se = elf.GetRPath())
+ {
+ rpathPosition = se->Position;
+ rpathSize = se->Size;
+ }
+ else
+ {
+ if(emsg)
+ {
+ *emsg = "No valid ELF RPATH entry exists in the file.";
+ }
+ return false;
+ }
+ }
+ // Make sure there is enough room to store the new rpath and at
+ // least one null terminator.
+ if(rpathSize < newRPath.length()+1)
+ {
+ if(emsg)
+ {
+ *emsg = "The replacement RPATH is too long.";
+ }
+ return false;
+ }
+
+ // Open the file for update and seek to the RPATH position.
+ std::ofstream f(file.c_str(),
+ std::ios::in | std::ios::out | std::ios::binary);
+ if(!f)
+ {
+ if(emsg)
+ {
+ *emsg = "Error opening file for update.";
+ }
+ return false;
+ }
+ if(!f.seekp(rpathPosition))
+ {
+ if(emsg)
+ {
+ *emsg = "Error seeking to RPATH position.";
+ }
+ return false;
+ }
+
+ // Write the new rpath. Follow it with enough null terminators to
+ // fill the string table entry.
+ f << newRPath;
+ for(unsigned long i=newRPath.length(); i < rpathSize; ++i)
+ {
+ f << '\0';
+ }
+
+ // Make sure everything was okay.
+ if(f)
+ {
+ return true;
+ }
+ else
+ {
+ if(emsg)
+ {
+ *emsg = "Error writing the new rpath to the file.";
+ }
+ return false;
+ }
+#else
+ (void)file;
+ (void)newRPath;
+ return false;
+#endif
+}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index e03c24cd2c..42282d3764 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -381,6 +381,11 @@ public:
static bool GuessLibrarySOName(std::string const& fullPath,
std::string& soname);
+ /** Try to set the RPATH in an ELF binary. */
+ static bool ChangeRPath(std::string const& file,
+ std::string const& newRPath,
+ std::string* emsg = 0);
+
private:
static bool s_ForceUnixPaths;
static bool s_RunCommandHideConsole;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index b4c36c6681..880c370fc2 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -3006,8 +3006,9 @@ void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
//----------------------------------------------------------------------------
bool cmTarget::IsChrpathUsed()
{
- // Enable use of "chrpath" if it is available, the user has turned
- // on the feature, and the rpath flag uses a separator.
+#if defined(CMAKE_USE_ELF_PARSER)
+ // Enable if the rpath flag uses a separator and the target uses ELF
+ // binaries.
if(const char* ll = this->GetLinkerLanguage(
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()))
{
@@ -3017,13 +3018,16 @@ bool cmTarget::IsChrpathUsed()
const char* sep = this->Makefile->GetDefinition(sepVar.c_str());
if(sep && *sep)
{
- if(this->Makefile->IsSet("CMAKE_CHRPATH") &&
- this->Makefile->IsOn("CMAKE_USE_CHRPATH"))
+ // TODO: Add ELF check to ABI detection and get rid of
+ // CMAKE_EXECUTABLE_FORMAT.
+ if(const char* fmt =
+ this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT"))
{
- return true;
+ return strcmp(fmt, "ELF") == 0;
}
}
}
+#endif
return false;
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 95c49da447..1b430e6040 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -335,7 +335,7 @@ public:
bool HaveBuildTreeRPATH();
bool HaveInstallTreeRPATH();
- /** Return true if chrpath might work for this target */
+ /** Return true if builtin chrpath will work for this target */
bool IsChrpathUsed();
std::string GetInstallNameDirForBuildTree(const char* config);