diff --git a/Makefile b/Makefile
index d06633d..bdae4cf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
DESTDIR=
PREFIX=/usr/local
-CXXFLAGS = -O2
+CXXFLAGS = -O2 -std=c++17
all: dylibbundler
diff --git a/README.md b/README.md
index b816d55..52ddf32 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,11 @@ Here is a list of flags you can pass to dylibbundler on the terminal.
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.
@@ -53,14 +58,19 @@ Copies libaries to a local directory, fixes their internal name so that they are
fixes dependencies where bundled libraries depend on each other. If this option is not passed, no libraries will be prepared for distribution.
+`-f`, `--frameworks`
+
+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.
+
+
`-i`, `--ignore` (path)
> Dylibs in (path) will be ignored. By default, dylibbundler will ignore libraries installed in `/usr/lib` since they are assumed to be present by default on all OS X 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 `./libs`) For an app bundle, it is often conveniant to set it to something like `./MyApp.app/Contents/libs`.
+> Sets the name of the directory in wich distribution-ready dylibs will be placed, relative to the current working directory. (Default is either `./libs` or `./MyApp.app/Contents/Frameworks` if using the `-a` flag for an app bundle.
`-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/../libs/`, which points to a directory named `libs` inside the `Contents` directory of the bundle.)
+> Sets the "inner" installation path of libraries, usually inside the bundle and relative to executable. (Default is either `@executable_path/../libs/`, which points to a directory named `libs` inside the `Contents` directory of the bundle, or `@executable_path/../Frameworks/` if using the `-a` flag.)
`-s`, `--search-path` (search path)
> Check for libraries in the specified path
@@ -77,7 +87,7 @@ fixes dependencies where bundled libraries depend on each other. If this option
> If the output directory does not exist, create it.
A command may look like
-`% dylibbundler -od -b -x ./HelloWorld.app/Contents/MacOS/helloworld -d ./HelloWorld.app/Contents/libs/`
+`% dylibbundler -cd -b -f -a ./HelloWorld.app -x ./HelloWorld.app/Contents/PlugIns/printsupport`
If you want to create a universal binary by merging toghether two builds from PPC and Intel machines, you can ease it up by putting the ppc and intel libs in different directories, then to create the universal binary you only have to lipo the executable.
diff --git a/src/Dependency.cpp b/src/Dependency.cpp
index 32efff0..f132af1 100644
--- a/src/Dependency.cpp
+++ b/src/Dependency.cpp
@@ -39,66 +39,22 @@ THE SOFTWARE.
#include
#include
-std::string stripPrefix(std::string in)
-{
- return in.substr(in.rfind("/")+1);
-}
-std::string& rtrim(std::string &s) {
- s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end());
- return s;
-}
-
-//the paths to search for dylibs, store it globally to parse the environment variables only once
-std::vector paths;
-
-//initialize the dylib search paths
-void initSearchPaths(){
- //Check the same paths the system would search for dylibs
- std::string searchPaths;
- char *dyldLibPath = std::getenv("DYLD_LIBRARY_PATH");
- if( dyldLibPath!=0 )
- searchPaths = dyldLibPath;
- dyldLibPath = std::getenv("DYLD_FALLBACK_FRAMEWORK_PATH");
- if (dyldLibPath != 0)
- {
- if (!searchPaths.empty() && searchPaths[ searchPaths.size()-1 ] != ':') searchPaths += ":";
- searchPaths += dyldLibPath;
- }
- dyldLibPath = std::getenv("DYLD_FALLBACK_LIBRARY_PATH");
- if (dyldLibPath!=0 )
- {
- 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 += "/";
- paths.push_back(item);
- }
- }
-}
-
-// if some libs are missing prefixes, this will be set to true
-// more stuff will then be necessary to do
-bool missing_prefixes = false;
-
-Dependency::Dependency(std::string path)
+Dependency::Dependency(std::string path, std::string dependent_file) : is_framework(false)
{
char original_file_buffer[PATH_MAX];
std::string original_file;
+ std::string warning_msg;
+
+ rtrim_in_place(path);
if (isRpath(path))
{
- original_file = searchFilenameInRpaths(path);
+ original_file = searchFilenameInRpaths(path, dependent_file);
}
- else if (not realpath(rtrim(path).c_str(), original_file_buffer))
+ else if (not realpath(path.c_str(), original_file_buffer))
{
- std::cerr << "\n/!\\ WARNING : Cannot resolve path '" << path.c_str() << "'" << std::endl;
+ warning_msg = "\n/!\\ WARNING : Cannot resolve path '" + path + "'\n";
original_file = path;
}
else
@@ -107,72 +63,85 @@ Dependency::Dependency(std::string path)
}
// check if given path is a symlink
- if (original_file != rtrim(path))
+ if (original_file != path) addSymlink(path);
+
+ prefix = filePrefix(original_file);
+ filename = stripPrefix(original_file);
+
+ if (!prefix.empty() && prefix[ prefix.size()-1 ] != '/') prefix += "/";
+
+ // check if this dependency is in /usr/lib, /System/Library, or in ignored list
+ if (!Settings::isPrefixBundled(prefix)) return;
+
+ if (original_file.find(".framework") != std::string::npos)
{
- filename = stripPrefix(original_file);
- prefix = original_file.substr(0, original_file.rfind("/")+1);
- addSymlink(path);
+ is_framework = true;
+ std::string framework_root = getFrameworkRoot(original_file);
+ std::string framework_path = getFrameworkPath(original_file);
+ std::string framework_name = stripPrefix(framework_root);
+ prefix = filePrefix(framework_root);
+ filename = framework_name + "/" + framework_path;
}
- else
- {
- filename = stripPrefix(path);
- prefix = path.substr(0, path.rfind("/")+1);
- }
-
+
//check if the lib is in a known location
- if( !prefix.empty() && prefix[ prefix.size()-1 ] != '/' ) prefix += "/";
- if( prefix.empty() || !fileExists( prefix+filename ) )
+ if (prefix.empty() || !fileExists(prefix+filename))
{
//the paths contains at least /usr/lib so if it is empty we have not initialized it
- if( paths.empty() ) initSearchPaths();
+ size_t search_path_count = Settings::searchPathAmount();
+ if (search_path_count == 0) initSearchPaths();
//check if file is contained in one of the paths
- for( size_t i=0; i " << symlinks[n].c_str() << std::endl;;
+ {
+ std::cout << " symlink --> " << symlinks[n].c_str() << std::endl;
+ }
}
std::string Dependency::getInstallPath()
{
return Settings::destFolder() + new_name;
}
+
std::string Dependency::getInnerPath()
{
return Settings::inside_lib_path() + new_name;
}
-
void Dependency::addSymlink(std::string s)
{
// calling std::find on this vector is not near as slow as an extra invocation of install_name_tool
@@ -183,10 +152,11 @@ void Dependency::addSymlink(std::string s)
// it returns true and merges both entries into one.
bool Dependency::mergeIfSameAs(Dependency& dep2)
{
- if(dep2.getOriginalFileName().compare(filename) == 0)
+ if (dep2.getOriginalFileName().compare(filename) == 0)
{
const int samount = getSymlinkAmount();
- for(int n=0; n
#include
#include
+#include
#include
#include