collect dependencies & rpaths in a single otool call

This commit is contained in:
SCG82 2020-01-06 06:45:18 -08:00
parent 7f41661132
commit e5cacbb3e6
8 changed files with 220 additions and 149 deletions

View File

@ -15,35 +15,33 @@
Dependency::Dependency(std::string path, const std::string& dependent_file) : is_framework(false) Dependency::Dependency(std::string path, const std::string& dependent_file) : is_framework(false)
{ {
char original_file_buffer[PATH_MAX]; char buffer[PATH_MAX];
rtrim_in_place(path);
std::string original_file; std::string original_file;
std::string warning_msg; std::string warning_msg;
rtrim_in_place(path);
if (Settings::verboseOutput()) {
std::cout<< "** Dependency ctor **" << std::endl;
if (path != dependent_file)
std::cout << " dependent file: " << dependent_file << std::endl;
std::cout << " dependency path: " << path << std::endl;
}
if (isRpath(path)) { if (isRpath(path)) {
original_file = searchFilenameInRpaths(path, dependent_file); original_file = searchFilenameInRpaths(path, dependent_file);
} }
else if (realpath(path.c_str(), original_file_buffer)) { else if (realpath(path.c_str(), buffer)) {
original_file = original_file_buffer; original_file = buffer;
if (Settings::verboseOutput())
std::cout << " original_file: " << original_file << std::endl;
} }
else { else {
warning_msg = "\n/!\\ WARNING: Cannot resolve path '" + path + "'\n"; warning_msg = "\n/!\\ WARNING: Cannot resolve path '" + path + "'\n";
original_file = path; original_file = path;
} }
if (Settings::verboseOutput()) {
std::cout<< "** Dependency ctor **" << std::endl;
if (path != dependent_file)
std::cout << " dependent file: " << dependent_file << std::endl;
std::cout << " dependency path: " << path << std::endl;
std::cout << " original_file: " << original_file << std::endl;
}
// check if given path is a symlink // check if given path is a symlink
if (original_file != path) if (original_file != path)
addSymlink(path); AddSymlink(path);
prefix = filePrefix(original_file); prefix = filePrefix(original_file);
filename = stripPrefix(original_file); filename = stripPrefix(original_file);
@ -72,10 +70,8 @@ Dependency::Dependency(std::string path, const std::string& dependent_file) : is
// check if the lib is in a known location // check if the lib is in a known location
if (prefix.empty() || !fileExists(prefix+filename)) { if (prefix.empty() || !fileExists(prefix+filename)) {
std::vector<std::string> search_paths = Settings::searchPaths(); std::vector<std::string> search_paths = Settings::searchPaths();
// the paths contains at least /usr/lib so if it is empty we have not initialized it
if (search_paths.empty()) if (search_paths.empty())
initSearchPaths(); initSearchPaths();
// check if file is contained in one of the paths // check if file is contained in one of the paths
for (const auto& search_path : search_paths) { for (const auto& search_path : search_paths) {
if (fileExists(search_path+filename)) { if (fileExists(search_path+filename)) {
@ -103,45 +99,37 @@ Dependency::Dependency(std::string path, const std::string& dependent_file) : is
new_name = filename; new_name = filename;
} }
std::string Dependency::getInstallPath() const std::string Dependency::InnerPath() const
{
return Settings::destFolder() + new_name;
}
std::string Dependency::getInnerPath() const
{ {
return Settings::insideLibPath() + new_name; return Settings::insideLibPath() + new_name;
} }
void Dependency::print() const std::string Dependency::InstallPath() const
{ {
std::cout << "\n* " << filename << " from " << prefix << std::endl; return Settings::destFolder() + new_name;
for (const auto& symlink : symlinks) {
std::cout << " symlink --> " << symlink << std::endl;
}
} }
void Dependency::addSymlink(const std::string& s) void Dependency::AddSymlink(const std::string& path)
{ {
if (std::find(symlinks.begin(), symlinks.end(), s) == symlinks.end()) if (std::find(symlinks.begin(), symlinks.end(), path) == symlinks.end())
symlinks.push_back(s); symlinks.push_back(path);
} }
bool Dependency::mergeIfSameAs(Dependency& dep2) bool Dependency::MergeIfIdentical(Dependency& dependency)
{ {
if (dep2.getOriginalFileName() == filename) { if (dependency.OriginalFilename() == filename) {
for (const auto& symlink : symlinks) { for (const auto& symlink : symlinks) {
dep2.addSymlink(symlink); dependency.AddSymlink(symlink);
} }
return true; return true;
} }
return false; return false;
} }
void Dependency::copyToAppBundle() const void Dependency::CopyToBundle() const
{ {
std::string original_path = getOriginalPath(); std::string original_path = OriginalPath();
std::string dest_path = getInstallPath(); std::string dest_path = InstallPath();
if (is_framework) { if (is_framework) {
original_path = getFrameworkRoot(original_path); original_path = getFrameworkRoot(original_path);
@ -149,11 +137,11 @@ void Dependency::copyToAppBundle() const
} }
if (Settings::verboseOutput()) { if (Settings::verboseOutput()) {
std::string inner_path = getInnerPath(); std::string inner_path = InnerPath();
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: " << getInstallPath() << std::endl; std::cout << " - install path: " << InstallPath() << std::endl;
} }
copyFile(original_path, dest_path); copyFile(original_path, dest_path);
@ -167,20 +155,28 @@ void Dependency::copyToAppBundle() const
deleteFile(dest_path + "/*.prl"); deleteFile(dest_path + "/*.prl");
} }
changeId(getInstallPath(), "@rpath/"+new_name); changeId(InstallPath(), "@rpath/" + new_name);
} }
void Dependency::fixDependentFiles(const std::string& file) const void Dependency::FixDependentFile(const std::string& dependent_file) const
{ {
changeInstallName(file, getOriginalPath(), getInnerPath()); changeInstallName(dependent_file, OriginalPath(), InnerPath());
for (const auto& symlink : symlinks) { for (const auto& symlink : symlinks) {
changeInstallName(file, symlink, getInnerPath()); changeInstallName(dependent_file, symlink, InnerPath());
} }
if (Settings::missingPrefixes()) { if (Settings::missingPrefixes()) {
changeInstallName(file, filename, getInnerPath()); changeInstallName(dependent_file, filename, InnerPath());
for (const auto& symlink : symlinks) { for (const auto& symlink : symlinks) {
changeInstallName(file, symlink, getInnerPath()); changeInstallName(dependent_file, symlink, InnerPath());
} }
} }
} }
void Dependency::Print() const
{
std::cout << "\n* " << filename << " from " << prefix << std::endl;
for (const auto& symlink : symlinks) {
std::cout << " symlink --> " << symlink << std::endl;
}
}

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#ifndef _depend_h_ #ifndef DYLIBBUNDLER_DEPENDENCY_H
#define _depend_h_ #define DYLIBBUNDLER_DEPENDENCY_H
#include <string> #include <string>
#include <vector> #include <vector>
@ -10,25 +10,25 @@ class Dependency {
public: public:
Dependency(std::string path, const std::string& dependent_file); Dependency(std::string path, const std::string& dependent_file);
[[nodiscard]] bool isFramework() const { return is_framework; } [[nodiscard]] bool IsFramework() const { return is_framework; }
[[nodiscard]] std::string getPrefix() const { return prefix; } [[nodiscard]] std::string Prefix() const { return prefix; }
[[nodiscard]] std::string getOriginalFileName() const { return filename; } [[nodiscard]] std::string OriginalFilename() const { return filename; }
[[nodiscard]] std::string getOriginalPath() const { return prefix + filename; } [[nodiscard]] std::string OriginalPath() const { return prefix + filename; }
[[nodiscard]] std::string getInstallPath() const; [[nodiscard]] std::string InnerPath() const;
[[nodiscard]] std::string getInnerPath() const; [[nodiscard]] std::string InstallPath() const;
void print() const; void AddSymlink(const std::string& path);
void addSymlink(const std::string& s);
// Compare the given dependency with this one. If both refer to the same file, // Compare the given dependency with this one. If both refer to the same file,
// merge both entries into one and return true. // merge both entries into one and return true.
bool mergeIfSameAs(Dependency& dep2); bool MergeIfIdentical(Dependency& dependency);
void copyToAppBundle() const; void CopyToBundle() const;
void fixDependentFiles(const std::string& file) const; void FixDependentFile(const std::string& dependent_file) const;
void Print() const;
private: private:
bool is_framework; bool is_framework;

View File

@ -23,6 +23,7 @@ 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, bool> rpaths_collected;
bool qt_plugins_called = false; bool qt_plugins_called = false;
void addDependency(const std::string& path, const std::string& dependent_file) void addDependency(const std::string& path, const std::string& dependent_file)
@ -32,71 +33,98 @@ void addDependency(const std::string& path, const std::string& dependent_file)
// check if this library was already added to |deps| to avoid duplicates // check if this library was already added to |deps| to avoid duplicates
bool in_deps = false; bool in_deps = false;
for (auto& dep : deps) { for (auto& dep : deps) {
if (dependency.mergeIfSameAs(dep)) if (dependency.MergeIfIdentical(dep))
in_deps = true; in_deps = true;
} }
// check if this library was already added to |deps_per_file[dependent_file]| to avoid duplicates // check if this library was already added to |deps_per_file[dependent_file]| to avoid duplicates
bool in_deps_per_file = false; bool in_deps_per_file = false;
for (auto& dep : deps_per_file[dependent_file]) { for (auto& dep : deps_per_file[dependent_file]) {
if (dependency.mergeIfSameAs(dep)) if (dependency.MergeIfIdentical(dep))
in_deps_per_file = true; in_deps_per_file = true;
} }
// check if this library is in /usr/lib, /System/Library, or in ignored list // check if this library is in /usr/lib, /System/Library, or in ignored list
if (!Settings::isPrefixBundled(dependency.getPrefix())) if (!Settings::isPrefixBundled(dependency.Prefix()))
return; return;
if (!in_deps && dependency.isFramework()) if (!in_deps && dependency.IsFramework())
frameworks.insert(dependency.getOriginalPath()); frameworks.insert(dependency.OriginalPath());
if (!in_deps) if (!in_deps)
deps.push_back(dependency); deps.push_back(dependency);
if (!in_deps_per_file) if (!in_deps_per_file)
deps_per_file[dependent_file].push_back(dependency); deps_per_file[dependent_file].push_back(dependency);
} }
void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines) void collectDependencies(const std::string& dependent_file)
{ {
parseLoadCommands(dependent_file, std::string("LC_LOAD_DYLIB"), std::string("name"), lines); if (deps_collected.find(dependent_file) != deps_collected.end() && Settings::fileHasRpath(dependent_file))
} return;
void collectDependenciesForFile(const std::string& file, std::vector<std::string>& lines) std::map<std::string,std::string> cmds_values;
{ std::string dylib = "LC_LOAD_DYLIB";
if (deps_collected.find(file) == deps_collected.end()) std::string rpath = "LC_RPATH";
collectDependencies(file, lines); cmds_values[dylib] = "name";
} cmds_values[rpath] = "path";
std::map<std::string,std::vector<std::string>> cmds_results;
void collectDependenciesForFile(const std::string& dependent_file) parseLoadCommands(dependent_file, cmds_values, cmds_results);
{
std::vector<std::string> lines;
collectDependenciesForFile(dependent_file, lines);
collectRpathsForFilename(dependent_file);
for (const auto& line : lines) { if (rpaths_collected.find(dependent_file) == rpaths_collected.end()) {
if (!Settings::isPrefixBundled(line)) auto rpath_results = cmds_results[rpath];
continue; // skip system/ignored prefixes for (const auto& rpath_result : rpath_results) {
addDependency(line, dependent_file); rpaths.insert(rpath_result);
Settings::addRpathForFile(dependent_file, rpath_result);
if (Settings::verboseOutput())
std::cout << " rpath: " << rpath_result << std::endl;
}
rpaths_collected[dependent_file] = true;
} }
deps_collected[dependent_file] = true;
}
void collectRpaths(const std::string& filename) if (deps_collected.find(dependent_file) == deps_collected.end()) {
{ auto dylib_results = cmds_results[dylib];
std::vector<std::string> lines; for (const auto& dylib_result : dylib_results) {
parseLoadCommands(filename, std::string("LC_RPATH"), std::string("path"), lines); // skip system/ignored prefixes
for (const auto& line : lines) { if (Settings::isPrefixBundled(dylib_result))
rpaths.insert(line); addDependency(dylib_result, dependent_file);
Settings::addRpathForFile(filename, line); }
if (Settings::verboseOutput()) deps_collected[dependent_file] = true;
std::cout << " rpath: " << line << std::endl;
} }
} }
void collectRpathsForFilename(const std::string& filename) //void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines)
{ //{
if (!Settings::fileHasRpath(filename)) // if (deps_collected.find(dependent_file) == deps_collected.end())
collectRpaths(filename); // parseLoadCommands(dependent_file, std::string("LC_LOAD_DYLIB"), std::string("name"), lines);
} //}
//void collectDependencies(const std::string& dependent_file)
//{
// std::vector<std::string> lines;
// collectDependencies(dependent_file, lines);
// collectRpaths(dependent_file);
//
// for (const auto& line : lines) {
// if (!Settings::isPrefixBundled(line))
// continue; // skip system/ignored prefixes
// addDependency(line, dependent_file);
// }
// deps_collected[dependent_file] = true;
//}
//void collectRpaths(const std::string& filename)
//{
// if (!Settings::fileHasRpath(filename)) {
// std::vector<std::string> lines;
// parseLoadCommands(filename, std::string("LC_RPATH"), std::string("path"), lines);
// for (const auto &line : lines) {
// rpaths.insert(line);
// Settings::addRpathForFile(filename, line);
// if (Settings::verboseOutput())
// std::cout << " rpath: " << line << std::endl;
// }
// }
//}
void collectSubDependencies() void collectSubDependencies()
{ {
@ -110,21 +138,23 @@ void collectSubDependencies()
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].OriginalPath();
if (Settings::verboseOutput()) if (Settings::verboseOutput())
std::cout << " (collect sub deps) original path: " << original_path << std::endl; std::cout << " (collect sub deps) original path: " << original_path << std::endl;
if (isRpath(original_path)) if (isRpath(original_path))
original_path = searchFilenameInRpaths(original_path); original_path = searchFilenameInRpaths(original_path);
std::vector<std::string> lines; // std::vector<std::string> lines;
collectDependenciesForFile(original_path, lines); // collectDependencies(original_path, lines);
collectRpathsForFilename(original_path); // collectRpaths(original_path);
//
// for (const auto& line : lines) {
// if (!Settings::isPrefixBundled(line))
// continue; // skip system/ignored prefixes
// addDependency(line, original_path);
// }
for (const auto& line : lines) { collectDependencies(original_path);
if (!Settings::isPrefixBundled(line))
continue; // skip system/ignored prefixes
addDependency(line, original_path);
}
} }
// if no more dependencies were added on this iteration, stop searching // if no more dependencies were added on this iteration, stop searching
if (deps.size() == deps_size) if (deps.size() == deps_size)
@ -143,28 +173,30 @@ void collectSubDependencies()
void changeLibPathsOnFile(const std::string& file_to_fix) void changeLibPathsOnFile(const std::string& file_to_fix)
{ {
if (deps_collected.find(file_to_fix) == deps_collected.end()) if (deps_collected.find(file_to_fix) == deps_collected.end() || rpaths_collected.find(file_to_fix) == rpaths_collected.end())
collectDependenciesForFile(file_to_fix); collectDependencies(file_to_fix);
std::cout << "* Fixing dependencies on " << file_to_fix << "\n"; std::cout << "* Fixing dependencies on " << file_to_fix << "\n";
const size_t dep_amount = deps_per_file[file_to_fix].size(); std::vector<Dependency> dependencies = deps_per_file[file_to_fix];
for (size_t n=0; n<dep_amount; ++n) { for (auto& dependency : dependencies) {
deps_per_file[file_to_fix][n].fixDependentFiles(file_to_fix); dependency.FixDependentFile(file_to_fix);
} }
} }
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)
{ {
std::vector<std::string> rpaths_to_fix; std::vector<std::string> rpaths_to_fix;
if (Settings::fileHasRpath(original_file)) if (!Settings::fileHasRpath(original_file))
rpaths_to_fix = Settings::getRpathsForFile(original_file); return;
for (const auto& i : rpaths_to_fix) { rpaths_to_fix = Settings::getRpathsForFile(original_file);
for (const auto& rpath_to_fix : rpaths_to_fix) {
std::string command = std::string("install_name_tool -rpath "); std::string command = std::string("install_name_tool -rpath ");
command += i + " " + Settings::insideLibPath() + " " + file_to_fix; command.append(rpath_to_fix).append(" ").append(Settings::insideLibPath());
command.append(" ").append(file_to_fix);
if (systemp(command) != 0) { if (systemp(command) != 0) {
std::cerr << "\n\n/!\\ ERROR: An error occured while trying to fix dependencies of " << file_to_fix << "\n"; std::cerr << "\n\n/!\\ ERROR: An error occured while trying to fix rpath " << rpath_to_fix << " of " << file_to_fix << std::endl;
exit(1); exit(1);
} }
} }
@ -173,21 +205,22 @@ void fixRpathsOnFile(const std::string& original_file, const std::string& file_t
void bundleDependencies() void bundleDependencies()
{ {
for (const auto& dep : deps) { for (const auto& dep : deps) {
dep.print(); dep.Print();
} }
std::cout << "\n"; std::cout << "\n";
if (Settings::verboseOutput()) { if (Settings::verboseOutput()) {
std::cout << "rpaths:" << std::endl;
for (const auto& rpath : rpaths) { for (const auto& rpath : rpaths) {
std::cout << "rpaths: " << rpath << std::endl; std::cout << "* " << rpath << std::endl;
} }
} }
// copy & fix up dependencies // copy & fix up dependencies
if (Settings::bundleLibs()) { if (Settings::bundleLibs()) {
createDestDir(); createDestDir();
for (const auto& dep : deps) { for (const auto& dep : deps) {
dep.copyToAppBundle(); dep.CopyToBundle();
changeLibPathsOnFile(dep.getInstallPath()); changeLibPathsOnFile(dep.InstallPath());
fixRpathsOnFile(dep.getOriginalPath(), dep.getInstallPath()); fixRpathsOnFile(dep.OriginalPath(), dep.InstallPath());
} }
} }
// fix up selected files // fix up selected files
@ -261,7 +294,7 @@ void bundleQtPlugins()
std::vector<std::string> files = lsDir(dest + plugin+"/"); std::vector<std::string> files = lsDir(dest + plugin+"/");
for (const auto& file : files) { for (const auto& file : files) {
Settings::addFileToFix(dest + plugin+"/"+file); Settings::addFileToFix(dest + plugin+"/"+file);
collectDependenciesForFile(dest + plugin+"/"+file); collectDependencies(dest + plugin + "/" + file);
changeId(dest + plugin+"/"+file, "@rpath/" + plugin+"/"+file); changeId(dest + plugin+"/"+file, "@rpath/" + plugin+"/"+file);
} }
} }
@ -276,7 +309,7 @@ void bundleQtPlugins()
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");
collectDependenciesForFile(dest + "platforms/libqcocoa.dylib"); collectDependencies(dest + "platforms/libqcocoa.dylib");
fixupPlugin("printsupport"); fixupPlugin("printsupport");
fixupPlugin("styles"); fixupPlugin("styles");

View File

@ -1,23 +1,18 @@
#pragma once #pragma once
#ifndef _DYLIB_BUNDLER_H_ #ifndef DYLIBBUNDLER_DYLIBBUNDLER_H
#define _DYLIB_BUNDLER_H_ #define DYLIBBUNDLER_DYLIBBUNDLER_H
#include <string> #include <string>
#include <vector> #include <vector>
void addDependency(const std::string& path, const std::string& dependent_file); void addDependency(const std::string& path, 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);
// 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 collectDependencies(const std::string& dependent_file);
void collectDependenciesForFile(const std::string& dependent_file);
void collectRpaths(const std::string& filename); //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();

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#ifndef _settings_ #ifndef DYLIBBUNDLER_SETTINGS_H
#define _settings_ #define DYLIBBUNDLER_SETTINGS_H
#include <string> #include <string>
#include <vector> #include <vector>

View File

@ -299,27 +299,32 @@ std::string getUserInputDirForFile(const std::string& filename, const std::strin
} }
} }
void parseLoadCommands(const std::string& file, const std::string& cmd, const std::string& value, std::vector<std::string>& lines) void otool(const std::string& flags, const std::string& file, std::vector<std::string>& lines)
{ {
std::string command = "otool -l " + file; std::string command = "otool " + flags + " " + file;
std::string output = systemOutput(command); std::string output = systemOutput(command);
if (output.find("can't open file") != std::string::npos if (output.find("can't open file") != std::string::npos
|| output.find("No such 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.find("at least one file must be specified") != std::string::npos
|| output.empty()) { || output.empty()) {
std::cerr << "\n\n/!\\ ERROR: Cannot find file " << file << " to read its load commands\n"; std::cerr << "\n\n/!\\ ERROR: Cannot find file " << file << " to read its load commands\n";
exit(1); exit(1);
} }
tokenize(output, "\n", &lines);
}
void parseLoadCommands(const std::string& file, const std::string& cmd, const std::string& value, std::vector<std::string>& lines)
{
std::vector<std::string> raw_lines; std::vector<std::string> raw_lines;
tokenize(output, "\n", &raw_lines); otool("-l", file, raw_lines);
bool searching = false; bool searching = false;
std::string cmd_line = std::string("cmd ") + cmd; std::string cmd_line = std::string("cmd ") + cmd;
std::string value_line = std::string(value + std::string(" ")); std::string value_line = std::string(value + std::string(" "));
for (const auto& line : raw_lines) { for (const auto& raw_line : raw_lines) {
if (line.find(cmd_line) != std::string::npos) { if (raw_line.find(cmd_line) != std::string::npos) {
if (searching) { if (searching) {
std::cerr << "\n\n/!\\ ERROR: Failed to find " << value << " before next cmd\n"; std::cerr << "\n\n/!\\ ERROR: Failed to find " << value << " before next cmd\n";
exit(1); exit(1);
@ -327,23 +332,62 @@ void parseLoadCommands(const std::string& file, const std::string& cmd, const st
searching = true; searching = true;
} }
else if (searching) { else if (searching) {
size_t start_pos = line.find(value_line); size_t start_pos = raw_line.find(value_line);
if (start_pos == std::string::npos) if (start_pos == std::string::npos)
continue; continue;
size_t start = start_pos + value.size() + 1; // exclude data label "|value| " size_t start = start_pos + value.size() + 1; // exclude data label "|value| "
size_t end = std::string::npos; size_t end = std::string::npos;
if (value == "name" || value == "path") { if (value == "name" || value == "path") {
size_t end_pos = line.find(" ("); size_t end_pos = raw_line.find(" (");
if (end_pos == std::string::npos) if (end_pos == std::string::npos)
continue; continue;
end = end_pos - start; end = end_pos - start;
} }
lines.push_back(line.substr(start, end)); lines.push_back(raw_line.substr(start, end));
searching = false; searching = false;
} }
} }
} }
void parseLoadCommands(const std::string& file, const std::map<std::string,std::string>& cmds_values, std::map<std::string,std::vector<std::string>>& cmds_results)
{
std::vector<std::string> raw_lines;
otool("-l", file, raw_lines);
for (const auto& cmd_value : cmds_values) {
std::vector<std::string> lines;
std::string cmd = cmd_value.first;
std::string value = cmd_value.second;
std::string cmd_line = std::string("cmd ") + cmd;
std::string value_line = std::string(value) + std::string(" ");
bool searching = false;
for (const auto& raw_line : raw_lines) {
if (raw_line.find(cmd_line) != std::string::npos) {
if (searching) {
std::cerr << "\n\n/!\\ ERROR: Failed to find " << value << " before next cmd\n";
exit(1);
}
searching = true;
} else if (searching) {
size_t start_pos = raw_line.find(value_line);
if (start_pos == std::string::npos)
continue;
size_t start = start_pos + value.size() + 1; // exclude data label "|value| "
size_t end = std::string::npos;
if (value == "name" || value == "path") {
size_t end_pos = raw_line.find(" (");
if (end_pos == std::string::npos)
continue;
end = end_pos - start;
}
lines.push_back(raw_line.substr(start, end));
searching = false;
}
}
cmds_results[cmd] = lines;
}
}
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)
{ {
if (Settings::verboseOutput()) { if (Settings::verboseOutput()) {

View File

@ -1,8 +1,9 @@
#pragma once #pragma once
#ifndef _utils_h_ #ifndef DYLIBBUNDLER_UTILS_H
#define _utils_h_ #define DYLIBBUNDLER_UTILS_H
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
@ -44,7 +45,9 @@ void createDestDir();
std::string getUserInputDirForFile(const std::string& filename, const std::string& dependent_file); std::string getUserInputDirForFile(const std::string& filename, const std::string& dependent_file);
void otool(const std::string& flags, const std::string& file, std::vector<std::string>& lines);
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);
void parseLoadCommands(const std::string& file, const std::map<std::string,std::string>& cmds_values, std::map<std::string,std::vector<std::string>>& cmds_results);
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);

View File

@ -126,7 +126,7 @@ int main(int argc, const char* argv[])
const std::vector<std::string> files_to_fix = Settings::filesToFix(); const std::vector<std::string> files_to_fix = Settings::filesToFix();
for (const auto& file_to_fix : files_to_fix) { for (const auto& file_to_fix : files_to_fix) {
collectDependenciesForFile(file_to_fix); collectDependencies(file_to_fix);
} }
collectSubDependencies(); collectSubDependencies();
bundleDependencies(); bundleDependencies();