improve backwards compatibility. more refining

This commit is contained in:
SCG82 2020-01-02 22:05:38 -08:00
parent 6348de25a8
commit ad8e86a7ea
7 changed files with 110 additions and 102 deletions

View File

@ -21,43 +21,6 @@
#include "Settings.h" #include "Settings.h"
#include "Utils.h" #include "Utils.h"
// the paths to search for dylibs, store it globally to parse the environment variables only once
std::vector<std::string> paths;
// initialize the dylib search paths
void initSearchPaths()
{
// check the same paths the system would search for dylibs
std::string searchPaths;
char *dyldLibPath = std::getenv("DYLD_LIBRARY_PATH");
if (dyldLibPath != 0)
searchPaths = dyldLibPath;
dyldLibPath = std::getenv("DYLD_FALLBACK_FRAMEWORK_PATH");
if (dyldLibPath != 0) {
if (!searchPaths.empty() && searchPaths[searchPaths.size()-1] != ':')
searchPaths += ":";
searchPaths += dyldLibPath;
}
dyldLibPath = std::getenv("DYLD_FALLBACK_LIBRARY_PATH");
if (dyldLibPath != 0) {
if (!searchPaths.empty() && searchPaths[searchPaths.size()-1] != ':')
searchPaths += ":";
searchPaths += dyldLibPath;
}
if (!searchPaths.empty()) {
std::stringstream ss(searchPaths);
std::string item;
while (std::getline(ss, item, ':')) {
if (item[item.size()-1] != '/')
item += "/";
paths.push_back(item);
}
}
}
// if some libs are missing prefixes, then more stuff will be necessary to do
bool missing_prefixes = false;
Dependency::Dependency(std::string path, std::string dependent_file) : is_framework(false) Dependency::Dependency(std::string path, std::string dependent_file) : is_framework(false)
{ {
char original_file_buffer[PATH_MAX]; char original_file_buffer[PATH_MAX];
@ -93,6 +56,9 @@ Dependency::Dependency(std::string path, std::string dependent_file) : is_framew
prefix = filePrefix(original_file); prefix = filePrefix(original_file);
filename = stripPrefix(original_file); filename = stripPrefix(original_file);
if (!prefix.empty() && prefix[prefix.size()-1] != '/')
prefix += "/";
// check if this dependency is in /usr/lib, /System/Library, or in ignored list // check if this dependency is in /usr/lib, /System/Library, or in ignored list
if (!Settings::isPrefixBundled(prefix)) if (!Settings::isPrefixBundled(prefix))
return; return;
@ -102,8 +68,8 @@ Dependency::Dependency(std::string path, std::string dependent_file) : is_framew
std::string framework_root = getFrameworkRoot(original_file); std::string framework_root = getFrameworkRoot(original_file);
std::string framework_path = getFrameworkPath(original_file); std::string framework_path = getFrameworkPath(original_file);
std::string framework_name = stripPrefix(framework_root); std::string framework_name = stripPrefix(framework_root);
filename = framework_name + "/" + framework_path;
prefix = filePrefix(framework_root); prefix = filePrefix(framework_root);
filename = framework_name + "/" + framework_path;
if (Settings::verboseOutput()) { if (Settings::verboseOutput()) {
std::cout << "framework root: " << framework_root << std::endl; std::cout << "framework root: " << framework_root << std::endl;
std::cout << "framework path: " << framework_path << std::endl; std::cout << "framework path: " << framework_path << std::endl;
@ -112,20 +78,20 @@ Dependency::Dependency(std::string path, std::string dependent_file) : is_framew
} }
// 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() || !fileExists(prefix+filename)) { if (prefix.empty() || !fileExists(prefix+filename)) {
// the paths contains at least /usr/lib so if it is empty we have not initialized it // the paths contains at least /usr/lib so if it is empty we have not initialized it
if (paths.empty()) size_t search_path_count = Settings::searchPathCount();
if (search_path_count == 0)
initSearchPaths(); initSearchPaths();
// check if file is contained in one of the paths // check if file is contained in one of the paths
for (size_t i=0; i<paths.size(); ++i) { search_path_count = Settings::searchPathCount();
if (fileExists(paths[i]+filename)) { for (size_t i=0; i<search_path_count; ++i) {
warning_msg += "FOUND " + filename + " in " + paths[i] + "\n"; std::string search_path = Settings::searchPath(i);
prefix = paths[i]; if (fileExists(search_path+filename)) {
missing_prefixes = true; warning_msg += "FOUND " + filename + " in " + search_path + "\n";
prefix = search_path;
Settings::missingPrefixes(true);
break; break;
} }
} }
@ -140,8 +106,8 @@ Dependency::Dependency(std::string path, std::string dependent_file) : is_framew
std::cerr << "\n/!\\ WARNING: Dependency " << filename << " of " << dependent_file << " not found\n"; std::cerr << "\n/!\\ WARNING: Dependency " << filename << " of " << dependent_file << " not found\n";
if (Settings::verboseOutput()) if (Settings::verboseOutput())
std::cout << " path: " << (prefix+filename) << std::endl; std::cout << " path: " << (prefix+filename) << std::endl;
missing_prefixes = true; Settings::missingPrefixes(true);
paths.push_back(getUserInputDirForFile(filename)); Settings::addSearchPath(getUserInputDirForFile(filename));
} }
new_name = filename; new_name = filename;
@ -188,8 +154,6 @@ void Dependency::copyYourself()
{ {
std::string original_path = getOriginalPath(); std::string original_path = getOriginalPath();
std::string dest_path = getInstallPath(); std::string dest_path = getInstallPath();
std::string inner_path = getInnerPath();
std::string install_path = getInstallPath();
if (is_framework) { if (is_framework) {
original_path = getFrameworkRoot(original_path); original_path = getFrameworkRoot(original_path);
@ -197,33 +161,31 @@ void Dependency::copyYourself()
} }
if (Settings::verboseOutput()) { if (Settings::verboseOutput()) {
std::string inner_path = getInnerPath();
std::cout << "original path: " << original_path << std::endl; std::cout << "original path: " << original_path << std::endl;
std::cout << "inner path: " << inner_path << std::endl; std::cout << "inner path: " << inner_path << std::endl;
std::cout << "dest_path: " << dest_path << std::endl; std::cout << "dest_path: " << dest_path << std::endl;
std::cout << "install path: " << install_path << std::endl; std::cout << "install path: " << getInstallPath() << std::endl;
} }
copyFile(original_path, dest_path); copyFile(original_path, dest_path);
if (is_framework) { if (is_framework) {
std::string headers_path = dest_path + std::string("/Headers"); std::string headers_path = dest_path + std::string("/Headers");
std::string headers_realpath = headers_path;
char buffer[PATH_MAX]; char buffer[PATH_MAX];
if (realpath(rtrim(headers_path).c_str(), buffer)) if (realpath(rtrim(headers_path).c_str(), buffer))
headers_realpath = buffer; headers_path = buffer;
if (Settings::verboseOutput()) if (Settings::verboseOutput())
std::cout << "headers path: " << headers_realpath << std::endl; std::cout << "headers path: " << headers_path << std::endl;
deleteFile(headers_path, true); deleteFile(headers_path, true);
deleteFile(headers_realpath, true);
deleteFile(dest_path + "/*.prl"); deleteFile(dest_path + "/*.prl");
} }
// fix the lib's inner name // fix the lib's inner name
changeId(install_path, "@rpath/"+new_name); changeId(getInstallPath(), "@rpath/"+new_name);
} }
void Dependency::fixFileThatDependsOnMe(std::string file_to_fix) void Dependency::fixFileThatDependsOnMe(std::string file_to_fix)
@ -236,7 +198,7 @@ void Dependency::fixFileThatDependsOnMe(std::string file_to_fix)
} }
// TODO: revise // TODO: revise
if (missing_prefixes) { if (Settings::missingPrefixes()) {
// for main lib file // for main lib file
changeInstallName(file_to_fix, filename, getInnerPath()); changeInstallName(file_to_fix, filename, getInnerPath());
// for symlinks // for symlinks

View File

@ -234,7 +234,7 @@ void addDependency(std::string path, std::string dependent_file)
} }
// Fill |lines| with dependencies of given |filename| // Fill |lines| with dependencies of given |filename|
void collectDependencies(std::string dependent_file, std::vector<std::string>& lines) void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines)
{ {
std::string cmd = "otool -l " + dependent_file; std::string cmd = "otool -l " + dependent_file;
std::string output = systemOutput(cmd); std::string output = systemOutput(cmd);
@ -268,19 +268,17 @@ void collectDependencies(std::string dependent_file, std::vector<std::string>& l
} }
} }
void collectDependencies(std::string dependent_file) void collectDependencies(const std::string& dependent_file)
{ {
std::vector<std::string> lines; std::vector<std::string> lines;
collectDependencies(dependent_file, lines); collectDependencies(dependent_file, lines);
for (size_t i=0; i<lines.size(); ++i) { for (size_t i=0; i<lines.size(); ++i) {
if (!Settings::bundleFrameworks()) {
if (lines[i].find(".framework") != std::string::npos)
continue;
}
// lines containing path begin with a tab // lines containing path begin with a tab
if (lines[i][0] != '\t') if (lines[i][0] != '\t')
continue; continue;
if (!Settings::isPrefixBundled(lines[i]))
continue;
// trim useless info, keep only library path // trim useless info, keep only library path
std::string dep_path = lines[i].substr(1, lines[i].rfind(" (") - 1); std::string dep_path = lines[i].substr(1, lines[i].rfind(" (") - 1);
if (isRpath(dep_path)) if (isRpath(dep_path))
@ -313,18 +311,16 @@ void collectSubDependencies()
original_path = searchFilenameInRpaths(original_path); original_path = searchFilenameInRpaths(original_path);
collectRpathsForFilename(original_path); collectRpathsForFilename(original_path);
std::vector<std::string> lines; std::vector<std::string> lines;
collectDependencies(original_path, lines); collectDependencies(original_path, lines);
for (size_t i=0; i<lines.size(); ++i) { for (size_t i=0; i<lines.size(); ++i) {
if (!Settings::bundleFrameworks()) {
if (lines[i].find(".framework") != std::string::npos)
continue;
}
// lines containing path begin with a tab // lines containing path begin with a tab
if (lines[i][0] != '\t') if (lines[i][0] != '\t')
continue; continue;
// skip system/ignored prefixes
if (!Settings::isPrefixBundled(lines[i]))
continue;
// trim useless info, keep only library name // trim useless info, keep only library name
std::string dep_path = lines[i].substr(1, lines[i].rfind(" (") - 1); std::string dep_path = lines[i].substr(1, lines[i].rfind(" (") - 1);
if (isRpath(dep_path)) { if (isRpath(dep_path)) {

View File

@ -14,7 +14,8 @@ std::string searchFilenameInRpaths(const std::string& 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);
void addDependency(std::string path, std::string dependent_file); void addDependency(std::string path, std::string dependent_file);
void collectDependencies(std::string dependent_file); void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines);
void collectDependencies(const std::string& dependent_file);
void collectSubDependencies(); void collectSubDependencies();
void doneWithDeps_go(); void doneWithDeps_go();

View File

@ -11,18 +11,22 @@ bool verbose_output = false;
bool bundle_libs = true; bool bundle_libs = true;
bool bundle_frameworks = false; bool bundle_frameworks = false;
std::string dest_folder_str = "Frameworks"; std::string dest_folder_str = "./libs/";
std::string inside_path_str = "@executable_path/../Frameworks/"; std::string dest_folder_str_app = "./Frameworks/";
std::string dest_folder = dest_folder_str;
std::string dest_path = dest_folder;
std::string inside_path_str = "@executable_path/../libs/";
std::string inside_path_str_app = "@executable_path/../Frameworks/";
std::string inside_path = inside_path_str;
std::string app_bundle; std::string app_bundle;
std::string dest_folder; bool appBundleProvided() { return !app_bundle.empty(); }
std::string appBundle() { return app_bundle; } std::string appBundle() { return app_bundle; }
void appBundle(std::string path) { void appBundle(std::string path) {
app_bundle = path; app_bundle = path;
// fix path if needed so it ends with '/'
if (app_bundle[app_bundle.size()-1] != '/') if (app_bundle[app_bundle.size()-1] != '/')
app_bundle += "/"; app_bundle += "/"; // fix path if needed so it ends with '/'
std::string cmd = "/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "; std::string cmd = "/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' ";
cmd += app_bundle + "Contents/Info.plist"; cmd += app_bundle + "Contents/Info.plist";
@ -30,60 +34,63 @@ void appBundle(std::string path) {
addFileToFix(app_bundle + "Contents/MacOS/" + bundle_executable); addFileToFix(app_bundle + "Contents/MacOS/" + bundle_executable);
// fix path if needed so it ends with '/' if (inside_path == inside_path_str)
if (dest_folder_str[dest_folder_str.size()-1] != '/') inside_path = inside_path_str_app;
dest_folder_str += "/"; if (dest_folder == dest_folder_str)
dest_folder = app_bundle + "Contents/" + dest_folder_str; dest_folder = dest_folder_str_app;
dest_path = app_bundle + "Contents/" + dest_folder;
char buffer[PATH_MAX];
if (realpath(dest_path.c_str(), buffer))
dest_path = buffer;
if (dest_path[dest_path.size()-1] != '/')
dest_path += "/";
} }
std::string destFolder() { return dest_folder; } std::string destFolder() { return dest_path; }
void destFolder(std::string path) void destFolder(std::string path)
{ {
dest_folder_str = path; if (path[path.size()-1] != '/')
// fix path if needed so it ends with '/' path += "/";
if (dest_folder_str[dest_folder_str.size()-1] != '/') dest_folder = path;
dest_folder_str += "/"; if (appBundleProvided()) {
dest_folder = dest_folder_str; char buffer[PATH_MAX];
if (!app_bundle.empty()) std::string dest_path = app_bundle + "Contents/" + path;
dest_folder = app_bundle + "Contents/" + dest_folder_str; if (realpath(dest_path.c_str(), buffer))
dest_path = buffer;
if (dest_path[dest_path.size()-1] != '/')
dest_path += "/";
dest_folder = dest_path;
}
} }
std::string executableFolder() { return app_bundle + "Contents/MacOS/"; } std::string executableFolder() { return app_bundle + "Contents/MacOS/"; }
std::string frameworksFolder() { return app_bundle + "Contents/Frameworks/"; } std::string frameworksFolder() { return app_bundle + "Contents/Frameworks/"; }
std::string pluginsFolder() { return app_bundle + "Contents/PlugIns/"; } std::string pluginsFolder() { return app_bundle + "Contents/PlugIns/"; }
std::string resourcesFolder() { return app_bundle + "Contents/Resources/"; } std::string resourcesFolder() { return app_bundle + "Contents/Resources/"; }
std::vector<std::string> files; std::vector<std::string> files;
void addFileToFix(std::string path) { files.push_back(path); } void addFileToFix(std::string path) { files.push_back(path); }
std::string fileToFix(const int n) { return files[n]; } std::string fileToFix(const int n) { return files[n]; }
std::vector<std::string> filesToFix() { return files; } std::vector<std::string> filesToFix() { return files; }
size_t filesToFixCount() { return files.size(); } size_t filesToFixCount() { return files.size(); }
std::string insideLibPath() { return inside_path_str; } std::string insideLibPath() { return inside_path; }
void insideLibPath(std::string p) void insideLibPath(std::string p)
{ {
inside_path_str = p; inside_path = p;
// fix path if needed so it ends with '/' // fix path if needed so it ends with '/'
if (inside_path_str[inside_path_str.size()-1] != '/') if (inside_path[inside_path.size()-1] != '/')
inside_path_str += "/"; inside_path += "/";
} }
std::vector<std::string> prefixes_to_ignore; std::vector<std::string> prefixes_to_ignore;
void ignorePrefix(std::string prefix) void ignorePrefix(std::string prefix)
{ {
if (prefix[prefix.size()-1] != '/') if (prefix[prefix.size()-1] != '/')
prefix += "/"; prefix += "/";
prefixes_to_ignore.push_back(prefix); prefixes_to_ignore.push_back(prefix);
} }
bool isPrefixIgnored(std::string prefix) bool isPrefixIgnored(std::string prefix)
{ {
for (size_t n=0; n<prefixes_to_ignore.size(); n++) { for (size_t n=0; n<prefixes_to_ignore.size(); n++) {
@ -134,4 +141,9 @@ void quietOutput(bool status) { quiet_output = status; }
bool verboseOutput() { return verbose_output; } bool verboseOutput() { return verbose_output; }
void verboseOutput(bool status) { verbose_output = status; } void verboseOutput(bool status) { verbose_output = status; }
// if some libs are missing prefixes, then more stuff will be necessary to do
bool missing_prefixes = false;
bool missingPrefixes() { return missing_prefixes; }
void missingPrefixes(bool status) { missing_prefixes = status; }
} // namespace Settings } // namespace Settings

View File

@ -54,6 +54,9 @@ void quietOutput(bool status);
bool verboseOutput(); bool verboseOutput();
void verboseOutput(bool status); void verboseOutput(bool status);
bool missingPrefixes();
void missingPrefixes(bool status);
} // namespace Settings } // namespace Settings
#endif #endif

View File

@ -3,6 +3,7 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
#include <sstream>
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -290,3 +291,33 @@ std::string getUserInputDirForFile(const std::string& filename)
} }
} }
} }
void initSearchPaths()
{
// check the same paths the system would search for dylibs
std::string searchPaths;
char *dyldLibPath = std::getenv("DYLD_LIBRARY_PATH");
if (dyldLibPath != 0)
searchPaths = dyldLibPath;
dyldLibPath = std::getenv("DYLD_FALLBACK_FRAMEWORK_PATH");
if (dyldLibPath != 0) {
if (!searchPaths.empty() && searchPaths[searchPaths.size()-1] != ':')
searchPaths += ":";
searchPaths += dyldLibPath;
}
dyldLibPath = std::getenv("DYLD_FALLBACK_LIBRARY_PATH");
if (dyldLibPath != 0) {
if (!searchPaths.empty() && searchPaths[searchPaths.size()-1] != ':')
searchPaths += ":";
searchPaths += dyldLibPath;
}
if (!searchPaths.empty()) {
std::stringstream ss(searchPaths);
std::string item;
while (std::getline(ss, item, ':')) {
if (item[item.size()-1] != '/')
item += "/";
Settings::addSearchPath(item);
}
}
}

View File

@ -39,4 +39,7 @@ bool mkdir(std::string path);
void createDestDir(); void createDestDir();
std::string getUserInputDirForFile(const std::string& filename); std::string getUserInputDirForFile(const std::string& filename);
// check the same paths the system would search for dylibs
void initSearchPaths();
#endif #endif