|
|
@@ -2,11 +2,13 @@
|
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
|
|
#include "cmInstallTargetGenerator.h"
|
|
|
|
|
|
+#include <algorithm>
|
|
|
#include <cassert>
|
|
|
#include <map>
|
|
|
#include <set>
|
|
|
#include <sstream>
|
|
|
#include <utility>
|
|
|
+#include <vector>
|
|
|
|
|
|
#include "cmComputeLinkInformation.h"
|
|
|
#include "cmGeneratorExpression.h"
|
|
|
@@ -680,33 +682,52 @@ void cmInstallTargetGenerator::AddChrpathPatchRule(
|
|
|
" this limitation.";
|
|
|
mf->IssueMessage(MessageType::WARNING, msg.str());
|
|
|
} else {
|
|
|
- // Note: These paths are kept unique to avoid
|
|
|
- // install_name_tool corruption.
|
|
|
- std::set<std::string> runpaths;
|
|
|
- for (std::string const& i : oldRuntimeDirs) {
|
|
|
- std::string runpath =
|
|
|
- mf->GetGlobalGenerator()->ExpandCFGIntDir(i, config);
|
|
|
-
|
|
|
- if (runpaths.find(runpath) == runpaths.end()) {
|
|
|
- runpaths.insert(runpath);
|
|
|
- os << indent << "execute_process(COMMAND " << installNameTool
|
|
|
- << "\n";
|
|
|
- os << indent << " -delete_rpath \"" << runpath << "\"\n";
|
|
|
- os << indent << " \"" << toDestDirPath << "\")\n";
|
|
|
+ // To be consistent with older versions, runpath changes must be ordered,
|
|
|
+ // deleted first, then added, *and* the same path must only appear once.
|
|
|
+ std::map<std::string, std::string> runpath_change;
|
|
|
+ std::vector<std::string> ordered;
|
|
|
+ for (std::string const& dir : oldRuntimeDirs) {
|
|
|
+ // Normalize path and add to map of changes to make
|
|
|
+ auto iter_inserted = runpath_change.insert(
|
|
|
+ { mf->GetGlobalGenerator()->ExpandCFGIntDir(dir, config),
|
|
|
+ "delete" });
|
|
|
+ if (iter_inserted.second) {
|
|
|
+ // Add path to ordered list of changes
|
|
|
+ ordered.push_back(iter_inserted.first->first);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- runpaths.clear();
|
|
|
- for (std::string const& i : newRuntimeDirs) {
|
|
|
- std::string runpath =
|
|
|
- mf->GetGlobalGenerator()->ExpandCFGIntDir(i, config);
|
|
|
+ for (std::string const& dir : newRuntimeDirs) {
|
|
|
+ // Normalize path and add to map of changes to make
|
|
|
+ auto iter_inserted = runpath_change.insert(
|
|
|
+ { mf->GetGlobalGenerator()->ExpandCFGIntDir(dir, config), "add" });
|
|
|
+ if (iter_inserted.second) {
|
|
|
+ // Add path to ordered list of changes
|
|
|
+ ordered.push_back(iter_inserted.first->first);
|
|
|
+ } else if (iter_inserted.first->second != "add") {
|
|
|
+ // Rpath was requested to be deleted and then later re-added. Drop it
|
|
|
+ // from the list by marking as an empty value.
|
|
|
+ iter_inserted.first->second.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (runpaths.find(runpath) == runpaths.end()) {
|
|
|
- os << indent << "execute_process(COMMAND " << installNameTool
|
|
|
- << "\n";
|
|
|
- os << indent << " -add_rpath \"" << runpath << "\"\n";
|
|
|
- os << indent << " \"" << toDestDirPath << "\")\n";
|
|
|
+ // Remove rpaths that are unchanged (value was set to empty)
|
|
|
+ ordered.erase(
|
|
|
+ std::remove_if(ordered.begin(), ordered.end(),
|
|
|
+ [&runpath_change](const std::string& runpath) {
|
|
|
+ return runpath_change.find(runpath)->second.empty();
|
|
|
+ }),
|
|
|
+ ordered.end());
|
|
|
+
|
|
|
+ if (!ordered.empty()) {
|
|
|
+ os << indent << "execute_process(COMMAND " << installNameTool << "\n";
|
|
|
+ for (std::string const& runpath : ordered) {
|
|
|
+ // Either 'add_rpath' or 'delete_rpath' since we've removed empty
|
|
|
+ // entries
|
|
|
+ os << indent << " -" << runpath_change.find(runpath)->second
|
|
|
+ << "_rpath \"" << runpath << "\"\n";
|
|
|
}
|
|
|
+ os << indent << " \"" << toDestDirPath << "\")\n";
|
|
|
}
|
|
|
}
|
|
|
} else {
|