summaryrefslogtreecommitdiffstats
path: root/meta/classes
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2013-08-22 11:07:22 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-08-22 18:30:07 +0100
commited5ace3437eb0f751172e6b93399639c94b89e59 (patch)
tree29537ecf7b1d66d88b0242977b14886b4c3ec7eb /meta/classes
parent8d5e6eed7802a6056f9eaa50a85e3eee00fe2742 (diff)
downloadopenembedded-core-contrib-ed5ace3437eb0f751172e6b93399639c94b89e59.tar.gz
chrpath: Add support for relocating darwin binaries
On darwin, install_name_tool can be used to relocate binaries/libraries. This adds support for adjusting them with relative paths rather than hardcoded ones. The Linux code is factored out into a function but is otherwise unchanged. Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes')
-rw-r--r--meta/classes/chrpath.bbclass138
1 files changed, 88 insertions, 50 deletions
diff --git a/meta/classes/chrpath.bbclass b/meta/classes/chrpath.bbclass
index 0c7ab77a815..61a24b3f5a0 100644
--- a/meta/classes/chrpath.bbclass
+++ b/meta/classes/chrpath.bbclass
@@ -1,18 +1,103 @@
CHRPATH_BIN ?= "chrpath"
PREPROCESS_RELOCATE_DIRS ?= ""
-def process_dir (directory, d):
+def process_file_linux(cmd, fpath, basedir, tmpdir, d):
import subprocess as sub
+
+ p = sub.Popen([cmd, '-l', fpath],stdout=sub.PIPE,stderr=sub.PIPE)
+ err, out = p.communicate()
+ # If returned succesfully, process stderr for results
+ if p.returncode != 0:
+ return
+
+ # Throw away everything other than the rpath list
+ curr_rpath = err.partition("RPATH=")[2]
+ #bb.note("Current rpath for %s is %s" % (fpath, curr_rpath.strip()))
+ rpaths = curr_rpath.split(":")
+ new_rpaths = []
+ for rpath in rpaths:
+ # If rpath is already dynamic copy it to new_rpath and continue
+ if rpath.find("$ORIGIN") != -1:
+ new_rpaths.append(rpath.strip())
+ continue
+ rpath = os.path.normpath(rpath)
+ # If the rpath shares a root with base_prefix determine a new dynamic rpath from the
+ # base_prefix shared root
+ if rpath.find(basedir) != -1:
+ depth = fpath.partition(basedir)[2].count('/')
+ libpath = rpath.partition(basedir)[2].strip()
+ # otherwise (i.e. cross packages) determine a shared root based on the TMPDIR
+ # NOTE: This will not work reliably for cross packages, particularly in the case
+ # where your TMPDIR is a short path (i.e. /usr/poky) as chrpath cannot insert an
+ # rpath longer than that which is already set.
+ elif rpath.find(tmpdir) != -1:
+ depth = fpath.rpartition(tmpdir)[2].count('/')
+ libpath = rpath.partition(tmpdir)[2].strip()
+ else:
+ new_rpaths.append(rpath.strip())
+ return
+ base = "$ORIGIN"
+ while depth > 1:
+ base += "/.."
+ depth-=1
+ new_rpaths.append("%s%s" % (base, libpath))
+
+ # if we have modified some rpaths call chrpath to update the binary
+ if len(new_rpaths):
+ args = ":".join(new_rpaths)
+ #bb.note("Setting rpath for %s to %s" %(fpath, args))
+ p = sub.Popen([cmd, '-r', args, fpath],stdout=sub.PIPE,stderr=sub.PIPE)
+ out, err = p.communicate()
+ if p.returncode != 0:
+ bb.error("%s: chrpath command failed with exit code %d:\n%s%s" % (d.getVar('PN', True), p.returncode, out, err))
+ raise bb.build.FuncFailed
+
+def process_file_darwin(cmd, fpath, basedir, tmpdir, d):
+ import subprocess as sub
+
+ p = sub.Popen([d.expand("${HOST_PREFIX}otool"), '-L', fpath],stdout=sub.PIPE,stderr=sub.PIPE)
+ err, out = p.communicate()
+ # If returned succesfully, process stderr for results
+ if p.returncode != 0:
+ return
+ for l in err.split("\n"):
+ if "(compatibility" not in l:
+ continue
+ rpath = l.partition("(compatibility")[0].strip()
+ if rpath.find(basedir) != -1:
+ depth = fpath.partition(basedir)[2].count('/')
+ libpath = rpath.partition(basedir)[2].strip()
+ else:
+ continue
+
+ base = "@loader_path"
+ while depth > 1:
+ base += "/.."
+ depth-=1
+ base = base + libpath
+ p = sub.Popen([d.expand("${HOST_PREFIX}install_name_tool"), '-change', rpath, base, fpath],stdout=sub.PIPE,stderr=sub.PIPE)
+ err, out = p.communicate()
+
+def process_dir (directory, d):
import stat
cmd = d.expand('${CHRPATH_BIN}')
tmpdir = os.path.normpath(d.getVar('TMPDIR'))
basedir = os.path.normpath(d.expand('${base_prefix}'))
+ hostos = d.getVar("HOST_OS", True)
#bb.debug("Checking %s for binaries to process" % directory)
if not os.path.exists(directory):
return
+ if "linux" in hostos:
+ process_file = process_file_linux
+ elif "darwin" in hostos:
+ process_file = process_file_darwin
+ else:
+ # Relocations not supported
+ return
+
dirs = os.listdir(directory)
for file in dirs:
fpath = directory + "/" + file
@@ -35,55 +120,8 @@ def process_dir (directory, d):
else:
# Temporarily make the file writeable so we can chrpath it
os.chmod(fpath, perms|stat.S_IRWXU)
-
- p = sub.Popen([cmd, '-l', fpath],stdout=sub.PIPE,stderr=sub.PIPE)
- err, out = p.communicate()
- # If returned succesfully, process stderr for results
- if p.returncode != 0:
- continue
-
- # Throw away everything other than the rpath list
- curr_rpath = err.partition("RPATH=")[2]
- #bb.note("Current rpath for %s is %s" % (fpath, curr_rpath.strip()))
- rpaths = curr_rpath.split(":")
- new_rpaths = []
- for rpath in rpaths:
- # If rpath is already dynamic copy it to new_rpath and continue
- if rpath.find("$ORIGIN") != -1:
- new_rpaths.append(rpath.strip())
- continue
- rpath = os.path.normpath(rpath)
- # If the rpath shares a root with base_prefix determine a new dynamic rpath from the
- # base_prefix shared root
- if rpath.find(basedir) != -1:
- depth = fpath.partition(basedir)[2].count('/')
- libpath = rpath.partition(basedir)[2].strip()
- # otherwise (i.e. cross packages) determine a shared root based on the TMPDIR
- # NOTE: This will not work reliably for cross packages, particularly in the case
- # where your TMPDIR is a short path (i.e. /usr/poky) as chrpath cannot insert an
- # rpath longer than that which is already set.
- elif rpath.find(tmpdir) != -1:
- depth = fpath.rpartition(tmpdir)[2].count('/')
- libpath = rpath.partition(tmpdir)[2].strip()
- else:
- new_rpaths.append(rpath.strip())
- continue
- base = "$ORIGIN"
- while depth > 1:
- base += "/.."
- depth-=1
- new_rpaths.append("%s%s" % (base, libpath))
-
- # if we have modified some rpaths call chrpath to update the binary
- if len(new_rpaths):
- args = ":".join(new_rpaths)
- #bb.note("Setting rpath for %s to %s" %(fpath, args))
- p = sub.Popen([cmd, '-r', args, fpath],stdout=sub.PIPE,stderr=sub.PIPE)
- out, err = p.communicate()
- if p.returncode != 0:
- bb.error("%s: chrpath command failed with exit code %d:\n%s%s" % (d.getVar('PN', True), p.returncode, out, err))
- raise bb.build.FuncFailed
-
+ process_file(cmd, fpath, basedir, tmpdir, d)
+
if perms:
os.chmod(fpath, perms)