1*4882a593Smuzhiyuninherit python3native 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun# Common variables used by all Rust builds 4*4882a593Smuzhiyunexport rustlibdir = "${libdir}/rust" 5*4882a593SmuzhiyunFILES:${PN} += "${rustlibdir}/*.so" 6*4882a593SmuzhiyunFILES:${PN}-dev += "${rustlibdir}/*.rlib ${rustlibdir}/*.rmeta" 7*4882a593SmuzhiyunFILES:${PN}-dbg += "${rustlibdir}/.debug" 8*4882a593Smuzhiyun 9*4882a593SmuzhiyunRUSTLIB = "-L ${STAGING_LIBDIR}/rust" 10*4882a593SmuzhiyunRUST_DEBUG_REMAP = "--remap-path-prefix=${WORKDIR}=/usr/src/debug/${PN}/${EXTENDPE}${PV}-${PR}" 11*4882a593SmuzhiyunRUSTFLAGS += "${RUSTLIB} ${RUST_DEBUG_REMAP}" 12*4882a593SmuzhiyunRUSTLIB_DEP ?= "libstd-rs" 13*4882a593Smuzhiyunexport RUST_TARGET_PATH = "${STAGING_LIBDIR_NATIVE}/rustlib" 14*4882a593SmuzhiyunRUST_PANIC_STRATEGY ?= "unwind" 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun# Native builds are not effected by TCLIBC. Without this, rust-native 17*4882a593Smuzhiyun# thinks it's "target" (i.e. x86_64-linux) is a musl target. 18*4882a593SmuzhiyunRUST_LIBC = "${TCLIBC}" 19*4882a593SmuzhiyunRUST_LIBC:class-crosssdk = "glibc" 20*4882a593SmuzhiyunRUST_LIBC:class-native = "glibc" 21*4882a593Smuzhiyun 22*4882a593Smuzhiyundef determine_libc(d, thing): 23*4882a593Smuzhiyun '''Determine which libc something should target''' 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun # BUILD is never musl, TARGET may be musl or glibc, 26*4882a593Smuzhiyun # HOST could be musl, but only if a compiler is built to be run on 27*4882a593Smuzhiyun # target in which case HOST_SYS != BUILD_SYS. 28*4882a593Smuzhiyun if thing == 'TARGET': 29*4882a593Smuzhiyun libc = d.getVar('RUST_LIBC') 30*4882a593Smuzhiyun elif thing == 'BUILD' and (d.getVar('HOST_SYS') != d.getVar('BUILD_SYS')): 31*4882a593Smuzhiyun libc = d.getVar('RUST_LIBC') 32*4882a593Smuzhiyun else: 33*4882a593Smuzhiyun libc = d.getVar('RUST_LIBC:class-native') 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun return libc 36*4882a593Smuzhiyun 37*4882a593Smuzhiyundef target_is_armv7(d): 38*4882a593Smuzhiyun '''Determine if target is armv7''' 39*4882a593Smuzhiyun # TUNE_FEATURES may include arm* even if the target is not arm 40*4882a593Smuzhiyun # in the case of *-native packages 41*4882a593Smuzhiyun if d.getVar('TARGET_ARCH') != 'arm': 42*4882a593Smuzhiyun return False 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun feat = d.getVar('TUNE_FEATURES') 45*4882a593Smuzhiyun feat = frozenset(feat.split()) 46*4882a593Smuzhiyun mach_overrides = d.getVar('MACHINEOVERRIDES') 47*4882a593Smuzhiyun mach_overrides = frozenset(mach_overrides.split(':')) 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun v7=frozenset(['armv7a', 'armv7r', 'armv7m', 'armv7ve']) 50*4882a593Smuzhiyun if mach_overrides.isdisjoint(v7) and feat.isdisjoint(v7): 51*4882a593Smuzhiyun return False 52*4882a593Smuzhiyun else: 53*4882a593Smuzhiyun return True 54*4882a593Smuzhiyuntarget_is_armv7[vardepvalue] = "${@target_is_armv7(d)}" 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun# Responsible for taking Yocto triples and converting it to Rust triples 57*4882a593Smuzhiyundef rust_base_triple(d, thing): 58*4882a593Smuzhiyun ''' 59*4882a593Smuzhiyun Mangle bitbake's *_SYS into something that rust might support (see 60*4882a593Smuzhiyun rust/mk/cfg/* for a list) 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun Note that os is assumed to be some linux form 63*4882a593Smuzhiyun ''' 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun # The llvm-target for armv7 is armv7-unknown-linux-gnueabihf 66*4882a593Smuzhiyun if thing == "TARGET" and target_is_armv7(d): 67*4882a593Smuzhiyun arch = "armv7" 68*4882a593Smuzhiyun else: 69*4882a593Smuzhiyun arch = oe.rust.arch_to_rust_arch(d.getVar('{}_ARCH'.format(thing))) 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun # All the Yocto targets are Linux and are 'unknown' 72*4882a593Smuzhiyun vendor = "-unknown" 73*4882a593Smuzhiyun os = d.getVar('{}_OS'.format(thing)) 74*4882a593Smuzhiyun libc = determine_libc(d, thing) 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun # Prefix with a dash and convert glibc -> gnu 77*4882a593Smuzhiyun if libc == "glibc": 78*4882a593Smuzhiyun libc = "-gnu" 79*4882a593Smuzhiyun elif libc == "musl": 80*4882a593Smuzhiyun libc = "-musl" 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun # Don't double up musl (only appears to be the case on aarch64) 83*4882a593Smuzhiyun if os == "linux-musl": 84*4882a593Smuzhiyun if libc != "-musl": 85*4882a593Smuzhiyun bb.fatal("{}_OS was '{}' but TCLIBC was not 'musl'".format(thing, os)) 86*4882a593Smuzhiyun os = "linux" 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun # This catches ARM targets and appends the necessary hard float bits 89*4882a593Smuzhiyun if os == "linux-gnueabi" or os == "linux-musleabi": 90*4882a593Smuzhiyun libc = bb.utils.contains('TUNE_FEATURES', 'callconvention-hard', 'hf', '', d) 91*4882a593Smuzhiyun return arch + vendor + '-' + os + libc 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun# In some cases uname and the toolchain differ on their idea of the arch name 95*4882a593SmuzhiyunRUST_BUILD_ARCH = "${@oe.rust.arch_to_rust_arch(d.getVar('BUILD_ARCH'))}" 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun# Naming explanation 98*4882a593Smuzhiyun# Yocto 99*4882a593Smuzhiyun# - BUILD_SYS - Yocto triple of the build environment 100*4882a593Smuzhiyun# - HOST_SYS - What we're building for in Yocto 101*4882a593Smuzhiyun# - TARGET_SYS - What we're building for in Yocto 102*4882a593Smuzhiyun# 103*4882a593Smuzhiyun# So when building '-native' packages BUILD_SYS == HOST_SYS == TARGET_SYS 104*4882a593Smuzhiyun# When building packages for the image HOST_SYS == TARGET_SYS 105*4882a593Smuzhiyun# This is a gross over simplification as there are other modes but 106*4882a593Smuzhiyun# currently this is all that's supported. 107*4882a593Smuzhiyun# 108*4882a593Smuzhiyun# Rust 109*4882a593Smuzhiyun# - TARGET - the system where the binary will run 110*4882a593Smuzhiyun# - HOST - the system where the binary is being built 111*4882a593Smuzhiyun# 112*4882a593Smuzhiyun# Rust additionally will use two additional cases: 113*4882a593Smuzhiyun# - undecorated (e.g. CC) - equivalent to TARGET 114*4882a593Smuzhiyun# - triple suffix (e.g. CC:x86_64_unknown_linux_gnu) - both 115*4882a593Smuzhiyun# see: https://github.com/alexcrichton/gcc-rs 116*4882a593Smuzhiyun# The way that Rust's internal triples and Yocto triples are mapped together 117*4882a593Smuzhiyun# its likely best to not use the triple suffix due to potential confusion. 118*4882a593Smuzhiyun 119*4882a593SmuzhiyunRUST_BUILD_SYS = "${@rust_base_triple(d, 'BUILD')}" 120*4882a593SmuzhiyunRUST_BUILD_SYS[vardepvalue] = "${RUST_BUILD_SYS}" 121*4882a593SmuzhiyunRUST_HOST_SYS = "${@rust_base_triple(d, 'HOST')}" 122*4882a593SmuzhiyunRUST_HOST_SYS[vardepvalue] = "${RUST_HOST_SYS}" 123*4882a593SmuzhiyunRUST_TARGET_SYS = "${@rust_base_triple(d, 'TARGET')}" 124*4882a593SmuzhiyunRUST_TARGET_SYS[vardepvalue] = "${RUST_TARGET_SYS}" 125*4882a593Smuzhiyun 126*4882a593Smuzhiyun# wrappers to get around the fact that Rust needs a single 127*4882a593Smuzhiyun# binary but Yocto's compiler and linker commands have 128*4882a593Smuzhiyun# arguments. Technically the archiver is always one command but 129*4882a593Smuzhiyun# this is necessary for builds that determine the prefix and then 130*4882a593Smuzhiyun# use those commands based on the prefix. 131*4882a593SmuzhiyunWRAPPER_DIR = "${WORKDIR}/wrapper" 132*4882a593SmuzhiyunRUST_BUILD_CC = "${WRAPPER_DIR}/build-rust-cc" 133*4882a593SmuzhiyunRUST_BUILD_CXX = "${WRAPPER_DIR}/build-rust-cxx" 134*4882a593SmuzhiyunRUST_BUILD_CCLD = "${WRAPPER_DIR}/build-rust-ccld" 135*4882a593SmuzhiyunRUST_BUILD_AR = "${WRAPPER_DIR}/build-rust-ar" 136*4882a593SmuzhiyunRUST_TARGET_CC = "${WRAPPER_DIR}/target-rust-cc" 137*4882a593SmuzhiyunRUST_TARGET_CXX = "${WRAPPER_DIR}/target-rust-cxx" 138*4882a593SmuzhiyunRUST_TARGET_CCLD = "${WRAPPER_DIR}/target-rust-ccld" 139*4882a593SmuzhiyunRUST_TARGET_AR = "${WRAPPER_DIR}/target-rust-ar" 140*4882a593Smuzhiyun 141*4882a593Smuzhiyuncreate_wrapper () { 142*4882a593Smuzhiyun file="$1" 143*4882a593Smuzhiyun shift 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun cat <<- EOF > "${file}" 146*4882a593Smuzhiyun #!/usr/bin/env python3 147*4882a593Smuzhiyun import os, sys 148*4882a593Smuzhiyun orig_binary = "$@" 149*4882a593Smuzhiyun binary = orig_binary.split()[0] 150*4882a593Smuzhiyun args = orig_binary.split() + sys.argv[1:] 151*4882a593Smuzhiyun os.execvp(binary, args) 152*4882a593Smuzhiyun EOF 153*4882a593Smuzhiyun chmod +x "${file}" 154*4882a593Smuzhiyun} 155*4882a593Smuzhiyun 156*4882a593Smuzhiyunexport WRAPPER_TARGET_CC = "${CC}" 157*4882a593Smuzhiyunexport WRAPPER_TARGET_CXX = "${CXX}" 158*4882a593Smuzhiyunexport WRAPPER_TARGET_CCLD = "${CCLD}" 159*4882a593Smuzhiyunexport WRAPPER_TARGET_LDFLAGS = "${LDFLAGS}" 160*4882a593Smuzhiyunexport WRAPPER_TARGET_AR = "${AR}" 161*4882a593Smuzhiyun 162*4882a593Smuzhiyun# compiler is used by gcc-rs 163*4882a593Smuzhiyun# linker is used by rustc/cargo 164*4882a593Smuzhiyun# archiver is used by the build of libstd-rs 165*4882a593Smuzhiyundo_rust_create_wrappers () { 166*4882a593Smuzhiyun mkdir -p "${WRAPPER_DIR}" 167*4882a593Smuzhiyun 168*4882a593Smuzhiyun # Yocto Build / Rust Host C compiler 169*4882a593Smuzhiyun create_wrapper "${RUST_BUILD_CC}" "${BUILD_CC}" 170*4882a593Smuzhiyun # Yocto Build / Rust Host C++ compiler 171*4882a593Smuzhiyun create_wrapper "${RUST_BUILD_CXX}" "${BUILD_CXX}" 172*4882a593Smuzhiyun # Yocto Build / Rust Host linker 173*4882a593Smuzhiyun create_wrapper "${RUST_BUILD_CCLD}" "${BUILD_CCLD}" "${BUILD_LDFLAGS}" 174*4882a593Smuzhiyun # Yocto Build / Rust Host archiver 175*4882a593Smuzhiyun create_wrapper "${RUST_BUILD_AR}" "${BUILD_AR}" 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun # Yocto Target / Rust Target C compiler 178*4882a593Smuzhiyun create_wrapper "${RUST_TARGET_CC}" "${WRAPPER_TARGET_CC}" "${WRAPPER_TARGET_LDFLAGS}" 179*4882a593Smuzhiyun # Yocto Target / Rust Target C++ compiler 180*4882a593Smuzhiyun create_wrapper "${RUST_TARGET_CXX}" "${WRAPPER_TARGET_CXX}" 181*4882a593Smuzhiyun # Yocto Target / Rust Target linker 182*4882a593Smuzhiyun create_wrapper "${RUST_TARGET_CCLD}" "${WRAPPER_TARGET_CCLD}" "${WRAPPER_TARGET_LDFLAGS}" 183*4882a593Smuzhiyun # Yocto Target / Rust Target archiver 184*4882a593Smuzhiyun create_wrapper "${RUST_TARGET_AR}" "${WRAPPER_TARGET_AR}" 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun} 187*4882a593Smuzhiyun 188*4882a593Smuzhiyunaddtask rust_create_wrappers before do_configure after do_patch do_prepare_recipe_sysroot 189*4882a593Smuzhiyundo_rust_create_wrappers[dirs] += "${WRAPPER_DIR}" 190