use full path for system (shell) commands. revise README

This commit is contained in:
SCG82 2020-01-07 23:46:08 -08:00
parent a121fb7d8f
commit bbcbaa4da4
4 changed files with 37 additions and 37 deletions

View File

@ -1,32 +1,31 @@
mac dylib bundler v2
================
mac dylib bundler v2.2
======================
About
-----
Mac OS X (now macOS) introduced an innovative and very useful way to package applications: app bundles.
While their design has all that is needed to ease distribution of resources and frameworks, it
seems like dynamic libraries (.dylib) are very complicated to distribute. Sure, applications developed
specifically for macOS (OS X) won't make use of them, however applications ported from Linux or other Unices may have
dependencies that will only compile as dylibs. By default, there exists no mechanism to bundle them but some command-line utilities provided by Apple - however it turns out that for a single program it is often necessary to issue dozens of commands! This often leads each developer to create their own "home solution" which are often hacky, non-portable and/or suboptimal.
**dylibbundler** is a small command-line programs that aims to make bundling .dylibs as easy as possible.
It automatically determines which dylibs are needed by your program, copies these libraries inside the app bundle, and fixes both them and the executable to be ready for distribution... all this with a single command! It will also work if your program uses plug-ins that have dependencies too.
It usually involves 2 actions :
* Creating a directory (by default called *Frameworks*) that can be placed inside the *Contents* folder of the app bundle.
* Fixing the executable file so that it is aware of the new location of its dependencies.
**dylibbundler** is a macOS command-line utility for producing relocatable application bundles. External dependencies (dynamic libraries) are copied inside the app bundle, and install names are made run-path-relative. (https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/RunpathDependentLibraries.html)
Installation
------------
In Terminal, cd to the main directory of dylibbundler and type "make". You can install with "sudo make install".
In Terminal, from within the macdylibbundler directory:
```bash
mkdir build && cd build
cmake ..
make
```
To install in '/usr/local/bin':
```bash
sudo make install
```
Using dylibbundler
----------------------------------
Here is a list of flags you can pass to dylibbundler:
------------------
options:
`-h`, `--help`
<blockquote>
@ -35,12 +34,12 @@ Displays a summary of options
`-a`, `--app` (path to app bundle)
<blockquote>
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.
Application bundle to make self-contained. Fixes the main executable of the app bundle. Add additional binary files to fix with the `-x` flag.
</blockquote>
`-x`, `--fix-file` (executable or plug-in filepath)
<blockquote>
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.
Executable file or dynamic library (ex: .dylib, .so) to fix. Any file 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.
</blockquote>
<!--
@ -57,10 +56,10 @@ Copy framework dependencies to app bundle and fix internal names and rpaths. If
</blockquote>
`-d`, `--dest-dir` (directory)
> Sets the name of the directory in wich distribution-ready dylibs will be placed, relative to `./MyApp.app/Contents/`. (Default is `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.)
> 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.)
*The difference between `-d` and `-p` is that `-d` is the location dylibbundler will put files in, while `-p` is the location where the libraries will be expected to be found when you launch the app (often using @executable_path, @loader_path, or @rpath).*
@ -68,7 +67,7 @@ Copy framework dependencies to app bundle and fix internal names and rpaths. If
> 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)*
> 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.

View File

@ -139,7 +139,7 @@ void DylibBundler::fixRpathsOnFile(const std::string& original_file, const std::
rpaths_to_fix = getRpathsForFile(original_file);
for (const auto& rpath_to_fix : rpaths_to_fix) {
std::string command = std::string("install_name_tool -rpath ");
std::string command = std::string("/usr/bin/install_name_tool -rpath ");
command.append(rpath_to_fix).append(" ").append(insideLibPath());
command.append(" ").append(file_to_fix);
if (systemp(command) != 0) {
@ -154,6 +154,7 @@ void DylibBundler::bundleDependencies()
for (const auto& dep : deps)
dep->Print();
std::cout << "\n";
if (verboseOutput()) {
std::cout << "rpaths:" << std::endl;
for (const auto& rpath : rpaths)
@ -263,7 +264,7 @@ void DylibBundler::bundleQtPlugins()
fixupPlugin("imageformats");
fixupPlugin("iconengines");
if (!qtSvgFound)
systemp(std::string("rm -f ") + dest + "imageformats/libqsvg.dylib");
systemp(std::string("/bin/rm -f ") + dest + "imageformats/libqsvg.dylib");
if (qtGuiFound) {
fixupPlugin("platforminputcontexts");
fixupPlugin("virtualkeyboard");
@ -314,7 +315,6 @@ std::string DylibBundler::getUserInputDirForFile(const std::string& filename, co
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;
@ -483,7 +483,7 @@ void DylibBundler::createDestDir()
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);
std::string command = std::string("/bin/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);
@ -508,7 +508,7 @@ void DylibBundler::createDestDir()
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);
std::string command = std::string("/usr/bin/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);
@ -517,7 +517,7 @@ void DylibBundler::changeId(const std::string& binary_file, const std::string& n
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(" ");
std::string command = std::string("/usr/bin/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;
@ -535,7 +535,7 @@ void DylibBundler::copyFile(const std::string& from, const std::string& to)
// copy file/directory
std::string overwrite_permission = std::string(overwrite ? "-f " : "-n ");
std::string command = std::string("cp -R ").append(overwrite_permission);
std::string command = std::string("/bin/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;
@ -543,7 +543,7 @@ void DylibBundler::copyFile(const std::string& from, const std::string& to)
}
// give file/directory write permission
std::string command2 = std::string("chmod -R +w ").append(to);
std::string command2 = std::string("/bin/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);
@ -553,7 +553,7 @@ void DylibBundler::copyFile(const std::string& from, const std::string& to)
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);
std::string command = std::string("/bin/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);
@ -570,7 +570,7 @@ 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);
std::string command = std::string("/bin/mkdir -p ").append(path);
if (systemp(command) != 0) {
std::cerr << "\n/!\\ ERROR: An error occured while creating " << path << std::endl;
return false;

View File

@ -66,7 +66,7 @@ void tokenize(const std::string& str, const char* delim, std::vector<std::string
std::vector<std::string> lsDir(const std::string& path)
{
std::string cmd = "ls " + path;
std::string cmd = "/bin/ls " + path;
std::string output = systemOutput(cmd);
std::vector<std::string> files;
tokenize(output, "\n", &files);
@ -93,13 +93,14 @@ bool isRpath(const std::string& path)
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");
cmd += app_bundle_path;
cmd += "Contents/Info.plist";
return rtrim(systemOutput(cmd));
}
std::string systemOutput(const std::string& cmd)
{
FILE *command_output = nullptr;
FILE* command_output = nullptr;
char output[128];
int amount_read = 1;
std::string full_output;
@ -133,7 +134,7 @@ std::string systemOutput(const std::string& cmd)
void otool(const std::string& flags, const std::string& file, std::vector<std::string>& lines)
{
std::string command = std::string("otool ").append(flags).append(" ").append(file);
std::string command = std::string("/bin/otool ").append(flags).append(" ").append(file);
std::string output = systemOutput(command);
if (output.find("can't open file") != std::string::npos

View File

@ -9,7 +9,7 @@
#include "DylibBundler.h"
const std::string VERSION = "2.1.0 (2020-01-04)";
const std::string VERSION = "2.2.0 (2020-01-07)";
void showHelp()
{