1*4882a593Smuzhiyun# removed, because firefox fails to configure when it finds native python3 instead of python2.7 from HOSTTOOLS
2*4882a593Smuzhiyun# inherit python3native
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun# Common variables used by all Rust builds
5*4882a593Smuzhiyunexport rustlibdir = "${libdir}/rust"
6*4882a593SmuzhiyunFILES:${PN} += "${rustlibdir}/*.so"
7*4882a593SmuzhiyunFILES:${PN}-dev += "${rustlibdir}/*.rlib ${rustlibdir}/*.rmeta"
8*4882a593SmuzhiyunFILES:${PN}-dbg += "${rustlibdir}/.debug"
9*4882a593Smuzhiyun
10*4882a593SmuzhiyunRUSTLIB = "-L ${STAGING_LIBDIR}/rust"
11*4882a593SmuzhiyunRUST_DEBUG_REMAP = "--remap-path-prefix=${WORKDIR}=/usr/src/debug/${PN}/${EXTENDPE}${PV}-${PR}"
12*4882a593SmuzhiyunRUSTFLAGS += "${RUSTLIB} ${RUST_DEBUG_REMAP}"
13*4882a593SmuzhiyunRUSTLIB_DEP ?= "libstd-rs"
14*4882a593Smuzhiyunexport RUST_TARGET_PATH = "${STAGING_LIBDIR_NATIVE}/rustlib"
15*4882a593SmuzhiyunRUST_PANIC_STRATEGY ?= "unwind"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun# Native builds are not effected by TCLIBC. Without this, rust-native
18*4882a593Smuzhiyun# thinks it's "target" (i.e. x86_64-linux) is a musl target.
19*4882a593SmuzhiyunRUST_LIBC = "${TCLIBC}"
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_HOST_SYS = "${@rust_base_triple(d, 'HOST')}"
121*4882a593SmuzhiyunRUST_TARGET_SYS = "${@rust_base_triple(d, 'TARGET')}"
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun# wrappers to get around the fact that Rust needs a single
124*4882a593Smuzhiyun# binary but Yocto's compiler and linker commands have
125*4882a593Smuzhiyun# arguments. Technically the archiver is always one command but
126*4882a593Smuzhiyun# this is necessary for builds that determine the prefix and then
127*4882a593Smuzhiyun# use those commands based on the prefix.
128*4882a593SmuzhiyunWRAPPER_DIR = "${WORKDIR}/wrapper"
129*4882a593SmuzhiyunRUST_BUILD_CC = "${WRAPPER_DIR}/build-rust-cc"
130*4882a593SmuzhiyunRUST_BUILD_CXX = "${WRAPPER_DIR}/build-rust-cxx"
131*4882a593SmuzhiyunRUST_BUILD_CCLD = "${WRAPPER_DIR}/build-rust-ccld"
132*4882a593SmuzhiyunRUST_BUILD_AR = "${WRAPPER_DIR}/build-rust-ar"
133*4882a593SmuzhiyunRUST_TARGET_CC = "${WRAPPER_DIR}/target-rust-cc"
134*4882a593SmuzhiyunRUST_TARGET_CXX = "${WRAPPER_DIR}/target-rust-cxx"
135*4882a593SmuzhiyunRUST_TARGET_CCLD = "${WRAPPER_DIR}/target-rust-ccld"
136*4882a593SmuzhiyunRUST_TARGET_AR = "${WRAPPER_DIR}/target-rust-ar"
137*4882a593Smuzhiyun
138*4882a593Smuzhiyuncreate_wrapper () {
139*4882a593Smuzhiyun	file="$1"
140*4882a593Smuzhiyun	shift
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun	cat <<- EOF > "${file}"
143*4882a593Smuzhiyun	#!/usr/bin/env python3
144*4882a593Smuzhiyun	import os, sys
145*4882a593Smuzhiyun	orig_binary = "$@"
146*4882a593Smuzhiyun	binary = orig_binary.split()[0]
147*4882a593Smuzhiyun	args = orig_binary.split() + sys.argv[1:]
148*4882a593Smuzhiyun	os.execvp(binary, args)
149*4882a593Smuzhiyun	EOF
150*4882a593Smuzhiyun	chmod +x "${file}"
151*4882a593Smuzhiyun}
152*4882a593Smuzhiyun
153*4882a593Smuzhiyunexport WRAPPER_TARGET_CC = "${CC}"
154*4882a593Smuzhiyunexport WRAPPER_TARGET_CXX = "${CXX}"
155*4882a593Smuzhiyunexport WRAPPER_TARGET_CCLD = "${CCLD}"
156*4882a593Smuzhiyunexport WRAPPER_TARGET_LDFLAGS = "${LDFLAGS}"
157*4882a593Smuzhiyunexport WRAPPER_TARGET_AR = "${AR}"
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun# compiler is used by gcc-rs
160*4882a593Smuzhiyun# linker is used by rustc/cargo
161*4882a593Smuzhiyun# archiver is used by the build of libstd-rs
162*4882a593Smuzhiyundo_rust_create_wrappers () {
163*4882a593Smuzhiyun	mkdir -p "${WRAPPER_DIR}"
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun	# Yocto Build / Rust Host C compiler
166*4882a593Smuzhiyun	create_wrapper "${RUST_BUILD_CC}" "${BUILD_CC}"
167*4882a593Smuzhiyun	# Yocto Build / Rust Host C++ compiler
168*4882a593Smuzhiyun	create_wrapper "${RUST_BUILD_CXX}" "${BUILD_CXX}"
169*4882a593Smuzhiyun	# Yocto Build / Rust Host linker
170*4882a593Smuzhiyun	create_wrapper "${RUST_BUILD_CCLD}" "${BUILD_CCLD}" "${BUILD_LDFLAGS}"
171*4882a593Smuzhiyun	# Yocto Build / Rust Host archiver
172*4882a593Smuzhiyun	create_wrapper "${RUST_BUILD_AR}" "${BUILD_AR}"
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun	# Yocto Target / Rust Target C compiler
175*4882a593Smuzhiyun	create_wrapper "${RUST_TARGET_CC}" "${WRAPPER_TARGET_CC}" "${WRAPPER_TARGET_LDFLAGS}"
176*4882a593Smuzhiyun	# Yocto Target / Rust Target C++ compiler
177*4882a593Smuzhiyun	create_wrapper "${RUST_TARGET_CXX}" "${WRAPPER_TARGET_CXX}"
178*4882a593Smuzhiyun	# Yocto Target / Rust Target linker
179*4882a593Smuzhiyun	create_wrapper "${RUST_TARGET_CCLD}" "${WRAPPER_TARGET_CCLD}" "${WRAPPER_TARGET_LDFLAGS}"
180*4882a593Smuzhiyun	# Yocto Target / Rust Target archiver
181*4882a593Smuzhiyun	create_wrapper "${RUST_TARGET_AR}" "${WRAPPER_TARGET_AR}"
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun}
184*4882a593Smuzhiyun
185*4882a593Smuzhiyunaddtask rust_create_wrappers before do_configure after do_patch do_prepare_recipe_sysroot
186*4882a593Smuzhiyundo_rust_create_wrappers[dirs] += "${WRAPPER_DIR}"
187