Add rpath support
This commit is contained in:
parent
4f5f54ac3a
commit
f5efd92f6e
|
@ -33,6 +33,7 @@ THE SOFTWARE.
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
#include "DylibBundler.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -91,7 +92,11 @@ Dependency::Dependency(std::string path)
|
||||||
char original_file_buffer[PATH_MAX];
|
char original_file_buffer[PATH_MAX];
|
||||||
std::string original_file;
|
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;
|
std::cerr << "\n/!\\ WARNING : Cannot resolve path '" << path.c_str() << "'" << std::endl;
|
||||||
original_file = path;
|
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;
|
std::cerr << "\n/!\\ WARNING : Library " << filename << " has an incomplete name (location unknown)" << std::endl;
|
||||||
missing_prefixes = true;
|
missing_prefixes = true;
|
||||||
|
|
||||||
while (true)
|
paths.push_back(getUserInputDirForFile(filename));
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//new_name = filename.substr(0, filename.find(".")) + ".dylib";
|
//new_name = filename.substr(0, filename.find(".")) + ".dylib";
|
||||||
|
|
|
@ -26,12 +26,15 @@ THE SOFTWARE.
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <set>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "Dependency.h"
|
#include "Dependency.h"
|
||||||
|
|
||||||
|
|
||||||
std::vector<Dependency> deps;
|
std::vector<Dependency> deps;
|
||||||
|
std::set<std::string> rpaths;
|
||||||
|
std::set<std::string> filenames_rpaths_already_collected;
|
||||||
|
|
||||||
void changeLibPathsOnFile(std::string file_to_fix)
|
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)
|
void addDependency(std::string path)
|
||||||
{
|
{
|
||||||
Dependency dep(path);
|
Dependency dep(path);
|
||||||
|
@ -93,10 +178,15 @@ void collectDependencies(std::string filename)
|
||||||
std::cout << "."; fflush(stdout);
|
std::cout << "."; fflush(stdout);
|
||||||
if(lines[n][0] != '\t') continue; // only lines beginning with a tab interest us
|
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
|
if( lines[n].find(".framework") != std::string::npos ) continue; //Ignore frameworks, we can not handle them
|
||||||
|
|
||||||
addDependency( // trim useless info, keep only library name
|
// trim useless info, keep only library name
|
||||||
lines[n].substr(1, lines[n].rfind(" (") - 1)
|
std::string dep_path = lines[n].substr(1, lines[n].rfind(" (") - 1);
|
||||||
);
|
if (isRpath(dep_path))
|
||||||
|
{
|
||||||
|
collectRpathsForFilename(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
addDependency(dep_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void collectSubDependencies()
|
void collectSubDependencies()
|
||||||
|
@ -112,7 +202,13 @@ void collectSubDependencies()
|
||||||
{
|
{
|
||||||
std::cout << "."; fflush(stdout);
|
std::cout << "."; fflush(stdout);
|
||||||
std::vector<std::string> lines;
|
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();
|
const int line_amount = lines.size();
|
||||||
for(int n=0; n<line_amount; n++)
|
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][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
|
if( lines[n].find(".framework") != std::string::npos ) continue; //Ignore frameworks, we can not handle them
|
||||||
|
|
||||||
addDependency( // trim useless info, keep only library name
|
// trim useless info, keep only library name
|
||||||
lines[n].substr(1, lines[n].rfind(" (") - 1)
|
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
|
||||||
}//next
|
}//next
|
||||||
|
|
||||||
|
|
|
@ -30,5 +30,7 @@ THE SOFTWARE.
|
||||||
void collectDependencies(std::string filename);
|
void collectDependencies(std::string filename);
|
||||||
void collectSubDependencies();
|
void collectSubDependencies();
|
||||||
void doneWithDeps_go();
|
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;
|
std::cout << " " << cmd.c_str() << std::endl;
|
||||||
return system(cmd.c_str());
|
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.
|
// like 'system', runs a command on the system shell, but also prints the command to stdout.
|
||||||
int systemp(std::string& cmd);
|
int systemp(std::string& cmd);
|
||||||
|
std::string getUserInputDirForFile(const std::string& filename);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue