summaryrefslogtreecommitdiffstats
path: root/meta/classes/chrpath.bbclass
diff options
context:
space:
mode:
Diffstat (limited to 'meta/classes/chrpath.bbclass')
-rw-r--r--meta/classes/chrpath.bbclass115
1 files changed, 115 insertions, 0 deletions
diff --git a/meta/classes/chrpath.bbclass b/meta/classes/chrpath.bbclass
new file mode 100644
index 0000000..7bdb1b9
--- /dev/null
+++ b/meta/classes/chrpath.bbclass
@@ -0,0 +1,115 @@
1CHRPATH_BIN ?= "chrpath"
2PREPROCESS_RELOCATE_DIRS ?= ""
3
4def process_file_linux(cmd, fpath, rootdir, baseprefix, tmpdir, d):
5 import subprocess as sub
6
7 p = sub.Popen([cmd, '-l', fpath],stdout=sub.PIPE,stderr=sub.PIPE)
8 err, out = p.communicate()
9 # If returned succesfully, process stderr for results
10 if p.returncode != 0:
11 return
12
13 # Throw away everything other than the rpath list
14 curr_rpath = err.partition("RPATH=")[2]
15 #bb.note("Current rpath for %s is %s" % (fpath, curr_rpath.strip()))
16 rpaths = curr_rpath.split(":")
17 new_rpaths = []
18 modified = False
19 for rpath in rpaths:
20 # If rpath is already dynamic copy it to new_rpath and continue
21 if rpath.find("$ORIGIN") != -1:
22 new_rpaths.append(rpath.strip())
23 continue
24 rpath = os.path.normpath(rpath)
25 if baseprefix not in rpath and tmpdir not in rpath:
26 new_rpaths.append(rpath.strip())
27 continue
28 new_rpaths.append("$ORIGIN/" + os.path.relpath(rpath.strip(), os.path.dirname(fpath.replace(rootdir, "/"))))
29 modified = True
30
31 # if we have modified some rpaths call chrpath to update the binary
32 if modified:
33 args = ":".join(new_rpaths)
34 #bb.note("Setting rpath for %s to %s" %(fpath, args))
35 p = sub.Popen([cmd, '-r', args, fpath],stdout=sub.PIPE,stderr=sub.PIPE)
36 out, err = p.communicate()
37 if p.returncode != 0:
38 bb.error("%s: chrpath command failed with exit code %d:\n%s%s" % (d.getVar('PN', True), p.returncode, out, err))
39 raise bb.build.FuncFailed
40
41def process_file_darwin(cmd, fpath, rootdir, baseprefix, tmpdir, d):
42 import subprocess as sub
43
44 p = sub.Popen([d.expand("${HOST_PREFIX}otool"), '-L', fpath],stdout=sub.PIPE,stderr=sub.PIPE)
45 err, out = p.communicate()
46 # If returned succesfully, process stderr for results
47 if p.returncode != 0:
48 return
49 for l in err.split("\n"):
50 if "(compatibility" not in l:
51 continue
52 rpath = l.partition("(compatibility")[0].strip()
53 if baseprefix not in rpath:
54 continue
55
56 newpath = "@loader_path/" + os.path.relpath(rpath, os.path.dirname(fpath.replace(rootdir, "/")))
57 bb.warn("%s %s %s %s" % (fpath, rpath, newpath, rootdir))
58 p = sub.Popen([d.expand("${HOST_PREFIX}install_name_tool"), '-change', rpath, newpath, fpath],stdout=sub.PIPE,stderr=sub.PIPE)
59 err, out = p.communicate()
60
61def process_dir (rootdir, directory, d):
62 import stat
63
64 cmd = d.expand('${CHRPATH_BIN}')
65 tmpdir = os.path.normpath(d.getVar('TMPDIR'))
66 baseprefix = os.path.normpath(d.expand('${base_prefix}'))
67 hostos = d.getVar("HOST_OS", True)
68
69 #bb.debug("Checking %s for binaries to process" % directory)
70 if not os.path.exists(directory):
71 return
72
73 if "linux" in hostos:
74 process_file = process_file_linux
75 elif "darwin" in hostos:
76 process_file = process_file_darwin
77 else:
78 # Relocations not supported
79 return
80
81 dirs = os.listdir(directory)
82 for file in dirs:
83 fpath = directory + "/" + file
84 fpath = os.path.normpath(fpath)
85 if os.path.islink(fpath):
86 # Skip symlinks
87 continue
88
89 if os.path.isdir(fpath):
90 process_dir(rootdir, fpath, d)
91 else:
92 #bb.note("Testing %s for relocatability" % fpath)
93
94 # We need read and write permissions for chrpath, if we don't have
95 # them then set them temporarily. Take a copy of the files
96 # permissions so that we can restore them afterwards.
97 perms = os.stat(fpath)[stat.ST_MODE]
98 if os.access(fpath, os.W_OK|os.R_OK):
99 perms = None
100 else:
101 # Temporarily make the file writeable so we can chrpath it
102 os.chmod(fpath, perms|stat.S_IRWXU)
103 process_file(cmd, fpath, rootdir, baseprefix, tmpdir, d)
104
105 if perms:
106 os.chmod(fpath, perms)
107
108def rpath_replace (path, d):
109 bindirs = d.expand("${bindir} ${sbindir} ${base_sbindir} ${base_bindir} ${libdir} ${base_libdir} ${libexecdir} ${PREPROCESS_RELOCATE_DIRS}").split()
110
111 for bindir in bindirs:
112 #bb.note ("Processing directory " + bindir)
113 directory = path + "/" + bindir
114 process_dir (path, directory, d)
115