1*92b42cb3SPatrick Williams# 2*92b42cb3SPatrick Williams# Copyright OpenEmbedded Contributors 3*92b42cb3SPatrick Williams# 4*92b42cb3SPatrick Williams# SPDX-License-Identifier: MIT 5*92b42cb3SPatrick Williams# 6*92b42cb3SPatrick Williams 7*92b42cb3SPatrick WilliamsUNINATIVE_LOADER ?= "${UNINATIVE_STAGING_DIR}-uninative/${BUILD_ARCH}-linux/lib/${@bb.utils.contains('BUILD_ARCH', 'x86_64', 'ld-linux-x86-64.so.2', '', d)}${@bb.utils.contains('BUILD_ARCH', 'i686', 'ld-linux.so.2', '', d)}${@bb.utils.contains('BUILD_ARCH', 'aarch64', 'ld-linux-aarch64.so.1', '', d)}${@bb.utils.contains('BUILD_ARCH', 'ppc64le', 'ld64.so.2', '', d)}" 8*92b42cb3SPatrick WilliamsUNINATIVE_STAGING_DIR ?= "${STAGING_DIR}" 9*92b42cb3SPatrick Williams 10*92b42cb3SPatrick WilliamsUNINATIVE_URL ?= "unset" 11*92b42cb3SPatrick WilliamsUNINATIVE_TARBALL ?= "${BUILD_ARCH}-nativesdk-libc-${UNINATIVE_VERSION}.tar.xz" 12*92b42cb3SPatrick Williams# Example checksums 13*92b42cb3SPatrick Williams#UNINATIVE_CHECKSUM[aarch64] = "dead" 14*92b42cb3SPatrick Williams#UNINATIVE_CHECKSUM[i686] = "dead" 15*92b42cb3SPatrick Williams#UNINATIVE_CHECKSUM[x86_64] = "dead" 16*92b42cb3SPatrick WilliamsUNINATIVE_DLDIR ?= "${DL_DIR}/uninative/" 17*92b42cb3SPatrick Williams 18*92b42cb3SPatrick Williams# Enabling uninative will change the following variables so they need to go the parsing ignored variables list to prevent multiple recipe parsing 19*92b42cb3SPatrick WilliamsBB_HASHCONFIG_IGNORE_VARS += "NATIVELSBSTRING SSTATEPOSTUNPACKFUNCS BUILD_LDFLAGS" 20*92b42cb3SPatrick Williams 21*92b42cb3SPatrick Williamsaddhandler uninative_event_fetchloader 22*92b42cb3SPatrick Williamsuninative_event_fetchloader[eventmask] = "bb.event.BuildStarted" 23*92b42cb3SPatrick Williams 24*92b42cb3SPatrick Williamsaddhandler uninative_event_enable 25*92b42cb3SPatrick Williamsuninative_event_enable[eventmask] = "bb.event.ConfigParsed" 26*92b42cb3SPatrick Williams 27*92b42cb3SPatrick Williamspython uninative_event_fetchloader() { 28*92b42cb3SPatrick Williams """ 29*92b42cb3SPatrick Williams This event fires on the parent and will try to fetch the tarball if the 30*92b42cb3SPatrick Williams loader isn't already present. 31*92b42cb3SPatrick Williams """ 32*92b42cb3SPatrick Williams 33*92b42cb3SPatrick Williams chksum = d.getVarFlag("UNINATIVE_CHECKSUM", d.getVar("BUILD_ARCH")) 34*92b42cb3SPatrick Williams if not chksum: 35*92b42cb3SPatrick Williams bb.fatal("Uninative selected but not configured correctly, please set UNINATIVE_CHECKSUM[%s]" % d.getVar("BUILD_ARCH")) 36*92b42cb3SPatrick Williams 37*92b42cb3SPatrick Williams loader = d.getVar("UNINATIVE_LOADER") 38*92b42cb3SPatrick Williams loaderchksum = loader + ".chksum" 39*92b42cb3SPatrick Williams if os.path.exists(loader) and os.path.exists(loaderchksum): 40*92b42cb3SPatrick Williams with open(loaderchksum, "r") as f: 41*92b42cb3SPatrick Williams readchksum = f.read().strip() 42*92b42cb3SPatrick Williams if readchksum == chksum: 43*92b42cb3SPatrick Williams return 44*92b42cb3SPatrick Williams 45*92b42cb3SPatrick Williams import subprocess 46*92b42cb3SPatrick Williams try: 47*92b42cb3SPatrick Williams # Save and restore cwd as Fetch.download() does a chdir() 48*92b42cb3SPatrick Williams olddir = os.getcwd() 49*92b42cb3SPatrick Williams 50*92b42cb3SPatrick Williams tarball = d.getVar("UNINATIVE_TARBALL") 51*92b42cb3SPatrick Williams tarballdir = os.path.join(d.getVar("UNINATIVE_DLDIR"), chksum) 52*92b42cb3SPatrick Williams tarballpath = os.path.join(tarballdir, tarball) 53*92b42cb3SPatrick Williams 54*92b42cb3SPatrick Williams if not os.path.exists(tarballpath + ".done"): 55*92b42cb3SPatrick Williams bb.utils.mkdirhier(tarballdir) 56*92b42cb3SPatrick Williams if d.getVar("UNINATIVE_URL") == "unset": 57*92b42cb3SPatrick Williams bb.fatal("Uninative selected but not configured, please set UNINATIVE_URL") 58*92b42cb3SPatrick Williams 59*92b42cb3SPatrick Williams localdata = bb.data.createCopy(d) 60*92b42cb3SPatrick Williams localdata.setVar('FILESPATH', "") 61*92b42cb3SPatrick Williams localdata.setVar('DL_DIR', tarballdir) 62*92b42cb3SPatrick Williams # Our games with path manipulation of DL_DIR mean standard PREMIRRORS don't work 63*92b42cb3SPatrick Williams # and we can't easily put 'chksum' into the url path from a url parameter with 64*92b42cb3SPatrick Williams # the current fetcher url handling 65*92b42cb3SPatrick Williams premirrors = bb.fetch2.mirror_from_string(localdata.getVar("PREMIRRORS")) 66*92b42cb3SPatrick Williams for line in premirrors: 67*92b42cb3SPatrick Williams try: 68*92b42cb3SPatrick Williams (find, replace) = line 69*92b42cb3SPatrick Williams except ValueError: 70*92b42cb3SPatrick Williams continue 71*92b42cb3SPatrick Williams if find.startswith("http"): 72*92b42cb3SPatrick Williams localdata.appendVar("PREMIRRORS", " ${UNINATIVE_URL}${UNINATIVE_TARBALL} %s/uninative/%s/${UNINATIVE_TARBALL}" % (replace, chksum)) 73*92b42cb3SPatrick Williams 74*92b42cb3SPatrick Williams srcuri = d.expand("${UNINATIVE_URL}${UNINATIVE_TARBALL};sha256sum=%s" % chksum) 75*92b42cb3SPatrick Williams bb.note("Fetching uninative binary shim %s (will check PREMIRRORS first)" % srcuri) 76*92b42cb3SPatrick Williams 77*92b42cb3SPatrick Williams fetcher = bb.fetch2.Fetch([srcuri], localdata, cache=False) 78*92b42cb3SPatrick Williams fetcher.download() 79*92b42cb3SPatrick Williams localpath = fetcher.localpath(srcuri) 80*92b42cb3SPatrick Williams if localpath != tarballpath and os.path.exists(localpath) and not os.path.exists(tarballpath): 81*92b42cb3SPatrick Williams # Follow the symlink behavior from the bitbake fetch2. 82*92b42cb3SPatrick Williams # This will cover the case where an existing symlink is broken 83*92b42cb3SPatrick Williams # as well as if there are two processes trying to create it 84*92b42cb3SPatrick Williams # at the same time. 85*92b42cb3SPatrick Williams if os.path.islink(tarballpath): 86*92b42cb3SPatrick Williams # Broken symbolic link 87*92b42cb3SPatrick Williams os.unlink(tarballpath) 88*92b42cb3SPatrick Williams 89*92b42cb3SPatrick Williams # Deal with two processes trying to make symlink at once 90*92b42cb3SPatrick Williams try: 91*92b42cb3SPatrick Williams os.symlink(localpath, tarballpath) 92*92b42cb3SPatrick Williams except FileExistsError: 93*92b42cb3SPatrick Williams pass 94*92b42cb3SPatrick Williams 95*92b42cb3SPatrick Williams # ldd output is "ldd (Ubuntu GLIBC 2.23-0ubuntu10) 2.23", extract last option from first line 96*92b42cb3SPatrick Williams glibcver = subprocess.check_output(["ldd", "--version"]).decode('utf-8').split('\n')[0].split()[-1] 97*92b42cb3SPatrick Williams if bb.utils.vercmp_string(d.getVar("UNINATIVE_MAXGLIBCVERSION"), glibcver) < 0: 98*92b42cb3SPatrick Williams raise RuntimeError("Your host glibc version (%s) is newer than that in uninative (%s). Disabling uninative so that sstate is not corrupted." % (glibcver, d.getVar("UNINATIVE_MAXGLIBCVERSION"))) 99*92b42cb3SPatrick Williams 100*92b42cb3SPatrick Williams cmd = d.expand("\ 101*92b42cb3SPatrick Williamsmkdir -p ${UNINATIVE_STAGING_DIR}-uninative; \ 102*92b42cb3SPatrick Williamscd ${UNINATIVE_STAGING_DIR}-uninative; \ 103*92b42cb3SPatrick Williamstar -xJf ${UNINATIVE_DLDIR}/%s/${UNINATIVE_TARBALL}; \ 104*92b42cb3SPatrick Williams${UNINATIVE_STAGING_DIR}-uninative/relocate_sdk.py \ 105*92b42cb3SPatrick Williams ${UNINATIVE_STAGING_DIR}-uninative/${BUILD_ARCH}-linux \ 106*92b42cb3SPatrick Williams ${UNINATIVE_LOADER} \ 107*92b42cb3SPatrick Williams ${UNINATIVE_LOADER} \ 108*92b42cb3SPatrick Williams ${UNINATIVE_STAGING_DIR}-uninative/${BUILD_ARCH}-linux/${bindir_native}/patchelf-uninative \ 109*92b42cb3SPatrick Williams ${UNINATIVE_STAGING_DIR}-uninative/${BUILD_ARCH}-linux${base_libdir_native}/libc*.so*" % chksum) 110*92b42cb3SPatrick Williams subprocess.check_output(cmd, shell=True) 111*92b42cb3SPatrick Williams 112*92b42cb3SPatrick Williams with open(loaderchksum, "w") as f: 113*92b42cb3SPatrick Williams f.write(chksum) 114*92b42cb3SPatrick Williams 115*92b42cb3SPatrick Williams enable_uninative(d) 116*92b42cb3SPatrick Williams 117*92b42cb3SPatrick Williams except RuntimeError as e: 118*92b42cb3SPatrick Williams bb.warn(str(e)) 119*92b42cb3SPatrick Williams except bb.fetch2.BBFetchException as exc: 120*92b42cb3SPatrick Williams bb.warn("Disabling uninative as unable to fetch uninative tarball: %s" % str(exc)) 121*92b42cb3SPatrick Williams bb.warn("To build your own uninative loader, please bitbake uninative-tarball and set UNINATIVE_TARBALL appropriately.") 122*92b42cb3SPatrick Williams except subprocess.CalledProcessError as exc: 123*92b42cb3SPatrick Williams bb.warn("Disabling uninative as unable to install uninative tarball: %s" % str(exc)) 124*92b42cb3SPatrick Williams bb.warn("To build your own uninative loader, please bitbake uninative-tarball and set UNINATIVE_TARBALL appropriately.") 125*92b42cb3SPatrick Williams finally: 126*92b42cb3SPatrick Williams os.chdir(olddir) 127*92b42cb3SPatrick Williams} 128*92b42cb3SPatrick Williams 129*92b42cb3SPatrick Williamspython uninative_event_enable() { 130*92b42cb3SPatrick Williams """ 131*92b42cb3SPatrick Williams This event handler is called in the workers and is responsible for setting 132*92b42cb3SPatrick Williams up uninative if a loader is found. 133*92b42cb3SPatrick Williams """ 134*92b42cb3SPatrick Williams enable_uninative(d) 135*92b42cb3SPatrick Williams} 136*92b42cb3SPatrick Williams 137*92b42cb3SPatrick Williamsdef enable_uninative(d): 138*92b42cb3SPatrick Williams loader = d.getVar("UNINATIVE_LOADER") 139*92b42cb3SPatrick Williams if os.path.exists(loader): 140*92b42cb3SPatrick Williams bb.debug(2, "Enabling uninative") 141*92b42cb3SPatrick Williams d.setVar("NATIVELSBSTRING", "universal%s" % oe.utils.host_gcc_version(d)) 142*92b42cb3SPatrick Williams d.appendVar("SSTATEPOSTUNPACKFUNCS", " uninative_changeinterp") 143*92b42cb3SPatrick Williams d.appendVarFlag("SSTATEPOSTUNPACKFUNCS", "vardepvalueexclude", "| uninative_changeinterp") 144*92b42cb3SPatrick Williams d.appendVar("BUILD_LDFLAGS", " -Wl,--allow-shlib-undefined -Wl,--dynamic-linker=${UNINATIVE_LOADER}") 145*92b42cb3SPatrick Williams d.appendVarFlag("BUILD_LDFLAGS", "vardepvalueexclude", "| -Wl,--allow-shlib-undefined -Wl,--dynamic-linker=${UNINATIVE_LOADER}") 146*92b42cb3SPatrick Williams d.appendVarFlag("BUILD_LDFLAGS", "vardepsexclude", "UNINATIVE_LOADER") 147*92b42cb3SPatrick Williams d.prependVar("PATH", "${STAGING_DIR}-uninative/${BUILD_ARCH}-linux${bindir_native}:") 148*92b42cb3SPatrick Williams 149*92b42cb3SPatrick Williamspython uninative_changeinterp () { 150*92b42cb3SPatrick Williams import subprocess 151*92b42cb3SPatrick Williams import stat 152*92b42cb3SPatrick Williams import oe.qa 153*92b42cb3SPatrick Williams 154*92b42cb3SPatrick Williams if not (bb.data.inherits_class('native', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross', d)): 155*92b42cb3SPatrick Williams return 156*92b42cb3SPatrick Williams 157*92b42cb3SPatrick Williams sstateinst = d.getVar('SSTATE_INSTDIR') 158*92b42cb3SPatrick Williams for walkroot, dirs, files in os.walk(sstateinst): 159*92b42cb3SPatrick Williams for file in files: 160*92b42cb3SPatrick Williams if file.endswith(".so") or ".so." in file: 161*92b42cb3SPatrick Williams continue 162*92b42cb3SPatrick Williams f = os.path.join(walkroot, file) 163*92b42cb3SPatrick Williams if os.path.islink(f): 164*92b42cb3SPatrick Williams continue 165*92b42cb3SPatrick Williams s = os.stat(f) 166*92b42cb3SPatrick Williams if not ((s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) or (s[stat.ST_MODE] & stat.S_IXOTH)): 167*92b42cb3SPatrick Williams continue 168*92b42cb3SPatrick Williams elf = oe.qa.ELFFile(f) 169*92b42cb3SPatrick Williams try: 170*92b42cb3SPatrick Williams elf.open() 171*92b42cb3SPatrick Williams except oe.qa.NotELFFileError: 172*92b42cb3SPatrick Williams continue 173*92b42cb3SPatrick Williams if not elf.isDynamic(): 174*92b42cb3SPatrick Williams continue 175*92b42cb3SPatrick Williams 176*92b42cb3SPatrick Williams os.chmod(f, s[stat.ST_MODE] | stat.S_IWUSR) 177*92b42cb3SPatrick Williams subprocess.check_output(("patchelf-uninative", "--set-interpreter", d.getVar("UNINATIVE_LOADER"), f), stderr=subprocess.STDOUT) 178*92b42cb3SPatrick Williams os.chmod(f, s[stat.ST_MODE]) 179*92b42cb3SPatrick Williams} 180