mirror of
https://git.yoctoproject.org/poky
synced 2026-01-29 21:08:42 +01:00
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>
141 lines
5.0 KiB
Plaintext
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)
|
|
|