From 75349a2850d4a75082a4368402b8af821546c4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pedro=20Bol=C3=ADvar=20Puente?= Date: Tue, 20 Feb 2024 22:12:09 +0100 Subject: [PATCH 1/2] Add -xr or --fix-recursiver argument to fix all objects in folder Sometimes, when bundling apps with lots of plug-ins, it is cumbersome to list all these plug-ins or modules directly when passing them to the `dylibbundler` tool. With this new argument, the tool can find by itself all files to fix in a given tree. For now, it does so by trying to detect whether it's a Mach-O object file. Alternatively we could use a different check (e.g. looking for certain extensions, like `.so` files). --- src/Settings.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++++- src/Settings.h | 3 ++- src/main.cpp | 36 ++++++++++++++++++++-------------- 3 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/Settings.cpp b/src/Settings.cpp index 1d9674b..f861bd4 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -23,7 +23,11 @@ THE SOFTWARE. */ #include "Settings.h" +#include "Utils.h" + #include +#include +#include namespace Settings { @@ -63,6 +67,51 @@ void addFileToFix(const std::string& path){ files.push_back(path); } int fileToFixAmount(){ return files.size(); } std::string fileToFix(const int n){ return files[n]; } +namespace { + +bool isMachOFile(const std::string& path) { + auto file = std::ifstream{path, std::ios::binary}; + if (!file) { + return false; + } + + // Read the first 4 bytes + char buffer[4]; + if (!file.read(buffer, 4)) { + return false; + } + + // Check if the magic number of the file looks like Mach-O file... + if (std::memcmp(buffer, "\xcf\xfa\xed\xfe", 4) == 0 || std::memcmp(buffer, "\xce\xfa\xed\xfe", 4) == 0) { + // Now make sure by calling the `file` command... + static const auto prefix = std::string{"Mach-O"}; + auto type = system_get_output("file -b \"" + path + "\""); + return type.compare(0, prefix.length(), prefix) == 0; + } + + return false; +} + +} + +void addFolderToFix(const std::string& path) +{ + // we use find as a silly way to list all files inside the folder without + // doing the recursion in C++, which without C++17 std::filesystem is a bit + // cumbersome... + auto all_files = std::vector{}; + tokenize(system_get_output("find \"" + path + "\""), "\n", &all_files); + + auto prefix = std::string{"Mach-O"}; + for (auto&& file : all_files) { + if (isMachOFile(file)) { + std::cout << " * Found file " << file << std::endl; + files.push_back(std::move(file)); + } + } + +} + std::string inside_path_str = "@executable_path/../libs/"; std::string inside_lib_path(){ return inside_path_str; } void inside_lib_path(const std::string& p) @@ -104,7 +153,7 @@ bool isPrefixBundled(const std::string& prefix) if(prefix.find("@executable_path") != std::string::npos) return false; if(isSystemLibrary(prefix)) return false; if(isPrefixIgnored(prefix)) return false; - + return true; } diff --git a/src/Settings.h b/src/Settings.h index c03afc5..2f27612 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -34,7 +34,7 @@ bool isSystemLibrary(const std::string& prefix); bool isPrefixBundled(const std::string& prefix); bool isPrefixIgnored(const std::string& prefix); void ignore_prefix(std::string prefix); - + bool canOverwriteFiles(); void canOverwriteFiles(bool permission); @@ -54,6 +54,7 @@ std::string destFolder(); void destFolder(const std::string& path); void addFileToFix(const std::string& path); +void addFolderToFix(const std::string& path); int fileToFixAmount(); std::string fileToFix(const int n); diff --git a/src/main.cpp b/src/main.cpp index 173fc9d..bbd28b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,9 +36,9 @@ THE SOFTWARE. TODO - what happens if a library is not remembered by full path but only name? (support improved, still not perfect) - could get mixed up if symlink and original are not in the same location (won't happen for UNIX prefixes like /usr/, but in random directories?) - + FIXME: why does it copy plugins i try to fix to the libs directory? - + */ const std::string VERSION = "1.0.5"; @@ -53,7 +53,7 @@ void showHelp() { std::cout << "dylibbundler " << VERSION << std::endl; std::cout << "dylibbundler is a utility that helps bundle dynamic libraries inside macOS app bundles.\n" << std::endl; - + std::cout << "-x, --fix-file " << std::endl; std::cout << "-b, --bundle-deps" << std::endl; std::cout << "-d, --dest-dir " << std::endl; @@ -69,8 +69,8 @@ void showHelp() int main (int argc, char * const argv[]) { - - // parse arguments + + // parse arguments for(int i=0; i Date: Wed, 21 Feb 2024 16:32:39 +0100 Subject: [PATCH 2/2] Add mechanism to pass the signing identity for codesigning --- src/Settings.cpp | 3 +++ src/Settings.h | 3 +++ src/Utils.cpp | 31 ++++++++++++++++--------------- src/main.cpp | 6 ++++++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/Settings.cpp b/src/Settings.cpp index f861bd4..7b2a30e 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -36,6 +36,7 @@ bool overwrite_files = false; bool overwrite_dir = false; bool create_dir = false; bool codesign = true; +std::string codesign_identity = "-"; bool canOverwriteFiles(){ return overwrite_files; } bool canOverwriteDir(){ return overwrite_dir; } @@ -47,6 +48,8 @@ void canOverwriteDir(bool permission){ overwrite_dir = permission; } void canCreateDir(bool permission){ create_dir = permission; } void canCodesign(bool permission){ codesign = permission; } +std::string signingIdentity(){ return codesign_identity; } +void signingIdentity(const std::string& str) { codesign_identity = str; } bool bundleLibs_bool = false; bool bundleLibs(){ return bundleLibs_bool; } diff --git a/src/Settings.h b/src/Settings.h index 2f27612..95d3b7f 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -47,6 +47,9 @@ void canCreateDir(bool permission); bool canCodesign(); void canCodesign(bool permission); +std::string signingIdentity(); +void signingIdentity(const std::string& str); + bool bundleLibs(); void bundleLibs(bool on); diff --git a/src/Utils.cpp b/src/Utils.cpp index 168f659..4a16934 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -44,27 +44,27 @@ void setInstallPath(string loc) void tokenize(const string& str, const char* delim, vector* vectorarg) { vector& tokens = *vectorarg; - + string delimiters(delim); - + // skip delimiters at beginning. string::size_type lastPos = str.find_first_not_of( delimiters , 0); - + // find first "non-delimiter". string::size_type pos = str.find_first_of(delimiters, lastPos); - + while (string::npos != pos || string::npos != lastPos) { // found a token, add it to the vector. tokens.push_back(str.substr(lastPos, pos - lastPos)); - + // skip delimiters. Note the "not_of" lastPos = str.find_first_not_of(delimiters, pos); - + // find next "non-delimiter" pos = str.find_first_of(delimiters, lastPos); } - + } @@ -106,7 +106,7 @@ void copyFile(const string& from, const string& to) } string override_permission = string(override ? "-f " : "-n "); - + // copy file to local directory string command = string("cp ") + override_permission + string("\"") + from + string("\" \"") + to + string("\""); if( from != to && systemp( command ) != 0 ) @@ -114,7 +114,7 @@ void copyFile(const string& from, const string& to) cerr << "\n\nError : An error occured while trying to copy file " << from << " to " << to << endl; exit(1); } - + // give it write permission string command2 = string("chmod +w \"") + to + "\""; if( systemp( command2 ) != 0 ) @@ -129,14 +129,14 @@ std::string system_get_output(const std::string& cmd) FILE * command_output; char output[128]; int amount_read = 1; - + std::string full_output; - + try { command_output = popen(cmd.c_str(), "r"); if(command_output == NULL) throw; - + while(amount_read > 0) { amount_read = fread(output, 1, 127, command_output); @@ -154,10 +154,10 @@ std::string system_get_output(const std::string& cmd) pclose(command_output); return ""; } - + int return_value = pclose(command_output); if(return_value != 0) return ""; - + return full_output; } @@ -223,7 +223,8 @@ void adhocCodeSign(const std::string& file) if( Settings::canCodesign() == false ) return; // Add ad-hoc signature for ARM (Apple Silicon) binaries - std::string signCommand = std::string("codesign --force --deep --preserve-metadata=entitlements,requirements,flags,runtime --sign - \"") + file + "\""; + std::string signCommand = std::string("codesign --force --deep --preserve-metadata=entitlements,requirements,flags,runtime --sign ") + + Settings::signingIdentity() + " \"" + file + "\""; if( systemp( signCommand ) != 0 ) { // If the codesigning fails, it may be a bug in Apple's codesign utility. diff --git a/src/main.cpp b/src/main.cpp index bbd28b7..274781a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -129,6 +129,12 @@ int main (int argc, char * const argv[]) Settings::canCodesign(false); continue; } + else if(strcmp(argv[i],"-si")==0 or strcmp(argv[i],"--signing-identity")==0) + { + i++; + Settings::signingIdentity(argv[i]); + continue; + } else if(strcmp(argv[i],"-h")==0 or strcmp(argv[i],"--help")==0) { showHelp();