Prevent adding duplicate rpaths to bundled libs
This commit is contained in:
parent
27fbccaeab
commit
45d343e975
|
@ -1,7 +1,8 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
from subprocess import Popen, PIPE, check_call, check_output
|
||||||
import pprint
|
import pprint
|
||||||
|
import re
|
||||||
|
|
||||||
SYS_PATHS = ["/System/", "/usr/lib/"]
|
SYS_PATHS = ["/System/", "/usr/lib/"]
|
||||||
|
|
||||||
|
@ -63,8 +64,9 @@ class DepsGraph:
|
||||||
stack.append(ck)
|
stack.append(ck)
|
||||||
operation(self, self.graph[node_key], *op_args)
|
operation(self, self.graph[node_key], *op_args)
|
||||||
|
|
||||||
|
|
||||||
def is_macho(path):
|
def is_macho(path):
|
||||||
output = subprocess.check_output(["file", path])
|
output = check_output(["file", path])
|
||||||
if output.count("Mach-O") != 0:
|
if output.count("Mach-O") != 0:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ def get_path(name, search_paths):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def list_install_names(path_macho):
|
def list_install_names(path_macho):
|
||||||
output = subprocess.check_output(["otool", "-L", path_macho])
|
output = check_output(["otool", "-L", path_macho])
|
||||||
lines = output.split("\t")
|
lines = output.split("\t")
|
||||||
libs = []
|
libs = []
|
||||||
|
|
||||||
|
@ -129,7 +131,7 @@ def create_dep_nodes(install_names, search_paths):
|
||||||
path = get_path(lib_name, search_paths)
|
path = get_path(lib_name, search_paths)
|
||||||
|
|
||||||
if install_path != "" and lib[0] != "@":
|
if install_path != "" and lib[0] != "@":
|
||||||
#we have an absolte path install name
|
#we have an absolute path install name
|
||||||
if not path:
|
if not path:
|
||||||
path = install_path
|
path = install_path
|
||||||
|
|
||||||
|
@ -148,7 +150,6 @@ def paths_at_depth(prefix, paths, depth):
|
||||||
filtered.append(p)
|
filtered.append(p)
|
||||||
return filtered
|
return filtered
|
||||||
|
|
||||||
|
|
||||||
def should_visit(prefix, path_filters, path):
|
def should_visit(prefix, path_filters, path):
|
||||||
s_path = path.strip('/').split('/')
|
s_path = path.strip('/').split('/')
|
||||||
filters = []
|
filters = []
|
||||||
|
@ -227,14 +228,44 @@ def in_bundle(lib, bundle_path):
|
||||||
|
|
||||||
def copy_into_bundle(graph, node, bundle_path):
|
def copy_into_bundle(graph, node, bundle_path):
|
||||||
if not in_bundle(node.path, bundle_path):
|
if not in_bundle(node.path, bundle_path):
|
||||||
subprocess.check_call(["cp", "-L", os.path.join(node.path, node.name),
|
check_call([ "cp", "-L", os.path.join(node.path, node.name),
|
||||||
os.path.join(bundle_path, "lib", node.name)])
|
os.path.join(bundle_path, "lib", node.name) ])
|
||||||
|
|
||||||
node.path = os.path.join(bundle_path, "lib")
|
node.path = os.path.join(bundle_path, "lib")
|
||||||
|
|
||||||
#fix permissions
|
#fix permissions
|
||||||
subprocess.check_call(["chmod", "a+w", os.path.join(bundle_path,
|
check_call([ "chmod", "a+w",
|
||||||
"lib", node.name)])
|
os.path.join(bundle_path, "lib", node.name) ])
|
||||||
|
|
||||||
|
def get_rpaths(library):
|
||||||
|
"Returns a list of rpaths specified within library"
|
||||||
|
|
||||||
|
out = check_output(["otool", "-l", library])
|
||||||
|
|
||||||
|
pathRegex = r"^path (.*) \(offset \d+\)$"
|
||||||
|
expectingRpath = False
|
||||||
|
rpaths = []
|
||||||
|
for line in out.split('\n'):
|
||||||
|
line = line.strip()
|
||||||
|
|
||||||
|
if "cmd LC_RPATH" in line:
|
||||||
|
expectingRpath = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
if "Load command" in line:
|
||||||
|
expectingRpath = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not expectingRpath:
|
||||||
|
continue
|
||||||
|
|
||||||
|
m = re.match(pathRegex, line)
|
||||||
|
if m:
|
||||||
|
rpaths.append(m.group(1))
|
||||||
|
expectingRpath = False
|
||||||
|
|
||||||
|
return rpaths
|
||||||
|
|
||||||
def add_rpaths(graph, node, bundle_path):
|
def add_rpaths(graph, node, bundle_path):
|
||||||
if node.children:
|
if node.children:
|
||||||
lib = os.path.join(node.path, node.name)
|
lib = os.path.join(node.path, node.name)
|
||||||
|
@ -245,8 +276,8 @@ def add_rpaths(graph, node, bundle_path):
|
||||||
for install_name in install_names:
|
for install_name in install_names:
|
||||||
name = os.path.basename(install_name)
|
name = os.path.basename(install_name)
|
||||||
#change install names to use rpaths
|
#change install names to use rpaths
|
||||||
subprocess.check_call(["install_name_tool", "-change",
|
check_call([ "install_name_tool", "-change",
|
||||||
install_name, "@rpath/" + name, lib])
|
install_name, "@rpath/" + name, lib ])
|
||||||
|
|
||||||
dep_node = node.children[node.children.index(name)]
|
dep_node = node.children[node.children.index(name)]
|
||||||
rel_path = os.path.relpath(graph.get_node(dep_node).path,
|
rel_path = os.path.relpath(graph.get_node(dep_node).path,
|
||||||
|
@ -258,8 +289,12 @@ def add_rpaths(graph, node, bundle_path):
|
||||||
rpath = "@loader_path/" + rel_path + "/"
|
rpath = "@loader_path/" + rel_path + "/"
|
||||||
if rpath not in rpaths:
|
if rpath not in rpaths:
|
||||||
rpaths.append(rpath)
|
rpaths.append(rpath)
|
||||||
for path in rpaths:
|
|
||||||
subprocess.call(["install_name_tool", "-add_rpath", path, lib])
|
for rpath in rpaths:
|
||||||
|
# Ensure that lib has rpath set
|
||||||
|
if not rpath in get_rpaths(lib):
|
||||||
|
check_output([ "install_name_tool",
|
||||||
|
"-add_rpath", rpath, lib ])
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user