Files
poky/meta/classes/chrpath.bbclass
Richard Purdie ff525695f2 classes: Add SPDX license identifiers
As stated in our top level license files, the license is MIT unless
otherwise stated. Add SPDX identifers accordingly. Replace older
license statementa with the standardised syntax. Also drop "All
Rights Reserved" expression as it isn't used now, doesn't mean anything
and is confusing.

(From OE-Core rev: 081a391fe09a21265881e39a2a496e4e10b4f80b)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2022-08-12 11:58:01 +01:00

141 lines
5.0 KiB
Plaintext

#
# Copyright OpenEmbedded Contributors
#
# SPDX-License-Identifier: MIT
#
CHRPATH_BIN ?= "chrpath"
PREPROCESS_RELOCATE_DIRS ?= ""
def process_file_linux(cmd, fpath, rootdir, baseprefix, tmpdir, d, break_hardlinks = False):
import subprocess, oe.qa
with oe.qa.ELFFile(fpath) as elf:
try:
elf.open()
except oe.qa.NotELFFileError:
return
try:
out = subprocess.check_output([cmd, "-l", fpath], universal_newlines=True)
except subprocess.CalledProcessError:
return
# Handle RUNPATH as well as RPATH
out = out.replace("RUNPATH=","RPATH=")
# Throw away everything other than the rpath list
curr_rpath = out.partition("RPATH=")[2]
#bb.note("Current rpath for %s is %s" % (fpath, curr_rpath.strip()))
rpaths = curr_rpath.strip().split(":")
new_rpaths = []
modified = False
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)
continue
rpath = os.path.normpath(rpath)
if baseprefix not in rpath and tmpdir not in rpath:
# Skip standard search paths
if rpath in ['/lib', '/usr/lib', '/lib64/', '/usr/lib64']:
bb.warn("Skipping RPATH %s as is a standard search path for %s" % (rpath, fpath))
modified = True
continue
new_rpaths.append(rpath)
continue
new_rpaths.append("$ORIGIN/" + os.path.relpath(rpath, os.path.dirname(fpath.replace(rootdir, "/"))))
modified = True
# if we have modified some rpaths call chrpath to update the binary
if modified:
if break_hardlinks:
bb.utils.break_hardlinks(fpath)
args = ":".join(new_rpaths)
#bb.note("Setting rpath for %s to %s" %(fpath, args))
try:
subprocess.check_output([cmd, "-r", args, fpath],
stderr=subprocess.PIPE, universal_newlines=True)
except subprocess.CalledProcessError as e:
bb.fatal("chrpath command failed with exit code %d:\n%s\n%s" % (e.returncode, e.stdout, e.stderr))
def process_file_darwin(cmd, fpath, rootdir, baseprefix, tmpdir, d, break_hardlinks = False):
import subprocess as sub
p = sub.Popen([d.expand("${HOST_PREFIX}otool"), '-L', fpath],stdout=sub.PIPE,stderr=sub.PIPE)
out, err = p.communicate()
# If returned successfully, process stdout for results
if p.returncode != 0:
return
for l in out.split("\n"):
if "(compatibility" not in l:
continue
rpath = l.partition("(compatibility")[0].strip()
if baseprefix not in rpath:
continue
if break_hardlinks:
bb.utils.break_hardlinks(fpath)
newpath = "@loader_path/" + os.path.relpath(rpath, os.path.dirname(fpath.replace(rootdir, "/")))
p = sub.Popen([d.expand("${HOST_PREFIX}install_name_tool"), '-change', rpath, newpath, fpath],stdout=sub.PIPE,stderr=sub.PIPE)
out, err = p.communicate()
def process_dir(rootdir, directory, d, break_hardlinks = False):
bb.debug(2, "Checking %s for binaries to process" % directory)
if not os.path.exists(directory):
return
import stat
rootdir = os.path.normpath(rootdir)
cmd = d.expand('${CHRPATH_BIN}')
tmpdir = os.path.normpath(d.getVar('TMPDIR', False))
baseprefix = os.path.normpath(d.expand('${base_prefix}'))
hostos = d.getVar("HOST_OS")
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
fpath = os.path.normpath(fpath)
if os.path.islink(fpath):
# Skip symlinks
continue
if os.path.isdir(fpath):
process_dir(rootdir, fpath, d, break_hardlinks = break_hardlinks)
else:
#bb.note("Testing %s for relocatability" % fpath)
# We need read and write permissions for chrpath, if we don't have
# them then set them temporarily. Take a copy of the files
# permissions so that we can restore them afterwards.
perms = os.stat(fpath)[stat.ST_MODE]
if os.access(fpath, os.W_OK|os.R_OK):
perms = None
else:
# Temporarily make the file writeable so we can chrpath it
os.chmod(fpath, perms|stat.S_IRWXU)
process_file(cmd, fpath, rootdir, baseprefix, tmpdir, d, break_hardlinks = break_hardlinks)
if perms:
os.chmod(fpath, perms)
def rpath_replace (path, d):
bindirs = d.expand("${bindir} ${sbindir} ${base_sbindir} ${base_bindir} ${libdir} ${base_libdir} ${libexecdir} ${PREPROCESS_RELOCATE_DIRS}").split()
for bindir in bindirs:
#bb.note ("Processing directory " + bindir)
directory = path + "/" + bindir
process_dir (path, directory, d)