Add rpath support
This commit is contained in:
parent
4f5f54ac3a
commit
f5efd92f6e
|
@ -33,6 +33,7 @@ THE SOFTWARE.
|
|||
#include <sys/param.h>
|
||||
#include "Utils.h"
|
||||
#include "Settings.h"
|
||||
#include "DylibBundler.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sstream>
|
||||
|
@ -91,7 +92,11 @@ Dependency::Dependency(std::string path)
|
|||
char original_file_buffer[PATH_MAX];
|
||||
std::string original_file;
|
||||
|
||||
if (not realpath(rtrim(path).c_str(), original_file_buffer))
|
||||
if (isRpath(path))
|
||||
{
|
||||
original_file = searchFilenameInRpaths(path);
|
||||
}
|
||||
else if (not realpath(rtrim(path).c_str(), original_file_buffer))
|
||||
{
|
||||
std::cerr << "\n/!\\ WARNING : Cannot resolve path '" << path.c_str() << "'" << std::endl;
|
||||
original_file = path;
|
||||
|
@ -141,31 +146,7 @@ Dependency::Dependency(std::string path)
|
|||
std::cerr << "\n/!\\ WARNING : Library " << filename << " has an incomplete name (location unknown)" << std::endl;
|
||||
missing_prefixes = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::cout << "Please specify now where this library can be found (or write 'quit' to abort): "; fflush(stdout);
|
||||
|
||||
char buffer[128];
|
||||
std::cin >> buffer;
|
||||
prefix = buffer;
|
||||
std::cout << std::endl;
|
||||
|
||||
if(prefix.compare("quit")==0) exit(1);
|
||||
|
||||
if( !prefix.empty() && prefix[ prefix.size()-1 ] != '/' ) prefix += "/";
|
||||
|
||||
if( !fileExists( prefix+filename ) )
|
||||
{
|
||||
std::cerr << (prefix+filename) << " does not exist. Try again" << std::endl;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
pathes.push_back( prefix );
|
||||
std::cerr << (prefix+filename) << " was found. /!\\MANUALLY CHECK THE EXECUTABLE WITH 'otool -L', DYLIBBUNDLDER MAY NOT HANDLE CORRECTLY THIS UNSTANDARD/ILL-FORMED DEPENDENCY" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
paths.push_back(getUserInputDirForFile(filename));
|
||||
}
|
||||
|
||||
//new_name = filename.substr(0, filename.find(".")) + ".dylib";
|
||||
|
|
|
@ -26,12 +26,15 @@ THE SOFTWARE.
|
|||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <set>
|
||||
#include "Utils.h"
|
||||
#include "Settings.h"
|
||||
#include "Dependency.h"
|
||||
|
||||
|
||||
std::vector<Dependency> deps;
|
||||
std::set<std::string> rpaths;
|
||||
std::set<std::string> filenames_rpaths_already_collected;
|
||||
|
||||
void changeLibPathsOnFile(std::string file_to_fix)
|
||||
{
|
||||
|
@ -44,6 +47,88 @@ void changeLibPathsOnFile(std::string file_to_fix)
|
|||
}
|
||||
}
|
||||
|
||||
void collectRpaths(const std::string& filename)
|
||||
{
|
||||
if (!fileExists(filename))
|
||||
{
|
||||
std::cerr << "\n/!\\ WARNING : can't collect rpaths for inexistent file '" << filename << "'\n";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string cmd = "otool -l " + filename;
|
||||
std::string output = system_get_output(cmd);
|
||||
|
||||
std::vector<std::string> lc_lines;
|
||||
tokenize(output, "\n", &lc_lines);
|
||||
|
||||
size_t pos = 0;
|
||||
bool read_rpath = false;
|
||||
while (pos < lc_lines.size())
|
||||
{
|
||||
std::string line = lc_lines[pos];
|
||||
pos++;
|
||||
|
||||
if (read_rpath)
|
||||
{
|
||||
size_t start_pos = line.find("path ");
|
||||
size_t end_pos = line.find(" (");
|
||||
if (start_pos == std::string::npos || end_pos == std::string::npos)
|
||||
{
|
||||
std::cerr << "\n/!\\ WARNING: Unexpected LC_RPATH format\n";
|
||||
continue;
|
||||
}
|
||||
start_pos += 5;
|
||||
std::string rpath = line.substr(start_pos, end_pos - start_pos);
|
||||
rpaths.insert(rpath);
|
||||
read_rpath = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.find("LC_RPATH") != std::string::npos)
|
||||
{
|
||||
read_rpath = true;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void collectRpathsForFilename(const std::string& filename)
|
||||
{
|
||||
if (filenames_rpaths_already_collected.find(filename) == filenames_rpaths_already_collected.end())
|
||||
{
|
||||
collectRpaths(filename);
|
||||
filenames_rpaths_already_collected.insert(filename);
|
||||
}
|
||||
}
|
||||
|
||||
std::string searchFilenameInRpaths(const std::string& rpath_file)
|
||||
{
|
||||
char buffer[PATH_MAX];
|
||||
std::string fullpath;
|
||||
std::string suffix = rpath_file.substr(7, rpath_file.size()-6);
|
||||
|
||||
for (std::set<std::string>::iterator it = rpaths.begin(); it != rpaths.end(); ++it)
|
||||
{
|
||||
std::string path = *it + "/" + suffix;
|
||||
if (realpath(path.c_str(), buffer))
|
||||
{
|
||||
fullpath = buffer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fullpath.empty())
|
||||
{
|
||||
std::cerr << "\n/!\\ WARNING : can't get path for '" << rpath_file << "'\n";
|
||||
fullpath = getUserInputDirForFile(suffix) + suffix;
|
||||
if (realpath(fullpath.c_str(), buffer)) {
|
||||
fullpath = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return fullpath;
|
||||
}
|
||||
|
||||
void addDependency(std::string path)
|
||||
{
|
||||
Dependency dep(path);
|
||||
|
@ -93,10 +178,15 @@ void collectDependencies(std::string filename)
|
|||
std::cout << "."; fflush(stdout);
|
||||
if(lines[n][0] != '\t') continue; // only lines beginning with a tab interest us
|
||||
if( lines[n].find(".framework") != std::string::npos ) continue; //Ignore frameworks, we can not handle them
|
||||
|
||||
addDependency( // trim useless info, keep only library name
|
||||
lines[n].substr(1, lines[n].rfind(" (") - 1)
|
||||
);
|
||||
|
||||
// trim useless info, keep only library name
|
||||
std::string dep_path = lines[n].substr(1, lines[n].rfind(" (") - 1);
|
||||
if (isRpath(dep_path))
|
||||
{
|
||||
collectRpathsForFilename(filename);
|
||||
}
|
||||
|
||||
addDependency(dep_path);
|
||||
}
|
||||
}
|
||||
void collectSubDependencies()
|
||||
|
@ -112,7 +202,13 @@ void collectSubDependencies()
|
|||
{
|
||||
std::cout << "."; fflush(stdout);
|
||||
std::vector<std::string> lines;
|
||||
collectDependencies(deps[n].getOriginalPath(), lines);
|
||||
std::string original_path = deps[n].getOriginalPath();
|
||||
if (isRpath(original_path))
|
||||
{
|
||||
original_path = searchFilenameInRpaths(original_path);
|
||||
}
|
||||
collectRpathsForFilename(original_path);
|
||||
collectDependencies(original_path, lines);
|
||||
|
||||
const int line_amount = lines.size();
|
||||
for(int n=0; n<line_amount; n++)
|
||||
|
@ -120,9 +216,14 @@ void collectSubDependencies()
|
|||
if(lines[n][0] != '\t') continue; // only lines beginning with a tab interest us
|
||||
if( lines[n].find(".framework") != std::string::npos ) continue; //Ignore frameworks, we can not handle them
|
||||
|
||||
addDependency( // trim useless info, keep only library name
|
||||
lines[n].substr(1, lines[n].rfind(" (") - 1)
|
||||
);
|
||||
// trim useless info, keep only library name
|
||||
std::string dep_path = lines[n].substr(1, lines[n].rfind(" (") - 1);
|
||||
if (isRpath(dep_path))
|
||||
{
|
||||
collectRpathsForFilename(searchFilenameInRpaths(dep_path));
|
||||
}
|
||||
|
||||
addDependency(dep_path);
|
||||
}//next
|
||||
}//next
|
||||
|
||||
|
|
|
@ -30,5 +30,7 @@ THE SOFTWARE.
|
|||
void collectDependencies(std::string filename);
|
||||
void collectSubDependencies();
|
||||
void doneWithDeps_go();
|
||||
bool isRpath(const std::string& path);
|
||||
std::string searchFilenameInRpaths(const std::string& rpath_dep);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -177,3 +177,30 @@ int systemp(std::string& cmd)
|
|||
std::cout << " " << cmd.c_str() << std::endl;
|
||||
return system(cmd.c_str());
|
||||
}
|
||||
|
||||
std::string getUserInputDirForFile(const std::string& filename)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
std::cout << "Please specify now the directory where this library can be found (or write 'quit' to abort): "; fflush(stdout);
|
||||
|
||||
std::string prefix;
|
||||
std::cin >> prefix;
|
||||
std::cout << std::endl;
|
||||
|
||||
if(prefix.compare("quit")==0) exit(1);
|
||||
|
||||
if( !prefix.empty() && prefix[ prefix.size()-1 ] != '/' ) prefix += "/";
|
||||
|
||||
if( !fileExists( prefix+filename ) )
|
||||
{
|
||||
std::cerr << (prefix+filename) << " does not exist. Try again" << std::endl;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << (prefix+filename) << " was found. /!\\MANUALLY CHECK THE EXECUTABLE WITH 'otool -L', DYLIBBUNDLDER MAY NOT HANDLE CORRECTLY THIS UNSTANDARD/ILL-FORMED DEPENDENCY" << std::endl;
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,5 +41,6 @@ std::string system_get_output(std::string cmd);
|
|||
|
||||
// like 'system', runs a command on the system shell, but also prints the command to stdout.
|
||||
int systemp(std::string& cmd);
|
||||
std::string getUserInputDirForFile(const std::string& filename);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue