Skip to content

Commit

Permalink
install: Do not remove compiler-defined RPATH entries
Browse files Browse the repository at this point in the history
Some compilers may add their own RPATH entries when invoking the linker.
For example, a GCC installation may contain the following definition in
the specs file:

  *link_libgcc:
  %D -rpath <<some specific rpath in which libstdc++.so can be found>>

In this case binaries may contain RPATH entries that CMake did not add.
When we update the RPATH on installation we must preserve these entries
even if CMake thinks the INSTALL_RPATH value should be empty.

Fix this by always using file(RPATH_CHANGE) and teach it to behave as
file(RPATH_REMOVE) if the actual RPATH in the file is empty after
replacing the build-tree RPATH with the install-tree RPATH.  This will
preserve any compiler-added RPATH value instead of removing it.
  • Loading branch information
liorgold authored and bradking committed Jan 15, 2016
1 parent b8d002a commit 3ec9226
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 13 deletions.
16 changes: 4 additions & 12 deletions Source/cmInstallTargetGenerator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -791,18 +791,10 @@ ::AddChrpathPatchRule(std::ostream& os, Indent const& indent,
}

// Write a rule to run chrpath to set the install-tree RPATH
if(newRpath.empty())
{
os << indent << "file(RPATH_REMOVE\n"
<< indent << " FILE \"" << toDestDirPath << "\")\n";
}
else
{
os << indent << "file(RPATH_CHANGE\n"
<< indent << " FILE \"" << toDestDirPath << "\"\n"
<< indent << " OLD_RPATH \"" << oldRpath << "\"\n"
<< indent << " NEW_RPATH \"" << newRpath << "\")\n";
}
os << indent << "file(RPATH_CHANGE\n"
<< indent << " FILE \"" << toDestDirPath << "\"\n"
<< indent << " OLD_RPATH \"" << oldRpath << "\"\n"
<< indent << " NEW_RPATH \"" << newRpath << "\")\n";
}
}

Expand Down
27 changes: 26 additions & 1 deletion Source/cmSystemTools.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2565,6 +2565,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
*changed = false;
}
int rp_count = 0;
bool remove_rpath = true;
cmSystemToolsRPathInfo rp[2];
{
// Parse the ELF binary.
Expand Down Expand Up @@ -2622,6 +2623,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
// If it contains the new rpath instead then it is okay.
if(cmSystemToolsFindRPath(se[i]->Value, newRPath) != std::string::npos)
{
remove_rpath = false;
continue;
}
if(emsg)
Expand All @@ -2642,13 +2644,30 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
rp[rp_count].Size = se[i]->Size;
rp[rp_count].Name = se_name[i];

std::string::size_type prefix_len = pos;

// If oldRPath was at the end of the file's RPath, and newRPath is empty,
// we should remove the unnecessary ':' at the end.
if (newRPath.empty() &&
pos > 0 &&
se[i]->Value[pos - 1] == ':' &&
pos + oldRPath.length() == se[i]->Value.length())
{
prefix_len--;
}

// Construct the new value which preserves the part of the path
// not being changed.
rp[rp_count].Value = se[i]->Value.substr(0, pos);
rp[rp_count].Value = se[i]->Value.substr(0, prefix_len);
rp[rp_count].Value += newRPath;
rp[rp_count].Value += se[i]->Value.substr(pos+oldRPath.length(),
oldRPath.npos);

if (!rp[rp_count].Value.empty())
{
remove_rpath = false;
}

// Make sure there is enough room to store the new rpath and at
// least one null terminator.
if(rp[rp_count].Size < rp[rp_count].Value.length()+1)
Expand All @@ -2673,6 +2692,12 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
return true;
}

// If the resulting rpath is empty, just remove the entire entry instead.
if (remove_rpath)
{
return cmSystemTools::RemoveRPath(file, emsg, changed);
}

{
// Open the file for update.
cmsys::ofstream f(file.c_str(),
Expand Down

0 comments on commit 3ec9226

Please sign in to comment.