move searchFilenameInRpaths to Util.cpp
This commit is contained in:
parent
ab607a8e66
commit
bc8c55e6c2
|
@ -17,7 +17,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "DylibBundler.h"
|
// #include "DylibBundler.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <regex>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#ifdef __linux
|
#ifdef __linux
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
|
@ -21,218 +19,10 @@ 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> frameworks;
|
std::set<std::string> frameworks;
|
||||||
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::vector<std::string>> rpaths_per_file;
|
||||||
std::map<std::string, std::string> rpath_to_fullpath;
|
// std::map<std::string, std::string> rpath_to_fullpath;
|
||||||
bool qt_plugins_called = false;
|
bool qt_plugins_called = false;
|
||||||
|
|
||||||
void changeLibPathsOnFile(std::string file_to_fix)
|
|
||||||
{
|
|
||||||
if (deps_collected.find(file_to_fix) == deps_collected.end())
|
|
||||||
collectDependenciesForFile(file_to_fix);
|
|
||||||
|
|
||||||
std::cout << "* Fixing dependencies on " << file_to_fix << "\n";
|
|
||||||
|
|
||||||
const size_t dep_amount = deps_per_file[file_to_fix].size();
|
|
||||||
for (size_t n=0; n<dep_amount; ++n) {
|
|
||||||
deps_per_file[file_to_fix][n].fixFileThatDependsOnMe(file_to_fix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// void collectRpaths(const std::string& filename)
|
|
||||||
// {
|
|
||||||
// if (!fileExists(filename)) {
|
|
||||||
// std::cerr << "\n/!\\ WARNING: Can't collect rpaths for nonexistent file '" << filename << "'\n";
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (Settings::verboseOutput())
|
|
||||||
// std::cout << " collecting rpaths for: " << filename << std::endl;
|
|
||||||
|
|
||||||
// std::string cmd = "otool -l " + filename;
|
|
||||||
// std::string output = systemOutput(cmd);
|
|
||||||
|
|
||||||
// if (output.find("can't open file") != std::string::npos
|
|
||||||
// || output.find("No such file") != std::string::npos
|
|
||||||
// || output.find("at least one file must be specified") != std::string::npos
|
|
||||||
// || output.size() < 1) {
|
|
||||||
// std::cerr << "\n\n/!\\ ERROR: Cannot find file " << filename << " to read its rpaths\n";
|
|
||||||
// exit(1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// std::vector<std::string> lc_lines;
|
|
||||||
// tokenize(output, "\n", &lc_lines);
|
|
||||||
|
|
||||||
// bool searching = false;
|
|
||||||
// for (const auto& line : lc_lines) {
|
|
||||||
// if (line.find("cmd LC_RPATH") != std::string::npos) {
|
|
||||||
// if (searching) {
|
|
||||||
// std::cerr << "\n\n/!\\ ERROR: Failed to find path before next cmd" << std::endl;
|
|
||||||
// exit(1);
|
|
||||||
// }
|
|
||||||
// searching = true;
|
|
||||||
// }
|
|
||||||
// else if (searching) {
|
|
||||||
// size_t start_pos = line.find("path ");
|
|
||||||
// size_t end_pos = line.find(" (");
|
|
||||||
// if (start_pos == std::string::npos || end_pos == std::string::npos)
|
|
||||||
// continue;
|
|
||||||
// start_pos += 5; // to exclude "path "
|
|
||||||
// std::string rpath = line.substr(start_pos, end_pos - start_pos);
|
|
||||||
// rpaths.insert(rpath);
|
|
||||||
// rpaths_per_file[filename].push_back(rpath);
|
|
||||||
// searching = false;
|
|
||||||
// if (Settings::verboseOutput())
|
|
||||||
// std::cout << " rpath: " << rpath << std::endl;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
void collectRpaths(const std::string& filename)
|
|
||||||
{
|
|
||||||
std::vector<std::string> lines;
|
|
||||||
parseLoadCommands(filename, std::string("LC_RPATH"), std::string("path"), lines);
|
|
||||||
for (const auto& line : lines) {
|
|
||||||
rpaths.insert(line);
|
|
||||||
rpaths_per_file[filename].push_back(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void collectRpathsForFilename(const std::string& filename)
|
|
||||||
{
|
|
||||||
if (rpaths_per_file.find(filename) == rpaths_per_file.end())
|
|
||||||
collectRpaths(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string searchFilenameInRpaths(const std::string& rpath_file, const std::string& dependent_file)
|
|
||||||
{
|
|
||||||
if (Settings::verboseOutput()) {
|
|
||||||
if (dependent_file != rpath_file)
|
|
||||||
std::cout << " dependent file: " << dependent_file << std::endl;
|
|
||||||
std::cout << " dependency: " << rpath_file << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string fullpath;
|
|
||||||
std::string suffix = rpath_file.substr(rpath_file.rfind("/")+1);
|
|
||||||
char fullpath_buffer[PATH_MAX];
|
|
||||||
|
|
||||||
const auto check_path = [&](std::string path) {
|
|
||||||
char buffer[PATH_MAX];
|
|
||||||
std::string file_prefix = filePrefix(dependent_file);
|
|
||||||
if (path.find("@executable_path") != std::string::npos || path.find("@loader_path") != std::string::npos) {
|
|
||||||
if (path.find("@executable_path") != std::string::npos) {
|
|
||||||
if (Settings::appBundleProvided())
|
|
||||||
path = std::regex_replace(path, std::regex("@executable_path/"), Settings::executableFolder());
|
|
||||||
}
|
|
||||||
if (dependent_file != rpath_file) {
|
|
||||||
if (path.find("@loader_path") != std::string::npos)
|
|
||||||
path = std::regex_replace(path, std::regex("@loader_path/"), file_prefix);
|
|
||||||
}
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << " path to search: " << path << std::endl;
|
|
||||||
if (realpath(path.c_str(), buffer)) {
|
|
||||||
fullpath = buffer;
|
|
||||||
rpath_to_fullpath[rpath_file] = fullpath;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (path.find("@rpath") != std::string::npos) {
|
|
||||||
if (Settings::appBundleProvided()) {
|
|
||||||
std::string pathE = std::regex_replace(path, std::regex("@rpath/"), Settings::executableFolder());
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << " path to search: " << pathE << std::endl;
|
|
||||||
if (realpath(pathE.c_str(), buffer)) {
|
|
||||||
fullpath = buffer;
|
|
||||||
rpath_to_fullpath[rpath_file] = fullpath;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dependent_file != rpath_file) {
|
|
||||||
std::string pathL = std::regex_replace(path, std::regex("@rpath/"), file_prefix);
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << " path to search: " << pathL << std::endl;
|
|
||||||
if (realpath(pathL.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 (auto 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 (Settings::verboseOutput())
|
|
||||||
std::cout << " trying rpath: " << path << std::endl;
|
|
||||||
if (check_path(path))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fullpath.empty()) {
|
|
||||||
size_t search_path_count = Settings::searchPathCount();
|
|
||||||
for (size_t i=0; i<search_path_count; ++i) {
|
|
||||||
std::string search_path = Settings::searchPath(i);
|
|
||||||
if (fileExists(search_path+suffix)) {
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << "FOUND " + suffix + " in " + search_path + "\n";
|
|
||||||
fullpath = search_path + suffix;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fullpath.empty()) {
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << " ** rpath fullpath: not found" << std::endl;
|
|
||||||
if (!Settings::quietOutput())
|
|
||||||
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'\n";
|
|
||||||
fullpath = getUserInputDirForFile(suffix) + suffix;
|
|
||||||
if (Settings::quietOutput() && fullpath.empty())
|
|
||||||
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'\n";
|
|
||||||
if (realpath(fullpath.c_str(), fullpath_buffer))
|
|
||||||
fullpath = fullpath_buffer;
|
|
||||||
}
|
|
||||||
else if (Settings::verboseOutput()) {
|
|
||||||
std::cout << " ** rpath fullpath: " << fullpath << std::endl;
|
|
||||||
}
|
|
||||||
} else if (Settings::verboseOutput()) {
|
|
||||||
std::cout << " ** rpath fullpath: " << fullpath << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
std::vector<std::string> rpaths_to_fix;
|
|
||||||
std::map<std::string, std::vector<std::string>>::iterator found = rpaths_per_file.find(original_file);
|
|
||||||
if (found != rpaths_per_file.end())
|
|
||||||
rpaths_to_fix = found->second;
|
|
||||||
|
|
||||||
for (size_t i=0; i < rpaths_to_fix.size(); ++i) {
|
|
||||||
std::string command =
|
|
||||||
std::string("install_name_tool -rpath ")
|
|
||||||
+ rpaths_to_fix[i] + " "
|
|
||||||
+ Settings::insideLibPath() + " "
|
|
||||||
+ file_to_fix;
|
|
||||||
if (systemp(command) != 0) {
|
|
||||||
std::cerr << "\n\n/!\\ ERROR: An error occured while trying to fix dependencies of " << file_to_fix << "\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addDependency(std::string path, std::string dependent_file)
|
void addDependency(std::string path, std::string dependent_file)
|
||||||
{
|
{
|
||||||
Dependency dep(path, dependent_file);
|
Dependency dep(path, dependent_file);
|
||||||
|
@ -265,43 +55,10 @@ void addDependency(std::string path, std::string dependent_file)
|
||||||
deps_per_file[dependent_file].push_back(dep);
|
deps_per_file[dependent_file].push_back(dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines)
|
std::string searchFilenameInRpaths(const std::string& rpath_file)
|
||||||
// {
|
{
|
||||||
// std::string cmd = "otool -l " + dependent_file;
|
return searchFilenameInRpaths(rpath_file, rpath_file);
|
||||||
// std::string output = systemOutput(cmd);
|
}
|
||||||
|
|
||||||
// if (output.find("can't open file") != std::string::npos
|
|
||||||
// || output.find("No such file") != std::string::npos
|
|
||||||
// || output.find("at least one file must be specified") != std::string::npos
|
|
||||||
// || output.size() < 1) {
|
|
||||||
// std::cerr << "\n\n/!\\ ERROR: Cannot find file " << dependent_file << " to read its dependencies\n";
|
|
||||||
// exit(1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// std::vector<std::string> raw_lines;
|
|
||||||
// tokenize(output, "\n", &raw_lines);
|
|
||||||
|
|
||||||
// bool searching = false;
|
|
||||||
// for (const auto& line : raw_lines) {
|
|
||||||
// if (line.find("cmd LC_LOAD_DYLIB") != std::string::npos) {
|
|
||||||
// if (searching) {
|
|
||||||
// std::cerr << "\n\n/!\\ ERROR: Failed to find name before next cmd" << std::endl;
|
|
||||||
// exit(1);
|
|
||||||
// }
|
|
||||||
// searching = true;
|
|
||||||
// }
|
|
||||||
// else if (searching) {
|
|
||||||
// size_t found = line.find("name ");
|
|
||||||
// size_t start_pos = line.find("name ");
|
|
||||||
// size_t end_pos = line.find(" (");
|
|
||||||
// if (start_pos == std::string::npos || end_pos == std::string::npos)
|
|
||||||
// continue;
|
|
||||||
// start_pos += 5; // to exclude "name "
|
|
||||||
// lines.push_back('\t' + line.substr(start_pos, end_pos - start_pos));
|
|
||||||
// searching = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines)
|
void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines)
|
||||||
{
|
{
|
||||||
|
@ -321,20 +78,32 @@ void collectDependenciesForFile(const std::string& dependent_file)
|
||||||
collectRpathsForFilename(dependent_file);
|
collectRpathsForFilename(dependent_file);
|
||||||
|
|
||||||
for (size_t i=0; i<lines.size(); ++i) {
|
for (size_t i=0; i<lines.size(); ++i) {
|
||||||
// lines containing path begin with a tab
|
|
||||||
if (lines[i][0] != '\t')
|
|
||||||
continue;
|
|
||||||
if (!Settings::isPrefixBundled(lines[i]))
|
if (!Settings::isPrefixBundled(lines[i]))
|
||||||
continue;
|
continue; // skip system/ignored prefixes
|
||||||
// trim useless info, keep only library path
|
addDependency(lines[i], dependent_file);
|
||||||
std::string dep_path = lines[i].substr(1, lines[i].rfind(" (") - 1);
|
|
||||||
// if (isRpath(dep_path))
|
|
||||||
// collectRpathsForFilename(searchFilenameInRpaths(dep_path, dependent_file));
|
|
||||||
addDependency(dep_path, dependent_file);
|
|
||||||
}
|
}
|
||||||
deps_collected[dependent_file] = true;
|
deps_collected[dependent_file] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void collectRpaths(const std::string& filename)
|
||||||
|
{
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
parseLoadCommands(filename, std::string("LC_RPATH"), std::string("path"), lines);
|
||||||
|
for (const auto& line : lines) {
|
||||||
|
rpaths.insert(line);
|
||||||
|
// rpaths_per_file[filename].push_back(line);
|
||||||
|
Settings::addRpathForFile(filename, line);
|
||||||
|
if (Settings::verboseOutput())
|
||||||
|
std::cout << " rpath: " << line << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void collectRpathsForFilename(const std::string& filename)
|
||||||
|
{
|
||||||
|
if (!Settings::fileHasRpath(filename))
|
||||||
|
collectRpaths(filename);
|
||||||
|
}
|
||||||
|
|
||||||
void collectSubDependencies()
|
void collectSubDependencies()
|
||||||
{
|
{
|
||||||
size_t dep_counter = deps.size();
|
size_t dep_counter = deps.size();
|
||||||
|
@ -346,7 +115,6 @@ void collectSubDependencies()
|
||||||
size_t deps_size = deps.size();
|
size_t deps_size = deps.size();
|
||||||
while (true) {
|
while (true) {
|
||||||
deps_size = deps.size();
|
deps_size = deps.size();
|
||||||
|
|
||||||
for (size_t n=0; n<deps_size; ++n) {
|
for (size_t n=0; n<deps_size; ++n) {
|
||||||
std::string original_path = deps[n].getOriginalPath();
|
std::string original_path = deps[n].getOriginalPath();
|
||||||
if (Settings::verboseOutput())
|
if (Settings::verboseOutput())
|
||||||
|
@ -354,22 +122,14 @@ void collectSubDependencies()
|
||||||
if (isRpath(original_path))
|
if (isRpath(original_path))
|
||||||
original_path = searchFilenameInRpaths(original_path);
|
original_path = searchFilenameInRpaths(original_path);
|
||||||
|
|
||||||
collectRpathsForFilename(original_path);
|
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
collectDependenciesForFile(original_path, lines);
|
collectDependenciesForFile(original_path, lines);
|
||||||
|
collectRpathsForFilename(original_path);
|
||||||
|
|
||||||
for (size_t i=0; i<lines.size(); ++i) {
|
for (size_t i=0; i<lines.size(); ++i) {
|
||||||
// lines containing path begin with a tab
|
|
||||||
if (lines[i][0] != '\t')
|
|
||||||
continue;
|
|
||||||
// skip system/ignored prefixes
|
|
||||||
if (!Settings::isPrefixBundled(lines[i]))
|
if (!Settings::isPrefixBundled(lines[i]))
|
||||||
continue;
|
continue; // skip system/ignored prefixes
|
||||||
// trim useless info, keep only library name
|
addDependency(lines[i], original_path);
|
||||||
std::string dep_path = lines[i].substr(1, lines[i].rfind(" (") - 1);
|
|
||||||
// if (isRpath(dep_path))
|
|
||||||
// collectRpathsForFilename(searchFilenameInRpaths(dep_path, original_path));
|
|
||||||
addDependency(dep_path, original_path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if no more dependencies were added on this iteration, stop searching
|
// if no more dependencies were added on this iteration, stop searching
|
||||||
|
@ -377,30 +137,62 @@ void collectSubDependencies()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::verboseOutput()) {
|
if (Settings::verboseOutput()) {
|
||||||
std::cout << "(post sub) # OF FILES: " << Settings::filesToFixCount() << std::endl;
|
std::cout << "(post sub) # OF FILES: " << Settings::filesToFixCount() << std::endl;
|
||||||
std::cout << "(post sub) # OF DEPS: " << deps.size() << std::endl;
|
std::cout << "(post sub) # OF DEPS: " << deps.size() << std::endl;
|
||||||
}
|
}
|
||||||
if (Settings::bundleFrameworks()) {
|
if (Settings::bundleLibs() && Settings::bundleFrameworks()) {
|
||||||
if (!qt_plugins_called || (deps.size() != dep_counter))
|
if (!qt_plugins_called || (deps.size() != dep_counter))
|
||||||
copyQtPlugins();
|
copyQtPlugins();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void changeLibPathsOnFile(std::string file_to_fix)
|
||||||
|
{
|
||||||
|
if (deps_collected.find(file_to_fix) == deps_collected.end())
|
||||||
|
collectDependenciesForFile(file_to_fix);
|
||||||
|
|
||||||
|
std::cout << "* Fixing dependencies on " << file_to_fix << "\n";
|
||||||
|
|
||||||
|
const size_t dep_amount = deps_per_file[file_to_fix].size();
|
||||||
|
for (size_t n=0; n<dep_amount; ++n) {
|
||||||
|
deps_per_file[file_to_fix][n].fixFileThatDependsOnMe(file_to_fix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fixRpathsOnFile(const std::string& original_file, const std::string& file_to_fix)
|
||||||
|
{
|
||||||
|
std::vector<std::string> rpaths_to_fix;
|
||||||
|
if (Settings::fileHasRpath(original_file))
|
||||||
|
rpaths_to_fix = Settings::getRpathsForFile(original_file);
|
||||||
|
|
||||||
|
for (size_t i=0; i < rpaths_to_fix.size(); ++i) {
|
||||||
|
std::string command =
|
||||||
|
std::string("install_name_tool -rpath ")
|
||||||
|
+ rpaths_to_fix[i] + " "
|
||||||
|
+ Settings::insideLibPath() + " "
|
||||||
|
+ file_to_fix;
|
||||||
|
if (systemp(command) != 0) {
|
||||||
|
std::cerr << "\n\n/!\\ ERROR: An error occured while trying to fix dependencies of " << file_to_fix << "\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void doneWithDeps_go()
|
void doneWithDeps_go()
|
||||||
{
|
{
|
||||||
if (Settings::verboseOutput()) {
|
|
||||||
for (std::set<std::string>::iterator it = rpaths.begin(); it != rpaths.end(); ++it) {
|
|
||||||
std::cout << "rpaths: " << *it << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t deps_size = deps.size();
|
const size_t deps_size = deps.size();
|
||||||
for (size_t n=0; n<deps_size; ++n) {
|
for (size_t n=0; n<deps_size; ++n) {
|
||||||
deps[n].print();
|
deps[n].print();
|
||||||
}
|
}
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
|
if (Settings::verboseOutput()) {
|
||||||
|
for (std::set<std::string>::iterator it = rpaths.begin(); it != rpaths.end(); ++it) {
|
||||||
|
std::cout << "rpaths: " << *it << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// copy & fix up dependencies
|
||||||
if (Settings::bundleLibs()) {
|
if (Settings::bundleLibs()) {
|
||||||
createDestDir();
|
createDestDir();
|
||||||
for (size_t n=0; n<deps_size; ++n) {
|
for (size_t n=0; n<deps_size; ++n) {
|
||||||
|
@ -409,7 +201,7 @@ void doneWithDeps_go()
|
||||||
fixRpathsOnFile(deps[n].getOriginalPath(), deps[n].getInstallPath());
|
fixRpathsOnFile(deps[n].getOriginalPath(), deps[n].getInstallPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// fix up selected files
|
||||||
const size_t filesToFixSize = Settings::filesToFix().size();
|
const size_t filesToFixSize = Settings::filesToFix().size();
|
||||||
for (size_t j=0; j<filesToFixSize; ++j) {
|
for (size_t j=0; j<filesToFixSize; ++j) {
|
||||||
changeLibPathsOnFile(Settings::fileToFix(j));
|
changeLibPathsOnFile(Settings::fileToFix(j));
|
||||||
|
@ -417,22 +209,8 @@ void doneWithDeps_go()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createQtConf(std::string directory)
|
|
||||||
{
|
|
||||||
std::string contents = "[Paths]\n"
|
|
||||||
"Plugins = PlugIns\n"
|
|
||||||
"Imports = Resources/qml\n"
|
|
||||||
"Qml2Imports = Resources/qml\n";
|
|
||||||
if (directory[directory.size()-1] != '/')
|
|
||||||
directory += "/";
|
|
||||||
std::ofstream out(directory + "qt.conf");
|
|
||||||
out << contents;
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyQtPlugins()
|
void copyQtPlugins()
|
||||||
{
|
{
|
||||||
qt_plugins_called = true;
|
|
||||||
bool qtCoreFound = false;
|
bool qtCoreFound = false;
|
||||||
bool qtGuiFound = false;
|
bool qtGuiFound = false;
|
||||||
bool qtNetworkFound = false;
|
bool qtNetworkFound = false;
|
||||||
|
@ -477,12 +255,12 @@ void copyQtPlugins()
|
||||||
|
|
||||||
if (!qtCoreFound)
|
if (!qtCoreFound)
|
||||||
return;
|
return;
|
||||||
|
if (!qt_plugins_called)
|
||||||
createQtConf(Settings::resourcesFolder());
|
createQtConf(Settings::resourcesFolder());
|
||||||
|
qt_plugins_called = true;
|
||||||
|
|
||||||
|
const auto fixupPlugin = [original_file](std::string plugin) {
|
||||||
std::string dest = Settings::pluginsFolder();
|
std::string dest = Settings::pluginsFolder();
|
||||||
|
|
||||||
const auto fixupPlugin = [original_file,dest] (std::string plugin) {
|
|
||||||
std::string framework_root = getFrameworkRoot(original_file);
|
std::string framework_root = getFrameworkRoot(original_file);
|
||||||
std::string prefix = filePrefix(framework_root);
|
std::string prefix = filePrefix(framework_root);
|
||||||
std::string qt_prefix = filePrefix(prefix.substr(0, prefix.size()-1));
|
std::string qt_prefix = filePrefix(prefix.substr(0, prefix.size()-1));
|
||||||
|
@ -504,6 +282,7 @@ void copyQtPlugins()
|
||||||
std::string qt_prefix = filePrefix(prefix.substr(0, prefix.size()-1));
|
std::string qt_prefix = filePrefix(prefix.substr(0, prefix.size()-1));
|
||||||
std::string qt_plugins_prefix = qt_prefix + "plugins/";
|
std::string qt_plugins_prefix = qt_prefix + "plugins/";
|
||||||
|
|
||||||
|
std::string dest = Settings::pluginsFolder();
|
||||||
mkdir(dest + "platforms");
|
mkdir(dest + "platforms");
|
||||||
copyFile(qt_plugins_prefix + "platforms/libqcocoa.dylib", dest + "platforms");
|
copyFile(qt_plugins_prefix + "platforms/libqcocoa.dylib", dest + "platforms");
|
||||||
Settings::addFileToFix(dest + "platforms/libqcocoa.dylib");
|
Settings::addFileToFix(dest + "platforms/libqcocoa.dylib");
|
||||||
|
@ -541,6 +320,5 @@ void copyQtPlugins()
|
||||||
fixupPlugin("texttospeech");
|
fixupPlugin("texttospeech");
|
||||||
if (qtWebViewFound)
|
if (qtWebViewFound)
|
||||||
fixupPlugin("webview");
|
fixupPlugin("webview");
|
||||||
|
|
||||||
collectSubDependencies();
|
collectSubDependencies();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,30 +2,29 @@
|
||||||
#define _DYLIB_BUNDLER_H_
|
#define _DYLIB_BUNDLER_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
void changeLibPathsOnFile(std::string file_to_fix);
|
void addDependency(std::string path, std::string dependent_file);
|
||||||
|
|
||||||
void collectRpaths(const std::string& filename);
|
|
||||||
void collectRpathsForFilename(const std::string& filename);
|
|
||||||
|
|
||||||
std::string searchFilenameInRpaths(const std::string& rpath_file, const std::string& dependent_file);
|
std::string searchFilenameInRpaths(const std::string& rpath_file, const std::string& dependent_file);
|
||||||
std::string searchFilenameInRpaths(const std::string& rpath_file);
|
std::string searchFilenameInRpaths(const std::string& rpath_file);
|
||||||
|
|
||||||
void fixRpathsOnFile(const std::string& original_file, const std::string& file_to_fix);
|
|
||||||
|
|
||||||
void addDependency(std::string path, std::string dependent_file);
|
|
||||||
|
|
||||||
// fill |lines| with dependencies of |dependent_file|
|
// fill |lines| with dependencies of |dependent_file|
|
||||||
void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines);
|
void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines);
|
||||||
void collectDependenciesForFile(const std::string& dependent_file, std::vector<std::string>& lines);
|
void collectDependenciesForFile(const std::string& dependent_file, std::vector<std::string>& lines);
|
||||||
void collectDependenciesForFile(const std::string& dependent_file);
|
void collectDependenciesForFile(const std::string& dependent_file);
|
||||||
|
|
||||||
|
void collectRpaths(const std::string& filename);
|
||||||
|
void collectRpathsForFilename(const std::string& filename);
|
||||||
|
|
||||||
// recursively collect each dependency's dependencies
|
// recursively collect each dependency's dependencies
|
||||||
void collectSubDependencies();
|
void collectSubDependencies();
|
||||||
|
|
||||||
|
void changeLibPathsOnFile(std::string file_to_fix);
|
||||||
|
void fixRpathsOnFile(const std::string& original_file, const std::string& file_to_fix);
|
||||||
|
|
||||||
void doneWithDeps_go();
|
void doneWithDeps_go();
|
||||||
|
|
||||||
void createQtConf(std::string directory);
|
|
||||||
void copyQtPlugins();
|
void copyQtPlugins();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
@ -153,4 +156,14 @@ bool missing_prefixes = false;
|
||||||
bool missingPrefixes() { return missing_prefixes; }
|
bool missingPrefixes() { return missing_prefixes; }
|
||||||
void missingPrefixes(bool status) { missing_prefixes = status; }
|
void missingPrefixes(bool status) { missing_prefixes = status; }
|
||||||
|
|
||||||
|
std::map<std::string, std::string> rpath_to_fullpath;
|
||||||
|
std::string getFullPath(const std::string& rpath) { return rpath_to_fullpath[rpath]; }
|
||||||
|
void rpathToFullPath(const std::string& rpath, const std::string& fullpath) { rpath_to_fullpath[rpath] = fullpath; }
|
||||||
|
bool rpathFound(const std::string& rpath) { return rpath_to_fullpath.find(rpath) != rpath_to_fullpath.end(); }
|
||||||
|
|
||||||
|
std::map<std::string, std::vector<std::string>> rpaths_per_file;
|
||||||
|
std::vector<std::string> getRpathsForFile(const std::string& file) { return rpaths_per_file[file]; }
|
||||||
|
void addRpathForFile(const std::string& file, const std::string& rpath) { rpaths_per_file[file].push_back(rpath); }
|
||||||
|
bool fileHasRpath(const std::string& file) { return rpaths_per_file.find(file) != rpaths_per_file.end(); }
|
||||||
|
|
||||||
} // namespace Settings
|
} // namespace Settings
|
||||||
|
|
|
@ -62,6 +62,14 @@ void verboseOutput(bool status);
|
||||||
bool missingPrefixes();
|
bool missingPrefixes();
|
||||||
void missingPrefixes(bool status);
|
void missingPrefixes(bool status);
|
||||||
|
|
||||||
|
std::string getFullPath(const std::string& rpath);
|
||||||
|
void rpathToFullPath(const std::string& rpath, const std::string& fullpath);
|
||||||
|
bool rpathFound(const std::string& rpath);
|
||||||
|
|
||||||
|
std::vector<std::string> getRpathsForFile(const std::string& file);
|
||||||
|
void addRpathForFile(const std::string& file, const std::string& rpath);
|
||||||
|
bool fileHasRpath(const std::string& file);
|
||||||
|
|
||||||
} // namespace Settings
|
} // namespace Settings
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
125
src/Utils.cpp
125
src/Utils.cpp
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <regex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -152,7 +154,7 @@ std::string bundleExecutableName(const std::string& app_bundle_path)
|
||||||
{
|
{
|
||||||
std::string cmd = "/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "
|
std::string cmd = "/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "
|
||||||
+ app_bundle_path + "Contents/Info.plist";
|
+ app_bundle_path + "Contents/Info.plist";
|
||||||
return systemOutput(cmd);
|
return rtrim(systemOutput(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeId(const std::string& binary_file, const std::string& new_id)
|
void changeId(const std::string& binary_file, const std::string& new_id)
|
||||||
|
@ -349,6 +351,114 @@ void parseLoadCommands(const std::string& file, const std::string& cmd, const st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string searchFilenameInRpaths(const std::string& rpath_file, const std::string& dependent_file)
|
||||||
|
{
|
||||||
|
if (Settings::verboseOutput()) {
|
||||||
|
if (dependent_file != rpath_file)
|
||||||
|
std::cout << " dependent file: " << dependent_file << std::endl;
|
||||||
|
std::cout << " dependency: " << rpath_file << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fullpath;
|
||||||
|
std::string suffix = rpath_file.substr(rpath_file.rfind("/")+1);
|
||||||
|
char fullpath_buffer[PATH_MAX];
|
||||||
|
|
||||||
|
const auto check_path = [&](std::string path) {
|
||||||
|
char buffer[PATH_MAX];
|
||||||
|
std::string file_prefix = filePrefix(dependent_file);
|
||||||
|
if (path.find("@executable_path") != std::string::npos || path.find("@loader_path") != std::string::npos) {
|
||||||
|
if (path.find("@executable_path") != std::string::npos) {
|
||||||
|
if (Settings::appBundleProvided())
|
||||||
|
path = std::regex_replace(path, std::regex("@executable_path/"), Settings::executableFolder());
|
||||||
|
}
|
||||||
|
if (dependent_file != rpath_file) {
|
||||||
|
if (path.find("@loader_path") != std::string::npos)
|
||||||
|
path = std::regex_replace(path, std::regex("@loader_path/"), file_prefix);
|
||||||
|
}
|
||||||
|
if (Settings::verboseOutput())
|
||||||
|
std::cout << " path to search: " << path << std::endl;
|
||||||
|
if (realpath(path.c_str(), buffer)) {
|
||||||
|
fullpath = buffer;
|
||||||
|
Settings::rpathToFullPath(rpath_file, fullpath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (path.find("@rpath") != std::string::npos) {
|
||||||
|
if (Settings::appBundleProvided()) {
|
||||||
|
std::string pathE = std::regex_replace(path, std::regex("@rpath/"), Settings::executableFolder());
|
||||||
|
if (Settings::verboseOutput())
|
||||||
|
std::cout << " path to search: " << pathE << std::endl;
|
||||||
|
if (realpath(pathE.c_str(), buffer)) {
|
||||||
|
fullpath = buffer;
|
||||||
|
Settings::rpathToFullPath(rpath_file, fullpath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dependent_file != rpath_file) {
|
||||||
|
std::string pathL = std::regex_replace(path, std::regex("@rpath/"), file_prefix);
|
||||||
|
if (Settings::verboseOutput())
|
||||||
|
std::cout << " path to search: " << pathL << std::endl;
|
||||||
|
if (realpath(pathL.c_str(), buffer)) {
|
||||||
|
fullpath = buffer;
|
||||||
|
Settings::rpathToFullPath(rpath_file, fullpath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// fullpath previously stored
|
||||||
|
if (Settings::rpathFound(rpath_file)) {
|
||||||
|
fullpath = Settings::getFullPath(rpath_file);
|
||||||
|
}
|
||||||
|
else if (!check_path(rpath_file)) {
|
||||||
|
auto rpaths_for_file = Settings::getRpathsForFile(dependent_file);
|
||||||
|
for (auto it = rpaths_for_file.begin(); it != rpaths_for_file.end(); ++it) {
|
||||||
|
std::string rpath = *it;
|
||||||
|
if (rpath[rpath.size()-1] != '/')
|
||||||
|
rpath += "/";
|
||||||
|
std::string path = rpath + suffix;
|
||||||
|
if (Settings::verboseOutput())
|
||||||
|
std::cout << " trying rpath: " << path << std::endl;
|
||||||
|
if (check_path(path))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fullpath.empty()) {
|
||||||
|
size_t search_path_count = Settings::searchPathCount();
|
||||||
|
for (size_t i=0; i<search_path_count; ++i) {
|
||||||
|
std::string search_path = Settings::searchPath(i);
|
||||||
|
if (fileExists(search_path+suffix)) {
|
||||||
|
if (Settings::verboseOutput())
|
||||||
|
std::cout << "FOUND " + suffix + " in " + search_path + "\n";
|
||||||
|
fullpath = search_path + suffix;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fullpath.empty()) {
|
||||||
|
if (Settings::verboseOutput())
|
||||||
|
std::cout << " ** rpath fullpath: not found" << std::endl;
|
||||||
|
if (!Settings::quietOutput())
|
||||||
|
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'\n";
|
||||||
|
fullpath = getUserInputDirForFile(suffix) + suffix;
|
||||||
|
if (Settings::quietOutput() && fullpath.empty())
|
||||||
|
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'\n";
|
||||||
|
if (realpath(fullpath.c_str(), fullpath_buffer))
|
||||||
|
fullpath = fullpath_buffer;
|
||||||
|
}
|
||||||
|
else if (Settings::verboseOutput()) {
|
||||||
|
std::cout << " ** rpath fullpath: " << fullpath << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Settings::verboseOutput()) {
|
||||||
|
std::cout << " ** rpath fullpath: " << fullpath << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullpath;
|
||||||
|
}
|
||||||
|
|
||||||
void initSearchPaths()
|
void initSearchPaths()
|
||||||
{
|
{
|
||||||
std::string searchPaths;
|
std::string searchPaths;
|
||||||
|
@ -377,3 +487,16 @@ void initSearchPaths()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createQtConf(std::string directory)
|
||||||
|
{
|
||||||
|
std::string contents = "[Paths]\n"
|
||||||
|
"Plugins = PlugIns\n"
|
||||||
|
"Imports = Resources/qml\n"
|
||||||
|
"Qml2Imports = Resources/qml\n";
|
||||||
|
if (directory[directory.size()-1] != '/')
|
||||||
|
directory += "/";
|
||||||
|
std::ofstream out(directory + "qt.conf");
|
||||||
|
out << contents;
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
|
@ -38,14 +38,19 @@ void changeInstallName(const std::string& binary_file, const std::string& old_na
|
||||||
void copyFile(const std::string& from, const std::string& to);
|
void copyFile(const std::string& from, const std::string& to);
|
||||||
void deleteFile(const std::string& path, bool overwrite);
|
void deleteFile(const std::string& path, bool overwrite);
|
||||||
void deleteFile(const std::string& path);
|
void deleteFile(const std::string& path);
|
||||||
|
|
||||||
bool mkdir(const std::string& path);
|
bool mkdir(const std::string& path);
|
||||||
|
|
||||||
void createDestDir();
|
void createDestDir();
|
||||||
|
|
||||||
std::string getUserInputDirForFile(const std::string& filename);
|
std::string getUserInputDirForFile(const std::string& filename);
|
||||||
|
|
||||||
void parseLoadCommands(const std::string& file, const std::string& cmd, const std::string& value, std::vector<std::string>& lines);
|
void parseLoadCommands(const std::string& file, const std::string& cmd, const std::string& value, std::vector<std::string>& lines);
|
||||||
|
|
||||||
|
std::string searchFilenameInRpaths(const std::string& rpath_file, const std::string& dependent_file);
|
||||||
|
|
||||||
// check the same paths the system would search for dylibs
|
// check the same paths the system would search for dylibs
|
||||||
void initSearchPaths();
|
void initSearchPaths();
|
||||||
|
|
||||||
|
void createQtConf(std::string directory);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -94,6 +94,10 @@ int main(int argc, const char* argv[])
|
||||||
Settings::verboseOutput(true);
|
Settings::verboseOutput(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(argv[i],"-b") == 0 || strcmp(argv[i],"--bundle-libs") == 0) {
|
||||||
|
// old flag, on by default now. ignore.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
else if (strcmp(argv[i],"-V") == 0 || strcmp(argv[i],"--version") == 0) {
|
else if (strcmp(argv[i],"-V") == 0 || strcmp(argv[i],"--version") == 0) {
|
||||||
std::cout << "dylibbundler " << VERSION << std::endl;
|
std::cout << "dylibbundler " << VERSION << std::endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -102,10 +106,6 @@ int main(int argc, const char* argv[])
|
||||||
showHelp();
|
showHelp();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-b") == 0 || strcmp(argv[i],"--bundle-libs") == 0) {
|
|
||||||
// old flag, on by default now. ignore.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (i > 0) {
|
else if (i > 0) {
|
||||||
// unknown flag, abort
|
// unknown flag, abort
|
||||||
std::cerr << "Unknown flag " << argv[i] << std::endl << std::endl;
|
std::cerr << "Unknown flag " << argv[i] << std::endl << std::endl;
|
||||||
|
@ -114,7 +114,7 @@ int main(int argc, const char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Settings::bundleLibs() && Settings::filesToFixCount() < 1) {
|
if (Settings::filesToFixCount() < 1) {
|
||||||
showHelp();
|
showHelp();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue