#!/usr/bin/env python

import re
import sys
import os
import shutil
import stat

is_bad_lib = re.compile(r'(/usr/local|/opt)').match
is_sys_lib = re.compile(r'(/usr|/System)').match
otool_libname_extract = re.compile(r'\s+(/.*?)[\(\s:]').search
goodlist = []
badlist = []
link_map = {}

def otool(cmdline):
	pipe = os.popen("otool " + cmdline, 'r')
	output = pipe.readlines()
	pipe.close()
	return output

def collectlibs(lib, masterlist, targetdir):
	global goodlist, link_map
	liblist = otool("-L '" + lib + "'")
	locallist = []

	for l in liblist:
		lr = otool_libname_extract(l)
		if not lr: continue
		l = lr.group(1)
		if is_bad_lib(l) and not l in badlist:
			badlist.append(l)
		if ((not is_sys_lib(l)) or is_bad_lib(l)) and not l in masterlist:
			locallist.append(l)
			print "found %s:" % l

			check = l
			link_list = []
			while check:
				if os.path.isfile(check) and not os.path.islink(check):
					os.system("cp '%s' '%s'" % (check, targetdir))
					print "    FILE %s ... copied to target" % check
					if link_list:
						for link in link_list:
							link_map[link] = os.path.basename(check)
					break
					
				if os.path.islink(check):
					print "    LINK %s" % check
					link_list.append(os.path.basename(check))
					check = os.path.dirname(check) + "/" + os.readlink(check)

		elif not l in goodlist and not l in masterlist:
			goodlist.append(l)
	masterlist.extend(locallist)

	for l in locallist:
		collectlibs(l, masterlist, targetdir)

exit;
binname = sys.argv[1]
targetdir = os.path.dirname(binname)
print "Searching for libraries in ", binname, "..."
libs = [binname]
collectlibs(sys.argv[1], libs, targetdir)


print
print "System libraries used..."
goodlist.sort()
for l in goodlist:
	print l


print
print "Fixing library install names..."
in_tool_cmdline = "install_name_tool "
for lib in libs:
	libbase = os.path.basename(lib)
	if libbase in link_map:
		libbase = link_map[libbase]
	in_tool_cmdline = in_tool_cmdline + ("-change '%s' '@executable_path/%s' " % (lib, libbase))
for lib in libs:
	libbase = os.path.basename(lib)

	if libbase in link_map:
		libbase = link_map[libbase]
		print "%s -> @executable_path/%s (REMAPPED)" % (lib, libbase)
	else:
		print "%s -> @executable_path/%s" % (lib, libbase)

	os.system("%s -id '@executable_path/%s' '%s/%s'" % (in_tool_cmdline, libbase, targetdir, libbase))
	sys.stdout.flush()

if badlist:
	print
	print "WARNING: The following libraries have blacklisted paths:"
	for lib in sorted(badlist):
		print lib
	print "These paths normally have files from a package manager, which means that end result may not work if copied to another machine."

print
print "All done!"

#!/usr/bin/env python

import re
import sys
import os
import shutil
import stat

is_bad_lib = re.compile(r'(/usr/local|/opt)').match
is_sys_lib = re.compile(r'(/usr|/System)').match
otool_libname_extract = re.compile(r'\s+(/.*?)[\(\s:]').search
goodlist = []
badlist = []
link_map = {}

def otool(cmdline):
	pipe = os.popen("otool " + cmdline, 'r')
	output = pipe.readlines()
	pipe.close()
	return output

def collectlibs(lib, masterlist, targetdir):
	global goodlist, link_map
	liblist = otool("-L '" + lib + "'")
	locallist = []

	for l in liblist:
		lr = otool_libname_extract(l)
		if not lr: continue
		l = lr.group(1)
		if is_bad_lib(l) and not l in badlist:
			badlist.append(l)
		if ((not is_sys_lib(l)) or is_bad_lib(l)) and not l in masterlist:
			locallist.append(l)
			print "found %s:" % l

			check = l
			link_list = []
			while check:
				if os.path.isfile(check) and not os.path.islink(check):
					os.system("cp '%s' '%s'" % (check, targetdir))
					print "    FILE %s ... copied to target" % check
					if link_list:
						for link in link_list:
							link_map[link] = os.path.basename(check)
					break
					
				if os.path.islink(check):
					print "    LINK %s" % check
					link_list.append(os.path.basename(check))
					check = os.path.dirname(check) + "/" + os.readlink(check)

		elif not l in goodlist and not l in masterlist:
			goodlist.append(l)
	masterlist.extend(locallist)

	for l in locallist:
		collectlibs(l, masterlist, targetdir)

exit;
binname = sys.argv[1]
targetdir = os.path.dirname(binname)
print "Searching for libraries in ", binname, "..."
libs = [binname]
collectlibs(sys.argv[1], libs, targetdir)


print
print "System libraries used..."
goodlist.sort()
for l in goodlist:
	print l


print
print "Fixing library install names..."
in_tool_cmdline = "install_name_tool "
for lib in libs:
	libbase = os.path.basename(lib)
	if libbase in link_map:
		libbase = link_map[libbase]
	in_tool_cmdline = in_tool_cmdline + ("-change '%s' '@executable_path/%s' " % (lib, libbase))
for lib in libs:
	libbase = os.path.basename(lib)

	if libbase in link_map:
		libbase = link_map[libbase]
		print "%s -> @executable_path/%s (REMAPPED)" % (lib, libbase)
	else:
		print "%s -> @executable_path/%s" % (lib, libbase)

	os.system("%s -id '@executable_path/%s' '%s/%s'" % (in_tool_cmdline, libbase, targetdir, libbase))
	sys.stdout.flush()

if badlist:
	print
	print "WARNING: The following libraries have blacklisted paths:"
	for lib in sorted(badlist):
		print lib
	print "These paths normally have files from a package manager, which means that end result may not work if copied to another machine."

print
print "All done!"

#!/usr/bin/env python