create DylibBundler class
This commit is contained in:
parent
ee0c02888a
commit
cbfcd534d1
|
@ -8,9 +8,9 @@ if(NOT CMAKE_BUILD_TYPE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
string(REPLACE "-O3" "-O2" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
string(REPLACE "-O3" "-O2" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
||||||
#string(REPLACE "-std=c++1z" "-std=c++2a" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
|
||||||
|
|
||||||
add_compile_options(-pipe -Wall -Wextra -Wpedantic)
|
add_compile_options(-pipe -Wall -Wextra -Wpedantic)
|
||||||
|
add_link_options(-Wl,-dead_strip)
|
||||||
|
|
||||||
include_directories(src)
|
include_directories(src)
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,12 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Settings.h"
|
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
Dependency::Dependency(std::string path, const std::string& dependent_file) : is_framework(false)
|
Dependency::Dependency(std::string path, const std::string& dependent_file, DylibBundler* db)
|
||||||
|
: is_framework(false),
|
||||||
|
db_(db)
|
||||||
|
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
rtrim_in_place(path);
|
rtrim_in_place(path);
|
||||||
|
@ -21,7 +23,7 @@ Dependency::Dependency(std::string path, const std::string& dependent_file) : is
|
||||||
std::string warning_msg;
|
std::string warning_msg;
|
||||||
|
|
||||||
if (isRpath(path)) {
|
if (isRpath(path)) {
|
||||||
original_file = searchFilenameInRpaths(path, dependent_file);
|
original_file = db_->searchFilenameInRpaths(path, dependent_file);
|
||||||
}
|
}
|
||||||
else if (realpath(path.c_str(), buffer)) {
|
else if (realpath(path.c_str(), buffer)) {
|
||||||
original_file = buffer;
|
original_file = buffer;
|
||||||
|
@ -31,7 +33,7 @@ Dependency::Dependency(std::string path, const std::string& dependent_file) : is
|
||||||
original_file = path;
|
original_file = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::verboseOutput()) {
|
if (db_->verboseOutput()) {
|
||||||
std::cout<< "** Dependency ctor **" << std::endl;
|
std::cout<< "** Dependency ctor **" << std::endl;
|
||||||
if (path != dependent_file)
|
if (path != dependent_file)
|
||||||
std::cout << " dependent file: " << dependent_file << std::endl;
|
std::cout << " dependent file: " << dependent_file << std::endl;
|
||||||
|
@ -50,7 +52,7 @@ Dependency::Dependency(std::string path, const std::string& dependent_file) : is
|
||||||
prefix += "/";
|
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 (!db_->isPrefixBundled(prefix))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (original_file.find(".framework") != std::string::npos) {
|
if (original_file.find(".framework") != std::string::npos) {
|
||||||
|
@ -60,7 +62,7 @@ Dependency::Dependency(std::string path, const std::string& dependent_file) : is
|
||||||
std::string framework_name = stripPrefix(framework_root);
|
std::string framework_name = stripPrefix(framework_root);
|
||||||
prefix = filePrefix(framework_root);
|
prefix = filePrefix(framework_root);
|
||||||
filename = framework_name + "/" + framework_path;
|
filename = framework_name + "/" + framework_path;
|
||||||
if (Settings::verboseOutput()) {
|
if (db_->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;
|
||||||
std::cout << " framework name: " << framework_name << std::endl;
|
std::cout << " framework name: " << framework_name << std::endl;
|
||||||
|
@ -69,31 +71,31 @@ 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 = db_->searchPaths();
|
||||||
if (search_paths.empty())
|
if (search_paths.empty())
|
||||||
initSearchPaths();
|
db_->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)) {
|
||||||
warning_msg += "FOUND " + filename + " in " + search_path + "\n";
|
warning_msg += "FOUND " + filename + " in " + search_path + "\n";
|
||||||
prefix = search_path;
|
prefix = search_path;
|
||||||
Settings::missingPrefixes(true);
|
db_->missingPrefixes(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Settings::quietOutput())
|
if (!db_->quietOutput())
|
||||||
std::cout << warning_msg;
|
std::cout << warning_msg;
|
||||||
|
|
||||||
// if the location is still unknown, ask the user for search path
|
// if the location is still unknown, ask the user for search path
|
||||||
if (!Settings::isPrefixIgnored(prefix) && (prefix.empty() || !fileExists(prefix+filename))) {
|
if (!db_->isPrefixIgnored(prefix) && (prefix.empty() || !fileExists(prefix+filename))) {
|
||||||
if (!Settings::quietOutput())
|
if (!db_->quietOutput())
|
||||||
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 (db_->verboseOutput())
|
||||||
std::cout << " path: " << (prefix+filename) << std::endl;
|
std::cout << " path: " << (prefix+filename) << std::endl;
|
||||||
Settings::missingPrefixes(true);
|
db_->missingPrefixes(true);
|
||||||
Settings::addSearchPath(getUserInputDirForFile(filename, dependent_file));
|
db_->addSearchPath(db_->getUserInputDirForFile(filename, dependent_file));
|
||||||
}
|
}
|
||||||
|
|
||||||
new_name = filename;
|
new_name = filename;
|
||||||
|
@ -101,12 +103,12 @@ Dependency::Dependency(std::string path, const std::string& dependent_file) : is
|
||||||
|
|
||||||
std::string Dependency::InnerPath() const
|
std::string Dependency::InnerPath() const
|
||||||
{
|
{
|
||||||
return Settings::insideLibPath() + new_name;
|
return db_->insideLibPath() + new_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Dependency::InstallPath() const
|
std::string Dependency::InstallPath() const
|
||||||
{
|
{
|
||||||
return Settings::destFolder() + new_name;
|
return db_->destFolder() + new_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dependency::AddSymlink(const std::string& path)
|
void Dependency::AddSymlink(const std::string& path)
|
||||||
|
@ -115,12 +117,11 @@ void Dependency::AddSymlink(const std::string& path)
|
||||||
symlinks.push_back(path);
|
symlinks.push_back(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dependency::MergeIfIdentical(Dependency& dependency)
|
bool Dependency::MergeIfIdentical(Dependency* dependency)
|
||||||
{
|
{
|
||||||
if (dependency.OriginalFilename() == filename) {
|
if (dependency->OriginalFilename() == filename) {
|
||||||
for (const auto& symlink : symlinks) {
|
for (const auto& symlink : symlinks)
|
||||||
dependency.AddSymlink(symlink);
|
dependency->AddSymlink(symlink);
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -133,10 +134,10 @@ void Dependency::CopyToBundle() const
|
||||||
|
|
||||||
if (is_framework) {
|
if (is_framework) {
|
||||||
original_path = getFrameworkRoot(original_path);
|
original_path = getFrameworkRoot(original_path);
|
||||||
dest_path = Settings::destFolder() + stripPrefix(original_path);
|
dest_path = db_->destFolder() + stripPrefix(original_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::verboseOutput()) {
|
if (db_->verboseOutput()) {
|
||||||
std::string inner_path = InnerPath();
|
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;
|
||||||
|
@ -144,31 +145,31 @@ void Dependency::CopyToBundle() const
|
||||||
std::cout << " - install path: " << InstallPath() << std::endl;
|
std::cout << " - install path: " << InstallPath() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
copyFile(original_path, dest_path);
|
db_->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");
|
||||||
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_path = buffer;
|
headers_path = buffer;
|
||||||
deleteFile(headers_path, true);
|
db_->deleteFile(headers_path, true);
|
||||||
deleteFile(dest_path + "/*.prl");
|
db_->deleteFile(dest_path + "/*.prl");
|
||||||
}
|
}
|
||||||
|
|
||||||
changeId(InstallPath(), "@rpath/" + new_name);
|
db_->changeId(InstallPath(), "@rpath/" + new_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dependency::FixDependentFile(const std::string& dependent_file) const
|
void Dependency::FixDependentFile(const std::string& dependent_file) const
|
||||||
{
|
{
|
||||||
changeInstallName(dependent_file, OriginalPath(), InnerPath());
|
db_->changeInstallName(dependent_file, OriginalPath(), InnerPath());
|
||||||
for (const auto& symlink : symlinks) {
|
for (const auto& symlink : symlinks) {
|
||||||
changeInstallName(dependent_file, symlink, InnerPath());
|
db_->changeInstallName(dependent_file, symlink, InnerPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::missingPrefixes()) {
|
if (db_->missingPrefixes()) {
|
||||||
changeInstallName(dependent_file, filename, InnerPath());
|
db_->changeInstallName(dependent_file, filename, InnerPath());
|
||||||
for (const auto& symlink : symlinks) {
|
for (const auto& symlink : symlinks) {
|
||||||
changeInstallName(dependent_file, symlink, InnerPath());
|
db_->changeInstallName(dependent_file, symlink, InnerPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,11 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "DylibBundler.h"
|
||||||
|
|
||||||
class Dependency {
|
class Dependency {
|
||||||
public:
|
public:
|
||||||
Dependency(std::string path, const std::string& dependent_file);
|
Dependency(std::string path, const std::string& dependent_file, DylibBundler* db);
|
||||||
|
|
||||||
[[nodiscard]] bool IsFramework() const { return is_framework; }
|
[[nodiscard]] bool IsFramework() const { return is_framework; }
|
||||||
|
|
||||||
|
@ -23,7 +25,7 @@ public:
|
||||||
|
|
||||||
// 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 MergeIfIdentical(Dependency& dependency);
|
bool MergeIfIdentical(Dependency* dependency);
|
||||||
|
|
||||||
void CopyToBundle() const;
|
void CopyToBundle() const;
|
||||||
void FixDependentFile(const std::string& dependent_file) const;
|
void FixDependentFile(const std::string& dependent_file) const;
|
||||||
|
@ -40,6 +42,8 @@ private:
|
||||||
|
|
||||||
// installation
|
// installation
|
||||||
std::string new_name;
|
std::string new_name;
|
||||||
|
|
||||||
|
DylibBundler* db_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <regex>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#ifdef __linux
|
#ifdef __linux
|
||||||
|
@ -15,50 +17,48 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Dependency.h"
|
#include "Dependency.h"
|
||||||
#include "Settings.h"
|
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
std::vector<Dependency> deps;
|
DylibBundler::DylibBundler() : qt_plugins_called(false)
|
||||||
std::map<std::string, std::vector<Dependency>> deps_per_file;
|
|
||||||
std::map<std::string, bool> deps_collected;
|
|
||||||
std::set<std::string> frameworks;
|
|
||||||
std::set<std::string> rpaths;
|
|
||||||
std::map<std::string, bool> rpaths_collected;
|
|
||||||
bool qt_plugins_called = false;
|
|
||||||
|
|
||||||
void addDependency(const std::string& path, const std::string& dependent_file)
|
|
||||||
{
|
{
|
||||||
Dependency dependency(path, dependent_file);
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DylibBundler::~DylibBundler() = default;
|
||||||
|
|
||||||
|
void DylibBundler::addDependency(const std::string& path, const std::string& dependent_file)
|
||||||
|
{
|
||||||
|
Dependency* dependency = new Dependency(path, dependent_file, this);
|
||||||
|
|
||||||
// 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.MergeIfIdentical(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.MergeIfIdentical(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.Prefix()))
|
if (!this->isPrefixBundled(dependency->Prefix()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!in_deps && dependency.IsFramework())
|
if (!in_deps && dependency->IsFramework())
|
||||||
frameworks.insert(dependency.OriginalPath());
|
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)
|
void DylibBundler::collectDependencies(const std::string& dependent_file)
|
||||||
{
|
{
|
||||||
if (deps_collected.find(dependent_file) != deps_collected.end() && Settings::fileHasRpath(dependent_file))
|
if (deps_collected.find(dependent_file) != deps_collected.end() && fileHasRpath(dependent_file))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::map<std::string,std::string> cmds_values;
|
std::map<std::string,std::string> cmds_values;
|
||||||
|
@ -74,8 +74,8 @@ void collectDependencies(const std::string& dependent_file)
|
||||||
auto rpath_results = cmds_results[rpath];
|
auto rpath_results = cmds_results[rpath];
|
||||||
for (const auto& rpath_result : rpath_results) {
|
for (const auto& rpath_result : rpath_results) {
|
||||||
rpaths.insert(rpath_result);
|
rpaths.insert(rpath_result);
|
||||||
Settings::addRpathForFile(dependent_file, rpath_result);
|
addRpathForFile(dependent_file, rpath_result);
|
||||||
if (Settings::verboseOutput())
|
if (verboseOutput())
|
||||||
std::cout << " rpath: " << rpath_result << std::endl;
|
std::cout << " rpath: " << rpath_result << std::endl;
|
||||||
}
|
}
|
||||||
rpaths_collected[dependent_file] = true;
|
rpaths_collected[dependent_file] = true;
|
||||||
|
@ -85,52 +85,18 @@ void collectDependencies(const std::string& dependent_file)
|
||||||
auto dylib_results = cmds_results[dylib];
|
auto dylib_results = cmds_results[dylib];
|
||||||
for (const auto& dylib_result : dylib_results) {
|
for (const auto& dylib_result : dylib_results) {
|
||||||
// skip system/ignored prefixes
|
// skip system/ignored prefixes
|
||||||
if (Settings::isPrefixBundled(dylib_result))
|
if (isPrefixBundled(dylib_result))
|
||||||
addDependency(dylib_result, dependent_file);
|
addDependency(dylib_result, dependent_file);
|
||||||
}
|
}
|
||||||
deps_collected[dependent_file] = true;
|
deps_collected[dependent_file] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines)
|
void DylibBundler::collectSubDependencies()
|
||||||
//{
|
|
||||||
// if (deps_collected.find(dependent_file) == deps_collected.end())
|
|
||||||
// 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()
|
|
||||||
{
|
{
|
||||||
size_t dep_counter = deps.size();
|
size_t dep_counter = deps.size();
|
||||||
if (Settings::verboseOutput()) {
|
if (verboseOutput()) {
|
||||||
std::cout << "(pre sub) # OF FILES: " << Settings::filesToFixCount() << std::endl;
|
std::cout << "(pre sub) # OF FILES: " << filesToFixCount() << std::endl;
|
||||||
std::cout << "(pre sub) # OF DEPS: " << deps.size() << std::endl;
|
std::cout << "(pre sub) # OF DEPS: " << deps.size() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,22 +104,12 @@ 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].OriginalPath();
|
std::string original_path = deps[n]->OriginalPath();
|
||||||
if (Settings::verboseOutput())
|
if (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;
|
|
||||||
// collectDependencies(original_path, lines);
|
|
||||||
// collectRpaths(original_path);
|
|
||||||
//
|
|
||||||
// for (const auto& line : lines) {
|
|
||||||
// if (!Settings::isPrefixBundled(line))
|
|
||||||
// continue; // skip system/ignored prefixes
|
|
||||||
// addDependency(line, original_path);
|
|
||||||
// }
|
|
||||||
|
|
||||||
collectDependencies(original_path);
|
collectDependencies(original_path);
|
||||||
}
|
}
|
||||||
// if no more dependencies were added on this iteration, stop searching
|
// if no more dependencies were added on this iteration, stop searching
|
||||||
|
@ -161,39 +117,39 @@ void collectSubDependencies()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::verboseOutput()) {
|
if (verboseOutput()) {
|
||||||
std::cout << "(post sub) # OF FILES: " << Settings::filesToFixCount() << std::endl;
|
std::cout << "(post sub) # OF FILES: " << filesToFixCount() << std::endl;
|
||||||
std::cout << "(post sub) # OF DEPS: " << deps.size() << std::endl;
|
std::cout << "(post sub) # OF DEPS: " << deps.size() << std::endl;
|
||||||
}
|
}
|
||||||
if (Settings::bundleLibs() && Settings::bundleFrameworks()) {
|
if (bundleLibs() && bundleFrameworks()) {
|
||||||
if (!qt_plugins_called || (deps.size() != dep_counter))
|
if (!qt_plugins_called || (deps.size() != dep_counter))
|
||||||
bundleQtPlugins();
|
bundleQtPlugins();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeLibPathsOnFile(const std::string& file_to_fix)
|
void DylibBundler::changeLibPathsOnFile(const std::string& file_to_fix)
|
||||||
{
|
{
|
||||||
if (deps_collected.find(file_to_fix) == deps_collected.end() || rpaths_collected.find(file_to_fix) == rpaths_collected.end())
|
if (deps_collected.find(file_to_fix) == deps_collected.end() || rpaths_collected.find(file_to_fix) == rpaths_collected.end())
|
||||||
collectDependencies(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";
|
||||||
|
|
||||||
std::vector<Dependency> dependencies = deps_per_file[file_to_fix];
|
std::vector<Dependency*> dependencies = deps_per_file[file_to_fix];
|
||||||
for (auto& dependency : dependencies) {
|
for (auto& dependency : dependencies) {
|
||||||
dependency.FixDependentFile(file_to_fix);
|
dependency->FixDependentFile(file_to_fix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fixRpathsOnFile(const std::string& original_file, const std::string& file_to_fix)
|
void DylibBundler::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 (!fileHasRpath(original_file))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rpaths_to_fix = Settings::getRpathsForFile(original_file);
|
rpaths_to_fix = getRpathsForFile(original_file);
|
||||||
for (const auto& rpath_to_fix : rpaths_to_fix) {
|
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.append(rpath_to_fix).append(" ").append(Settings::insideLibPath());
|
command.append(rpath_to_fix).append(" ").append(insideLibPath());
|
||||||
command.append(" ").append(file_to_fix);
|
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 rpath " << rpath_to_fix << " of " << file_to_fix << std::endl;
|
std::cerr << "\n\n/!\\ ERROR: An error occured while trying to fix rpath " << rpath_to_fix << " of " << file_to_fix << std::endl;
|
||||||
|
@ -202,36 +158,36 @@ void fixRpathsOnFile(const std::string& original_file, const std::string& file_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bundleDependencies()
|
void DylibBundler::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 (verboseOutput()) {
|
||||||
std::cout << "rpaths:" << std::endl;
|
std::cout << "rpaths:" << std::endl;
|
||||||
for (const auto& rpath : rpaths) {
|
for (const auto& rpath : rpaths) {
|
||||||
std::cout << "* " << rpath << std::endl;
|
std::cout << "* " << rpath << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// copy & fix up dependencies
|
// copy & fix up dependencies
|
||||||
if (Settings::bundleLibs()) {
|
if (bundleLibs()) {
|
||||||
createDestDir();
|
createDestDir();
|
||||||
for (const auto& dep : deps) {
|
for (const auto& dep : deps) {
|
||||||
dep.CopyToBundle();
|
dep->CopyToBundle();
|
||||||
changeLibPathsOnFile(dep.InstallPath());
|
changeLibPathsOnFile(dep->InstallPath());
|
||||||
fixRpathsOnFile(dep.OriginalPath(), dep.InstallPath());
|
fixRpathsOnFile(dep->OriginalPath(), dep->InstallPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fix up selected files
|
// fix up selected files
|
||||||
const auto files = Settings::filesToFix();
|
const auto files = filesToFix();
|
||||||
for (const auto& file : files) {
|
for (const auto& file : files) {
|
||||||
changeLibPathsOnFile(file);
|
changeLibPathsOnFile(file);
|
||||||
fixRpathsOnFile(file, file);
|
fixRpathsOnFile(file, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bundleQtPlugins()
|
void DylibBundler::bundleQtPlugins()
|
||||||
{
|
{
|
||||||
bool qtCoreFound = false;
|
bool qtCoreFound = false;
|
||||||
bool qtGuiFound = false;
|
bool qtGuiFound = false;
|
||||||
|
@ -279,11 +235,11 @@ void bundleQtPlugins()
|
||||||
if (!qtCoreFound)
|
if (!qtCoreFound)
|
||||||
return;
|
return;
|
||||||
if (!qt_plugins_called)
|
if (!qt_plugins_called)
|
||||||
createQtConf(Settings::resourcesFolder());
|
createQtConf(resourcesFolder());
|
||||||
qt_plugins_called = true;
|
qt_plugins_called = true;
|
||||||
|
|
||||||
const auto fixupPlugin = [original_file](const std::string& plugin) {
|
const auto fixupPlugin = [&](const std::string& plugin) {
|
||||||
std::string dest = Settings::pluginsFolder();
|
std::string dest = pluginsFolder();
|
||||||
std::string framework_root = getFrameworkRoot(original_file);
|
std::string framework_root = getFrameworkRoot(original_file);
|
||||||
std::string prefix = filePrefix(framework_root);
|
std::string prefix = filePrefix(framework_root);
|
||||||
std::string qt_prefix = filePrefix(prefix.substr(0, prefix.size()-1));
|
std::string qt_prefix = filePrefix(prefix.substr(0, prefix.size()-1));
|
||||||
|
@ -293,9 +249,12 @@ void bundleQtPlugins()
|
||||||
copyFile(qt_plugins_prefix + plugin, dest);
|
copyFile(qt_plugins_prefix + plugin, dest);
|
||||||
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);
|
std::string suffix = std::string("").append(plugin).append("/").append(file);
|
||||||
collectDependencies(dest + plugin + "/" + file);
|
std::string file_to_fix = dest.append(suffix);
|
||||||
changeId(dest + plugin+"/"+file, "@rpath/" + plugin+"/"+file);
|
std::string new_rpath = std::string("@rpath/").append(suffix);
|
||||||
|
addFileToFix(file_to_fix);
|
||||||
|
collectDependencies(file_to_fix);
|
||||||
|
changeId(file_to_fix, new_rpath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -305,10 +264,10 @@ void bundleQtPlugins()
|
||||||
std::string qt_prefix = filePrefix(prefix.substr(0, prefix.size()-1));
|
std::string qt_prefix = filePrefix(prefix.substr(0, prefix.size()-1));
|
||||||
std::string qt_plugins_prefix = qt_prefix + "plugins/";
|
std::string qt_plugins_prefix = qt_prefix + "plugins/";
|
||||||
|
|
||||||
std::string dest = Settings::pluginsFolder();
|
std::string dest = pluginsFolder();
|
||||||
mkdir(dest + "platforms");
|
mkdir(dest + "platforms");
|
||||||
copyFile(qt_plugins_prefix + "platforms/libqcocoa.dylib", dest + "platforms");
|
copyFile(qt_plugins_prefix + "platforms/libqcocoa.dylib", dest + "platforms");
|
||||||
Settings::addFileToFix(dest + "platforms/libqcocoa.dylib");
|
addFileToFix(dest + "platforms/libqcocoa.dylib");
|
||||||
collectDependencies(dest + "platforms/libqcocoa.dylib");
|
collectDependencies(dest + "platforms/libqcocoa.dylib");
|
||||||
|
|
||||||
fixupPlugin("printsupport");
|
fixupPlugin("printsupport");
|
||||||
|
@ -346,3 +305,300 @@ void bundleQtPlugins()
|
||||||
|
|
||||||
collectSubDependencies();
|
collectSubDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string DylibBundler::getUserInputDirForFile(const std::string& filename, const std::string& dependent_file)
|
||||||
|
{
|
||||||
|
std::vector<std::string> search_paths = userSearchPaths();
|
||||||
|
for (auto& search_path : search_paths) {
|
||||||
|
if (!search_path.empty() && search_path[search_path.size()-1] != '/')
|
||||||
|
search_path += "/";
|
||||||
|
if (fileExists(search_path + filename)) {
|
||||||
|
if (!quietOutput()) {
|
||||||
|
std::cerr << (search_path + filename) << " was found\n"
|
||||||
|
<< "/!\\ WARNING: dylibbundler MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Check the executable with 'otool -L'\n";
|
||||||
|
}
|
||||||
|
return search_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (quietOutput())
|
||||||
|
std::cerr << "\n/!\\ WARNING: Dependency " << filename << " of " << dependent_file << " not found\n";
|
||||||
|
std::cout << "\nPlease specify the directory where this file is located (or enter 'quit' to abort): ";
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
std::string prefix;
|
||||||
|
std::cin >> prefix;
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
if (prefix == "quit" || prefix == "exit" || prefix == "abort")
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
if (!prefix.empty() && prefix[prefix.size()-1] != '/')
|
||||||
|
prefix += "/";
|
||||||
|
|
||||||
|
if (!fileExists(prefix+filename)) {
|
||||||
|
std::cerr << (prefix+filename) << " does not exist. Try again...\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << (prefix+filename) << " was found\n"
|
||||||
|
<< "/!\\ WARNING: dylibbundler MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Check the executable with 'otool -L'\n";
|
||||||
|
addUserSearchPath(prefix);
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DylibBundler::searchFilenameInRpaths(const std::string& rpath_file, const std::string& dependent_file)
|
||||||
|
{
|
||||||
|
if (verboseOutput()) {
|
||||||
|
if (dependent_file != rpath_file)
|
||||||
|
std::cout << " dependent file: " << dependent_file << std::endl;
|
||||||
|
std::cout << " dependency: " << rpath_file << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fullpath;
|
||||||
|
std::string suffix = rpath_file.substr(rpath_file.rfind('/')+1);
|
||||||
|
char fullpath_buffer[PATH_MAX];
|
||||||
|
|
||||||
|
const auto check_path = [&](std::string path) {
|
||||||
|
char buffer[PATH_MAX];
|
||||||
|
std::string file_prefix = filePrefix(dependent_file);
|
||||||
|
if (path.find("@executable_path") != std::string::npos || path.find("@loader_path") != std::string::npos) {
|
||||||
|
if (path.find("@executable_path") != std::string::npos) {
|
||||||
|
if (appBundleProvided())
|
||||||
|
path = std::regex_replace(path, std::regex("@executable_path/"), executableFolder());
|
||||||
|
}
|
||||||
|
if (dependent_file != rpath_file) {
|
||||||
|
if (path.find("@loader_path") != std::string::npos)
|
||||||
|
path = std::regex_replace(path, std::regex("@loader_path/"), file_prefix);
|
||||||
|
}
|
||||||
|
if (verboseOutput())
|
||||||
|
std::cout << " path to search: " << path << std::endl;
|
||||||
|
if (realpath(path.c_str(), buffer)) {
|
||||||
|
fullpath = buffer;
|
||||||
|
rpathToFullPath(rpath_file, fullpath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (path.find("@rpath") != std::string::npos) {
|
||||||
|
if (appBundleProvided()) {
|
||||||
|
std::string pathE = std::regex_replace(path, std::regex("@rpath/"), executableFolder());
|
||||||
|
if (verboseOutput())
|
||||||
|
std::cout << " path to search: " << pathE << std::endl;
|
||||||
|
if (realpath(pathE.c_str(), buffer)) {
|
||||||
|
fullpath = buffer;
|
||||||
|
rpathToFullPath(rpath_file, fullpath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dependent_file != rpath_file) {
|
||||||
|
std::string pathL = std::regex_replace(path, std::regex("@rpath/"), file_prefix);
|
||||||
|
if (verboseOutput())
|
||||||
|
std::cout << " path to search: " << pathL << std::endl;
|
||||||
|
if (realpath(pathL.c_str(), buffer)) {
|
||||||
|
fullpath = buffer;
|
||||||
|
rpathToFullPath(rpath_file, fullpath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// fullpath previously stored
|
||||||
|
if (rpathFound(rpath_file)) {
|
||||||
|
fullpath = getFullPath(rpath_file);
|
||||||
|
}
|
||||||
|
else if (!check_path(rpath_file)) {
|
||||||
|
auto rpaths_for_file = getRpathsForFile(dependent_file);
|
||||||
|
for (auto rpath : rpaths_for_file) {
|
||||||
|
if (rpath[rpath.size()-1] != '/')
|
||||||
|
rpath += "/";
|
||||||
|
std::string path = rpath + suffix;
|
||||||
|
if (verboseOutput())
|
||||||
|
std::cout << " trying rpath: " << path << std::endl;
|
||||||
|
if (check_path(path))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fullpath.empty()) {
|
||||||
|
std::vector<std::string> search_paths = searchPaths();
|
||||||
|
for (const auto& search_path : search_paths) {
|
||||||
|
if (fileExists(search_path+suffix)) {
|
||||||
|
if (verboseOutput())
|
||||||
|
std::cout << "FOUND " << suffix << " in " << search_path << std::endl;
|
||||||
|
fullpath = search_path + suffix;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fullpath.empty()) {
|
||||||
|
if (verboseOutput())
|
||||||
|
std::cout << " ** rpath fullpath: not found" << std::endl;
|
||||||
|
if (!quietOutput())
|
||||||
|
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'\n";
|
||||||
|
fullpath = getUserInputDirForFile(suffix, dependent_file) + suffix;
|
||||||
|
if (quietOutput() && fullpath.empty())
|
||||||
|
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'\n";
|
||||||
|
if (realpath(fullpath.c_str(), fullpath_buffer))
|
||||||
|
fullpath = fullpath_buffer;
|
||||||
|
}
|
||||||
|
else if (verboseOutput()) {
|
||||||
|
std::cout << " ** rpath fullpath: " << fullpath << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (verboseOutput()) {
|
||||||
|
std::cout << " ** rpath fullpath: " << fullpath << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DylibBundler::searchFilenameInRpaths(const std::string& rpath_file)
|
||||||
|
{
|
||||||
|
return searchFilenameInRpaths(rpath_file, rpath_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DylibBundler::initSearchPaths()
|
||||||
|
{
|
||||||
|
std::string searchPaths;
|
||||||
|
char *dyldLibPath = std::getenv("DYLD_LIBRARY_PATH");
|
||||||
|
if (dyldLibPath != nullptr)
|
||||||
|
searchPaths = dyldLibPath;
|
||||||
|
dyldLibPath = std::getenv("DYLD_FALLBACK_FRAMEWORK_PATH");
|
||||||
|
if (dyldLibPath != nullptr) {
|
||||||
|
if (!searchPaths.empty() && searchPaths[searchPaths.size()-1] != ':')
|
||||||
|
searchPaths += ":";
|
||||||
|
searchPaths += dyldLibPath;
|
||||||
|
}
|
||||||
|
dyldLibPath = std::getenv("DYLD_FALLBACK_LIBRARY_PATH");
|
||||||
|
if (dyldLibPath != nullptr) {
|
||||||
|
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 += "/";
|
||||||
|
addSearchPath(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DylibBundler::createDestDir()
|
||||||
|
{
|
||||||
|
std::string dest_folder = destFolder();
|
||||||
|
if (verboseOutput())
|
||||||
|
std::cout << "Checking output directory " << dest_folder << "\n";
|
||||||
|
|
||||||
|
bool dest_exists = fileExists(dest_folder);
|
||||||
|
|
||||||
|
if (dest_exists && canOverwriteDir()) {
|
||||||
|
std::cout << "Erasing old output directory " << dest_folder << "\n";
|
||||||
|
std::string command = std::string("rm -r ").append(dest_folder);
|
||||||
|
if (systemp(command) != 0) {
|
||||||
|
std::cerr << "\n\n/!\\ ERROR: An error occured while attempting to overwrite destination folder\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
dest_exists = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dest_exists) {
|
||||||
|
if (canCreateDir()) {
|
||||||
|
std::cout << "Creating output directory " << dest_folder << "\n\n";
|
||||||
|
if (!mkdir(dest_folder)) {
|
||||||
|
std::cerr << "\n/!\\ ERROR: An error occured while creating " << dest_folder << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "\n\n/!\\ ERROR: Destination folder does not exist. Create it or pass the '-cd' or '-od' flag\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DylibBundler::changeId(const std::string& binary_file, const std::string& new_id)
|
||||||
|
{
|
||||||
|
std::string command = std::string("install_name_tool -id ").append(new_id).append(" ").append(binary_file);
|
||||||
|
if (systemp(command) != 0) {
|
||||||
|
std::cerr << "\n\nError: An error occured while trying to change identity of library " << binary_file << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DylibBundler::changeInstallName(const std::string& binary_file, const std::string& old_name, const std::string& new_name)
|
||||||
|
{
|
||||||
|
std::string command = std::string("install_name_tool -change ").append(old_name).append(" ");
|
||||||
|
command.append(new_name).append(" ").append(binary_file);
|
||||||
|
if (systemp(command) != 0) {
|
||||||
|
std::cerr << "\n\nError: An error occured while trying to fix dependencies of " << binary_file << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DylibBundler::copyFile(const std::string& from, const std::string& to)
|
||||||
|
{
|
||||||
|
bool overwrite = canOverwriteFiles();
|
||||||
|
if (fileExists(to) && !overwrite) {
|
||||||
|
std::cerr << "\n\nError: File " << to << " already exists. Remove it or enable overwriting (-of)\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy file/directory
|
||||||
|
std::string overwrite_permission = std::string(overwrite ? "-f " : "-n ");
|
||||||
|
std::string command = std::string("cp -R ").append(overwrite_permission);
|
||||||
|
command.append(from).append(" ").append(to);
|
||||||
|
if (from != to && systemp(command) != 0) {
|
||||||
|
std::cerr << "\n\nError: An error occured while trying to copy file " << from << " to " << to << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// give file/directory write permission
|
||||||
|
std::string command2 = std::string("chmod -R +w ").append(to);
|
||||||
|
if (systemp(command2) != 0) {
|
||||||
|
std::cerr << "\n\nError: An error occured while trying to set write permissions on file " << to << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DylibBundler::deleteFile(const std::string& path, bool overwrite)
|
||||||
|
{
|
||||||
|
std::string overwrite_permission = std::string(overwrite ? "-f " : " ");
|
||||||
|
std::string command = std::string("rm -r ").append(overwrite_permission).append(path);
|
||||||
|
if (systemp(command) != 0) {
|
||||||
|
std::cerr << "\n\nError: An error occured while trying to delete " << path << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DylibBundler::deleteFile(const std::string& path)
|
||||||
|
{
|
||||||
|
bool overwrite = canOverwriteFiles();
|
||||||
|
deleteFile(path, overwrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DylibBundler::mkdir(const std::string& path)
|
||||||
|
{
|
||||||
|
if (verboseOutput())
|
||||||
|
std::cout << "Creating directory " << path << std::endl;
|
||||||
|
std::string command = std::string("mkdir -p ").append(path);
|
||||||
|
if (systemp(command) != 0) {
|
||||||
|
std::cerr << "\n/!\\ ERROR: An error occured while creating " << path << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DylibBundler::systemp(const std::string& cmd)
|
||||||
|
{
|
||||||
|
if (!quietOutput())
|
||||||
|
std::cout << " " << cmd << "\n";
|
||||||
|
return system(cmd.c_str());
|
||||||
|
}
|
||||||
|
|
|
@ -3,25 +3,56 @@
|
||||||
#ifndef DYLIBBUNDLER_DYLIBBUNDLER_H
|
#ifndef DYLIBBUNDLER_DYLIBBUNDLER_H
|
||||||
#define DYLIBBUNDLER_DYLIBBUNDLER_H
|
#define DYLIBBUNDLER_DYLIBBUNDLER_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
void addDependency(const std::string& path, const std::string& dependent_file);
|
//#include "Dependency.h"
|
||||||
|
#include "Settings.h"
|
||||||
|
|
||||||
// fill |lines| with dependencies of |dependent_file|
|
class Dependency;
|
||||||
//void collectDependencies(const std::string& dependent_file, std::vector<std::string>& lines);
|
|
||||||
void collectDependencies(const std::string& dependent_file);
|
|
||||||
|
|
||||||
//void collectRpaths(const std::string& filename);
|
class DylibBundler : public Settings {
|
||||||
|
public:
|
||||||
|
DylibBundler();
|
||||||
|
~DylibBundler() override;
|
||||||
|
|
||||||
// recursively collect each dependency's dependencies
|
void addDependency(const std::string &path, const std::string &dependent_file);
|
||||||
void collectSubDependencies();
|
void collectDependencies(const std::string &dependent_file);
|
||||||
|
void collectSubDependencies();
|
||||||
|
void changeLibPathsOnFile(const std::string &file_to_fix);
|
||||||
|
void fixRpathsOnFile(const std::string &original_file, const std::string &file_to_fix);
|
||||||
|
void bundleDependencies();
|
||||||
|
void bundleQtPlugins();
|
||||||
|
|
||||||
void changeLibPathsOnFile(const std::string& file_to_fix);
|
std::string getUserInputDirForFile(const std::string& filename, const std::string& dependent_file);
|
||||||
void fixRpathsOnFile(const std::string& original_file, const std::string& file_to_fix);
|
std::string searchFilenameInRpaths(const std::string& rpath_file, const std::string& dependent_file);
|
||||||
|
std::string searchFilenameInRpaths(const std::string& rpath_file);
|
||||||
|
|
||||||
void bundleDependencies();
|
// check the same paths the system would search for dylibs
|
||||||
|
void initSearchPaths();
|
||||||
|
void createDestDir();
|
||||||
|
|
||||||
void bundleQtPlugins();
|
void changeId(const std::string& binary_file, const std::string& new_id);
|
||||||
|
void changeInstallName(const std::string& binary_file, const std::string& old_name, const std::string& new_name);
|
||||||
|
|
||||||
|
void copyFile(const std::string& from, const std::string& to);
|
||||||
|
void deleteFile(const std::string& path, bool overwrite);
|
||||||
|
void deleteFile(const std::string& path);
|
||||||
|
bool mkdir(const std::string& path);
|
||||||
|
|
||||||
|
// run a command in the system shell (like 'system') but also print the command to stdout
|
||||||
|
int systemp(const std::string& cmd);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Dependency*> deps;
|
||||||
|
std::map<std::string, std::vector<Dependency*>> deps_per_file;
|
||||||
|
std::map<std::string, bool> deps_collected;
|
||||||
|
std::set<std::string> frameworks;
|
||||||
|
std::set<std::string> rpaths;
|
||||||
|
std::map<std::string, bool> rpaths_collected;
|
||||||
|
bool qt_plugins_called;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
112
src/Settings.cpp
112
src/Settings.cpp
|
@ -8,28 +8,27 @@
|
||||||
|
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
namespace Settings {
|
Settings::Settings() : overwrite_files(false),
|
||||||
|
overwrite_dir(false),
|
||||||
|
create_dir(false),
|
||||||
|
quiet_output(false),
|
||||||
|
verbose_output(false),
|
||||||
|
bundle_libs(true),
|
||||||
|
bundle_frameworks(false),
|
||||||
|
missing_prefixes(false),
|
||||||
|
dest_folder_str("./libs/"),
|
||||||
|
dest_folder_str_app("./Frameworks/"),
|
||||||
|
inside_path_str("@executable_path/../libs/"),
|
||||||
|
inside_path_str_app("@executable_path/../Frameworks/")
|
||||||
|
{
|
||||||
|
dest_folder = dest_folder_str;
|
||||||
|
dest_path = dest_folder;
|
||||||
|
inside_path = inside_path_str;
|
||||||
|
}
|
||||||
|
|
||||||
bool overwrite_files = false;
|
Settings::~Settings() = default;
|
||||||
bool overwrite_dir = false;
|
|
||||||
bool create_dir = false;
|
|
||||||
bool quiet_output = false;
|
|
||||||
bool verbose_output = false;
|
|
||||||
bool bundle_libs = true;
|
|
||||||
bool bundle_frameworks = false;
|
|
||||||
|
|
||||||
std::string dest_folder_str = "./libs/";
|
void Settings::appBundle(std::string path)
|
||||||
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 appBundle() { return app_bundle; }
|
|
||||||
void appBundle(std::string path)
|
|
||||||
{
|
{
|
||||||
app_bundle = std::move(path);
|
app_bundle = std::move(path);
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
|
@ -55,10 +54,8 @@ void appBundle(std::string path)
|
||||||
if (dest_path[dest_path.size()-1] != '/')
|
if (dest_path[dest_path.size()-1] != '/')
|
||||||
dest_path += "/";
|
dest_path += "/";
|
||||||
}
|
}
|
||||||
bool appBundleProvided() { return !app_bundle.empty(); }
|
|
||||||
|
|
||||||
std::string destFolder() { return dest_path; }
|
void Settings::destFolder(std::string path)
|
||||||
void destFolder(std::string path)
|
|
||||||
{
|
{
|
||||||
dest_path = std::move(path);
|
dest_path = std::move(path);
|
||||||
if (appBundleProvided())
|
if (appBundleProvided())
|
||||||
|
@ -70,21 +67,15 @@ void destFolder(std::string path)
|
||||||
dest_path += "/";
|
dest_path += "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string insideLibPath() { return inside_path; }
|
|
||||||
void insideLibPath(std::string p)
|
void Settings::insideLibPath(std::string p)
|
||||||
{
|
{
|
||||||
inside_path = std::move(p);
|
inside_path = std::move(p);
|
||||||
if (inside_path[inside_path.size()-1] != '/')
|
if (inside_path[inside_path.size()-1] != '/')
|
||||||
inside_path += "/";
|
inside_path += "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string executableFolder() { return app_bundle + "Contents/MacOS/"; }
|
void Settings::addFileToFix(std::string path)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
if (realpath(path.c_str(), buffer))
|
if (realpath(path.c_str(), buffer))
|
||||||
|
@ -92,17 +83,14 @@ void addFileToFix(std::string path)
|
||||||
files.push_back(path);
|
files.push_back(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> filesToFix() { return files; }
|
void Settings::ignorePrefix(std::string prefix)
|
||||||
size_t filesToFixCount() { return files.size(); }
|
|
||||||
|
|
||||||
std::vector<std::string> prefixes_to_ignore;
|
|
||||||
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(const std::string& prefix)
|
|
||||||
|
bool Settings::isPrefixIgnored(const std::string& prefix)
|
||||||
{
|
{
|
||||||
for (const auto& prefix_to_ignore : prefixes_to_ignore) {
|
for (const auto& prefix_to_ignore : prefixes_to_ignore) {
|
||||||
if (prefix == prefix_to_ignore)
|
if (prefix == prefix_to_ignore)
|
||||||
|
@ -111,7 +99,7 @@ bool isPrefixIgnored(const std::string& prefix)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPrefixBundled(const std::string& prefix)
|
bool Settings::isPrefixBundled(const std::string& prefix)
|
||||||
{
|
{
|
||||||
if (!bundle_frameworks && prefix.find(".framework") != std::string::npos)
|
if (!bundle_frameworks && prefix.find(".framework") != std::string::npos)
|
||||||
return false;
|
return false;
|
||||||
|
@ -125,49 +113,3 @@ bool isPrefixBundled(const std::string& prefix)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> search_paths;
|
|
||||||
std::vector<std::string> searchPaths() { return search_paths; }
|
|
||||||
void addSearchPath(const std::string& path) { search_paths.push_back(path); }
|
|
||||||
|
|
||||||
std::vector<std::string> user_search_paths;
|
|
||||||
std::vector<std::string> userSearchPaths() { return user_search_paths; }
|
|
||||||
void addUserSearchPath(const std::string& path) { user_search_paths.push_back(path); }
|
|
||||||
|
|
||||||
bool canCreateDir() { return create_dir; }
|
|
||||||
void canCreateDir(bool permission) { create_dir = permission; }
|
|
||||||
|
|
||||||
bool canOverwriteDir() { return overwrite_dir; }
|
|
||||||
void canOverwriteDir(bool permission) { overwrite_dir = permission; }
|
|
||||||
|
|
||||||
bool canOverwriteFiles() { return overwrite_files; }
|
|
||||||
void canOverwriteFiles(bool permission) { overwrite_files = permission; }
|
|
||||||
|
|
||||||
bool bundleLibs() { return bundle_libs; }
|
|
||||||
void bundleLibs(bool status) { bundle_libs = status; }
|
|
||||||
|
|
||||||
bool bundleFrameworks() { return bundle_frameworks; }
|
|
||||||
void bundleFrameworks(bool status) { bundle_frameworks = status; }
|
|
||||||
|
|
||||||
bool quietOutput() { return quiet_output; }
|
|
||||||
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; }
|
|
||||||
|
|
||||||
std::map<std::string, std::string> rpath_to_fullpath;
|
|
||||||
std::string getFullPath(const std::string& rpath) { return rpath_to_fullpath[rpath]; }
|
|
||||||
void rpathToFullPath(const std::string& rpath, const std::string& fullpath) { rpath_to_fullpath[rpath] = fullpath; }
|
|
||||||
bool rpathFound(const std::string& rpath) { return rpath_to_fullpath.find(rpath) != rpath_to_fullpath.end(); }
|
|
||||||
|
|
||||||
std::map<std::string, std::vector<std::string>> rpaths_per_file;
|
|
||||||
std::vector<std::string> getRpathsForFile(const std::string& file) { return rpaths_per_file[file]; }
|
|
||||||
void addRpathForFile(const std::string& file, const std::string& rpath) { rpaths_per_file[file].push_back(rpath); }
|
|
||||||
bool fileHasRpath(const std::string& file) { return rpaths_per_file.find(file) != rpaths_per_file.end(); }
|
|
||||||
|
|
||||||
} // namespace Settings
|
|
||||||
|
|
123
src/Settings.h
123
src/Settings.h
|
@ -3,6 +3,11 @@
|
||||||
#ifndef DYLIBBUNDLER_SETTINGS_H
|
#ifndef DYLIBBUNDLER_SETTINGS_H
|
||||||
#define DYLIBBUNDLER_SETTINGS_H
|
#define DYLIBBUNDLER_SETTINGS_H
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -10,69 +15,97 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Settings {
|
class Settings {
|
||||||
|
public:
|
||||||
|
Settings();
|
||||||
|
virtual ~Settings();
|
||||||
|
|
||||||
bool isPrefixBundled(const std::string& prefix);
|
virtual bool isPrefixBundled(const std::string &prefix);
|
||||||
bool isPrefixIgnored(const std::string& prefix);
|
virtual bool isPrefixIgnored(const std::string &prefix);
|
||||||
void ignorePrefix(std::string prefix);
|
virtual void ignorePrefix(std::string prefix);
|
||||||
|
virtual std::string appBundle() { return app_bundle; }
|
||||||
|
virtual void appBundle(std::string path);
|
||||||
|
virtual bool appBundleProvided() { return !app_bundle.empty(); }
|
||||||
|
|
||||||
std::string appBundle();
|
virtual std::string destFolder() { return dest_path; }
|
||||||
void appBundle(std::string path);
|
virtual void destFolder(std::string path);
|
||||||
bool appBundleProvided();
|
virtual std::string insideLibPath() { return inside_path; }
|
||||||
|
virtual void insideLibPath(std::string p);
|
||||||
|
|
||||||
std::string destFolder();
|
virtual std::string executableFolder() { return app_bundle + "Contents/MacOS/"; }
|
||||||
void destFolder(std::string path);
|
virtual std::string frameworksFolder() { return app_bundle + "Contents/Frameworks/"; }
|
||||||
|
virtual std::string pluginsFolder() { return app_bundle + "Contents/PlugIns/"; }
|
||||||
|
virtual std::string resourcesFolder() { return app_bundle + "Contents/Resources/"; }
|
||||||
|
|
||||||
std::string insideLibPath();
|
virtual std::vector<std::string> filesToFix() { return files; }
|
||||||
void insideLibPath(std::string p);
|
virtual void addFileToFix(std::string path);
|
||||||
|
virtual size_t filesToFixCount() { return files.size(); }
|
||||||
|
|
||||||
std::string executableFolder();
|
virtual std::vector<std::string> searchPaths() { return search_paths; }
|
||||||
std::string frameworksFolder();
|
virtual void addSearchPath(const std::string& path) { search_paths.push_back(path); }
|
||||||
std::string pluginsFolder();
|
|
||||||
std::string resourcesFolder();
|
|
||||||
|
|
||||||
std::vector<std::string> filesToFix();
|
virtual std::vector<std::string> userSearchPaths() { return user_search_paths; }
|
||||||
void addFileToFix(std::string path);
|
virtual void addUserSearchPath(const std::string& path) { user_search_paths.push_back(path); }
|
||||||
size_t filesToFixCount();
|
|
||||||
|
|
||||||
std::vector<std::string> searchPaths();
|
virtual bool canCreateDir() { return create_dir; }
|
||||||
void addSearchPath(const std::string& path);
|
virtual void canCreateDir(bool permission) { create_dir = permission; }
|
||||||
|
|
||||||
std::vector<std::string> userSearchPaths();
|
virtual bool canOverwriteDir() { return overwrite_dir; }
|
||||||
void addUserSearchPath(const std::string& path);
|
virtual void canOverwriteDir(bool permission) { overwrite_dir = permission; }
|
||||||
|
|
||||||
bool canCreateDir();
|
virtual bool canOverwriteFiles() { return overwrite_files; }
|
||||||
void canCreateDir(bool permission);
|
virtual void canOverwriteFiles(bool permission) { overwrite_files = permission; }
|
||||||
|
|
||||||
bool canOverwriteDir();
|
virtual bool bundleLibs() { return bundle_libs; }
|
||||||
void canOverwriteDir(bool permission);
|
virtual void bundleLibs(bool status) { bundle_libs = status; }
|
||||||
|
|
||||||
bool canOverwriteFiles();
|
virtual bool bundleFrameworks() { return bundle_frameworks; }
|
||||||
void canOverwriteFiles(bool permission);
|
virtual void bundleFrameworks(bool status) { bundle_frameworks = status; }
|
||||||
|
|
||||||
bool bundleLibs();
|
virtual bool quietOutput() { return quiet_output; }
|
||||||
void bundleLibs(bool status);
|
virtual void quietOutput(bool status) { quiet_output = status; }
|
||||||
|
|
||||||
bool bundleFrameworks();
|
virtual bool verboseOutput() { return verbose_output; }
|
||||||
void bundleFrameworks(bool status);
|
virtual void verboseOutput(bool status) { verbose_output = status; }
|
||||||
|
|
||||||
bool quietOutput();
|
virtual bool missingPrefixes() { return missing_prefixes; }
|
||||||
void quietOutput(bool status);
|
virtual void missingPrefixes(bool status) { missing_prefixes = status; }
|
||||||
|
|
||||||
bool verboseOutput();
|
virtual std::string getFullPath(const std::string& rpath) { return rpath_to_fullpath[rpath]; }
|
||||||
void verboseOutput(bool status);
|
virtual void rpathToFullPath(const std::string& rpath, const std::string& fullpath) { rpath_to_fullpath[rpath] = fullpath; }
|
||||||
|
virtual bool rpathFound(const std::string& rpath) { return rpath_to_fullpath.find(rpath) != rpath_to_fullpath.end(); }
|
||||||
|
|
||||||
bool missingPrefixes();
|
virtual std::vector<std::string> getRpathsForFile(const std::string& file) { return rpaths_per_file[file]; }
|
||||||
void missingPrefixes(bool status);
|
virtual void addRpathForFile(const std::string& file, const std::string& rpath) { rpaths_per_file[file].push_back(rpath); }
|
||||||
|
virtual bool fileHasRpath(const std::string& file) { return rpaths_per_file.find(file) != rpaths_per_file.end(); }
|
||||||
|
|
||||||
std::string getFullPath(const std::string& rpath);
|
protected:
|
||||||
void rpathToFullPath(const std::string& rpath, const std::string& fullpath);
|
bool overwrite_files;
|
||||||
bool rpathFound(const std::string& rpath);
|
bool overwrite_dir;
|
||||||
|
bool create_dir;
|
||||||
|
bool quiet_output;
|
||||||
|
bool verbose_output;
|
||||||
|
bool bundle_libs;
|
||||||
|
bool bundle_frameworks;
|
||||||
|
bool missing_prefixes;
|
||||||
|
|
||||||
std::vector<std::string> getRpathsForFile(const std::string& file);
|
std::string dest_folder_str;
|
||||||
void addRpathForFile(const std::string& file, const std::string& rpath);
|
std::string dest_folder_str_app;
|
||||||
bool fileHasRpath(const std::string& file);
|
std::string dest_folder;
|
||||||
|
std::string dest_path;
|
||||||
|
|
||||||
} // namespace Settings
|
std::string inside_path_str;
|
||||||
|
std::string inside_path_str_app;
|
||||||
|
std::string inside_path;
|
||||||
|
|
||||||
|
std::string app_bundle;
|
||||||
|
std::vector<std::string> prefixes_to_ignore;
|
||||||
|
std::vector<std::string> search_paths;
|
||||||
|
std::vector<std::string> files;
|
||||||
|
|
||||||
|
std::vector<std::string> user_search_paths;
|
||||||
|
std::map<std::string, std::string> rpath_to_fullpath;
|
||||||
|
std::map<std::string, std::vector<std::string>> rpaths_per_file;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
425
src/Utils.cpp
425
src/Utils.cpp
|
@ -7,9 +7,7 @@
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
// #include <stdio.h>
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
// #include <sys/stat.h>
|
|
||||||
#ifndef __clang__
|
#ifndef __clang__
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,6 +25,13 @@ std::string stripPrefix(const std::string& in)
|
||||||
return in.substr(in.rfind('/')+1);
|
return in.substr(in.rfind('/')+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string stripLSlash(const std::string& in)
|
||||||
|
{
|
||||||
|
if (in[0] == '.' && in[1] == '/')
|
||||||
|
return in.substr(2, in.size());
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
std::string getFrameworkRoot(const std::string& in)
|
std::string getFrameworkRoot(const std::string& in)
|
||||||
{
|
{
|
||||||
return in.substr(0, in.find(".framework")+10);
|
return in.substr(0, in.find(".framework")+10);
|
||||||
|
@ -37,13 +42,6 @@ std::string getFrameworkPath(const std::string& in)
|
||||||
return in.substr(in.rfind(".framework/")+11);
|
return in.substr(in.rfind(".framework/")+11);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string stripLSlash(const std::string& in)
|
|
||||||
{
|
|
||||||
if (in[0] == '.' && in[1] == '/')
|
|
||||||
return in.substr(2, in.size());
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rtrim_in_place(std::string& s)
|
void rtrim_in_place(std::string& s)
|
||||||
{
|
{
|
||||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char c) {
|
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char c) {
|
||||||
|
@ -57,6 +55,59 @@ std::string rtrim(std::string s)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tokenize(const std::string& str, const char* delim, std::vector<std::string>* tokens)
|
||||||
|
{
|
||||||
|
std::vector<std::string>& out = *tokens;
|
||||||
|
std::string delimiters(delim);
|
||||||
|
|
||||||
|
// skip delimiters at beginning
|
||||||
|
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
||||||
|
// find first non-delimiter
|
||||||
|
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
|
||||||
|
|
||||||
|
while (pos != std::string::npos || lastPos != std::string::npos) {
|
||||||
|
// found a token, add it to the vector
|
||||||
|
out.push_back(str.substr(lastPos, pos - lastPos));
|
||||||
|
// skip delimiters
|
||||||
|
lastPos = str.find_first_not_of(delimiters, pos);
|
||||||
|
// find next non-delimiter
|
||||||
|
pos = str.find_first_of(delimiters, lastPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> lsDir(const std::string& path)
|
||||||
|
{
|
||||||
|
std::string cmd = "ls " + path;
|
||||||
|
std::string output = systemOutput(cmd);
|
||||||
|
std::vector<std::string> files;
|
||||||
|
tokenize(output, "\n", &files);
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fileExists(const std::string& filename)
|
||||||
|
{
|
||||||
|
if (access(filename.c_str(), F_OK) != -1)
|
||||||
|
return true;
|
||||||
|
const std::string delims = " \f\n\r\t\v";
|
||||||
|
std::string rtrimmed = filename.substr(0, filename.find_last_not_of(delims)+1);
|
||||||
|
std::string ftrimmed = rtrimmed.substr(rtrimmed.find_first_not_of(delims));
|
||||||
|
if (access(ftrimmed.c_str(), F_OK) != -1)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isRpath(const std::string& path)
|
||||||
|
{
|
||||||
|
return path.find("@rpath") != std::string::npos || path.find("@loader_path") != std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string bundleExecutableName(const std::string& app_bundle_path)
|
||||||
|
{
|
||||||
|
std::string cmd = std::string("/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' ");
|
||||||
|
cmd.append(app_bundle_path).append("Contents/Info.plist");
|
||||||
|
return rtrim(systemOutput(cmd));
|
||||||
|
}
|
||||||
|
|
||||||
std::string systemOutput(const std::string& cmd)
|
std::string systemOutput(const std::string& cmd)
|
||||||
{
|
{
|
||||||
FILE *command_output = nullptr;
|
FILE *command_output = nullptr;
|
||||||
|
@ -93,215 +144,9 @@ std::string systemOutput(const std::string& cmd)
|
||||||
return full_output;
|
return full_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
int systemp(const std::string& cmd)
|
|
||||||
{
|
|
||||||
if (!Settings::quietOutput())
|
|
||||||
std::cout << " " << cmd << "\n";
|
|
||||||
return system(cmd.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void tokenize(const std::string& str, const char* delim, std::vector<std::string>* vectorarg)
|
|
||||||
{
|
|
||||||
std::vector<std::string>& tokens = *vectorarg;
|
|
||||||
std::string delimiters(delim);
|
|
||||||
|
|
||||||
// skip delimiters at beginning
|
|
||||||
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
|
||||||
// find first non-delimiter
|
|
||||||
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
|
|
||||||
|
|
||||||
while (pos != std::string::npos || lastPos != std::string::npos) {
|
|
||||||
// found a token, add it to the vector
|
|
||||||
tokens.push_back(str.substr(lastPos, pos - lastPos));
|
|
||||||
// skip delimiters
|
|
||||||
lastPos = str.find_first_not_of(delimiters, pos);
|
|
||||||
// find next non-delimiter
|
|
||||||
pos = str.find_first_of(delimiters, lastPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> lsDir(const std::string& path)
|
|
||||||
{
|
|
||||||
std::string cmd = "ls " + path;
|
|
||||||
std::string output = systemOutput(cmd);
|
|
||||||
std::vector<std::string> files;
|
|
||||||
tokenize(output, "\n", &files);
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fileExists(const std::string& filename)
|
|
||||||
{
|
|
||||||
if (access(filename.c_str(), F_OK) != -1)
|
|
||||||
return true;
|
|
||||||
std::string delims = " \f\n\r\t\v";
|
|
||||||
std::string rtrimmed = filename.substr(0, filename.find_last_not_of(delims)+1);
|
|
||||||
std::string ftrimmed = rtrimmed.substr(rtrimmed.find_first_not_of(delims));
|
|
||||||
if (access(ftrimmed.c_str(), F_OK) != -1)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isRpath(const std::string& path)
|
|
||||||
{
|
|
||||||
return path.find("@rpath") != std::string::npos || path.find("@loader_path") != std::string::npos;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string bundleExecutableName(const std::string& app_bundle_path)
|
|
||||||
{
|
|
||||||
std::string cmd = "/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' " + app_bundle_path + "Contents/Info.plist";
|
|
||||||
return rtrim(systemOutput(cmd));
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeId(const std::string& binary_file, const std::string& new_id)
|
|
||||||
{
|
|
||||||
std::string command = std::string("install_name_tool -id ") + new_id + " " + binary_file;
|
|
||||||
if (systemp(command) != 0) {
|
|
||||||
std::cerr << "\n\nError: An error occured while trying to change identity of library " << binary_file << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeInstallName(const std::string& binary_file, const std::string& old_name, const std::string& new_name)
|
|
||||||
{
|
|
||||||
std::string command = std::string("install_name_tool -change ") + old_name + " " + new_name + " " + binary_file;
|
|
||||||
if (systemp(command) != 0) {
|
|
||||||
std::cerr << "\n\nError: An error occured while trying to fix dependencies of " << binary_file << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyFile(const std::string& from, const std::string& to)
|
|
||||||
{
|
|
||||||
bool overwrite = Settings::canOverwriteFiles();
|
|
||||||
if (fileExists(to) && !overwrite) {
|
|
||||||
std::cerr << "\n\nError: File " << to << " already exists. Remove it or enable overwriting (-of)\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy file/directory
|
|
||||||
std::string overwrite_permission = std::string(overwrite ? "-f " : "-n ");
|
|
||||||
std::string command = std::string("cp -R ") + overwrite_permission + from + std::string(" ") + to;
|
|
||||||
if (from != to && systemp(command) != 0) {
|
|
||||||
std::cerr << "\n\nError: An error occured while trying to copy file " << from << " to " << to << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// give file/directory write permission
|
|
||||||
std::string command2 = std::string("chmod -R +w ") + to;
|
|
||||||
if (systemp(command2) != 0) {
|
|
||||||
std::cerr << "\n\nError: An error occured while trying to set write permissions on file " << to << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void deleteFile(const std::string& path, bool overwrite)
|
|
||||||
{
|
|
||||||
std::string overwrite_permission = std::string(overwrite ? "-f " : " ");
|
|
||||||
std::string command = std::string("rm -r ") + overwrite_permission + path;
|
|
||||||
if (systemp(command) != 0) {
|
|
||||||
std::cerr << "\n\nError: An error occured while trying to delete " << path << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void deleteFile(const std::string& path)
|
|
||||||
{
|
|
||||||
bool overwrite = Settings::canOverwriteFiles();
|
|
||||||
deleteFile(path, overwrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mkdir(const std::string& path)
|
|
||||||
{
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << "Creating directory " << path << std::endl;
|
|
||||||
std::string command = std::string("mkdir -p ") + path;
|
|
||||||
if (systemp(command) != 0) {
|
|
||||||
std::cerr << "\n/!\\ ERROR: An error occured while creating " << path << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void createDestDir()
|
|
||||||
{
|
|
||||||
std::string dest_folder = Settings::destFolder();
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << "Checking output directory " << dest_folder << "\n";
|
|
||||||
|
|
||||||
bool dest_exists = fileExists(dest_folder);
|
|
||||||
|
|
||||||
if (dest_exists && Settings::canOverwriteDir()) {
|
|
||||||
std::cout << "Erasing old output directory " << dest_folder << "\n";
|
|
||||||
std::string command = std::string("rm -r ") + dest_folder;
|
|
||||||
if (systemp(command) != 0) {
|
|
||||||
std::cerr << "\n\n/!\\ ERROR: An error occured while attempting to overwrite destination folder\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
dest_exists = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dest_exists) {
|
|
||||||
if (Settings::canCreateDir()) {
|
|
||||||
std::cout << "Creating output directory " << dest_folder << "\n\n";
|
|
||||||
if (!mkdir(dest_folder)) {
|
|
||||||
std::cerr << "\n/!\\ ERROR: An error occured while creating " << dest_folder << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "\n\n/!\\ ERROR: Destination folder does not exist. Create it or pass the '-cd' or '-od' flag\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getUserInputDirForFile(const std::string& filename, const std::string& dependent_file)
|
|
||||||
{
|
|
||||||
std::vector<std::string> search_paths = Settings::userSearchPaths();
|
|
||||||
for (auto& search_path : search_paths) {
|
|
||||||
if (!search_path.empty() && search_path[search_path.size() - 1] != '/')
|
|
||||||
search_path += "/";
|
|
||||||
if (fileExists(search_path + filename)) {
|
|
||||||
if (!Settings::quietOutput()) {
|
|
||||||
std::cerr << (search_path + filename) << " was found\n"
|
|
||||||
<< "/!\\ WARNING: dylibbundler MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Check the executable with 'otool -L'\n";
|
|
||||||
}
|
|
||||||
return search_path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (Settings::quietOutput())
|
|
||||||
std::cerr << "\n/!\\ WARNING: Dependency " << filename << " of " << dependent_file << " not found\n";
|
|
||||||
std::cout << "\nPlease specify the directory where this file is located (or enter 'quit' to abort): ";
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
std::string prefix;
|
|
||||||
std::cin >> prefix;
|
|
||||||
std::cout << std::endl;
|
|
||||||
|
|
||||||
if (prefix == "quit" || prefix == "exit" || prefix == "abort")
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
if (!prefix.empty() && prefix[prefix.size()-1] != '/')
|
|
||||||
prefix += "/";
|
|
||||||
|
|
||||||
if (!fileExists(prefix+filename)) {
|
|
||||||
std::cerr << (prefix+filename) << " does not exist. Try again...\n";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << (prefix+filename) << " was found\n"
|
|
||||||
<< "/!\\ WARNING: dylibbundler MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Check the executable with 'otool -L'\n";
|
|
||||||
Settings::addUserSearchPath(prefix);
|
|
||||||
return prefix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void otool(const std::string& flags, const std::string& file, std::vector<std::string>& lines)
|
void otool(const std::string& flags, const std::string& file, std::vector<std::string>& lines)
|
||||||
{
|
{
|
||||||
std::string command = "otool " + flags + " " + file;
|
std::string command = std::string("otool ").append(flags).append(" ").append(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
|
||||||
|
@ -321,8 +166,8 @@ void parseLoadCommands(const std::string& file, const std::string& cmd, const st
|
||||||
otool("-l", file, 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 ").append(cmd);
|
||||||
std::string value_line = std::string(value + std::string(" "));
|
std::string value_line = std::string(value).append(" ");
|
||||||
for (const auto& raw_line : raw_lines) {
|
for (const auto& raw_line : raw_lines) {
|
||||||
if (raw_line.find(cmd_line) != std::string::npos) {
|
if (raw_line.find(cmd_line) != std::string::npos) {
|
||||||
if (searching) {
|
if (searching) {
|
||||||
|
@ -358,8 +203,8 @@ void parseLoadCommands(const std::string& file, const std::map<std::string,std::
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
std::string cmd = cmd_value.first;
|
std::string cmd = cmd_value.first;
|
||||||
std::string value = cmd_value.second;
|
std::string value = cmd_value.second;
|
||||||
std::string cmd_line = std::string("cmd ") + cmd;
|
std::string cmd_line = std::string("cmd ").append(cmd);
|
||||||
std::string value_line = std::string(value) + std::string(" ");
|
std::string value_line = std::string(value).append(" ");
|
||||||
bool searching = false;
|
bool searching = false;
|
||||||
for (const auto& raw_line : raw_lines) {
|
for (const auto& raw_line : raw_lines) {
|
||||||
if (raw_line.find(cmd_line) != std::string::npos) {
|
if (raw_line.find(cmd_line) != std::string::npos) {
|
||||||
|
@ -388,146 +233,6 @@ void parseLoadCommands(const std::string& file, const std::map<std::string,std::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string searchFilenameInRpaths(const std::string& rpath_file, const std::string& dependent_file)
|
|
||||||
{
|
|
||||||
if (Settings::verboseOutput()) {
|
|
||||||
if (dependent_file != rpath_file)
|
|
||||||
std::cout << " dependent file: " << dependent_file << std::endl;
|
|
||||||
std::cout << " dependency: " << rpath_file << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string fullpath;
|
|
||||||
std::string suffix = rpath_file.substr(rpath_file.rfind('/')+1);
|
|
||||||
char fullpath_buffer[PATH_MAX];
|
|
||||||
|
|
||||||
const auto check_path = [&](std::string path) {
|
|
||||||
char buffer[PATH_MAX];
|
|
||||||
std::string file_prefix = filePrefix(dependent_file);
|
|
||||||
if (path.find("@executable_path") != std::string::npos || path.find("@loader_path") != std::string::npos) {
|
|
||||||
if (path.find("@executable_path") != std::string::npos) {
|
|
||||||
if (Settings::appBundleProvided())
|
|
||||||
path = std::regex_replace(path, std::regex("@executable_path/"), Settings::executableFolder());
|
|
||||||
}
|
|
||||||
if (dependent_file != rpath_file) {
|
|
||||||
if (path.find("@loader_path") != std::string::npos)
|
|
||||||
path = std::regex_replace(path, std::regex("@loader_path/"), file_prefix);
|
|
||||||
}
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << " path to search: " << path << std::endl;
|
|
||||||
if (realpath(path.c_str(), buffer)) {
|
|
||||||
fullpath = buffer;
|
|
||||||
Settings::rpathToFullPath(rpath_file, fullpath);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (path.find("@rpath") != std::string::npos) {
|
|
||||||
if (Settings::appBundleProvided()) {
|
|
||||||
std::string pathE = std::regex_replace(path, std::regex("@rpath/"), Settings::executableFolder());
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << " path to search: " << pathE << std::endl;
|
|
||||||
if (realpath(pathE.c_str(), buffer)) {
|
|
||||||
fullpath = buffer;
|
|
||||||
Settings::rpathToFullPath(rpath_file, fullpath);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dependent_file != rpath_file) {
|
|
||||||
std::string pathL = std::regex_replace(path, std::regex("@rpath/"), file_prefix);
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << " path to search: " << pathL << std::endl;
|
|
||||||
if (realpath(pathL.c_str(), buffer)) {
|
|
||||||
fullpath = buffer;
|
|
||||||
Settings::rpathToFullPath(rpath_file, fullpath);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// fullpath previously stored
|
|
||||||
if (Settings::rpathFound(rpath_file)) {
|
|
||||||
fullpath = Settings::getFullPath(rpath_file);
|
|
||||||
}
|
|
||||||
else if (!check_path(rpath_file)) {
|
|
||||||
auto rpaths_for_file = Settings::getRpathsForFile(dependent_file);
|
|
||||||
for (auto rpath : rpaths_for_file) {
|
|
||||||
if (rpath[rpath.size()-1] != '/')
|
|
||||||
rpath += "/";
|
|
||||||
std::string path = rpath + suffix;
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << " trying rpath: " << path << std::endl;
|
|
||||||
if (check_path(path))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fullpath.empty()) {
|
|
||||||
std::vector<std::string> search_paths = Settings::searchPaths();
|
|
||||||
for (const auto& search_path : search_paths) {
|
|
||||||
if (fileExists(search_path+suffix)) {
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << "FOUND " << suffix << " in " << search_path << std::endl;
|
|
||||||
fullpath = search_path + suffix;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fullpath.empty()) {
|
|
||||||
if (Settings::verboseOutput())
|
|
||||||
std::cout << " ** rpath fullpath: not found" << std::endl;
|
|
||||||
if (!Settings::quietOutput())
|
|
||||||
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'\n";
|
|
||||||
fullpath = getUserInputDirForFile(suffix, dependent_file) + suffix;
|
|
||||||
if (Settings::quietOutput() && fullpath.empty())
|
|
||||||
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'\n";
|
|
||||||
if (realpath(fullpath.c_str(), fullpath_buffer))
|
|
||||||
fullpath = fullpath_buffer;
|
|
||||||
}
|
|
||||||
else if (Settings::verboseOutput()) {
|
|
||||||
std::cout << " ** rpath fullpath: " << fullpath << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Settings::verboseOutput()) {
|
|
||||||
std::cout << " ** rpath fullpath: " << fullpath << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fullpath;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string searchFilenameInRpaths(const std::string& rpath_file)
|
|
||||||
{
|
|
||||||
return searchFilenameInRpaths(rpath_file, rpath_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
void initSearchPaths()
|
|
||||||
{
|
|
||||||
std::string searchPaths;
|
|
||||||
char *dyldLibPath = std::getenv("DYLD_LIBRARY_PATH");
|
|
||||||
if (dyldLibPath != nullptr)
|
|
||||||
searchPaths = dyldLibPath;
|
|
||||||
dyldLibPath = std::getenv("DYLD_FALLBACK_FRAMEWORK_PATH");
|
|
||||||
if (dyldLibPath != nullptr) {
|
|
||||||
if (!searchPaths.empty() && searchPaths[searchPaths.size()-1] != ':')
|
|
||||||
searchPaths += ":";
|
|
||||||
searchPaths += dyldLibPath;
|
|
||||||
}
|
|
||||||
dyldLibPath = std::getenv("DYLD_FALLBACK_LIBRARY_PATH");
|
|
||||||
if (dyldLibPath != nullptr) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void createQtConf(std::string directory)
|
void createQtConf(std::string directory)
|
||||||
{
|
{
|
||||||
std::string contents = "[Paths]\n"
|
std::string contents = "[Paths]\n"
|
||||||
|
|
32
src/Utils.h
32
src/Utils.h
|
@ -6,55 +6,33 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "DylibBundler.h"
|
||||||
|
|
||||||
std::string filePrefix(const std::string& in);
|
std::string filePrefix(const std::string& in);
|
||||||
std::string stripPrefix(const std::string& in);
|
std::string stripPrefix(const std::string& in);
|
||||||
|
std::string stripLSlash(const std::string& in);
|
||||||
|
|
||||||
std::string getFrameworkRoot(const std::string& in);
|
std::string getFrameworkRoot(const std::string& in);
|
||||||
std::string getFrameworkPath(const std::string& in);
|
std::string getFrameworkPath(const std::string& in);
|
||||||
|
|
||||||
std::string stripLSlash(const std::string& in);
|
|
||||||
|
|
||||||
// trim from end (in place)
|
// trim from end (in place)
|
||||||
void rtrim_in_place(std::string& s);
|
void rtrim_in_place(std::string& s);
|
||||||
// trim from end (copying)
|
// trim from end (copying)
|
||||||
std::string rtrim(std::string s);
|
std::string rtrim(std::string s);
|
||||||
|
void tokenize(const std::string& str, const char* delimiters, std::vector<std::string>* tokens);
|
||||||
// execute a command in the native shell and return output in string
|
|
||||||
std::string systemOutput(const std::string& cmd);
|
|
||||||
// run a command in the system shell (like 'system') but also print the command to stdout
|
|
||||||
int systemp(const std::string& cmd);
|
|
||||||
|
|
||||||
void tokenize(const std::string& str, const char* delimiters, std::vector<std::string>*);
|
|
||||||
|
|
||||||
std::vector<std::string> lsDir(const std::string& path);
|
std::vector<std::string> lsDir(const std::string& path);
|
||||||
bool fileExists(const std::string& filename);
|
bool fileExists(const std::string& filename);
|
||||||
bool isRpath(const std::string& path);
|
bool isRpath(const std::string& path);
|
||||||
|
|
||||||
std::string bundleExecutableName(const std::string& app_bundle_path);
|
std::string bundleExecutableName(const std::string& app_bundle_path);
|
||||||
|
|
||||||
void changeId(const std::string& binary_file, const std::string& new_id);
|
// execute a command in the native shell and return output in string
|
||||||
void changeInstallName(const std::string& binary_file, const std::string& old_name, const std::string& new_name);
|
std::string systemOutput(const std::string& cmd);
|
||||||
|
|
||||||
void copyFile(const std::string& from, const std::string& to);
|
|
||||||
void deleteFile(const std::string& path, bool overwrite);
|
|
||||||
void deleteFile(const std::string& path);
|
|
||||||
bool mkdir(const std::string& path);
|
|
||||||
|
|
||||||
void createDestDir();
|
|
||||||
|
|
||||||
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 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);
|
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);
|
|
||||||
|
|
||||||
// check the same paths the system would search for dylibs
|
|
||||||
void initSearchPaths();
|
|
||||||
|
|
||||||
void createQtConf(std::string directory);
|
void createQtConf(std::string directory);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
41
src/main.cpp
41
src/main.cpp
|
@ -1,4 +1,3 @@
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -9,7 +8,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "DylibBundler.h"
|
#include "DylibBundler.h"
|
||||||
#include "Settings.h"
|
|
||||||
|
|
||||||
const std::string VERSION = "2.1.0 (2020-01-04)";
|
const std::string VERSION = "2.1.0 (2020-01-04)";
|
||||||
|
|
||||||
|
@ -36,65 +34,66 @@ void showHelp()
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int main(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
|
DylibBundler* db = new DylibBundler();
|
||||||
// parse arguments
|
// parse arguments
|
||||||
for (int i=0; i<argc; i++) {
|
for (int i=0; i<argc; i++) {
|
||||||
if (strcmp(argv[i],"-a") == 0 || strcmp(argv[i],"--app") == 0) {
|
if (strcmp(argv[i],"-a") == 0 || strcmp(argv[i],"--app") == 0) {
|
||||||
i++;
|
i++;
|
||||||
Settings::appBundle(argv[i]);
|
db->appBundle(argv[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-x") == 0 || strcmp(argv[i],"--fix-file") == 0) {
|
else if (strcmp(argv[i],"-x") == 0 || strcmp(argv[i],"--fix-file") == 0) {
|
||||||
i++;
|
i++;
|
||||||
Settings::addFileToFix(argv[i]);
|
db->addFileToFix(argv[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-f") == 0 || strcmp(argv[i],"--bundle-frameworks") == 0) {
|
else if (strcmp(argv[i],"-f") == 0 || strcmp(argv[i],"--bundle-frameworks") == 0) {
|
||||||
Settings::bundleFrameworks(true);
|
db->bundleFrameworks(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-d") == 0 || strcmp(argv[i],"--dest-dir") == 0) {
|
else if (strcmp(argv[i],"-d") == 0 || strcmp(argv[i],"--dest-dir") == 0) {
|
||||||
i++;
|
i++;
|
||||||
Settings::destFolder(argv[i]);
|
db->destFolder(argv[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-p") == 0 || strcmp(argv[i],"--install-path") == 0) {
|
else if (strcmp(argv[i],"-p") == 0 || strcmp(argv[i],"--install-path") == 0) {
|
||||||
i++;
|
i++;
|
||||||
Settings::insideLibPath(argv[i]);
|
db->insideLibPath(argv[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--search-path") == 0) {
|
else if (strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--search-path") == 0) {
|
||||||
i++;
|
i++;
|
||||||
Settings::addUserSearchPath(argv[i]);
|
db->addUserSearchPath(argv[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-i") == 0 || strcmp(argv[i],"--ignore") == 0) {
|
else if (strcmp(argv[i],"-i") == 0 || strcmp(argv[i],"--ignore") == 0) {
|
||||||
i++;
|
i++;
|
||||||
Settings::ignorePrefix(argv[i]);
|
db->ignorePrefix(argv[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-of") == 0 || strcmp(argv[i],"--overwrite-files") == 0) {
|
else if (strcmp(argv[i],"-of") == 0 || strcmp(argv[i],"--overwrite-files") == 0) {
|
||||||
Settings::canOverwriteFiles(true);
|
db->canOverwriteFiles(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-cd") == 0 || strcmp(argv[i],"--create-dir") == 0) {
|
else if (strcmp(argv[i],"-cd") == 0 || strcmp(argv[i],"--create-dir") == 0) {
|
||||||
Settings::canCreateDir(true);
|
db->canCreateDir(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-od") == 0 || strcmp(argv[i],"--overwrite-dir") == 0) {
|
else if (strcmp(argv[i],"-od") == 0 || strcmp(argv[i],"--overwrite-dir") == 0) {
|
||||||
Settings::canOverwriteDir(true);
|
db->canOverwriteDir(true);
|
||||||
Settings::canCreateDir(true);
|
db->canCreateDir(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-n") == 0 || strcmp(argv[i],"--just-print") == 0) {
|
else if (strcmp(argv[i],"-n") == 0 || strcmp(argv[i],"--just-print") == 0) {
|
||||||
Settings::bundleLibs(false);
|
db->bundleLibs(false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-q") == 0 || strcmp(argv[i],"--quiet") == 0) {
|
else if (strcmp(argv[i],"-q") == 0 || strcmp(argv[i],"--quiet") == 0) {
|
||||||
Settings::quietOutput(true);
|
db->quietOutput(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0) {
|
else if (strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0) {
|
||||||
Settings::verboseOutput(true);
|
db->verboseOutput(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i],"-b") == 0 || strcmp(argv[i],"--bundle-libs") == 0) {
|
else if (strcmp(argv[i],"-b") == 0 || strcmp(argv[i],"--bundle-libs") == 0) {
|
||||||
|
@ -117,19 +116,19 @@ int main(int argc, const char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::filesToFixCount() < 1) {
|
if (db->filesToFixCount() < 1) {
|
||||||
showHelp();
|
showHelp();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Collecting dependencies...\n";
|
std::cout << "Collecting dependencies...\n";
|
||||||
|
|
||||||
const std::vector<std::string> files_to_fix = Settings::filesToFix();
|
const std::vector<std::string> files_to_fix = db->filesToFix();
|
||||||
for (const auto& file_to_fix : files_to_fix) {
|
for (const auto& file_to_fix : files_to_fix) {
|
||||||
collectDependencies(file_to_fix);
|
db->collectDependencies(file_to_fix);
|
||||||
}
|
}
|
||||||
collectSubDependencies();
|
db->collectSubDependencies();
|
||||||
bundleDependencies();
|
db->bundleDependencies();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue