clean up & refine formatting

This commit is contained in:
SCG82 2019-12-14 13:03:55 -08:00
parent fa16d5e817
commit 98ee4209da
6 changed files with 76 additions and 196 deletions

View File

@ -14,7 +14,6 @@
#include <sys/param.h>
#include "DylibBundler.h"
// #include "ParallelForEach.h"
#include "Settings.h"
#include "Utils.h"
@ -44,7 +43,7 @@ std::vector<std::string> paths;
// initialize the dylib search paths
void initSearchPaths()
{
//Check the same paths the system would search for dylibs
// check the same paths the system would search for dylibs
std::string searchPaths;
char *dyldLibPath = std::getenv("DYLD_LIBRARY_PATH");
if (dyldLibPath != 0)
@ -72,20 +71,20 @@ void initSearchPaths()
}
}
// if some libs are missing prefixes, this will be set to true
// more stuff will then be necessary to do
// if some libs are missing prefixes, then more stuff will be necessary to do
bool missing_prefixes = false;
Dependency::Dependency(std::string path)
{
char original_file_buffer[PATH_MAX];
std::string original_file;
std::string warning_msg;
if (isRpath(path)) {
original_file = searchFilenameInRpaths(path);
}
else if (!realpath(rtrim(path).c_str(), original_file_buffer)) {
std::cerr << "\n/!\\ WARNING : Cannot resolve path '" << path << "'" << std::endl;
warning_msg = "\n/!\\ WARNING: Cannot resolve path '" + path + "'.\n";
original_file = path;
}
else {
@ -114,31 +113,34 @@ Dependency::Dependency(std::string path)
// check if file is contained in one of the paths
for (size_t i=0; i<paths.size(); ++i) {
if (fileExists(paths[i]+filename)) {
std::cout << "FOUND " << filename << " in " << paths[i] << std::endl;
warning_msg += "FOUND " + filename + " in " + paths[i] + ".\n";
prefix = paths[i];
missing_prefixes = true; // the prefix was missing
missing_prefixes = true;
break;
}
}
}
if (Settings::verboseOutput())
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;
std::cerr << "\n/!\\ WARNING: Library " << filename << " has an incomplete name (location unknown).\n";
missing_prefixes = true;
paths.push_back(getUserInputDirForFile(filename));
}
// new_name = filename.substr(0, filename.find(".")) + ".dylib";
new_name = filename;
}
void Dependency::print()
{
std::cout << "\n * " << filename << " from " << prefix << "\n";
const int symamount = symlinks.size();
std::cout << std::endl << " * " << filename << " from " << prefix << std::endl;
for (int n=0; n<symamount; ++n)
std::cout << " symlink --> " << symlinks[n] << std::endl;;
std::cout << " symlink --> " << symlinks[n] << "\n";;
}
std::string Dependency::getInstallPath()
@ -153,13 +155,12 @@ std::string Dependency::getInnerPath()
void Dependency::addSymlink(std::string s)
{
// calling std::find on this vector is not near as slow as an extra invocation of install_name_tool
// calling std::find on this vector is not as slow as an extra invocation of install_name_tool
if (std::find(symlinks.begin(), symlinks.end(), s) == symlinks.end())
symlinks.push_back(s);
}
// compare the given Dependency with this one.
// if both refer to the same file, merge both entries into one
// compare given Dependency with this one. if both refer to the same file, merge into one entry.
bool Dependency::mergeIfSameAs(Dependency& dep2)
{
if (dep2.getOriginalFileName().compare(filename) == 0) {
@ -174,10 +175,11 @@ bool Dependency::mergeIfSameAs(Dependency& dep2)
void Dependency::copyYourself()
{
copyFile(getOriginalPath(), getInstallPath());
// Fix the lib's inner name
// fix the lib's inner name
std::string command = std::string("install_name_tool -id ") + getInnerPath() + " " + getInstallPath();
if (systemp(command) != 0) {
std::cerr << "\n\nError : An error occured while trying to change identity of library " << getInstallPath() << std::endl;
std::cerr << "\n\nError: An error occured while trying to change identity of library " << getInstallPath() << ".\n";
exit(1);
}
}
@ -187,7 +189,7 @@ void Dependency::fixFileThatDependsOnMe(std::string file_to_fix)
// for main lib file
std::string command = std::string("install_name_tool -change ") + getOriginalPath() + " " + getInnerPath() + " " + file_to_fix;
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 << ".\n";
exit(1);
}
@ -196,7 +198,7 @@ void Dependency::fixFileThatDependsOnMe(std::string file_to_fix)
for (int n=0; n<symamount; ++n) {
command = std::string("install_name_tool -change ") + symlinks[n] + " " + getInnerPath() + " " + file_to_fix;
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 << ".\n";
exit(1);
}
}
@ -206,7 +208,7 @@ void Dependency::fixFileThatDependsOnMe(std::string file_to_fix)
// for main lib file
command = std::string("install_name_tool -change ") + filename + " " + getInnerPath() + " " + file_to_fix;
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 << ".\n";
exit(1);
}
@ -214,7 +216,7 @@ void Dependency::fixFileThatDependsOnMe(std::string file_to_fix)
for (int n=0; n<symamount; ++n) {
command = std::string("install_name_tool -change ") + symlinks[n] + " " + getInnerPath() + " " + file_to_fix;
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 << ".\n";
exit(1);
}
}

View File

@ -6,14 +6,11 @@
#include <map>
#include <numeric>
#include <set>
#include <sys/wait.h>
#ifdef __linux
#include <linux/limits.h>
#endif
#include "Dependency.h"
// #include "ParallelForEach.h"
#include "Settings.h"
#include "Utils.h"
@ -21,32 +18,31 @@ std::vector<Dependency> deps;
std::map<std::string, std::vector<Dependency>> deps_per_file;
std::set<std::string> rpaths;
std::map<std::string, std::vector<std::string>> rpaths_per_file;
std::map<std::string, bool> deps_collected;
void changeLibPathsOnFile(std::string file_to_fix)
{
std::cout << "\n* Fixing dependencies on " << file_to_fix << std::endl;
if (deps_collected.find(file_to_fix) == deps_collected.end())
collectDependencies(file_to_fix);
std::cout << "\n* Fixing dependencies on " << file_to_fix << "...\n";
// const int dep_amount = deps.size();
std::vector<Dependency> deps_in_file = deps_per_file[file_to_fix];
const int dep_amount = deps_in_file.size();
for (int n=0; n<dep_amount; ++n) {
// deps[n].fixFileThatDependsOnMe(file_to_fix);
for (int n=0; n<dep_amount; ++n)
deps_in_file[n].fixFileThatDependsOnMe(file_to_fix);
}
}
bool isRpath(const std::string& path)
{
std::cout << "path: " << path << std::endl;
size_t result = path.find("@rpath");
std::cout << "isRpath? " << (result == 0 ? "yes" : "no") << std::endl;
return (result == 0);
}
void collectRpaths(const std::string& filename)
{
if (!fileExists(filename)) {
std::cerr << "\n/!\\ WARNING : can't collect rpaths for nonexistent file '" << filename << "'\n";
std::cerr << "\n/!\\ WARNING: Can't collect rpaths for nonexistent file '" << filename << "'.\n";
return;
}
@ -66,7 +62,7 @@ void collectRpaths(const std::string& filename)
size_t start_pos = line.find("path ");
size_t end_pos = line.find(" (");
if (start_pos == std::string::npos || end_pos == std::string::npos) {
std::cerr << "\n/!\\ WARNING: Unexpected LC_RPATH format\n";
std::cerr << "\n/!\\ WARNING: Unexpected LC_RPATH format.\n";
continue;
}
start_pos += 5;
@ -86,10 +82,8 @@ void collectRpaths(const std::string& filename)
void collectRpathsForFilename(const std::string& filename)
{
std::cout << "collecting rpaths for: " << filename << std::endl;
if (rpaths_per_file.find(filename) == rpaths_per_file.end()) {
if (rpaths_per_file.find(filename) == rpaths_per_file.end())
collectRpaths(filename);
}
}
std::string searchFilenameInRpaths(const std::string& rpath_file)
@ -97,7 +91,6 @@ std::string searchFilenameInRpaths(const std::string& rpath_file)
char buffer[PATH_MAX];
std::string fullpath;
std::string suffix = rpath_file.substr(7, rpath_file.size()-6);
std::cout << "suffix: " << suffix << std::endl;
for (std::set<std::string>::iterator it = rpaths.begin(); it != rpaths.end(); ++it) {
std::string path = *it + "/" + suffix;
@ -109,10 +102,10 @@ std::string searchFilenameInRpaths(const std::string& rpath_file)
if (fullpath.empty()) {
if (Settings::verboseOutput())
std::cerr << "\n/!\\ WARNING : can't get path for '" << rpath_file << "'\n";
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'.\n";
fullpath = getUserInputDirForFile(suffix) + suffix;
if (!Settings::verboseOutput() && fullpath.empty())
std::cerr << "\n/!\\ WARNING : can't get path for '" << rpath_file << "'\n";
std::cerr << "\n/!\\ WARNING: Can't get path for '" << rpath_file << "'.\n";
if (realpath(fullpath.c_str(), buffer))
fullpath = buffer;
}
@ -134,7 +127,7 @@ void fixRpathsOnFile(const std::string& original_file, const std::string& file_t
+ Settings::inside_lib_path() + " "
+ file_to_fix;
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\n/!\\ ERROR: An error occured while trying to fix dependencies of " << file_to_fix << ".\n";
exit(1);
}
}
@ -190,21 +183,18 @@ void addDependency(std::string path, std::string filename)
// Fill |lines| with dependencies of given |filename|
void collectDependencies(std::string filename, std::vector<std::string>& lines)
{
std::cout << "collecting deps for: " << filename << std::endl;
std::string cmd = "otool -L " + filename;
std::string output = system_get_output(cmd);
if (
output.find("can't open file") != std::string::npos ||
output.find("No such file") != std::string::npos ||
output.size() < 1
) {
std::cerr << "Cannot find file " << filename << " to read its dependencies" << std::endl;
if (output.find("can't open file") != std::string::npos
|| output.find("No such file") != std::string::npos
|| output.size() < 1) {
std::cerr << "\n\n/!\\ ERROR: Cannot find file " << filename << " to read its dependencies.\n";
exit(1);
}
// split output
tokenize(output, "\n", &lines);
deps_collected[filename] = true;
}
void collectDependencies(std::string filename)
@ -212,22 +202,19 @@ 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);
// only lines beginning with a tab interest us
if (lines[n][0] != '\t')
continue; // only lines beginning with a tab interest us
continue;
// ignore frameworks, we cannot handle them
if (lines[n].find(".framework") != std::string::npos)
continue; // ignore frameworks, we cannot handle them
continue;
// trim useless info, keep only library path
std::string dep_path = lines[n].substr(1, lines[n].rfind(" (") - 1);
if (isRpath(dep_path)) {
std::cout << "collecting rpaths for " << filename << std::endl;
if (isRpath(dep_path))
collectRpathsForFilename(filename);
}
// addDependency(dep_path);
addDependency(dep_path, filename);
}
}
@ -241,49 +228,51 @@ 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();
if (isRpath(original_path))
original_path = searchFilenameInRpaths(original_path);
collectRpathsForFilename(original_path);
std::vector<std::string> lines;
collectDependencies(original_path, lines);
const int line_amount = lines.size();
for (int n=0; n<line_amount; n++) {
// only lines beginning with a tab interest us
if (lines[n][0] != '\t')
continue; // only lines beginning with a tab interest us
continue;
// ignore frameworks, we cannot handle them
if (lines[n].find(".framework") != std::string::npos)
continue; //Ignore frameworks, we cannot handle them
continue;
// trim useless info, keep only library name
std::string dep_path = lines[n].substr(1, lines[n].rfind(" (") - 1);
if (isRpath(dep_path)) {
dep_path = searchFilenameInRpaths(dep_path);
collectRpathsForFilename(dep_path);
}
// addDependency(dep_path);
addDependency(dep_path, dep_path);
}
}
// if 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
break;
}
}
void createDestDir()
{
std::string dest_folder = Settings::destFolder();
std::cout << "* Checking output directory " << dest_folder << std::endl;
std::cout << "* Checking output directory " << dest_folder << "...\n";
bool dest_exists = fileExists(dest_folder);
if (dest_exists && Settings::canOverwriteDir()) {
std::cout << "* Erasing old output directory " << dest_folder << std::endl;
std::cout << "* Erasing old output directory " << dest_folder << "...\n";
std::string command = std::string("rm -r ") + dest_folder;
if (systemp(command) != 0) {
std::cerr << "\n\nError : An error occured while attempting to overwrite dest folder." << std::endl;
std::cerr << "\n\n/!\\ ERROR: An error occured while attempting to overwrite dest folder.\n";
exit(1);
}
dest_exists = false;
@ -291,59 +280,29 @@ void createDestDir()
if (!dest_exists) {
if (Settings::canCreateDir()) {
std::cout << "* Creating output directory " << dest_folder << std::endl;
std::cout << "* Creating output directory " << dest_folder << "\n";
std::string command = std::string("mkdir -p ") + dest_folder;
if (systemp(command) != 0) {
std::cerr << "\n\nError : An error occured while creating dest folder." << std::endl;
std::cerr << "\n\n/!\\ ERROR: An error occured while creating dest folder.\n";
exit(1);
}
}
else {
std::cerr << "\n\nError : Dest folder does not exist. Create it or pass the appropriate flag for automatic dest dir creation." << std::endl;
std::cerr << "\n\n/!\\ ERROR: Dest folder does not exist. Create it or pass the appropriate flag for automatic dest dir creation.\n";
exit(1);
}
}
}
// 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++)
// deps[n].print();
// std::cout << std::endl;
// // copy files if requested by user
// if (Settings::bundleLibs()) {
// createDestDir();
// parallel_for(dep_amount, [&](int start, int end) {
// for (int i=start; i<end; ++i) {
// deps[i].copyYourself();
// changeLibPathsOnFile(deps[i].getInstallPath());
// fixRpathsOnFile(deps[i].getOriginalPath(), deps[i].getInstallPath());
// }
// });
// }
// const int fileToFixAmount = Settings::fileToFixAmount();
// parallel_for(fileToFixAmount, [&](int start, int end) {
// for (int i=start; i<end; ++i) {
// changeLibPathsOnFile(Settings::fileToFix(i));
// fixRpathsOnFile(Settings::fileToFix(i), Settings::fileToFix(i));
// }
// });
// }
void doneWithDeps_go()
{
const int dep_amount = deps.size();
std::cout << std::endl;
std::cout << "\n";
for (int n=0; n<dep_amount; n++)
deps[n].print();
std::cout << std::endl;
std::cout << "\n";
// copy files if requested by user
if (Settings::bundleLibs()) {
@ -356,12 +315,6 @@ void doneWithDeps_go()
}
}
// auto files = Settings::filesToFix();
// parallel_for_each(files.begin(), files.end(), [](const std::string& file) {
// changeLibPathsOnFile(file);
// fixRpathsOnFile(file, file);
// });
const int fileToFixAmount = Settings::fileToFixAmount();
for (int n=0; n<fileToFixAmount; n++) {
changeLibPathsOnFile(Settings::fileToFix(n));

View File

@ -1,56 +0,0 @@
#ifndef _parallel_for_h_
#define _parallel_for_h_
#include <algorithm>
#include <thread>
#include <functional>
#include <vector>
/**
* @param nb_elements size of your for loop
* @param functor(start, end) : your function processing a sub chunk of the for loop.
* "start" is the first index to process (included) until the index "end" (excluded)
* @code
* for(int i = start; i < end; ++i)
* computation(i);
* @endcode
* @param use_threads : enable / disable threads.
*
*/
static void parallel_for(unsigned nb_elements,
std::function<void (int start, int end)> functor,
bool use_threads = true)
{
unsigned nb_threads_hint = std::thread::hardware_concurrency();
unsigned nb_threads = nb_threads_hint == 0 ? 8 : nb_threads_hint;
unsigned batch_size = nb_elements / nb_threads;
unsigned batch_remainder = nb_elements % nb_threads;
std::vector<std::thread> my_threads(nb_threads);
if (use_threads) {
// Multithread execution
for (unsigned i = 0; i < nb_threads; ++i) {
int start = i * batch_size;
my_threads[i] = std::thread(functor, start, start+batch_size);
}
}
else {
// Single thread execution (for easy debugging)
for (unsigned i = 0; i < nb_threads; ++i) {
int start = i * batch_size;
functor(start, start+batch_size);
}
}
// Deform the elements left
int start = nb_threads * batch_size;
functor(start, start+batch_remainder);
// Wait for the other thread to finish their task
if (use_threads)
std::for_each(my_threads.begin(), my_threads.end(), std::mem_fn(&std::thread::join));
}
#endif

View File

@ -1,22 +0,0 @@
#ifndef _ParallelForEach_h_
#define _ParallelForEach_h_
#include <dispatch/dispatch.h>
template<typename It, typename F>
inline void parallel_for_each(It a, It b, F&& f)
{
size_t count = std::distance(a,b);
using data_t = std::pair<It, F>;
data_t helper = data_t(a, std::forward<F>(f));
dispatch_apply_f(count,
dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0),
&helper,
[](void* ctx, size_t cnt) {
data_t* d = static_cast<data_t*>(ctx);
auto elem_it = std::next(d->first, cnt);
(*d).second(*(elem_it));
});
}
#endif

View File

@ -19,7 +19,7 @@ bool bundleLibs_bool = false;
bool bundleLibs() { return bundleLibs_bool; }
void bundleLibs(bool on) { bundleLibs_bool = on; }
std::string dest_folder_str = "./libs/";
std::string dest_folder_str = "./Frameworks/";
std::string destFolder() { return dest_folder_str; }
void destFolder(std::string path)
{

View File

@ -51,7 +51,7 @@ void copyFile(std::string from, std::string to)
{
bool overwrite = Settings::canOverwriteFiles();
if (fileExists(to) && !overwrite) {
std::cerr << "\n\nError : File " << to << " already exists. Remove it or enable overwriting." << std::endl;
std::cerr << "\n\nError: File " << to << " already exists. Remove it or enable overwriting." << "\n";
exit(1);
}
@ -60,14 +60,14 @@ void copyFile(std::string from, std::string to)
// copy file to local directory
std::string command = std::string("cp ") + overwrite_permission + from + std::string(" ") + to;
if (from != to && systemp(command) != 0) {
std::cerr << "\n\nError : An error occured while trying to copy file " << from << " to " << to << std::endl;
std::cerr << "\n\nError: An error occured while trying to copy file " << from << " to " << to << "\n";
exit(1);
}
// give it write permission
std::string command2 = std::string("chmod +w ") + to;
if (systemp(command2) != 0) {
std::cerr << "\n\nError : An error occured while trying to set write permissions on file " << to << std::endl;
std::cerr << "\n\nError: An error occured while trying to set write permissions on file " << to << "\n";
exit(1);
}
}
@ -96,7 +96,7 @@ std::string system_get_output(std::string cmd)
}
}
catch (...) {
std::cerr << "An error occured while executing command " << cmd << std::endl;
std::cerr << "An error occured while executing command " << cmd << "\n";
pclose(command_output);
return "";
}
@ -111,7 +111,7 @@ std::string system_get_output(std::string cmd)
int systemp(std::string& cmd)
{
if (Settings::verboseOutput()) {
std::cout << " " << cmd << std::endl;
std::cout << " " << cmd << "\n";
}
return system(cmd.c_str());
}
@ -129,18 +129,21 @@ std::string getUserInputDirForFile(const std::string& filename)
else {
if (Settings::verboseOutput()) {
std::cerr << (searchPath+filename) << " was found.\n"
<< "/!\\ dylibbundler MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Check the executable with 'otool -L'" << std::endl;
<< "/!\\ dylibbundler MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Check the executable with 'otool -L'" << "\n";
}
return searchPath;
}
}
while (true) {
std::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);
std::string prefix;
std::cin >> prefix;
std::cout << std::endl;
// std::cout << std::endl;
// getline(std::cin, prefix);
if (prefix.compare("quit") == 0)
exit(1);
@ -149,13 +152,13 @@ std::string getUserInputDirForFile(const std::string& filename)
prefix += "/";
if (!fileExists(prefix+filename)) {
std::cerr << (prefix+filename) << " does not exist. Try again" << std::endl;
std::cerr << (prefix+filename) << " does not exist. Try again\n";
continue;
}
else {
if (Settings::verboseOutput()) {
std::cerr << (prefix+filename) << " was found.\n"
<< "/!\\ dylibbundler MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Check the executable with 'otool -L'" << std::endl;
<< "/!\\ dylibbundler MAY NOT CORRECTLY HANDLE THIS DEPENDENCY: Check the executable with 'otool -L'\n";
}
return prefix;
}