deploy qt plugins

This commit is contained in:
SCG82 2020-01-04 06:06:11 -08:00
parent a58f2ec3b8
commit bf0586f410
9 changed files with 342 additions and 140 deletions

View File

@ -44,6 +44,7 @@ Dependency::Dependency(std::string path, std::string dependent_file) : is_framew
{
char original_file_buffer[PATH_MAX];
std::string original_file;
std::string warning_msg;
rtrim_in_place(path);
@ -53,7 +54,7 @@ Dependency::Dependency(std::string path, std::string dependent_file) : is_framew
}
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
@ -72,6 +73,16 @@ Dependency::Dependency(std::string path, std::string dependent_file) : is_framew
// 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)
{
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;
}
//check if the lib is in a known location
if (prefix.empty() || !fileExists(prefix+filename))
{
@ -86,18 +97,23 @@ Dependency::Dependency(std::string path, std::string dependent_file) : is_framew
std::string search_path = Settings::searchPath(i);
if (fileExists(search_path+filename))
{
std::cout << "FOUND " << filename << " in " << search_path << std::endl;
warning_msg += "FOUND " + filename + " in " + search_path + "\n";
prefix = search_path;
Settings::missingPrefixes(true); //the prefix was missing
break;
}
}
}
if (!Settings::quietOutput()) std::cout << warning_msg;
//If the location is still unknown, ask the user for search path
if ( !Settings::isPrefixIgnored(prefix) && ( prefix.empty() || !fileExists(prefix+filename) ) )
{
std::cerr << "\n/!\\ WARNING : Library " << filename << " has an incomplete name (location unknown)" << std::endl;
if (!Settings::quietOutput())
{
std::cerr << "\n/!\\ WARNING: Dependency " << filename << " of " << dependent_file << " not found\n";
}
Settings::missingPrefixes(true);
Settings::addSearchPath(getUserInputDirForFile(filename));
}
@ -107,13 +123,12 @@ Dependency::Dependency(std::string path, std::string dependent_file) : is_framew
void Dependency::print()
{
std::cout << std::endl;
std::cout << " * " << filename.c_str() << " from " << prefix.c_str() << std::endl;
std::cout << "\n* " << filename.c_str() << " from " << prefix.c_str() << std::endl;
const int symamount = symlinks.size();
for(int n=0; n<symamount; n++)
{
std::cout << " symlink --> " << symlinks[n].c_str() << std::endl;
std::cout << " symlink --> " << symlinks[n].c_str() << std::endl;
}
}

View File

@ -49,7 +49,9 @@ public:
std::string getOriginalPath() const{ return prefix+filename; }
std::string getInstallPath();
std::string getInnerPath();
bool isFramework(){ return is_framework; }
void addSymlink(std::string s);
int getSymlinkAmount() const{ return symlinks.size(); }

View File

@ -40,9 +40,11 @@ THE SOFTWARE.
std::vector<Dependency> deps;
std::map<std::string, std::vector<Dependency> > deps_per_file;
std::map<std::string, bool> deps_collected;
std::set<std::string> frameworks;
std::set<std::string> rpaths;
std::map<std::string, std::vector<std::string> > rpaths_per_file;
std::map<std::string, std::string> rpath_to_fullpath;
bool qt_plugins_called = false;
void changeLibPathsOnFile(std::string file_to_fix)
{
@ -50,7 +52,8 @@ void changeLibPathsOnFile(std::string file_to_fix)
{
collectDependencies(file_to_fix);
}
std::cout << "\n* Fixing dependencies on " << file_to_fix.c_str() << std::endl;
if (!Settings::quietOutput()) std::cout << "\n";
std::cout << "* Fixing dependencies on " << file_to_fix.c_str() << std::endl;
const int dep_amount = deps_per_file[file_to_fix].size();
for(int n=0; n<dep_amount; n++)
@ -206,11 +209,21 @@ std::string searchFilenameInRpaths(const std::string& rpath_file, const std::str
break;
}
}
std::cerr << "\n/!\\ WARNING : can't get path for '" << rpath_file << "'\n";
fullpath = getUserInputDirForFile(suffix) + suffix;
if (realpath(fullpath.c_str(), fullpath_buffer))
if (fullpath.empty())
{
fullpath = fullpath_buffer;
if (!Settings::quietOutput())
{
std::cerr << "\n/!\\ WARNING : can't get path for '" << rpath_file << "'\n";
}
fullpath = getUserInputDirForFile(suffix) + suffix;
if (Settings::quietOutput() && fullpath.empty())
{
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'\n";
}
if (realpath(fullpath.c_str(), fullpath_buffer))
{
fullpath = fullpath_buffer;
}
}
}
@ -231,11 +244,11 @@ void fixRpathsOnFile(const std::string& original_file, const std::string& file_t
rpaths_to_fix = found->second;
}
for(size_t i=0; i < rpaths_to_fix.size(); ++i)
for (size_t i=0; i < rpaths_to_fix.size(); ++i)
{
std::string command = std::string("install_name_tool -rpath ") +
rpaths_to_fix[i] + " " + Settings::inside_lib_path() + " " + file_to_fix;
if (systemp(command) != 0)
if ( systemp(command) != 0)
{
std::cerr << "\n\nError : An error occured while trying to fix dependencies of " << file_to_fix << std::endl;
exit(1);
@ -252,22 +265,23 @@ void addDependency(std::string path, std::string filename)
const int dep_amount = deps.size();
for(int n=0; n<dep_amount; n++)
{
if (dep.mergeIfSameAs(deps[n])) in_deps = true;
if(dep.mergeIfSameAs(deps[n])) in_deps = true;
}
// check if this library was already added to |deps_per_file[filename]| to avoid duplicates
std::vector<Dependency> deps_in_file = deps_per_file[filename];
bool in_deps_per_file = false;
const int deps_in_file_amount = deps_in_file.size();
const int deps_in_file_amount = deps_per_file[filename].size();
for(int n=0; n<deps_in_file_amount; n++)
{
if (dep.mergeIfSameAs(deps_in_file[n])) in_deps_per_file = true;
if(dep.mergeIfSameAs(deps_per_file[filename][n])) in_deps_per_file = true;
}
if (!Settings::isPrefixBundled(dep.getPrefix())) return;
if(!Settings::isPrefixBundled(dep.getPrefix())) return;
if(!in_deps && dep.isFramework()) frameworks.insert(dep.getOriginalPath());
if (!in_deps) deps.push_back(dep);
if (!in_deps_per_file) deps_per_file[filename].push_back(dep);
if(!in_deps) deps.push_back(dep);
if(!in_deps_per_file) deps_per_file[filename].push_back(dep);
}
/*
@ -316,23 +330,14 @@ void collectDependencies(std::string filename)
{
std::vector<std::string> lines;
collectDependencies(filename, lines);
std::cout << "."; fflush(stdout);
const int line_amount = lines.size();
for(int n=0; n<line_amount; n++)
{
std::cout << "."; fflush(stdout);
if (lines[n][0] != '\t') continue; // only lines beginning with a tab interest us
if (!Settings::isPrefixBundled(lines[n])) continue; // skip system/ignored prefixes
if(lines[n][0] != '\t') continue; // only lines beginning with a tab interest us
if(!Settings::isPrefixBundled(lines[n])) continue; // skip system/ignored prefixes
// trim useless info, keep only library name
std::string dep_path = lines[n].substr(1, lines[n].rfind(" (") - 1);
if (isRpath(dep_path))
{
collectRpathsForFilename(filename);
}
addDependency(dep_path, filename);
}
deps_collected[filename] = true;
@ -340,7 +345,7 @@ void collectDependencies(std::string filename)
void collectSubDependencies()
{
// print status to user
size_t dep_counter = deps.size();
int dep_amount = deps.size();
// recursively collect each dependencie's dependencies
@ -349,51 +354,48 @@ void collectSubDependencies()
dep_amount = deps.size();
for(int n=0; n<dep_amount; n++)
{
std::cout << "."; fflush(stdout);
std::vector<std::string> lines;
std::string original_path = deps[n].getOriginalPath();
std::string full_path = original_path;
if (isRpath(original_path))
{
full_path = searchFilenameInRpaths(original_path);
original_path = searchFilenameInRpaths(original_path);
}
collectRpathsForFilename(full_path);
collectDependencies(full_path, lines);
collectRpathsForFilename(original_path);
collectDependencies(original_path, lines);
const int line_amount = lines.size();
for(int n=0; n<line_amount; n++)
{
if (lines[n][0] != '\t') continue; // only lines beginning with a tab interest us
if (!Settings::isPrefixBundled(lines[n])) continue; // skip system/ignored prefixes
// trim useless info, keep only library name
std::string dep_path = lines[n].substr(1, lines[n].rfind(" (") - 1);
if (isRpath(dep_path))
{
collectRpathsForFilename(searchFilenameInRpaths(dep_path, original_path));
}
addDependency(dep_path, original_path);
}//next
}//next
if (deps.size() == dep_amount) break; // no more dependencies were added on this iteration, stop searching
}
if (Settings::bundleLibs() && Settings::bundleFrameworks())
{
if ( !qt_plugins_called || (deps.size() != dep_counter) ) copyQtPlugins();
}
}
void createDestDir()
{
std::string dest_folder = Settings::destFolder();
std::cout << "* Checking output directory " << dest_folder.c_str() << std::endl;
std::cout << "Checking output directory " << dest_folder.c_str() << std::endl;
// ----------- check dest folder stuff ----------
bool dest_exists = fileExists(dest_folder);
if (dest_exists and Settings::canOverwriteDir())
if(dest_exists and Settings::canOverwriteDir())
{
std::cout << "* Erasing old output directory " << dest_folder.c_str() << std::endl;
std::cout << "Erasing old output directory " << dest_folder.c_str() << std::endl;
std::string command = std::string("rm -r ") + dest_folder;
if (systemp(command) != 0)
if( systemp( command ) != 0)
{
std::cerr << "\n\nError : An error occured while attempting to overwrite dest folder." << std::endl;
exit(1);
@ -401,14 +403,14 @@ void createDestDir()
dest_exists = false;
}
if (!dest_exists)
if(!dest_exists)
{
if (Settings::canCreateDir())
if(Settings::canCreateDir())
{
std::cout << "* Creating output directory " << dest_folder.c_str() << std::endl;
std::cout << "Creating output directory " << dest_folder.c_str() << "\n\n";
std::string command = std::string("mkdir -p ") + dest_folder;
if (systemp(command) != 0)
if( systemp( command ) != 0)
{
std::cerr << "\n\nError : An error occured while creating dest folder." << std::endl;
exit(1);
@ -425,7 +427,6 @@ void createDestDir()
void doneWithDeps_go()
{
std::cout << std::endl;
const int dep_amount = deps.size();
// print info to user
for(int n=0; n<dep_amount; n++)
@ -435,7 +436,7 @@ void doneWithDeps_go()
std::cout << std::endl;
// copy files if requested by user
if (Settings::bundleLibs())
if(Settings::bundleLibs())
{
createDestDir();
@ -454,3 +455,117 @@ void doneWithDeps_go()
fixRpathsOnFile(Settings::fileToFix(n), Settings::fileToFix(n));
}
}
void copyQtPlugins()
{
bool qtCoreFound = false;
bool qtGuiFound = false;
bool qtNetworkFound = false;
bool qtSqlFound = false;
bool qtSvgFound = false;
bool qtMultimediaFound = false;
bool qt3dRenderFound = false;
bool qt3dQuickRenderFound = false;
bool qtPositioningFound = false;
bool qtLocationFound = false;
bool qtTextToSpeechFound = false;
bool qtWebViewFound = false;
std::string original_file;
for (std::set<std::string>::iterator it = frameworks.begin(); it != frameworks.end(); ++it)
{
std::string framework = *it;
if (framework.find("QtCore") != std::string::npos)
{
qtCoreFound = true;
original_file = framework;
}
if (framework.find("QtNetwork") != std::string::npos)
qtNetworkFound = true;
if (framework.find("QtSql") != std::string::npos)
qtSqlFound = true;
if (framework.find("QtSvg") != std::string::npos)
qtSvgFound = true;
if (framework.find("QtMultimedia") != std::string::npos)
qtMultimediaFound = true;
if (framework.find("Qt3DRender") != std::string::npos)
qt3dRenderFound = true;
if (framework.find("Qt3DQuickRender") != std::string::npos)
qt3dQuickRenderFound = true;
if (framework.find("QtPositioning") != std::string::npos)
qtPositioningFound = true;
if (framework.find("QtLocation") != std::string::npos)
qtLocationFound = true;
if (framework.find("TextToSpeech") != std::string::npos)
qtTextToSpeechFound = true;
if (framework.find("WebView") != std::string::npos)
qtWebViewFound = true;
}
if (!qtCoreFound) return;
if (!qt_plugins_called) createQtConf(Settings::resourcesFolder());
qt_plugins_called = true;
const auto fixupPlugin = [original_file](std::string plugin)
{
std::string dest = Settings::pluginsFolder();
std::string framework_root = getFrameworkRoot(original_file);
std::string prefix = filePrefix(framework_root);
std::string qt_prefix = filePrefix(prefix.substr(0, prefix.size()-1));
std::string qt_plugins_prefix = qt_prefix + "plugins/";
if (fileExists(qt_plugins_prefix + plugin))
{
mkdir(dest + plugin);
copyFile(qt_plugins_prefix + plugin, dest);
std::vector<std::string> files = lsDir(dest + plugin+"/");
for (const auto& file : files)
{
Settings::addFileToFix(dest + plugin+"/"+file);
collectDependencies(dest + plugin+"/"+file);
changeId(dest + plugin+"/"+file, "@rpath/" + plugin+"/"+file);
}
}
};
std::string framework_root = getFrameworkRoot(original_file);
std::string prefix = filePrefix(framework_root);
std::string qt_prefix = filePrefix(prefix.substr(0, prefix.size()-1));
std::string qt_plugins_prefix = qt_prefix + "plugins/";
std::string dest = Settings::pluginsFolder();
mkdir(dest + "platforms");
copyFile(qt_plugins_prefix + "platforms/libqcocoa.dylib", dest + "platforms");
Settings::addFileToFix(dest + "platforms/libqcocoa.dylib");
collectDependencies(dest + "platforms/libqcocoa.dylib");
fixupPlugin("printsupport");
fixupPlugin("styles");
fixupPlugin("imageformats");
fixupPlugin("iconengines");
if (!qtSvgFound) systemp(std::string("rm -f ") + dest + "imageformats/libqsvg.dylib");
if (qtGuiFound)
{
fixupPlugin("platforminputcontexts");
fixupPlugin("virtualkeyboard");
}
if (qtNetworkFound) fixupPlugin("bearer");
if (qtSqlFound) fixupPlugin("sqldrivers");
if (qtMultimediaFound)
{
fixupPlugin("mediaservice");
fixupPlugin("audio");
}
if (qt3dRenderFound)
{
fixupPlugin("sceneparsers");
fixupPlugin("geometryloaders");
}
if (qt3dQuickRenderFound) fixupPlugin("renderplugins");
if (qtPositioningFound) fixupPlugin("position");
if (qtLocationFound) fixupPlugin("geoservices");
if (qtTextToSpeechFound) fixupPlugin("texttospeech");
if (qtWebViewFound) fixupPlugin("webview");
collectSubDependencies();
}

View File

@ -37,9 +37,12 @@ std::string searchFilenameInRpaths(const std::string& rpath_dep);
void fixRpathsOnFile(const std::string& original_file, const std::string& file_to_fix);
void addDependency(std::string path, std::string dependent_file);
void collectDependencies(std::string filename);
void collectDependencies(std::string dependent_file, std::vector<std::string>& lines);
void collectDependencies(std::string dependent_file);
void collectSubDependencies();
void doneWithDeps_go();
void copyQtPlugins();
#endif

View File

@ -37,7 +37,7 @@ bool bundle_frameworks = false;
bool quiet_output = false;
std::string dest_folder_str = "./libs/";
std::string dest_folder_str_app = "Frameworks/";
std::string dest_folder_str_app = "./Frameworks/";
std::string dest_folder = dest_folder_str;
std::string dest_path = dest_folder;
@ -59,8 +59,8 @@ void bundleLibs(bool on){ bundle_libs = on; }
bool bundleFrameworks(){ return bundle_frameworks; }
void bundleFrameworks(bool on){ bundle_frameworks = on; }
bool quietOutput() { return quiet_output; }
void quietOutput(bool status) { quiet_output = status; }
bool quietOutput(){ return quiet_output; }
void quietOutput(bool status){ quiet_output = status; }
std::string app_bundle;
bool appBundleProvided(){ return !app_bundle.empty(); }
@ -68,50 +68,61 @@ std::string appBundle(){ return app_bundle; }
void appBundle(std::string path)
{
app_bundle = path;
// fix path if needed so it ends with '/'
if(app_bundle[ app_bundle.size()-1 ] != '/') app_bundle += "/";
addFileToFix(app_bundle + "Contents/MacOS/" + bundleExecutableName(app_bundle));
if(inside_path == inside_path_str) inside_path = inside_path_str_app;
if(dest_folder == dest_folder_str) dest_folder = dest_folder_str_app;
dest_path = app_bundle + "Contents/" + stripLSlash(dest_folder);
char buffer[PATH_MAX];
if(realpath(dest_path.c_str(), buffer)) dest_path = buffer;
if(realpath(app_bundle.c_str(), buffer))
app_bundle = buffer;
// fix path if needed so it ends with '/'
if(dest_path[ dest_path.size()-1 ] != '/') dest_path += "/";
if( app_bundle[ app_bundle.size()-1 ] != '/' )
app_bundle += "/";
std::string bundle_executable_path = app_bundle + "Contents/MacOS/" + bundleExecutableName(app_bundle);
if(realpath(bundle_executable_path.c_str(), buffer))
bundle_executable_path = buffer;
addFileToFix(bundle_executable_path);
if(inside_path == inside_path_str)
inside_path = inside_path_str_app;
if(dest_folder == dest_folder_str)
dest_folder = dest_folder_str_app;
dest_path = app_bundle + "Contents/" + stripLSlash(dest_folder);
if(realpath(dest_path.c_str(), buffer))
dest_path = buffer;
if( dest_path[ dest_path.size()-1 ] != '/' )
dest_path += "/";
}
std::string destFolder(){ return dest_path; }
void destFolder(std::string path)
{
// fix path if needed so it ends with '/'
if(path[ path.size()-1 ] != '/') path += "/";
dest_folder = path;
if(appBundleProvided())
{
char buffer[PATH_MAX];
std::string dest_path = app_bundle + "Contents/" + stripLSlash(path);
if(realpath(dest_path.c_str(), buffer)) dest_path = buffer;
// fix path if needed so it ends with '/'
if(dest_path[ dest_path.size()-1 ] != '/') dest_path += "/";
dest_folder = dest_path;
}
dest_path = path;
if(appBundleProvided()) dest_path = app_bundle + "Contents/" + stripLSlash(path);
char buffer[PATH_MAX];
if(realpath(dest_path.c_str(), buffer)) dest_path = buffer;
if( dest_path[ dest_path.size()-1 ] != '/' ) dest_path += "/";
}
std::string executableFolder() { return app_bundle + "Contents/MacOS/"; }
std::string frameworksFolder() { return app_bundle + "Contents/Frameworks/"; }
std::string pluginsFolder() { return app_bundle + "Contents/PlugIns/"; }
std::string resourcesFolder() { return app_bundle + "Contents/Resources/"; }
std::vector<std::string> files;
void addFileToFix(std::string path){ files.push_back(path); }
void addFileToFix(std::string path)
{
char buffer[PATH_MAX];
if(realpath(path.c_str(), buffer)) path = buffer;
files.push_back(path);
}
int fileToFixAmount(){ return files.size(); }
std::string fileToFix(const int n){ return files[n]; }
std::string inside_lib_path(){ return inside_path_str; }
std::string inside_lib_path(){ return inside_path; }
void inside_lib_path(std::string p)
{
inside_path_str = p;
inside_path = p;
// fix path if needed so it ends with '/'
if( inside_path_str[ inside_path_str.size()-1 ] != '/' ) inside_path_str += "/";
if( inside_path[ inside_path.size()-1 ] != '/' ) inside_path += "/";
}
std::vector<std::string> prefixes_to_ignore;

View File

@ -60,6 +60,9 @@ std::string destFolder();
void destFolder(std::string path);
std::string executableFolder();
std::string frameworksFolder();
std::string pluginsFolder();
std::string resourcesFolder();
void addFileToFix(std::string path);
int fileToFixAmount();

View File

@ -28,6 +28,7 @@ THE SOFTWARE.
#include "Settings.h"
#include <cstdlib>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <cstdio>
@ -76,49 +77,54 @@ string rtrim(string s)
void tokenize(const string& str, const char* delim, vector<string>* vectorarg)
{
vector<string>& tokens = *vectorarg;
string delimiters(delim);
// skip delimiters at beginning.
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
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)
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(string filename)
{
if (access(filename.c_str(), F_OK) != -1) return true; // file exists
if (access( filename.c_str(), F_OK ) != -1) return true; // file exists
string delims = " \f\n\r\t\v";
string rtrimmed = filename.substr(0, filename.find_last_not_of(delims)+1);
string ftrimmed = rtrimmed.substr(rtrimmed.find_first_not_of(delims));
if (access(ftrimmed.c_str(), F_OK) != -1) return true;
if (access( ftrimmed.c_str(), F_OK ) != -1) return true;
return false; // file doesn't exist
}
void copyFile(string from, string to)
{
bool overwrite = Settings::canOverwriteFiles();
if (!overwrite)
if(!overwrite)
{
if (fileExists(to))
if(fileExists( to ))
{
cerr << "\n\nError : File " << to.c_str() << " already exists. Remove it or enable overwriting." << endl;
exit(1);
}
}
// copy file/directory
// copy file to local directory
string overwrite_permission = string(overwrite ? "-f " : "-n ");
string command = string("cp -R ") + overwrite_permission + from + string(" ") + to;
if (from != to && systemp(command) != 0)
@ -127,9 +133,9 @@ void copyFile(string from, string to)
exit(1);
}
// give file/directory write permission
// give it write permission
string command2 = string("chmod -R +w ") + to;
if (systemp(command2) != 0)
if( systemp( command2 ) != 0 )
{
cerr << "\n\nError : An error occured while trying to set write permissions on file " << to << endl;
exit(1);
@ -140,7 +146,7 @@ void deleteFile(string path, bool overwrite)
{
string overwrite_permission = string(overwrite ? "-f " : " ");
string command = string("rm -r ") + overwrite_permission + path;
if (systemp(command) != 0)
if( systemp( command ) != 0 )
{
cerr << "\n\nError: An error occured while trying to delete " << path << endl;
exit(1);
@ -153,90 +159,118 @@ void deleteFile(string path)
deleteFile(path, overwrite);
}
string system_get_output(string cmd)
std::vector<std::string> lsDir(const std::string& path)
{
FILE* command_output;
std::string cmd = "ls " + path;
std::string output = system_get_output(cmd);
std::vector<std::string> files;
tokenize(output, "\n", &files);
return files;
}
bool mkdir(const std::string& path)
{
cout << "Creating directory " << path << std::endl;
string command = string("mkdir -p ") + path;
if( systemp( command ) != 0 )
{
cerr << "\n/!\\ ERROR: An error occured while creating " << path << endl;
return false;
}
return true;
}
std::string system_get_output(std::string cmd)
{
FILE * command_output;
char output[128];
int amount_read = 1;
string full_output;
std::string full_output;
try
{
command_output = popen(cmd.c_str(), "r");
if (command_output == NULL) throw;
if(command_output == NULL) throw;
while(amount_read > 0)
{
amount_read = fread(output, 1, 127, command_output);
if (amount_read <= 0) break;
output[amount_read] = '\0';
full_output += output;
if(amount_read <= 0) break;
else
{
output[amount_read] = '\0';
full_output += output;
}
}
}
catch(...)
{
cerr << "An error occured while executing command " << cmd.c_str() << endl;
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 "";
if(return_value != 0) return "";
return full_output;
}
int systemp(string& cmd)
int systemp(const std::string& cmd)
{
cout << " " << cmd.c_str() << endl;
if(!Settings::quietOutput()) std::cout << " " << cmd << "\n";
return system(cmd.c_str());
}
string getUserInputDirForFile(const string& filename)
std::string getUserInputDirForFile(const std::string& filename)
{
const int searchPathAmount = Settings::searchPathAmount();
for(int n=0; n<searchPathAmount; n++)
{
string searchPath = Settings::searchPath(n);
if (!searchPath.empty() && searchPath[ searchPath.size()-1 ] != '/') searchPath += "/";
auto searchPath = Settings::searchPath(n);
if( !searchPath.empty() && searchPath[ searchPath.size()-1 ] != '/' ) searchPath += "/";
if (!fileExists(searchPath+filename)) continue;
cerr << (searchPath+filename) << " was found. /!\\ DYLIBBUNDLER MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Manually check the executable with 'otool -L'" << endl;
if( !fileExists( searchPath+filename ) ) continue;
std::cerr << (searchPath+filename) << " was found. /!\\ DYLIBBUNDLER MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Manually check the executable with 'otool -L'" << std::endl;
return searchPath;
}
while(true)
while (true)
{
cout << "Please specify the directory where this library is located (or enter 'quit' to abort): "; fflush(stdout);
std::cout << "Please specify the directory where this library is located (or enter 'quit' to abort): "; fflush(stdout);
string prefix;
cin >> prefix;
cout << endl;
std::string prefix;
std::cin >> prefix;
std::cout << std::endl;
if (prefix.compare("quit") == 0) exit(1);
if(prefix.compare("quit")==0) exit(1);
if (!prefix.empty() && prefix[ prefix.size()-1 ] != '/') prefix += "/";
if (!fileExists(prefix+filename))
if( !fileExists( prefix+filename ) )
{
cerr << (prefix+filename) << " does not exist. Try again" << endl;
std::cerr << (prefix+filename) << " does not exist. Try again" << std::endl;
continue;
}
cerr << (prefix+filename) << " was found. /!\\ DYLIBBUNDLER MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Manually check the executable with 'otool -L'" << endl;
Settings::addSearchPath(prefix);
return prefix;
else
{
std::cerr << (prefix+filename) << " was found. /!\\ DYLIBBUNDLER MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Manually check the executable with 'otool -L'" << std::endl;
Settings::addSearchPath(prefix);
return prefix;
}
}
}
string bundleExecutableName(const string& app_bundle_path)
{
string cmd = "/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "
+ app_bundle_path + "Contents/Info.plist";
return system_get_output(cmd);
string cmd = "/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' " + app_bundle_path + "Contents/Info.plist";
return rtrim(system_get_output(cmd));
}
void changeId(string binary_file, string new_id)
{
string command = string("install_name_tool -id ") + new_id + " " + binary_file;
if (systemp(command) != 0)
if( systemp( command ) != 0 )
{
cerr << "\n\nError: An error occured while trying to change identity of library " << binary_file << endl;
exit(1);
@ -246,7 +280,7 @@ void changeId(string binary_file, string new_id)
void changeInstallName(string binary_file, string old_name, string new_name)
{
string command = string("install_name_tool -change ") + old_name + " " + new_name + " " + binary_file;
if (systemp(command) != 0)
if( systemp( command ) != 0 )
{
cerr << "\n\nError: An error occured while trying to fix dependencies of " << binary_file << endl;
exit(1);
@ -257,27 +291,39 @@ void initSearchPaths()
{
string searchPaths;
char* dyldLibPath = getenv("DYLD_LIBRARY_PATH");
if (dyldLibPath != 0) searchPaths = dyldLibPath;
if(dyldLibPath != 0) searchPaths = dyldLibPath;
dyldLibPath = getenv("DYLD_FALLBACK_FRAMEWORK_PATH");
if (dyldLibPath != 0)
if(dyldLibPath != 0)
{
if (!searchPaths.empty() && searchPaths[ searchPaths.size()-1 ] != ':') searchPaths += ":";
if( !searchPaths.empty() && searchPaths[ searchPaths.size()-1 ] != ':' ) searchPaths += ":";
searchPaths += dyldLibPath;
}
dyldLibPath = getenv("DYLD_FALLBACK_LIBRARY_PATH");
if (dyldLibPath!=0)
if(dyldLibPath != 0)
{
if (!searchPaths.empty() && searchPaths[ searchPaths.size()-1 ] != ':') searchPaths += ":";
if( !searchPaths.empty() && searchPaths[ searchPaths.size()-1 ] != ':' ) searchPaths += ":";
searchPaths += dyldLibPath;
}
if (!searchPaths.empty())
if(!searchPaths.empty())
{
stringstream ss(searchPaths);
string item;
while(getline(ss, item, ':'))
{
if (item[ item.size()-1 ] != '/') item += "/";
if( item[ item.size()-1 ] != '/' ) item += "/";
Settings::addSearchPath(item);
}
}
}
void createQtConf(std::string directory)
{
std::string contents = "[Paths]\n"
"Plugins = PlugIns\n"
"Imports = Resources/qml\n"
"Qml2Imports = Resources/qml\n";
if( directory[ directory.size()-1 ] != '/' ) directory += "/";
std::ofstream out(directory + "qt.conf");
out << contents;
out.close();
}

View File

@ -48,13 +48,18 @@ void tokenize(const std::string& str, const char* delimiters, std::vector<std::s
bool fileExists( std::string filename );
void copyFile(std::string from, std::string to);
void deleteFile(std::string path, bool overwrite);
void deleteFile(std::string path);
std::vector<std::string> lsDir(const std::string& path);
bool mkdir(const std::string& path);
// 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);
int systemp(const std::string& cmd);
std::string getUserInputDirForFile(const std::string& filename);
@ -66,4 +71,6 @@ void changeInstallName(std::string binary_file, std::string old_name, std::strin
// check the same paths the system would search for dylibs
void initSearchPaths();
void createQtConf(std::string directory);
#endif

View File

@ -65,7 +65,7 @@ void showHelp()
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 <location to ignore> (will ignore libraries in this directory)" << std::endl;
std::cout << "-q, --quiet Less verbose output" << std::endl;
std::cout << "-q, --quiet (less verbose output)" << std::endl;
std::cout << "-h, --help" << std::endl;
}
@ -162,7 +162,7 @@ int main (int argc, char * const argv[])
exit(0);
}
std::cout << "* Collecting dependencies"; fflush(stdout);
std::cout << "Collecting dependencies..." << std::endl;
const int amount = Settings::fileToFixAmount();
for(int n=0; n<amount; n++)