From 6348de25a84b1b5f815b6867d841fe4d82134e72 Mon Sep 17 00:00:00 2001 From: SCG82 Date: Sun, 29 Dec 2019 18:26:24 -0800 Subject: [PATCH] copy dependencies by default --- README.md | 37 ++++++++++-------- src/DylibBundler.cpp | 89 ++++++++++++++++++-------------------------- src/Settings.cpp | 2 +- src/Utils.cpp | 8 ++-- src/main.cpp | 88 ++++++++++++++++++++----------------------- 5 files changed, 105 insertions(+), 119 deletions(-) diff --git a/README.md b/README.md index a90863f..72295c7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -mac dylib bundler +mac dylib bundler v2 ================ @@ -40,26 +40,24 @@ Application bundle to make self-contained. Fixes the main executable of the app `-x`, `--fix-file` (executable or plug-in filepath)
-Fixes given executable or plug-in file (ex: .dylib, .so) anything on which `otool -L` works is accepted by `-x`. dylibbundler will walk through the dependencies of the specified file to build a dependency list. It will also fix the said files' dependencies so that it expects to find the libraries relative to itself (e.g. in the app bundle) instead of at an absolute path (e.g. /usr/local/lib). To pass multiple files to fix, simply specify multiple `-x` flags. +Fixes given executable or plug-in file (ex: .dylib, .so). Anything on which `otool -L` works is accepted by `-x`. dylibbundler will walk through the dependencies of the specified file to build a dependency list. It will also fix the said files' dependencies so that it expects to find the libraries relative to itself (e.g. in the app bundle) instead of at an absolute path (e.g. /usr/local/lib). To pass multiple files to fix, simply specify multiple `-x` flags.
+ -`-f`, `--bundle-frameworks` +`-f`, `--frameworks`
-Copies frameworks to a local directory, fixes their internal name so that they are aware of their new location, -fixes dependencies where bundled libraries depend on each other. If this option is not passed, dependencies contained in frameworks will be ignored. dylibbundler will also copy any needed Qt plugins and create qt.conf in the `Resources` directory (no need to run macdeployqt). +Copy framework dependencies to app bundle and fix internal names and rpaths. If this option is not passed, dependencies contained in frameworks will be ignored. dylibbundler will also deploy Qt frameworks & plugins, eliminating the need to use `macdeployqt`.
-`-i`, `--ignore` (path) -> Dylibs in (path) will be ignored. By default, dylibbundler will ignore libraries installed in `/usr/lib` & `/System/Library` since they are assumed to be present by default on all macOS installations. *(It is usually recommend not to install additional stuff in `/usr/`, always use ` /usr/local/` or another prefix to avoid confusion between system libs and libs you added yourself)* - `-d`, `--dest-dir` (directory) -> Sets the name of the directory in wich distribution-ready dylibs will be placed, relative to the current working directory. (Default is `./Frameworks`) For an app bundle, it is often conveniant to set it to something like `./MyApp.app/Contents/Frameworks`. +> Sets the name of the directory in wich distribution-ready dylibs will be placed, relative to `./MyApp.app/Contents/`. (Default is `Frameworks`). `-p`, `--install-path` (libraries install path) > Sets the "inner" installation path of libraries, usually inside the bundle and relative to executable. (Default is `@executable_path/../Frameworks/`, which points to a directory named `Frameworks` inside the `Contents` directory of the bundle.) @@ -69,20 +67,29 @@ fixes dependencies where bundled libraries depend on each other. If this option `-s`, `--search-path` (search path) > Check for libraries in the specified path. +`-i`, `--ignore` (path) +> Dylibs in (path) will be ignored. By default, dylibbundler will ignore libraries installed in `/usr/lib` & `/System/Library` since they are assumed to be present by default on all macOS installations. *(It is usually recommend not to install additional stuff in `/usr/`, always use ` /usr/local/` or another prefix to avoid confusion between system libs and libs you added yourself)* + `-of`, `--overwrite-files` > When copying libraries to the output directory, allow overwriting files when one with the same name already exists. -`-od`, `--overwrite-dir` -> If the output directory already exists, completely erase its current content before adding anything to it. (This option implies --create-dir) - `-cd`, `--create-dir` > If the output directory does not exist, create it. +`-od`, `--overwrite-dir` +> If the output directory already exists, completely erase its current content before adding anything to it. (This option implies --create-dir) + +`-n`, `--just-print` +> Print the dependencies found (without copying into app bundle). + `-q`, `--quiet` -> Print only summary information. +> Less verbose output. `-v`, `--verbose` -> Print extra information (useful for debugging). +> More verbose output (only recommended for debugging). + +`-V`, `--version` +> Print dylibbundler version number and exit. A command may look like -`% dylibbundler -q -od -b -x ./HelloWorld.app/Contents/MacOS/helloworld -d ./HelloWorld.app/Contents/Frameworks/` +`% dylibbundler -cd -of -f -q -a ./HelloWorld.app -x ./HelloWorld.app/Contents/PlugIns/printsupport` diff --git a/src/DylibBundler.cpp b/src/DylibBundler.cpp index df1e01e..f7dd0f9 100644 --- a/src/DylibBundler.cpp +++ b/src/DylibBundler.cpp @@ -25,16 +25,6 @@ std::map> rpaths_per_file; std::map rpath_to_fullpath; bool qt_plugins_called = false; -void initRpaths() -{ - std::string executable_path = Settings::executableFolder(); - std::string frameworks_path = Settings::frameworksFolder(); - std::string plugins_path = Settings::pluginsFolder(); - rpaths.insert(executable_path); - rpaths.insert(frameworks_path); - rpaths.insert(plugins_path); -} - void changeLibPathsOnFile(std::string file_to_fix) { if (deps_collected.find(file_to_fix) == deps_collected.end()) @@ -42,7 +32,7 @@ void changeLibPathsOnFile(std::string file_to_fix) std::cout << "* Fixing dependencies on " << file_to_fix << "\n"; - const int dep_amount = deps_per_file[file_to_fix].size(); + const size_t dep_amount = deps_per_file[file_to_fix].size(); for (size_t n=0; n lines; collectDependencies(dependent_file, lines); - for (size_t n=0; n lines; collectDependencies(original_path, lines); - for (size_t n=0; n lsDir(std::string path) bool fileExists(std::string filename) { if (access(filename.c_str(), F_OK) != -1) { - return true; // file exists + return true; } else { std::string delims = " \f\n\r\t\v"; @@ -131,7 +131,7 @@ bool fileExists(std::string filename) if (access(ftrimmed.c_str(), F_OK) != -1) return true; else - return false; // file doesn't exist + return false; } } @@ -168,14 +168,14 @@ void copyFile(std::string from, std::string to) std::string overwrite_permission = std::string(overwrite ? "-f " : "-n "); - // copy file to local directory + // copy file/directory 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 << "\n"; exit(1); } - // give it write permission + // 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 << "\n"; diff --git a/src/main.cpp b/src/main.cpp index cdeb241..126ad89 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,40 +8,30 @@ #include "Settings.h" #include "Utils.h" -/* - 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? - FIXME - no memory management is done at all (anyway the program closes immediately so who cares?) - */ - -const std::string VERSION = "1.0.0 (2019-12-16)"; -std::string installPath = ""; +const std::string VERSION = "2.0.0 (2019-12-29)"; void showHelp() { std::cout << "Usage: dylibbundler [options] -x file" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -a, --app Application bundle to make self-contained" << std::endl; - std::cout << " -x, --fix-file Object file(s) to bundle dependencies (optional)" << std::endl; - std::cout << " -b, --bundle-deps Copy dependencies to app bundle and fix internal names and rpaths" << std::endl; - std::cout << " -f, --bundle-frameworks Copy dependencies that are frameworks (experimental)" << std::endl; + std::cout << " -x, --fix-file Copy file's dependencies to app bundle and fix internal names and rpaths" << std::endl; + std::cout << " -f, --frameworks Copy dependencies that are frameworks (experimental)" << std::endl; std::cout << " -d, --dest-dir Directory to copy dependencies, relative to /Contents (default: ./Frameworks)" << std::endl; std::cout << " -p, --install-path Inner path (@rpath) of bundled dependencies (default: @executable_path/../Frameworks/)" << std::endl; - std::cout << " -s, --search-path Directory to add to list of locations searched" << std::endl; + std::cout << " -s, --search-path Add directory to search path" << std::endl; + std::cout << " -i, --ignore Ignore dependencies in this directory (default: /usr/lib & /System/Library)" << std::endl; std::cout << " -of, --overwrite-files Allow overwriting files in output directory" << std::endl; - std::cout << " -od, --overwrite-dir Overwrite output directory if it exists (implies --create-dir)" << std::endl; std::cout << " -cd, --create-dir Create output directory if needed" << std::endl; - std::cout << " -i, --ignore Ignore libraries in this directory (default: /usr/lib & /System/Library)" << std::endl; + std::cout << " -od, --overwrite-dir Overwrite (delete) output directory if it exists (implies --create-dir)" << std::endl; + std::cout << " -n, --just-print Print the dependencies found (without copying into app bundle)" << std::endl; std::cout << " -q, --quiet Less verbose output" << std::endl; std::cout << " -v, --verbose More verbose output" << std::endl; std::cout << " -V, --version Print dylibbundler version number and exit" << std::endl; std::cout << " -h, --help Print this message and exit" << std::endl; } -int main (int argc, char * const argv[]) +int main(int argc, const char* argv[]) { // parse arguments for (int i=0; i 0) { // unknown flag, abort - // ignore first one cause it's usually the path to the executable std::cerr << "Unknown flag " << argv[i] << std::endl << std::endl; showHelp(); exit(1); @@ -128,9 +121,10 @@ int main (int argc, char * const argv[]) std::cout << "* Collecting dependencies...\n"; - const size_t count = Settings::filesToFixCount(); - for (size_t n=0; n