mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-25 10:18:34 -06:00
Refactor: Break up logic in cmSystemTools::ChangeRPath()
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cmext/algorithm>
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
@@ -65,6 +66,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
@@ -2524,6 +2526,7 @@ std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have,
|
||||
#endif
|
||||
|
||||
#if defined(CMake_USE_ELF_PARSER)
|
||||
namespace {
|
||||
struct cmSystemToolsRPathInfo
|
||||
{
|
||||
unsigned long Position;
|
||||
@@ -2531,15 +2534,15 @@ struct cmSystemToolsRPathInfo
|
||||
std::string Name;
|
||||
std::string Value;
|
||||
};
|
||||
#endif
|
||||
|
||||
using EmptyCallback = std::function<bool(std::string*, const cmELF&)>;
|
||||
using AdjustCallback = std::function<bool(
|
||||
cm::optional<std::string>&, const std::string&, const char*, std::string*)>;
|
||||
|
||||
// FIXME: Dispatch if multiple formats are supported.
|
||||
#if defined(CMake_USE_ELF_PARSER)
|
||||
bool cmSystemTools::ChangeRPath(std::string const& file,
|
||||
std::string const& oldRPath,
|
||||
std::string const& newRPath,
|
||||
bool removeEnvironmentRPath, std::string* emsg,
|
||||
bool* changed)
|
||||
bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback,
|
||||
const AdjustCallback& adjustCallback, std::string* emsg,
|
||||
bool* changed)
|
||||
{
|
||||
if (changed) {
|
||||
*changed = false;
|
||||
@@ -2566,17 +2569,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
|
||||
++se_count;
|
||||
}
|
||||
if (se_count == 0) {
|
||||
if (newRPath.empty()) {
|
||||
// The new rpath is empty and there is no rpath anyway so it is
|
||||
// okay.
|
||||
return true;
|
||||
}
|
||||
if (emsg) {
|
||||
*emsg =
|
||||
cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ",
|
||||
elf.GetErrorMessage());
|
||||
}
|
||||
return false;
|
||||
return emptyCallback(emsg, elf);
|
||||
}
|
||||
|
||||
for (int i = 0; i < se_count; ++i) {
|
||||
@@ -2586,68 +2579,38 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure the current rpath contains the old rpath.
|
||||
std::string::size_type pos =
|
||||
cmSystemToolsFindRPath(se[i]->Value, oldRPath);
|
||||
if (pos == std::string::npos) {
|
||||
// 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) {
|
||||
std::ostringstream e;
|
||||
/* clang-format off */
|
||||
e << "The current " << se_name[i] << " is:\n"
|
||||
<< " " << se[i]->Value << "\n"
|
||||
<< "which does not contain:\n"
|
||||
<< " " << oldRPath << "\n"
|
||||
<< "as was expected.";
|
||||
/* clang-format on */
|
||||
*emsg = e.str();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store information about the entry in the file.
|
||||
rp[rp_count].Position = se[i]->Position;
|
||||
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.
|
||||
if (!removeEnvironmentRPath) {
|
||||
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());
|
||||
|
||||
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) {
|
||||
if (emsg) {
|
||||
*emsg = cmStrCat("The replacement path is too long for the ",
|
||||
se_name[i], " entry.");
|
||||
}
|
||||
// Adjust the rpath.
|
||||
cm::optional<std::string> outRPath;
|
||||
if (!adjustCallback(outRPath, se[i]->Value, se_name[i], emsg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This entry is ready for update.
|
||||
++rp_count;
|
||||
if (outRPath) {
|
||||
if (!outRPath->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 < outRPath->length() + 1) {
|
||||
if (emsg) {
|
||||
*emsg = cmStrCat("The replacement path is too long for the ",
|
||||
se_name[i], " entry.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This entry is ready for update.
|
||||
rp[rp_count].Value = std::move(*outRPath);
|
||||
++rp_count;
|
||||
} else {
|
||||
remove_rpath = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2706,6 +2669,81 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::function<bool(std::string*, const cmELF&)> MakeEmptyCallback(
|
||||
const std::string& newRPath)
|
||||
{
|
||||
return [newRPath](std::string* emsg, const cmELF& elf) -> bool {
|
||||
if (newRPath.empty()) {
|
||||
// The new rpath is empty and there is no rpath anyway so it is
|
||||
// okay.
|
||||
return true;
|
||||
}
|
||||
if (emsg) {
|
||||
*emsg =
|
||||
cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ",
|
||||
elf.GetErrorMessage());
|
||||
}
|
||||
return false;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
bool cmSystemTools::ChangeRPath(std::string const& file,
|
||||
std::string const& oldRPath,
|
||||
std::string const& newRPath,
|
||||
bool removeEnvironmentRPath, std::string* emsg,
|
||||
bool* changed)
|
||||
{
|
||||
auto adjustCallback = [oldRPath, newRPath, removeEnvironmentRPath](
|
||||
cm::optional<std::string>& outRPath,
|
||||
const std::string& inRPath, const char* se_name,
|
||||
std::string* emsg2) -> bool {
|
||||
// Make sure the current rpath contains the old rpath.
|
||||
std::string::size_type pos = cmSystemToolsFindRPath(inRPath, oldRPath);
|
||||
if (pos == std::string::npos) {
|
||||
// If it contains the new rpath instead then it is okay.
|
||||
if (cmSystemToolsFindRPath(inRPath, newRPath) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
if (emsg2) {
|
||||
std::ostringstream e;
|
||||
/* clang-format off */
|
||||
e << "The current " << se_name << " is:\n"
|
||||
<< " " << inRPath << "\n"
|
||||
<< "which does not contain:\n"
|
||||
<< " " << oldRPath << "\n"
|
||||
<< "as was expected.";
|
||||
/* clang-format on */
|
||||
*emsg2 = e.str();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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 && inRPath[pos - 1] == ':' &&
|
||||
pos + oldRPath.length() == inRPath.length()) {
|
||||
prefix_len--;
|
||||
}
|
||||
|
||||
// Construct the new value which preserves the part of the path
|
||||
// not being changed.
|
||||
outRPath.emplace();
|
||||
if (!removeEnvironmentRPath) {
|
||||
*outRPath += inRPath.substr(0, prefix_len);
|
||||
}
|
||||
*outRPath += newRPath;
|
||||
*outRPath += inRPath.substr(pos + oldRPath.length());
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg,
|
||||
changed);
|
||||
}
|
||||
#elif defined(CMake_USE_XCOFF_PARSER)
|
||||
bool cmSystemTools::ChangeRPath(std::string const& file,
|
||||
std::string const& oldRPath,
|
||||
|
||||
Reference in New Issue
Block a user