resolve run-time paths

This commit is contained in:
SCG82 2020-01-14 01:23:15 -08:00
parent c589a4fcaf
commit 5919c7f979
7 changed files with 102 additions and 30 deletions

View File

@ -1,6 +1,6 @@
DESTDIR= DESTDIR=
PREFIX=/usr/local PREFIX=/usr/local
CXXFLAGS = -O2 CXXFLAGS = -O2 -std=c++14
all: dylibbundler all: dylibbundler

View File

@ -87,14 +87,14 @@ void initSearchPaths(){
// more stuff will then be necessary to do // more stuff will then be necessary to do
bool missing_prefixes = false; bool missing_prefixes = false;
Dependency::Dependency(std::string path) Dependency::Dependency(std::string path, std::string dependent_file)
{ {
char original_file_buffer[PATH_MAX]; char original_file_buffer[PATH_MAX];
std::string original_file; std::string original_file;
if (isRpath(path)) if (isRpath(path))
{ {
original_file = searchFilenameInRpaths(path); original_file = searchFilenameInRpaths(path, dependent_file);
} }
else if (not realpath(rtrim(path).c_str(), original_file_buffer)) else if (not realpath(rtrim(path).c_str(), original_file_buffer))
{ {
@ -107,17 +107,10 @@ Dependency::Dependency(std::string path)
} }
// check if given path is a symlink // check if given path is a symlink
if (original_file != rtrim(path)) if (original_file != rtrim(path)) addSymlink(path);
{
filename = stripPrefix(original_file); filename = stripPrefix(path);
prefix = original_file.substr(0, original_file.rfind("/")+1); prefix = filePrefix(original_file);
addSymlink(path);
}
else
{
filename = stripPrefix(path);
prefix = path.substr(0, path.rfind("/")+1);
}
//check if the lib is in a known location //check if the lib is in a known location
if( !prefix.empty() && prefix[ prefix.size()-1 ] != '/' ) prefix += "/"; if( !prefix.empty() && prefix[ prefix.size()-1 ] != '/' ) prefix += "/";

View File

@ -39,7 +39,7 @@ class Dependency
// installation // installation
std::string new_name; std::string new_name;
public: public:
Dependency(std::string path); Dependency(std::string path, std::string dependent_file);
void print(); void print();

View File

@ -26,6 +26,7 @@ THE SOFTWARE.
#include <iostream> #include <iostream>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <regex>
#include <set> #include <set>
#include <map> #include <map>
#ifdef __linux #ifdef __linux
@ -40,7 +41,8 @@ std::vector<Dependency> deps;
std::map<std::string, std::vector<Dependency> > deps_per_file; std::map<std::string, std::vector<Dependency> > deps_per_file;
std::map<std::string, bool> deps_collected; std::map<std::string, bool> deps_collected;
std::set<std::string> rpaths; std::set<std::string> rpaths;
std::map<std::string, std::vector<std::string> > rpaths_per_file; std::map<std::string, std::set<std::string> > rpaths_per_file;
std::map<std::string, std::string> rpath_to_fullpath;
void changeLibPathsOnFile(std::string file_to_fix) void changeLibPathsOnFile(std::string file_to_fix)
{ {
@ -96,7 +98,7 @@ void collectRpaths(const std::string& filename)
start_pos += 5; start_pos += 5;
std::string rpath = line.substr(start_pos, end_pos - start_pos); std::string rpath = line.substr(start_pos, end_pos - start_pos);
rpaths.insert(rpath); rpaths.insert(rpath);
rpaths_per_file[filename].push_back(rpath); rpaths_per_file[filename].insert(rpath);
read_rpath = false; read_rpath = false;
continue; continue;
} }
@ -117,19 +119,86 @@ void collectRpathsForFilename(const std::string& filename)
} }
} }
std::string searchFilenameInRpaths(const std::string& rpath_file) std::string searchFilenameInRpaths(const std::string& rpath_file, const std::string& dependent_file)
{ {
char buffer[PATH_MAX]; char buffer[PATH_MAX];
std::string fullpath; std::string fullpath;
std::string suffix = rpath_file.substr(rpath_file.rfind("/")+1); std::string suffix = rpath_file.substr(rpath_file.rfind("/")+1);
for (std::set<std::string>::iterator it = rpaths.begin(); it != rpaths.end(); ++it) const auto check_path = [&](std::string path)
{ {
std::string path = *it + "/" + suffix; if (path.find("@executable_path") != std::string::npos)
if (realpath(path.c_str(), buffer))
{ {
fullpath = buffer; int count = Settings::fileToFixAmount();
break; for (int n=0; n<count; ++n)
{
std::string prefix = filePrefix(Settings::fileToFix(n));
path = std::regex_replace(path, std::regex("@executable_path/"), prefix);
if (realpath(path.c_str(), buffer))
{
fullpath = buffer;
rpath_to_fullpath[rpath_file] = fullpath;
return true;
}
}
}
else if (dependent_file != rpath_file)
{
if (path.find("@loader_path") != std::string::npos)
{
std::string prefix = filePrefix(dependent_file);
path = std::regex_replace(path, std::regex("@loader_path/"), prefix);
if (realpath(path.c_str(), buffer))
{
fullpath = buffer;
rpath_to_fullpath[rpath_file] = fullpath;
return true;
}
}
}
if (path.find("@rpath") != std::string::npos)
{
int count = Settings::fileToFixAmount();
for (int n=0; n<count; ++n)
{
std::string prefix = filePrefix(Settings::fileToFix(n));
path = std::regex_replace(path, std::regex("@rpath/"), prefix);
if (realpath(path.c_str(), buffer))
{
fullpath = buffer;
rpath_to_fullpath[rpath_file] = fullpath;
return true;
}
}
if (dependent_file != rpath_file)
{
std::string prefix = filePrefix(dependent_file);
path = std::regex_replace(path, std::regex("@rpath/"), prefix);
if (realpath(path.c_str(), buffer))
{
fullpath = buffer;
rpath_to_fullpath[rpath_file] = fullpath;
return true;
}
}
}
return false;
};
// fullpath previously stored
if (rpath_to_fullpath.find(rpath_file) != rpath_to_fullpath.end())
{
fullpath = rpath_to_fullpath[rpath_file];
}
else if (!check_path(rpath_file))
{
for (std::set<std::string>::iterator it = rpaths_per_file[dependent_file].begin(); it != rpaths_per_file[dependent_file].end(); ++it)
{
std::string rpath = *it;
if (rpath[rpath.size()-1] != '/') rpath += "/";
std::string path = rpath + suffix;
if (check_path(path)) break;
} }
} }
@ -145,19 +214,24 @@ std::string searchFilenameInRpaths(const std::string& rpath_file)
return fullpath; return fullpath;
} }
std::string searchFilenameInRpaths(const std::string& rpath_file)
{
return searchFilenameInRpaths(rpath_file, rpath_file);
}
void fixRpathsOnFile(const std::string& original_file, const std::string& file_to_fix) void fixRpathsOnFile(const std::string& original_file, const std::string& file_to_fix)
{ {
std::vector<std::string> rpaths_to_fix; std::set<std::string> rpaths_to_fix;
std::map<std::string, std::vector<std::string> >::iterator found = rpaths_per_file.find(original_file); std::map<std::string, std::set<std::string> >::iterator found = rpaths_per_file.find(original_file);
if (found != rpaths_per_file.end()) if (found != rpaths_per_file.end())
{ {
rpaths_to_fix = found->second; rpaths_to_fix = found->second;
} }
for (size_t i=0; i < rpaths_to_fix.size(); ++i) for (const auto& rpath_to_fix : rpaths_to_fix)
{ {
std::string command = std::string("install_name_tool -rpath ") + std::string command = std::string("install_name_tool -rpath ") +
rpaths_to_fix[i] + " " + Settings::inside_lib_path() + " " + file_to_fix; rpath_to_fix + " " + Settings::inside_lib_path() + " " + file_to_fix;
if ( systemp(command) != 0) if ( systemp(command) != 0)
{ {
std::cerr << "\n\nError : An error occured while trying to fix dependencies of " << file_to_fix << std::endl; std::cerr << "\n\nError : An error occured while trying to fix dependencies of " << file_to_fix << std::endl;
@ -168,7 +242,7 @@ void fixRpathsOnFile(const std::string& original_file, const std::string& file_t
void addDependency(std::string path, std::string filename) void addDependency(std::string path, std::string filename)
{ {
Dependency dep(path); Dependency dep(path, filename);
// we need to check if this library was already added to avoid duplicates // we need to check if this library was already added to avoid duplicates
bool in_deps = false; bool in_deps = false;
@ -213,7 +287,6 @@ void collectDependencies(std::string filename, std::vector<std::string>& lines)
deps_collected[filename] = true; deps_collected[filename] = true;
} }
void collectDependencies(std::string filename) void collectDependencies(std::string filename)
{ {
std::vector<std::string> lines; std::vector<std::string> lines;
@ -238,6 +311,7 @@ void collectDependencies(std::string filename)
addDependency(dep_path, filename); addDependency(dep_path, filename);
} }
} }
void collectSubDependencies() void collectSubDependencies()
{ {
// print status to user // print status to user

View File

@ -31,6 +31,7 @@ void collectDependencies(std::string filename);
void collectSubDependencies(); void collectSubDependencies();
void doneWithDeps_go(); void doneWithDeps_go();
bool isRpath(const std::string& path); bool isRpath(const std::string& path);
std::string searchFilenameInRpaths(const std::string& rpath_file, const std::string& dependent_file);
std::string searchFilenameInRpaths(const std::string& rpath_dep); std::string searchFilenameInRpaths(const std::string& rpath_dep);
#endif #endif

View File

@ -67,7 +67,10 @@ void tokenize(const string& str, const char* delim, vector<string>* vectorarg)
} }
std::string filePrefix(std::string in)
{
return in.substr(0, in.rfind("/")+1);
}
bool fileExists( std::string filename ) bool fileExists( std::string filename )
{ {

View File

@ -32,6 +32,7 @@ THE SOFTWARE.
class Library; class Library;
void tokenize(const std::string& str, const char* delimiters, std::vector<std::string>*); void tokenize(const std::string& str, const char* delimiters, std::vector<std::string>*);
std::string filePrefix(std::string in);
bool fileExists( std::string filename ); bool fileExists( std::string filename );
void copyFile(std::string from, std::string to); void copyFile(std::string from, std::string to);