diff --git a/LICENSE b/LICENSE index 3173c04..0d12cb2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 auriamg +Copyright (c) 2014 Marianne Gagnon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/makefile b/makefile new file mode 100644 index 0000000..fc4d69d --- /dev/null +++ b/makefile @@ -0,0 +1,15 @@ +dylibbundler: + g++ -c -I./src ./src/Settings.cpp -o ./Settings.o + g++ -c -I./src ./src/DylibBundler.cpp -o ./DylibBundler.o + g++ -c -I./src ./src/Dependency.cpp -o ./Dependency.o + g++ -c -I./src ./src/main.cpp -o ./main.o + g++ -c -I./src ./src/Utils.cpp -o ./Utils.o + g++ -o ./dylibbundler ./Settings.o ./DylibBundler.o ./Dependency.o ./main.o ./Utils.o + +clean: + rm -f *.o + rm -f ./dylibbundler + +install: dylibbundler + cp ./dylibbundler /usr/local/bin/dylibbundler + chmod 775 /usr/local/bin/dylibbundler \ No newline at end of file diff --git a/src/Dependency.cpp b/src/Dependency.cpp new file mode 100644 index 0000000..8140c58 --- /dev/null +++ b/src/Dependency.cpp @@ -0,0 +1,270 @@ +/* +The MIT License (MIT) + +Copyright (c) 2014 Marianne Gagnon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + +#include "Dependency.h" +#include +#include +#include +#include "Utils.h" +#include "Settings.h" + +#include +#include +#include + +std::string stripPrefix(std::string in) +{ + return in.substr(in.rfind("/")+1); +} + +//the pathes to search for dylibs, store it globally to parse the environment variables only once +std::vector pathes; + +//initialize the dylib search pathes +void initSearchPathes(){ + //Check the same pathes the system would search for dylibs + std::string searchPathes; + char *dyldLibPath = std::getenv("DYLD_LIBRARY_PATH"); + if( dyldLibPath!=0 ) + searchPathes = dyldLibPath; + dyldLibPath = std::getenv("DYLD_FALLBACK_FRAMEWORK_PATH"); + if (dyldLibPath != 0) + { + if (!searchPathes.empty() && searchPathes[ searchPathes.size()-1 ] != ':') searchPathes += ":"; + searchPathes += dyldLibPath; + } + dyldLibPath = std::getenv("DYLD_FALLBACK_LIBRARY_PATH"); + if (dyldLibPath!=0 ) + { + if (!searchPathes.empty() && searchPathes[ searchPathes.size()-1 ] != ':') searchPathes += ":"; + searchPathes += dyldLibPath; + } + if (!searchPathes.empty()) + { + std::stringstream ss(searchPathes); + std::string item; + while(std::getline(ss, item, ':')) + { + if (item[ item.size()-1 ] != '/') item += "/"; + pathes.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) +{ + // check if given path is a symlink + std::string cmd = "readlink -n " + path; + const bool is_symlink = system( (cmd+" > /dev/null").c_str())==0; + if (is_symlink) + { + char original_file_buffer[PATH_MAX]; + std::string original_file; + + if (not realpath(path.c_str(), original_file_buffer)) + { + std::cerr << "\n/!\\ WARNING : Cannot resolve symlink '" << path.c_str() << "'" << std::endl; + original_file = path; + } + else + { + original_file = original_file_buffer; + } + //original_file = original_file.substr(0, original_file.find("\n") ); + + filename = stripPrefix(original_file); + prefix = path.substr(0, path.rfind("/")+1); + addSymlink(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 ) ) + { + //the pathes contains at least /usr/lib so if it is empty we have not initilazed it + if( pathes.empty() ) initSearchPathes(); + + //check if file is contained in one of the pathes + for( size_t i=0; i> buffer; + prefix = buffer; + std::cout << std::endl; + + if(prefix.compare("quit")==0) exit(1); + + if( !prefix.empty() && prefix[ prefix.size()-1 ] != '/' ) prefix += "/"; + + if( !fileExists( prefix+filename ) ) + { + std::cerr << (prefix+filename) << " does not exist. Try again" << std::endl; + continue; + } + else + { + pathes.push_back( prefix ); + std::cerr << (prefix+filename) << " was found. /!\\MANUALLY CHECK THE EXECUTABLE WITH 'otool -L', DYLIBBUNDLDER MAY NOT HANDLE CORRECTLY THIS UNSTANDARD/ILL-FORMED DEPENDENCY" << std::endl; + break; + } + } + } + + //new_name = filename.substr(0, filename.find(".")) + ".dylib"; + new_name = filename; +} + +void Dependency::print() +{ + std::cout << std::endl; + std::cout << " * " << filename.c_str() << " from " << prefix.c_str() << std::endl; + + const int symamount = symlinks.size(); + for(int n=0; n " << 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){ symlinks.push_back(stripPrefix(s)); } + +// comapres the given Dependency with this one. If both refer to the same file, +// it returns true and merges both entries into one. +bool Dependency::mergeIfSameAs(Dependency& dep2) +{ + if(dep2.getOriginalFileName().compare(filename) == 0) + { + const int samount = dep2.getSymlinkAmount(); + for(int n=0; n +#include + +class Dependency +{ + // origin + std::string filename; + std::string prefix; + std::vector symlinks; + + // installation + std::string new_name; +public: + Dependency(std::string path); + + void print(); + + std::string getOriginalFileName() const{ return filename; } + std::string getOriginalPath() const{ return prefix+filename; } + std::string getInstallPath(); + std::string getInnerPath(); + + void addSymlink(std::string s); + int getSymlinkAmount() const{ return symlinks.size(); } + + std::string getSymlink(const int i) const{ return symlinks[i]; } + std::string getPrefix() const{ return prefix; } + + void copyYourself(); + void fixFileThatDependsOnMe(std::string file); + + // comapres the given Dependency with this one. If both refer to the same file, + // it returns true and merges both entries into one. + bool mergeIfSameAs(Dependency& dep2); +}; + + +#endif \ No newline at end of file diff --git a/src/DylibBundler.cpp b/src/DylibBundler.cpp new file mode 100644 index 0000000..0fef302 --- /dev/null +++ b/src/DylibBundler.cpp @@ -0,0 +1,202 @@ +/* +The MIT License (MIT) + +Copyright (c) 2014 Marianne Gagnon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + +#include "DylibBundler.h" +#include +#include +#include "Utils.h" +#include "Settings.h" +#include "Dependency.h" + + +std::vector deps; + +void changeLibPathsOnFile(std::string file_to_fix) +{ + std::cout << "\n* Fixing dependencies on " << file_to_fix.c_str() << std::endl; + + const int dep_amount = deps.size(); + for(int n=0; n& lines) +{ + // execute "otool -L" on the given file and collect the command's output + std::string cmd = "otool -L " + filename; + std::string output = system_get_output(cmd); + + if(output.find("can't open file")!=std::string::npos or output.find("No such file")!=std::string::npos or output.size()<1) + { + std::cerr << "Cannot find file " << filename << " to read its dependencies" << std::endl; + exit(1); + } + + // split output + tokenize(output, "\n", &lines); +} + + +void collectDependencies(std::string filename) +{ + std::vector lines; + collectDependencies(filename, lines); + + std::cout << "."; fflush(stdout); + + const int line_amount = lines.size(); + for(int n=0; n lines; + collectDependencies(deps[n].getOriginalPath(), lines); + + const int line_amount = lines.size(); + for(int n=0; n + +void collectDependencies(std::string filename); +void collectSubDependencies(); +void doneWithDeps_go(); + +#endif \ No newline at end of file diff --git a/src/Settings.cpp b/src/Settings.cpp new file mode 100644 index 0000000..12cdad3 --- /dev/null +++ b/src/Settings.cpp @@ -0,0 +1,94 @@ +/* +The MIT License (MIT) + +Copyright (c) 2014 Marianne Gagnon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + +#include "Settings.h" +#include + +namespace Settings +{ + +bool overwrite_files = false; +bool overwrite_dir = false; +bool create_dir = false; + +bool canOverwriteFiles(){ return overwrite_files; } +bool canOverwriteDir(){ return overwrite_dir; } +bool canCreateDir(){ return create_dir; } + +void canOverwriteFiles(bool permission){ overwrite_files = permission; } +void canOverwriteDir(bool permission){ overwrite_dir = permission; } +void canCreateDir(bool permission){ create_dir = permission; } + + +bool bundleLibs_bool = false; +bool bundleLibs(){ return bundleLibs_bool; } +void bundleLibs(bool on){ bundleLibs_bool = on; } + + +std::string dest_folder_str = "./libs/"; +std::string destFolder(){ return dest_folder_str; } +void destFolder(std::string path) +{ + dest_folder_str = path; + // fix path if needed so it ends with '/' + if( dest_folder_str[ dest_folder_str.size()-1 ] != '/' ) dest_folder_str += "/"; +} + +std::vector files; +void addFileToFix(std::string path){ files.push_back(path); } +int fileToFixAmount(){ return files.size(); } +std::string fileToFix(const int n){ return files[n]; } + +std::string inside_path_str = "@executable_path/../libs/"; +std::string inside_lib_path(){ return inside_path_str; } +void inside_lib_path(std::string p) +{ + inside_path_str = p; + // fix path if needed so it ends with '/' + if( inside_path_str[ inside_path_str.size()-1 ] != '/' ) inside_path_str += "/"; +} + +std::vector prefixes_to_ignore; +void ignore_prefix(std::string prefix) +{ + if( prefix[ prefix.size()-1 ] != '/' ) prefix += "/"; + prefixes_to_ignore.push_back(prefix); +} + +bool isPrefixBundled(std::string prefix) +{ + if(prefix.find(".framework") != std::string::npos) return false; + if(prefix.find("@executable_path") != std::string::npos) return false; + if(prefix.compare("/usr/lib/") == 0) return false; + + const int prefix_amount = prefixes_to_ignore.size(); + for(int n=0; n + +namespace Settings +{ + +bool isPrefixBundled(std::string prefix); +void ignore_prefix(std::string prefix); + +bool canOverwriteFiles(); +void canOverwriteFiles(bool permission); + +bool canOverwriteDir(); +void canOverwriteDir(bool permission); + +bool canCreateDir(); +void canCreateDir(bool permission); + +bool bundleLibs(); +void bundleLibs(bool on); + +std::string destFolder(); +void destFolder(std::string path); + +void addFileToFix(std::string path); +int fileToFixAmount(); +std::string fileToFix(const int n); + +std::string inside_lib_path(); +void inside_lib_path(std::string p); + +} +#endif \ No newline at end of file diff --git a/src/Utils.cpp b/src/Utils.cpp new file mode 100644 index 0000000..9bfc2c6 --- /dev/null +++ b/src/Utils.cpp @@ -0,0 +1,178 @@ +/* +The MIT License (MIT) + +Copyright (c) 2014 Marianne Gagnon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + + +#include "Utils.h" +#include "Dependency.h" +#include "Settings.h" +#include +#include +#include +#include +#include +#include +using namespace std; + +/* +void setInstallPath(string loc) +{ + path_to_libs_folder = 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); + } + +} + + + +bool fileExists( std::string filename ) +{ + if (access( filename.c_str(), F_OK ) != -1) + { + return true; // file exists + } + else + { + //std::cout << "access(filename) returned -1 on filename [" << filename << "] I will try trimming." << std::endl; + std::string delims = " \f\n\r\t\v"; + std::string rtrimmed = filename.substr(0, filename.find_last_not_of(delims) + 1); + std::string ftrimmed = rtrimmed.substr(rtrimmed.find_first_not_of(delims)); + if (access( ftrimmed.c_str(), F_OK ) != -1) + { + return true; + } + else + { + //std::cout << "Still failed. Cannot find the specified file." << std::endl; + return false;// file doesn't exist + } + } +} + +void fixLibDependency(string old_lib_path, string new_lib_name, string target_file_name) +{ + + string command = string("install_name_tool -change ") + old_lib_path + string(" ") + Settings::inside_lib_path() + new_lib_name + string(" ") + target_file_name; + if( systemp( command ) != 0 ) + { + cerr << "\n\nError : An error occured while trying to fix depency of " << old_lib_path << " in " << target_file_name << endl; + exit(1); + } +} + +void copyFile(string from, string to) +{ + bool override = Settings::canOverwriteFiles(); + if(!override) + { + if(fileExists( to )) + { + cerr << "\n\nError : File " << to.c_str() << " already exists. Remove it or enable overriding." << endl; + exit(1); + } + } + + string override_permission = string(override ? "-f " : "-n "); + + // copy file to local directory + string command = string("cp ") + override_permission + from + string(" ") + to; + if( systemp( command ) != 0 ) + { + 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 ) + { + cerr << "\n\nError : An error occured while trying to set write permissions on file " << to << endl; + exit(1); + } +} + +std::string system_get_output(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); + if(amount_read <= 0) break; + else + { + output[amount_read] = '\0'; + full_output += output; + } + } + } + catch(...) + { + std::cerr << "An error occured while executing command " << cmd.c_str() << std::endl; + pclose(command_output); + return ""; + } + + int return_value = pclose(command_output); + if(return_value != 0) return ""; + + return full_output; +} + +int systemp(std::string& cmd) +{ + std::cout << " " << cmd.c_str() << std::endl; + return system(cmd.c_str()); +} diff --git a/src/Utils.h b/src/Utils.h new file mode 100644 index 0000000..36ead35 --- /dev/null +++ b/src/Utils.h @@ -0,0 +1,45 @@ +/* +The MIT License (MIT) + +Copyright (c) 2014 Marianne Gagnon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + + +#ifndef _utils_h_ +#define _utils_h_ + +#include +#include + +class Library; + +void tokenize(const std::string& str, const char* delimiters, std::vector*); +bool fileExists( std::string filename ); + +void copyFile(std::string from, std::string to); + +// executes a command in the native shell and returns output in string +std::string system_get_output(std::string cmd); + +// like 'system', runs a command on the system shell, but also prints the command to stdout. +int systemp(std::string& cmd); + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..b8dbd46 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,149 @@ +/* +The MIT License (MIT) + +Copyright (c) 2014 Marianne Gagnon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + +#include +#include +#include +#include +#include "Settings.h" + +#include "Utils.h" +#include "DylibBundler.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? + + */ + +const std::string VERSION = "0.4.1"; + + +// FIXME - no memory management is done at all (anyway the program closes immediately so who cares?) + +std::string installPath = ""; + + +void showHelp() +{ + std::cout << "dylibbundler " << VERSION << std::endl; + std::cout << "dylibbundler is a utility that helps bundle dynamic libraries inside mac OS X 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; + std::cout << "-p, --install-path <'inner' path of bundled libraries (usually relative to executable, by default '@executable_path/../libs/')>" << std::endl; + std::cout << "-of, --overwrite-files (allow overwriting files in output directory)" << std::endl; + std::cout << "-od, --overwrite-dir (totally overwrite output directory if it already exists. implies --create-dir)" << std::endl; + std::cout << "-cd, --create-dir (creates output directory if necessary)" << std::endl; + std::cout << "-i, --ignore (will ignore libraries in this directory)" << std::endl; + std::cout << "-h, --help" << std::endl; +} + +int main (int argc, char * const argv[]) +{ + + // parse arguments + for(int i=0; i0) + { + // if we meet an 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); + } + } + + if(not Settings::bundleLibs() and Settings::fileToFixAmount()<1) + { + showHelp(); + exit(0); + } + + std::cout << "* Collecting dependencies"; fflush(stdout); + + const int amount = Settings::fileToFixAmount(); + for(int n=0; n