diff options
| author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2013-11-26 22:14:47 +0000 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2013-11-29 09:52:57 +0000 |
| commit | 6fcb96076ca60ef30062fda0ff8308cc840ab07d (patch) | |
| tree | 4848a18b376e0d066196ad4cb1486ccc30f31a89 | |
| parent | 572a8eb87489d549fff33d85a3760949730978eb (diff) | |
| download | poky-6fcb96076ca60ef30062fda0ff8308cc840ab07d.tar.gz | |
chrpath: Improve crazy code
The current code is a little bit overcomplicated, deficient and also
possibly broken.
Issues include:
a) Not maximally optisming rpaths (e.g. a lib in usr/lib might get an
rpath of $ORIGIN/../../usr/lib)
b) The return in the middle of the for loop look suspiciously like
it might break on some binaries
c) The depth function, loops of "../" prepending and so on can
be replaced with a call to os.path.relpath
This patch cleans up the above issues.
Running binaries should result in less "../" resolutions which can't
hurt performance either.
[YOCTO #3989]
(From OE-Core rev: feea54df6768036649ca6c57524e2a1f480ad249)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -rw-r--r-- | meta/classes/chrpath.bbclass | 54 |
1 files changed, 17 insertions, 37 deletions
diff --git a/meta/classes/chrpath.bbclass b/meta/classes/chrpath.bbclass index 61a24b3f5a..7bdb1b9938 100644 --- a/meta/classes/chrpath.bbclass +++ b/meta/classes/chrpath.bbclass | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | CHRPATH_BIN ?= "chrpath" | 1 | CHRPATH_BIN ?= "chrpath" |
| 2 | PREPROCESS_RELOCATE_DIRS ?= "" | 2 | PREPROCESS_RELOCATE_DIRS ?= "" |
| 3 | 3 | ||
| 4 | def process_file_linux(cmd, fpath, basedir, tmpdir, d): | 4 | def process_file_linux(cmd, fpath, rootdir, baseprefix, tmpdir, d): |
| 5 | import subprocess as sub | 5 | import subprocess as sub |
| 6 | 6 | ||
| 7 | p = sub.Popen([cmd, '-l', fpath],stdout=sub.PIPE,stderr=sub.PIPE) | 7 | p = sub.Popen([cmd, '-l', fpath],stdout=sub.PIPE,stderr=sub.PIPE) |
| @@ -15,35 +15,21 @@ def process_file_linux(cmd, fpath, basedir, tmpdir, d): | |||
| 15 | #bb.note("Current rpath for %s is %s" % (fpath, curr_rpath.strip())) | 15 | #bb.note("Current rpath for %s is %s" % (fpath, curr_rpath.strip())) |
| 16 | rpaths = curr_rpath.split(":") | 16 | rpaths = curr_rpath.split(":") |
| 17 | new_rpaths = [] | 17 | new_rpaths = [] |
| 18 | modified = False | ||
| 18 | for rpath in rpaths: | 19 | for rpath in rpaths: |
| 19 | # If rpath is already dynamic copy it to new_rpath and continue | 20 | # If rpath is already dynamic copy it to new_rpath and continue |
| 20 | if rpath.find("$ORIGIN") != -1: | 21 | if rpath.find("$ORIGIN") != -1: |
| 21 | new_rpaths.append(rpath.strip()) | 22 | new_rpaths.append(rpath.strip()) |
| 22 | continue | 23 | continue |
| 23 | rpath = os.path.normpath(rpath) | 24 | rpath = os.path.normpath(rpath) |
| 24 | # If the rpath shares a root with base_prefix determine a new dynamic rpath from the | 25 | if baseprefix not in rpath and tmpdir not in rpath: |
| 25 | # base_prefix shared root | ||
| 26 | if rpath.find(basedir) != -1: | ||
| 27 | depth = fpath.partition(basedir)[2].count('/') | ||
| 28 | libpath = rpath.partition(basedir)[2].strip() | ||
| 29 | # otherwise (i.e. cross packages) determine a shared root based on the TMPDIR | ||
| 30 | # NOTE: This will not work reliably for cross packages, particularly in the case | ||
| 31 | # where your TMPDIR is a short path (i.e. /usr/poky) as chrpath cannot insert an | ||
| 32 | # rpath longer than that which is already set. | ||
| 33 | elif rpath.find(tmpdir) != -1: | ||
| 34 | depth = fpath.rpartition(tmpdir)[2].count('/') | ||
| 35 | libpath = rpath.partition(tmpdir)[2].strip() | ||
| 36 | else: | ||
| 37 | new_rpaths.append(rpath.strip()) | 26 | new_rpaths.append(rpath.strip()) |
| 38 | return | 27 | continue |
| 39 | base = "$ORIGIN" | 28 | new_rpaths.append("$ORIGIN/" + os.path.relpath(rpath.strip(), os.path.dirname(fpath.replace(rootdir, "/")))) |
| 40 | while depth > 1: | 29 | modified = True |
| 41 | base += "/.." | ||
| 42 | depth-=1 | ||
| 43 | new_rpaths.append("%s%s" % (base, libpath)) | ||
| 44 | 30 | ||
| 45 | # if we have modified some rpaths call chrpath to update the binary | 31 | # if we have modified some rpaths call chrpath to update the binary |
| 46 | if len(new_rpaths): | 32 | if modified: |
| 47 | args = ":".join(new_rpaths) | 33 | args = ":".join(new_rpaths) |
| 48 | #bb.note("Setting rpath for %s to %s" %(fpath, args)) | 34 | #bb.note("Setting rpath for %s to %s" %(fpath, args)) |
| 49 | p = sub.Popen([cmd, '-r', args, fpath],stdout=sub.PIPE,stderr=sub.PIPE) | 35 | p = sub.Popen([cmd, '-r', args, fpath],stdout=sub.PIPE,stderr=sub.PIPE) |
| @@ -52,7 +38,7 @@ def process_file_linux(cmd, fpath, basedir, tmpdir, d): | |||
| 52 | bb.error("%s: chrpath command failed with exit code %d:\n%s%s" % (d.getVar('PN', True), p.returncode, out, err)) | 38 | bb.error("%s: chrpath command failed with exit code %d:\n%s%s" % (d.getVar('PN', True), p.returncode, out, err)) |
| 53 | raise bb.build.FuncFailed | 39 | raise bb.build.FuncFailed |
| 54 | 40 | ||
| 55 | def process_file_darwin(cmd, fpath, basedir, tmpdir, d): | 41 | def process_file_darwin(cmd, fpath, rootdir, baseprefix, tmpdir, d): |
| 56 | import subprocess as sub | 42 | import subprocess as sub |
| 57 | 43 | ||
| 58 | p = sub.Popen([d.expand("${HOST_PREFIX}otool"), '-L', fpath],stdout=sub.PIPE,stderr=sub.PIPE) | 44 | p = sub.Popen([d.expand("${HOST_PREFIX}otool"), '-L', fpath],stdout=sub.PIPE,stderr=sub.PIPE) |
| @@ -64,26 +50,20 @@ def process_file_darwin(cmd, fpath, basedir, tmpdir, d): | |||
| 64 | if "(compatibility" not in l: | 50 | if "(compatibility" not in l: |
| 65 | continue | 51 | continue |
| 66 | rpath = l.partition("(compatibility")[0].strip() | 52 | rpath = l.partition("(compatibility")[0].strip() |
| 67 | if rpath.find(basedir) != -1: | 53 | if baseprefix not in rpath: |
| 68 | depth = fpath.partition(basedir)[2].count('/') | ||
| 69 | libpath = rpath.partition(basedir)[2].strip() | ||
| 70 | else: | ||
| 71 | continue | 54 | continue |
| 72 | 55 | ||
| 73 | base = "@loader_path" | 56 | newpath = "@loader_path/" + os.path.relpath(rpath, os.path.dirname(fpath.replace(rootdir, "/"))) |
| 74 | while depth > 1: | 57 | bb.warn("%s %s %s %s" % (fpath, rpath, newpath, rootdir)) |
| 75 | base += "/.." | 58 | p = sub.Popen([d.expand("${HOST_PREFIX}install_name_tool"), '-change', rpath, newpath, fpath],stdout=sub.PIPE,stderr=sub.PIPE) |
| 76 | depth-=1 | ||
| 77 | base = base + libpath | ||
| 78 | p = sub.Popen([d.expand("${HOST_PREFIX}install_name_tool"), '-change', rpath, base, fpath],stdout=sub.PIPE,stderr=sub.PIPE) | ||
| 79 | err, out = p.communicate() | 59 | err, out = p.communicate() |
| 80 | 60 | ||
| 81 | def process_dir (directory, d): | 61 | def process_dir (rootdir, directory, d): |
| 82 | import stat | 62 | import stat |
| 83 | 63 | ||
| 84 | cmd = d.expand('${CHRPATH_BIN}') | 64 | cmd = d.expand('${CHRPATH_BIN}') |
| 85 | tmpdir = os.path.normpath(d.getVar('TMPDIR')) | 65 | tmpdir = os.path.normpath(d.getVar('TMPDIR')) |
| 86 | basedir = os.path.normpath(d.expand('${base_prefix}')) | 66 | baseprefix = os.path.normpath(d.expand('${base_prefix}')) |
| 87 | hostos = d.getVar("HOST_OS", True) | 67 | hostos = d.getVar("HOST_OS", True) |
| 88 | 68 | ||
| 89 | #bb.debug("Checking %s for binaries to process" % directory) | 69 | #bb.debug("Checking %s for binaries to process" % directory) |
| @@ -107,7 +87,7 @@ def process_dir (directory, d): | |||
| 107 | continue | 87 | continue |
| 108 | 88 | ||
| 109 | if os.path.isdir(fpath): | 89 | if os.path.isdir(fpath): |
| 110 | process_dir(fpath, d) | 90 | process_dir(rootdir, fpath, d) |
| 111 | else: | 91 | else: |
| 112 | #bb.note("Testing %s for relocatability" % fpath) | 92 | #bb.note("Testing %s for relocatability" % fpath) |
| 113 | 93 | ||
| @@ -120,7 +100,7 @@ def process_dir (directory, d): | |||
| 120 | else: | 100 | else: |
| 121 | # Temporarily make the file writeable so we can chrpath it | 101 | # Temporarily make the file writeable so we can chrpath it |
| 122 | os.chmod(fpath, perms|stat.S_IRWXU) | 102 | os.chmod(fpath, perms|stat.S_IRWXU) |
| 123 | process_file(cmd, fpath, basedir, tmpdir, d) | 103 | process_file(cmd, fpath, rootdir, baseprefix, tmpdir, d) |
| 124 | 104 | ||
| 125 | if perms: | 105 | if perms: |
| 126 | os.chmod(fpath, perms) | 106 | os.chmod(fpath, perms) |
| @@ -131,5 +111,5 @@ def rpath_replace (path, d): | |||
| 131 | for bindir in bindirs: | 111 | for bindir in bindirs: |
| 132 | #bb.note ("Processing directory " + bindir) | 112 | #bb.note ("Processing directory " + bindir) |
| 133 | directory = path + "/" + bindir | 113 | directory = path + "/" + bindir |
| 134 | process_dir (directory, d) | 114 | process_dir (path, directory, d) |
| 135 | 115 | ||
