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 "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)
{
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);
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
if (!Settings::isPrefixBundled(prefix))
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_path = getFrameworkPath(original_file);
std::string framework_name = stripPrefix(framework_root);
filename = framework_name + "/" + framework_path;
prefix = filePrefix(framework_root);
filename = framework_name + "/" + framework_path;
if (Settings::verboseOutput()) {
std::cout << "framework root: " << framework_root << 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
if (!prefix.empty() && prefix[prefix.size()-1] != '/')
prefix += "/";
if (prefix.empty() || !fileExists(prefix+filename)) {
// 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();
// check if file is contained in one of the paths
for (size_t i=0; i<paths.size(); ++i) {
if (fileExists(paths[i]+filename)) {
warning_msg += "FOUND " + filename + " in " + paths[i] + "\n";
prefix = paths[i];
missing_prefixes = true;
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+filename)) {
warning_msg += "FOUND " + filename + " in " + search_path + "\n";
prefix = search_path;
Settings::missingPrefixes(true);
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";
if (Settings::verboseOutput())
std::cout << " path: " << (prefix+filename) << std::endl;
missing_prefixes = true;
paths.push_back(getUserInputDirForFile(filename));
Settings::missingPrefixes(true);
Settings::addSearchPath(getUserInputDirForFile(filename));
}
new_name = filename;
@ -188,8 +154,6 @@ void Dependency::copyYourself()
{
std::string original_path = getOriginalPath();
std::string dest_path = getInstallPath();
std::string inner_path = getInnerPath();
std::string install_path = getInstallPath();
if (is_framework) {
original_path = getFrameworkRoot(original_path);
@ -197,33 +161,31 @@ void Dependency::copyYourself()
}
if (Settings::verboseOutput()) {
std::string inner_path = getInnerPath();
std::cout << "original path: " << original_path << std::endl;
std::cout << "inner path: " << inner_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);
if (is_framework) {
std::string headers_path = dest_path + std::string("/Headers");
std::string headers_realpath = headers_path;
char buffer[PATH_MAX];
if (realpath(rtrim(headers_path).c_str(), buffer))
headers_realpath = buffer;
headers_path = buffer;
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_realpath, true);
deleteFile(dest_path + "/*.prl");
}
// 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)
@ -236,7 +198,7 @@ void Dependency::fixFileThatDependsOnMe(std::string file_to_fix)
}
// TODO: revise
if (missing_prefixes) {
if (Settings::missingPrefixes()) {
// for main lib file
changeInstallName(file_to_fix, filename, getInnerPath());
// for symlinks

View File

@ -234,7 +234,7 @@ void addDependency(std::string path, std::string dependent_file)
}
// 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 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;
collectDependencies(dependent_file, lines);
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
if (lines[i][0] != '\t')
continue;
if (!Settings::isPrefixBundled(lines[i]))
continue;
// trim useless info, keep only library path
std::string dep_path = lines[i].substr(1, lines[i].rfind(" (") - 1);
if (isRpath(dep_path))
@ -313,18 +311,16 @@ void collectSubDependencies()
original_path = searchFilenameInRpaths(original_path);
collectRpathsForFilename(original_path);
std::vector<std::string> lines;
collectDependencies(original_path, lines);
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
if (lines[i][0] != '\t')
continue;
// skip system/ignored prefixes
if (!Settings::isPrefixBundled(lines[i]))
continue;
// trim useless info, keep only library name
std::string dep_path = lines[i].substr(1, lines[i].rfind(" (") - 1);
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 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 doneWithDeps_go();

View File

@ -11,18 +11,22 @@ bool verbose_output = false;
bool bundle_libs = true;
bool bundle_frameworks = false;
std::string dest_folder_str = "Frameworks";
std::string inside_path_str = "@executable_path/../Frameworks/";
std::string dest_folder_str = "./libs/";
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 dest_folder;
bool appBundleProvided() { return !app_bundle.empty(); }
std::string appBundle() { return app_bundle; }
void appBundle(std::string path) {
app_bundle = path;
// fix path if needed so it ends with '/'
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' ";
cmd += app_bundle + "Contents/Info.plist";
@ -30,60 +34,63 @@ void appBundle(std::string path) {
addFileToFix(app_bundle + "Contents/MacOS/" + bundle_executable);
// fix path if needed so it ends with '/'
if (dest_folder_str[dest_folder_str.size()-1] != '/')
dest_folder_str += "/";
dest_folder = app_bundle + "Contents/" + dest_folder_str;
if (inside_path == inside_path_str)
inside_path = inside_path_str_app;
if (dest_folder == 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)
{
dest_folder_str = path;
// fix path if needed so it ends with '/'
if (dest_folder_str[dest_folder_str.size()-1] != '/')
dest_folder_str += "/";
dest_folder = dest_folder_str;
if (!app_bundle.empty())
dest_folder = app_bundle + "Contents/" + dest_folder_str;
if (path[path.size()-1] != '/')
path += "/";
dest_folder = path;
if (appBundleProvided()) {
char buffer[PATH_MAX];
std::string dest_path = app_bundle + "Contents/" + path;
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 frameworksFolder() { return app_bundle + "Contents/Frameworks/"; }
std::string pluginsFolder() { return app_bundle + "Contents/PlugIns/"; }
std::string resourcesFolder() { return app_bundle + "Contents/Resources/"; }
std::vector<std::string> files;
void addFileToFix(std::string path) { files.push_back(path); }
std::string fileToFix(const int n) { return files[n]; }
std::vector<std::string> filesToFix() { return files; }
size_t filesToFixCount() { return files.size(); }
std::string insideLibPath() { return inside_path_str; }
std::string insideLibPath() { return inside_path; }
void insideLibPath(std::string p)
{
inside_path_str = p;
inside_path = p;
// fix path if needed so it ends with '/'
if (inside_path_str[inside_path_str.size()-1] != '/')
inside_path_str += "/";
if (inside_path[inside_path.size()-1] != '/')
inside_path += "/";
}
std::vector<std::string> prefixes_to_ignore;
void ignorePrefix(std::string prefix)
{
if (prefix[prefix.size()-1] != '/')
prefix += "/";
prefixes_to_ignore.push_back(prefix);
}
bool isPrefixIgnored(std::string prefix)
{
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; }
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

View File

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

View File

@ -3,6 +3,7 @@
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <stdio.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();
std::string getUserInputDirForFile(const std::string& filename);
// check the same paths the system would search for dylibs
void initSearchPaths();
#endif