collect dependencies & rpaths in a single otool call
This commit is contained in:
parent
7f41661132
commit
e5cacbb3e6
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
std::map<std::string,std::string> cmds_values;
|
||||||
|
std::string dylib = "LC_LOAD_DYLIB";
|
||||||
|
std::string rpath = "LC_RPATH";
|
||||||
|
cmds_values[dylib] = "name";
|
||||||
|
cmds_values[rpath] = "path";
|
||||||
|
std::map<std::string,std::vector<std::string>> cmds_results;
|
||||||
|
|
||||||
|
parseLoadCommands(dependent_file, cmds_values, cmds_results);
|
||||||
|
|
||||||
|
if (rpaths_collected.find(dependent_file) == rpaths_collected.end()) {
|
||||||
|
auto rpath_results = cmds_results[rpath];
|
||||||
|
for (const auto& rpath_result : rpath_results) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void collectDependenciesForFile(const std::string& file, std::vector<std::string>& lines)
|
if (deps_collected.find(dependent_file) == deps_collected.end()) {
|
||||||
{
|
auto dylib_results = cmds_results[dylib];
|
||||||
if (deps_collected.find(file) == deps_collected.end())
|
for (const auto& dylib_result : dylib_results) {
|
||||||
collectDependencies(file, lines);
|
// skip system/ignored prefixes
|
||||||
}
|
if (Settings::isPrefixBundled(dylib_result))
|
||||||
|
addDependency(dylib_result, dependent_file);
|
||||||
void collectDependenciesForFile(const std::string& dependent_file)
|
|
||||||
{
|
|
||||||
std::vector<std::string> lines;
|
|
||||||
collectDependenciesForFile(dependent_file, lines);
|
|
||||||
collectRpathsForFilename(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;
|
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);
|
|
||||||
Settings::addRpathForFile(filename, line);
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
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");
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -299,9 +299,9 @@ 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
|
||||||
|
@ -312,14 +312,19 @@ void parseLoadCommands(const std::string& file, const std::string& cmd, const st
|
||||||
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()) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue