diff --git a/README.md b/README.md index 8612ad9..a90863f 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,14 @@ Here is a list of flags you can pass to dylibbundler: Displays a summary of options +`-a`, `--app` (path to app bundle) +
+Application bundle to make self-contained. Fixes the main executable of the app bundle. Add additional binary files to fix up with the `-x` flag. +
+ `-x`, `--fix-file` (executable or plug-in filepath)
-Fixes given executable or plug-in file (a .dylib can work too. 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.
`-b`, `--bundle-deps` @@ -47,7 +52,7 @@ fixes dependencies where bundled libraries depend on each other. If this option `-f`, `--bundle-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, no frameworks will be prepared for distribution. +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).
`-i`, `--ignore` (path) diff --git a/src/Dependency.cpp b/src/Dependency.cpp index a75cbf3..f46d93b 100644 --- a/src/Dependency.cpp +++ b/src/Dependency.cpp @@ -177,10 +177,11 @@ bool Dependency::mergeIfSameAs(Dependency& dep2) void Dependency::print() { - std::cout << "\n * " << filename << " from " << prefix << "\n"; + std::cout << "\n* " << filename << " from " << prefix << "\n"; - for (size_t n=0; n " << symlinks[n] << "\n";; + for (size_t n=0; n " << symlinks[n] << "\n"; + } } void Dependency::copyYourself() @@ -217,6 +218,8 @@ void Dependency::copyYourself() deleteFile(headers_path, true); deleteFile(headers_realpath, true); + + deleteFile(dest_path + "/*.prl"); } // fix the lib's inner name @@ -228,15 +231,17 @@ void Dependency::fixFileThatDependsOnMe(std::string file_to_fix) // for main lib file changeInstallName(file_to_fix, getOriginalPath(), getInnerPath()); // for symlinks - for (size_t n=0; n lc_lines; - tokenize(output, "\n", &lc_lines); - bool rpath_found = false; - if (Settings::verboseOutput()) std::cout << "collecting rpaths for: " << filename << std::endl; size_t pos = 0; bool read_rpath = false; + + std::string cmd = "otool -l " + filename; + std::string output = systemOutput(cmd); + std::vector lc_lines; + + tokenize(output, "\n", &lc_lines); + while (pos < lc_lines.size()) { std::string line = lc_lines[pos]; pos++; - if (read_rpath) { size_t start_pos = line.find("path "); size_t end_pos = line.find(" ("); @@ -78,15 +76,13 @@ void collectRpaths(const std::string& filename) } start_pos += 5; // to exclude "path " std::string rpath = line.substr(start_pos, end_pos - start_pos); - if (Settings::verboseOutput()) { - std::cout << " rpath: " << rpath << std::endl; - } rpaths.insert(rpath); rpaths_per_file[filename].push_back(rpath); read_rpath = false; + if (Settings::verboseOutput()) + std::cout << " rpath: " << rpath << std::endl; continue; } - if (line.find("LC_RPATH") != std::string::npos) { read_rpath = true; pos++; @@ -102,24 +98,28 @@ void collectRpathsForFilename(const std::string& filename) 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]; - if (dependent_file != rpath_file) - std::cout << " dependent file: " << dependent_file << std::endl; - std::cout << " dependency: " << rpath_file << std::endl; - 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) path = std::regex_replace(path, std::regex("@executable_path/"), Settings::executableFolder()); - if (dependent_file != rpath_file) + if (dependent_file != rpath_file) { if (path.find("@loader_path") != std::string::npos) path = std::regex_replace(path, std::regex("@loader_path/"), file_prefix); - std::cout << " path to search: " << path << std::endl; + } + if (Settings::verboseOutput()) + std::cout << " path to search: " << path << std::endl; if (realpath(path.c_str(), buffer)) { fullpath = buffer; rpath_to_fullpath[rpath_file] = fullpath; @@ -129,14 +129,16 @@ std::string searchFilenameInRpaths(const std::string& rpath_file, const std::str else if (path.find("@rpath") != std::string::npos) { std::string pathE = std::regex_replace(path, std::regex("@rpath/"), Settings::executableFolder()); std::string pathL = std::regex_replace(path, std::regex("@rpath/"), file_prefix); - std::cout << " path to search: " << pathE << std::endl; + if (Settings::verboseOutput()) + std::cout << " path to search: " << pathE << std::endl; if (realpath(pathE.c_str(), buffer)) { fullpath = buffer; rpath_to_fullpath[rpath_file] = fullpath; return true; } if (dependent_file != rpath_file) { - std::cout << " path to search: " << pathL << std::endl; + if (Settings::verboseOutput()) + std::cout << " path to search: " << pathL << std::endl; if (realpath(pathL.c_str(), buffer)) { fullpath = buffer; rpath_to_fullpath[rpath_file] = fullpath; @@ -147,6 +149,7 @@ std::string searchFilenameInRpaths(const std::string& rpath_file, const std::str return false; }; + // fullpath previously stored if (rpath_to_fullpath.find(rpath_file) != rpath_to_fullpath.end()) { fullpath = rpath_to_fullpath[rpath_file]; } @@ -157,21 +160,21 @@ std::string searchFilenameInRpaths(const std::string& rpath_file, const std::str if (rpath[rpath.size()-1] != '/') rpath += "/"; std::string path = rpath + suffix; - std::cout << " trying rpath: " << path << std::endl; - if (check_path(path)) { + if (Settings::verboseOutput()) + std::cout << " trying rpath: " << path << std::endl; + if (check_path(path)) break; - } } } } if (Settings::verboseOutput()) { - // std::cout << "rpath file: " << rpath_file << std::endl; - // std::cout << "suffix: " << suffix << std::endl; - if (!fullpath.empty()) + if (!fullpath.empty()) { std::cout << " ** rpath fullpath: " << fullpath << std::endl; - else + } + else { std::cout << " ** rpath fullpath: not found" << std::endl; + } } if (fullpath.empty()) { @@ -218,9 +221,10 @@ void addDependency(std::string path, std::string dependent_file) // check if this library was already added to |deps| to avoid duplicates bool in_deps = false; - for (size_t n=0; n& l for (const auto& line : raw_lines) { if (line.find("cmd LC_LOAD_DYLIB") != std::string::npos) { if (searching) { - std::cerr << "Failed to find name before next cmd" << std::endl; + std::cerr << "\n\n/!\\ ERROR: Failed to find name before next cmd" << std::endl; exit(1); } searching = true; @@ -283,9 +287,10 @@ void collectDependencies(std::string dependent_file) collectDependencies(dependent_file, lines); for (size_t n=0; n::iterator it = rpaths.begin(); it != rpaths.end(); ++it) { + std::cout << "rpaths: " << *it << std::endl; + } + } + + const size_t deps_size = deps.size(); + + for (size_t n=0; n::iterator it = rpaths.begin(); it != rpaths.end(); ++it) { - std::cout << "rpaths: " << *it << std::endl; - } - - const size_t deps_size = deps.size(); - - std::cout << "\n"; - for (size_t n=0; n> prefix; std::cout << std::endl; - if (prefix.compare("quit") == 0) + if (prefix.compare("quit") == 0 || prefix.compare("exit") == 0 || prefix.compare("abort") == 0) exit(1); if (!prefix.empty() && prefix[prefix.size()-1] != '/') diff --git a/src/main.cpp b/src/main.cpp index a5c20db..89a5a74 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -126,9 +126,6 @@ int main (int argc, char * const argv[]) exit(0); } - // if (!Settings::appBundle().empty()) - // initRpaths(); - std::cout << "* Collecting dependencies...\n"; const size_t count = Settings::filesToFixCount();