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]; char original_file_buffer[PATH_MAX];
std::string original_file; std::string original_file;
std::string warning_msg;
rtrim_in_place(path); 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)) 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; original_file = path;
} }
else 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 // check if this dependency is in /usr/lib, /System/Library, or in ignored list
if (!Settings::isPrefixBundled(prefix)) return; 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 //check if the lib is in a known location
if (prefix.empty() || !fileExists(prefix+filename)) 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); std::string search_path = Settings::searchPath(i);
if (fileExists(search_path+filename)) 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; prefix = search_path;
Settings::missingPrefixes(true); //the prefix was missing Settings::missingPrefixes(true); //the prefix was missing
break; break;
} }
} }
} }
if (!Settings::quietOutput()) std::cout << warning_msg;
//If the location is still unknown, ask the user for search path //If the location is still unknown, ask the user for search path
if ( !Settings::isPrefixIgnored(prefix) && ( prefix.empty() || !fileExists(prefix+filename) ) ) 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::missingPrefixes(true);
Settings::addSearchPath(getUserInputDirForFile(filename)); Settings::addSearchPath(getUserInputDirForFile(filename));
} }
@ -107,13 +123,12 @@ Dependency::Dependency(std::string path, std::string dependent_file) : is_framew
void Dependency::print() void Dependency::print()
{ {
std::cout << std::endl; std::cout << "\n* " << filename.c_str() << " from " << prefix.c_str() << std::endl;
std::cout << " * " << filename.c_str() << " from " << prefix.c_str() << std::endl;
const int symamount = symlinks.size(); const int symamount = symlinks.size();
for(int n=0; n<symamount; n++) 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 getOriginalPath() const{ return prefix+filename; }
std::string getInstallPath(); std::string getInstallPath();
std::string getInnerPath(); std::string getInnerPath();
bool isFramework(){ return is_framework; }
void addSymlink(std::string s); void addSymlink(std::string s);
int getSymlinkAmount() const{ return symlinks.size(); } int getSymlinkAmount() const{ return symlinks.size(); }

View File

@ -40,9 +40,11 @@ THE SOFTWARE.
std::vector<Dependency> deps; std::vector<Dependency> deps;
std::map<std::string, std::vector<Dependency> > deps_per_file; std::map<std::string, std::vector<Dependency> > deps_per_file;
std::map<std::string, bool> deps_collected; std::map<std::string, bool> deps_collected;
std::set<std::string> frameworks;
std::set<std::string> rpaths; std::set<std::string> rpaths;
std::map<std::string, std::vector<std::string> > rpaths_per_file; std::map<std::string, std::vector<std::string> > rpaths_per_file;
std::map<std::string, std::string> rpath_to_fullpath; std::map<std::string, std::string> rpath_to_fullpath;
bool qt_plugins_called = false;
void changeLibPathsOnFile(std::string file_to_fix) void changeLibPathsOnFile(std::string file_to_fix)
{ {
@ -50,7 +52,8 @@ void changeLibPathsOnFile(std::string file_to_fix)
{ {
collectDependencies(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(); const int dep_amount = deps_per_file[file_to_fix].size();
for(int n=0; n<dep_amount; n++) for(int n=0; n<dep_amount; n++)
@ -206,11 +209,21 @@ std::string searchFilenameInRpaths(const std::string& rpath_file, const std::str
break; break;
} }
} }
std::cerr << "\n/!\\ WARNING : can't get path for '" << rpath_file << "'\n"; if (fullpath.empty())
fullpath = getUserInputDirForFile(suffix) + suffix;
if (realpath(fullpath.c_str(), fullpath_buffer))
{ {
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; 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 ") + std::string command = std::string("install_name_tool -rpath ") +
rpaths_to_fix[i] + " " + Settings::inside_lib_path() + " " + file_to_fix; 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; std::cerr << "\n\nError : An error occured while trying to fix dependencies of " << file_to_fix << std::endl;
exit(1); exit(1);
@ -252,22 +265,23 @@ void addDependency(std::string path, std::string filename)
const int dep_amount = deps.size(); const int dep_amount = deps.size();
for(int n=0; n<dep_amount; n++) 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 // 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; 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++) 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) deps.push_back(dep);
if (!in_deps_per_file) deps_per_file[filename].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; std::vector<std::string> lines;
collectDependencies(filename, lines); collectDependencies(filename, lines);
std::cout << "."; fflush(stdout);
const int line_amount = lines.size(); const int line_amount = lines.size();
for(int n=0; n<line_amount; n++) 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 (lines[n][0] != '\t') continue; // only lines beginning with a tab interest us if(!Settings::isPrefixBundled(lines[n])) continue; // skip system/ignored prefixes
if (!Settings::isPrefixBundled(lines[n])) continue; // skip system/ignored prefixes
// trim useless info, keep only library name // trim useless info, keep only library name
std::string dep_path = lines[n].substr(1, lines[n].rfind(" (") - 1); std::string dep_path = lines[n].substr(1, lines[n].rfind(" (") - 1);
if (isRpath(dep_path))
{
collectRpathsForFilename(filename);
}
addDependency(dep_path, filename); addDependency(dep_path, filename);
} }
deps_collected[filename] = true; deps_collected[filename] = true;
@ -340,7 +345,7 @@ void collectDependencies(std::string filename)
void collectSubDependencies() void collectSubDependencies()
{ {
// print status to user size_t dep_counter = deps.size();
int dep_amount = deps.size(); int dep_amount = deps.size();
// recursively collect each dependencie's dependencies // recursively collect each dependencie's dependencies
@ -349,51 +354,48 @@ void collectSubDependencies()
dep_amount = deps.size(); dep_amount = deps.size();
for(int n=0; n<dep_amount; n++) for(int n=0; n<dep_amount; n++)
{ {
std::cout << "."; fflush(stdout);
std::vector<std::string> lines; std::vector<std::string> lines;
std::string original_path = deps[n].getOriginalPath(); std::string original_path = deps[n].getOriginalPath();
std::string full_path = original_path;
if (isRpath(original_path)) if (isRpath(original_path))
{ {
full_path = searchFilenameInRpaths(original_path); original_path = searchFilenameInRpaths(original_path);
} }
collectRpathsForFilename(full_path); collectRpathsForFilename(original_path);
collectDependencies(full_path, lines); collectDependencies(original_path, lines);
const int line_amount = lines.size(); const int line_amount = lines.size();
for(int n=0; n<line_amount; n++) for(int n=0; n<line_amount; n++)
{ {
if (lines[n][0] != '\t') continue; // only lines beginning with a tab interest us 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 (!Settings::isPrefixBundled(lines[n])) continue; // skip system/ignored prefixes
// trim useless info, keep only library name // trim useless info, keep only library name
std::string dep_path = lines[n].substr(1, lines[n].rfind(" (") - 1); 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); addDependency(dep_path, original_path);
}//next }//next
}//next }//next
if (deps.size() == dep_amount) break; // no more dependencies were added on this iteration, stop searching 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() void createDestDir()
{ {
std::string dest_folder = Settings::destFolder(); 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 ---------- // ----------- check dest folder stuff ----------
bool dest_exists = fileExists(dest_folder); 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; 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; std::cerr << "\n\nError : An error occured while attempting to overwrite dest folder." << std::endl;
exit(1); exit(1);
@ -401,14 +403,14 @@ void createDestDir()
dest_exists = false; 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; 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; std::cerr << "\n\nError : An error occured while creating dest folder." << std::endl;
exit(1); exit(1);
@ -425,7 +427,6 @@ void createDestDir()
void doneWithDeps_go() void doneWithDeps_go()
{ {
std::cout << std::endl;
const int dep_amount = deps.size(); const int dep_amount = deps.size();
// print info to user // print info to user
for(int n=0; n<dep_amount; n++) for(int n=0; n<dep_amount; n++)
@ -435,7 +436,7 @@ void doneWithDeps_go()
std::cout << std::endl; std::cout << std::endl;
// copy files if requested by user // copy files if requested by user
if (Settings::bundleLibs()) if(Settings::bundleLibs())
{ {
createDestDir(); createDestDir();
@ -454,3 +455,117 @@ void doneWithDeps_go()
fixRpathsOnFile(Settings::fileToFix(n), Settings::fileToFix(n)); 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 fixRpathsOnFile(const std::string& original_file, const std::string& file_to_fix);
void addDependency(std::string path, std::string dependent_file); 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 collectSubDependencies();
void doneWithDeps_go(); void doneWithDeps_go();
void copyQtPlugins();
#endif #endif

View File

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

View File

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

View File

@ -28,6 +28,7 @@ THE SOFTWARE.
#include "Settings.h" #include "Settings.h"
#include <cstdlib> #include <cstdlib>
#include <unistd.h> #include <unistd.h>
#include <fstream>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <cstdio> #include <cstdio>
@ -76,49 +77,54 @@ string rtrim(string s)
void tokenize(const string& str, const char* delim, vector<string>* vectorarg) void tokenize(const string& str, const char* delim, vector<string>* vectorarg)
{ {
vector<string>& tokens = *vectorarg; vector<string>& tokens = *vectorarg;
string delimiters(delim); string delimiters(delim);
// skip delimiters at beginning. // 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". // find first "non-delimiter".
string::size_type pos = str.find_first_of(delimiters, lastPos); 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. // found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos)); tokens.push_back(str.substr(lastPos, pos - lastPos));
// skip delimiters. Note the "not_of" // skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of(delimiters, pos); lastPos = str.find_first_not_of(delimiters, pos);
// find next "non-delimiter" // find next "non-delimiter"
pos = str.find_first_of(delimiters, lastPos); pos = str.find_first_of(delimiters, lastPos);
} }
} }
bool fileExists(string filename) 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 delims = " \f\n\r\t\v";
string rtrimmed = filename.substr(0, filename.find_last_not_of(delims)+1); string rtrimmed = filename.substr(0, filename.find_last_not_of(delims)+1);
string ftrimmed = rtrimmed.substr(rtrimmed.find_first_not_of(delims)); 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 return false; // file doesn't exist
} }
void copyFile(string from, string to) void copyFile(string from, string to)
{ {
bool overwrite = Settings::canOverwriteFiles(); 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; cerr << "\n\nError : File " << to.c_str() << " already exists. Remove it or enable overwriting." << endl;
exit(1); exit(1);
} }
} }
// copy file/directory // copy file to local directory
string overwrite_permission = string(overwrite ? "-f " : "-n "); string overwrite_permission = string(overwrite ? "-f " : "-n ");
string command = string("cp -R ") + overwrite_permission + from + string(" ") + to; string command = string("cp -R ") + overwrite_permission + from + string(" ") + to;
if (from != to && systemp(command) != 0) if (from != to && systemp(command) != 0)
@ -127,9 +133,9 @@ void copyFile(string from, string to)
exit(1); exit(1);
} }
// give file/directory write permission // give it write permission
string command2 = string("chmod -R +w ") + to; 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; cerr << "\n\nError : An error occured while trying to set write permissions on file " << to << endl;
exit(1); exit(1);
@ -140,7 +146,7 @@ void deleteFile(string path, bool overwrite)
{ {
string overwrite_permission = string(overwrite ? "-f " : " "); string overwrite_permission = string(overwrite ? "-f " : " ");
string command = string("rm -r ") + overwrite_permission + path; 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; cerr << "\n\nError: An error occured while trying to delete " << path << endl;
exit(1); exit(1);
@ -153,90 +159,118 @@ void deleteFile(string path)
deleteFile(path, overwrite); 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]; char output[128];
int amount_read = 1; int amount_read = 1;
string full_output;
std::string full_output;
try try
{ {
command_output = popen(cmd.c_str(), "r"); command_output = popen(cmd.c_str(), "r");
if (command_output == NULL) throw; if(command_output == NULL) throw;
while(amount_read > 0) while(amount_read > 0)
{ {
amount_read = fread(output, 1, 127, command_output); amount_read = fread(output, 1, 127, command_output);
if (amount_read <= 0) break; if(amount_read <= 0) break;
output[amount_read] = '\0'; else
full_output += output; {
output[amount_read] = '\0';
full_output += output;
}
} }
} }
catch(...) 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); pclose(command_output);
return ""; return "";
} }
int return_value = pclose(command_output); int return_value = pclose(command_output);
if (return_value != 0) return ""; if(return_value != 0) return "";
return full_output; 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()); return system(cmd.c_str());
} }
string getUserInputDirForFile(const string& filename) std::string getUserInputDirForFile(const std::string& filename)
{ {
const int searchPathAmount = Settings::searchPathAmount(); const int searchPathAmount = Settings::searchPathAmount();
for(int n=0; n<searchPathAmount; n++) for(int n=0; n<searchPathAmount; n++)
{ {
string searchPath = Settings::searchPath(n); auto searchPath = Settings::searchPath(n);
if (!searchPath.empty() && searchPath[ searchPath.size()-1 ] != '/') searchPath += "/"; if( !searchPath.empty() && searchPath[ searchPath.size()-1 ] != '/' ) searchPath += "/";
if (!fileExists(searchPath+filename)) continue; 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; std::cerr << (searchPath+filename) << " was found. /!\\ DYLIBBUNDLER MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Manually check the executable with 'otool -L'" << std::endl;
return searchPath; 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; std::string prefix;
cin >> prefix; std::cin >> prefix;
cout << endl; 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 (!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; continue;
} }
else
cerr << (prefix+filename) << " was found. /!\\ DYLIBBUNDLER MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Manually check the executable with 'otool -L'" << endl; {
Settings::addSearchPath(prefix); std::cerr << (prefix+filename) << " was found. /!\\ DYLIBBUNDLER MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Manually check the executable with 'otool -L'" << std::endl;
return prefix; Settings::addSearchPath(prefix);
return prefix;
}
} }
} }
string bundleExecutableName(const string& app_bundle_path) string bundleExecutableName(const string& app_bundle_path)
{ {
string cmd = "/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' " string cmd = "/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' " + app_bundle_path + "Contents/Info.plist";
+ app_bundle_path + "Contents/Info.plist"; return rtrim(system_get_output(cmd));
return system_get_output(cmd);
} }
void changeId(string binary_file, string new_id) void changeId(string binary_file, string new_id)
{ {
string command = string("install_name_tool -id ") + new_id + " " + binary_file; 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; cerr << "\n\nError: An error occured while trying to change identity of library " << binary_file << endl;
exit(1); 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) void changeInstallName(string binary_file, string old_name, string new_name)
{ {
string command = string("install_name_tool -change ") + old_name + " " + new_name + " " + binary_file; 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; cerr << "\n\nError: An error occured while trying to fix dependencies of " << binary_file << endl;
exit(1); exit(1);
@ -257,27 +291,39 @@ void initSearchPaths()
{ {
string searchPaths; string searchPaths;
char* dyldLibPath = getenv("DYLD_LIBRARY_PATH"); char* dyldLibPath = getenv("DYLD_LIBRARY_PATH");
if (dyldLibPath != 0) searchPaths = dyldLibPath; if(dyldLibPath != 0) searchPaths = dyldLibPath;
dyldLibPath = getenv("DYLD_FALLBACK_FRAMEWORK_PATH"); 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; searchPaths += dyldLibPath;
} }
dyldLibPath = getenv("DYLD_FALLBACK_LIBRARY_PATH"); 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; searchPaths += dyldLibPath;
} }
if (!searchPaths.empty()) if(!searchPaths.empty())
{ {
stringstream ss(searchPaths); stringstream ss(searchPaths);
string item; string item;
while(getline(ss, item, ':')) while(getline(ss, item, ':'))
{ {
if (item[ item.size()-1 ] != '/') item += "/"; if( item[ item.size()-1 ] != '/' ) item += "/";
Settings::addSearchPath(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 ); bool fileExists( std::string filename );
void copyFile(std::string from, std::string to); void copyFile(std::string from, std::string to);
void deleteFile(std::string path, bool overwrite); void deleteFile(std::string path, bool overwrite);
void deleteFile(std::string path); 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 // executes a command in the native shell and returns output in string
std::string system_get_output(std::string cmd); std::string system_get_output(std::string cmd);
// like 'system', runs a command on the system shell, but also prints the command to stdout. // 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); 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 // check the same paths the system would search for dylibs
void initSearchPaths(); void initSearchPaths();
void createQtConf(std::string directory);
#endif #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 << "-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 << "-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 << "-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; std::cout << "-h, --help" << std::endl;
} }
@ -162,7 +162,7 @@ int main (int argc, char * const argv[])
exit(0); exit(0);
} }
std::cout << "* Collecting dependencies"; fflush(stdout); std::cout << "Collecting dependencies..." << std::endl;
const int amount = Settings::fileToFixAmount(); const int amount = Settings::fileToFixAmount();
for(int n=0; n<amount; n++) for(int n=0; n<amount; n++)