convert things to python, cargo-native now works

This commit is contained in:
Cody P Schafer
2014-11-14 15:58:13 -05:00
parent 810a7258a7
commit 64ad86c9e4
+171 -146
View File
@@ -11,7 +11,132 @@ LIC_FILES_CHKSUM ="\
file://COPYRIGHT;md5=0e8e4a3b5d8e1c90eb243d406369763a \
"
def rust_triple(arch, vendor, os, d):
export RUST_TARGET_PATH="${WORKDIR}/targets/"
## arm-unknown-linux-gnueabihf
DATA_LAYOUT[arm] = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32"
LLVM_TARGET[arm] = "arm-unknown-linux-gnueabihf"
TARGET_ENDIAN[arm] = "little"
TARGET_WORD_SIZE[arm] = "32"
FEATURES[arm] = "+v6,+vfp2"
PRE_LINK_ARGS[arm] = "-Wl,--as-needed"
## x86_64-unknown-linux-gnu
DATA_LAYOUT[x86_64] = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
LLVM_TARGET[x86_64] = "x86_64-unknown-linux-gnu"
TARGET_ENDIAN[x86_64] = "little"
TARGET_WORD_SIZE[x86_64] = "64"
PRE_LINK_ARGS[x86_64] = "-m64 -Wl,--as-needed"
def ldflags_for(d, thing):
cc_arch = d.getVar('{}_CC_ARCH'.format(thing), True) or ""
tc = d.getVar('TOOLCHAIN_OPTIONS', True) or ""
ldflags = d.getVar('{}_LDFLAGS'.format(thing), True) or ""
return tc.split() + ldflags.split() + cc_arch.split()
def arch_for(d, thing):
return d.getVar('{}_ARCH'.format(thing), True)
def sys_for(d, thing):
return d.getVar('{}_SYS'.format(thing), True)
def prefix_for(d, thing):
return d.getVar('{}_PREFIX'.format(thing), True)
## FIXME: TOOLCHAIN_OPTIONS is set to "" by native.bbclass and cross.bbclass,
## which prevents us from grabbing them when building a cross compiler (native doesn't matter).
def cflags_for(d, thing):
cc_arch = d.getVar('{}_CC_ARCH'.format(thing), True) or ""
flags = d.getVar('{}_CFLAGS'.format(thing), True) or ""
tc = d.getVar('TOOLCHAIN_OPTIONS', True) or ""
return ' '.join([cc_arch, flags, tc])
def cxxflags_for(d, thing):
cc_arch = d.getVar('{}_CC_ARCH'.format(thing), True) or ""
flags = d.getVar('{}_CXXFLAGS'.format(thing), True) or ""
tc = d.getVar('TOOLCHAIN_OPTIONS', True) or ""
return ' '.join([cc_arch, flags, tc])
def as_json(list_):
a = '['
for e in list_:
if type(e) == str:
a += '"{}",'.format(e)
else:
raise Exception
if len(e):
a = a[:-1]
a += ']'
return a
def rust_gen_target(d, thing, wd):
arch = arch_for(d, thing)
ldflags = ldflags_for(d, thing)
sys = sys_for(d, thing)
prefix = prefix_for(d, thing)
o = open(wd + sys + '.json', 'w')
data_layout = d.getVarFlag('DATA_LAYOUT', arch, True)
llvm_target = d.getVarFlag('LLVM_TARGET', arch, True)
target_word_size = d.getVarFlag('TARGET_WORD_SIZE', arch, True)
prefix = d.getVar('{}_PREFIX'.format(thing), True)
ccache = d.getVar('CCACHE', True)
linker = "{}{}gcc".format(ccache, prefix)
features = d.getVarFlag('FEATURES', arch, True) or ""
pre_link_args = (d.getVarFlag('PRE_LINK_ARGS', arch, True) or "").split()
o.write('''{{
"data-layout": "{}",
"llvm-target": "{}",
"target-endian": "little",
"target-word-size": "{}",
"arch": "{}",
"os": "linux",
"linker": "{}",
"features": "{}",
"dynamic-linking": true,
"executables": true,
"morestack": true,
"linker-is-gnu": true,
"has-rpath": true,
"position-independent-executables": true,
"pre-link-args": {}
}}'''.format(
data_layout,
llvm_target,
target_word_size,
arch,
linker,
features,
as_json(pre_link_args)
))
o.close()
python do_rust_gen_targets () {
import os
wd = d.getVar('WORKDIR', True) + '/targets/'
try:
os.makedirs(wd)
except OSError as e:
if e.errno != 17:
raise e
for thing in ['HOST', 'BUILD', 'TARGET']:
rust_gen_target(d, thing, wd)
}
addtask do_rust_gen_targets after do_patch before do_compile
def rust_base_triple(d, thing):
'''
Mangle bitbake's *_SYS into something that rust might support (see
rust/mk/cfg/* for a list)
'''
arch = d.getVar('{}_ARCH'.format(thing), True)
vendor = d.getVar('{}_VENDOR'.format(thing), True)
os = d.getVar('{}_OS'.format(thing), True)
if arch.startswith("arm"):
vendor = "-unknown"
if os.endswith("gnueabi"):
@@ -22,156 +147,56 @@ def rust_triple(arch, vendor, os, d):
os = "linux-gnu"
return arch + vendor + '-' + os
export RUST_TARGET_PATH="${WORKDIR}/targets/"
def rust_gen_mk_cfg(d, thing):
''''
Rust's build system adds support for new archs via 2 things:
1. a file in mk/cfg which defines how the runtime libraries are built
2. and rustc arch definition either built into the compiler or supplied as a .json file
## arm-unknown-linux-gnueabihf
DATA_LAYOUT[arm] = "e-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32"
LLVM_TARGET[arm] = "arm-unknown-linux-gnueabihf"
TARGET_ENDIAN[arm] = "little"
TARGET_WORD_SIZE[arm] = "32"
FEATURES[arm] = "+v6,+vfp2"
This generates a new #1 for the given 'thing' (one of HOST, TARGET, BUILD)
using a "similar" config that rust already supplies as a template.
## x86_64-unknown-linux-gnu
DATA_LAYOUT[x86_64] = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128"
LLVM_TARGET[x86_64] = "x86_64-unknown-linux-gnu"
TARGET_ENDIAN[x86_64] = "little"
TARGET_WORD_SIZE[x86_64] = "64"
PRE_LINK_ARGS[x86_64] = "-m64"
Note that the configure process also depends on the existence of #1, so we
have to run this before do_configure
'''
python rust_gen_targets () {
import shutil, subprocess
rust_base_sys = rust_base_triple(d, thing)
arch = arch_for(d, thing)
sys = sys_for(d, thing)
prefix = prefix_for(d, thing)
p = d.getVar('S', True) + '/mk/cfg/'
o = open(p + sys_for(d, thing), 'w')
r = subprocess.call(['sed',
# update all triplets to the new one
'-e', 's/{}/{}/g'.format(rust_base_sys, sys),
# Replace tools with our own (CROSS_PREFIX is appended to all tools
# by rust's build system)
'-e', 's/^CROSS_PREFIX_{}.*$/CROSS_PREFIX_{} := {}/'.format(sys, sys, prefix),
'-e', 's/^CC_{}=.*$/CC_{} := gcc/'.format(sys, sys),
'-e', 's/^CXX_{}.*$/CXX_{} := g++/'.format(sys, sys),
'-e', 's/^CPP_{}.*$/CPP_{} := gcc -E/'.format(sys, sys),
'-e', 's/^AR_{}.*$/AR_{} := ar/'.format(sys, sys),
# Append our flags to the existing ones
'-e', '/^CFG_GCCISH_CFLAGS/ s;$; {};'.format(cflags_for(d, thing)),
'-e', '/^CFG_GCCISH_CXXFLAGS/ s;$; {};'.format(cxxflags_for(d, thing)),
'-e', '/^CFG_GCCISH_LINK_FLAGS/ s;$; {};'.format(" ".join(ldflags_for(d, thing))),
p + rust_base_sys
], stdout=o)
if r:
raise Exception
python do_rust_arch_fixup () {
for thing in ['HOST', 'BUILD', 'TARGET']:
rust_gen_mk_cfg(d, thing)
}
# Generates a config file suitable for use as a compiler-and-runtime-build-time
# target specification (distinct from those target specifications used by
# `rustc --target`)
#
# Designed to operate where $1={host,target,build}, and creates targets for
# these using our triples in *_SYS.
rust_gen_mk_cfg () {
deref() {
eval echo "\$$1"
}
ARCH="$(deref $u_ARCH)"
local u=`echo $1 | tr '[:lower:]' '[:upper:]'`
local sys=$(deref ${u}_SYS)
local rust_base_sys=$(deref RUST_BASE_${u}_SYS)
local p="${S}/mk/cfg/"
if [ -z "$sys" ]; then
bbnote "Rust: no SYS for $u"
return
fi
if [ -z "$rust_base_sys" ]; then
bbfatal "Rust: no RUST_BUILD_SYS for $u (sys=$sys)"
fi
if ! [ -e "$p$rust_base_sys" ]; then
bberror "Could not find RUST_BASE_${u}_SYS = ${rust_base_sys}"
bbfatal "file '$p/$rust_base_sys'"
fi
# Use one of the existing configs as our base
cp -f "$p$rust_base_sys" "$p$sys"
# FIXME: right now we assume our targets lack regex special characters
# and assumes flags lack regex special chars and ';'
# 1. Fixup the target name for all variables
# 2. Blank CROSS_PREFIX (XXX: should we set it to "${CCACHE}${$u_PREFIX}"
# and adjust other vars as needed?)
# 3. Edit in our:
local bare_cc="$(deref ${u}_PREFIX)gcc"
local cc="${CCACHE}${bare_cc} $(deref ${u}_CC_ARCH)"
local cxx="${CCACHE}$(deref ${u}_PREFIX)g++ $(deref ${u}_CC_ARCH)"
local cpp="$(deref ${u}_PREFIX)gcc $(deref ${u}_CC_ARCH) -E"
local ar="$(deref ${u}_PREFIX)ar"
# 4. Append our:
# FIXME: TOOLCHAIN_OPTIONS are only for TARGET (which is sometimes HOST)
local c_flags="$(deref ${u}_CC_ARCH)${TOOLCHAIN_OPTIONS} $(deref ${u}_CFLAGS)"
local cxx_flags="$(deref ${u}_CC_ARCH)${TOOLCHAIN_OPTIONS} $(deref ${u}_CXXFLAGS)"
local link_flags="${TOOLCHAIN_OPTIONS} $(deref ${u}_LD_ARCH)"
sed -i \
-e "s/${rust_base_sys}/$sys/g" \
\
-e "s/^CROSS_PREFIX_${sys}.*\$//" \
-e "s/^CC_$sys=.\*\$/CC_$sys := ${cc}/" \
-e "s/^CXX_$sys=.\*\$/CXX_$sys := ${cxx}/" \
-e "s/^CPP_$sys=.\*\$/CPP_$sys := ${cpp}/" \
-e "s/^AR_$sys=.\*\$/AR_$sys := ${ar}/" \
\
-e "/^CFG_GCCISH_CFLAGS/ s;\$; ${c_flags};" \
-e "/^CFG_GCCISH_CXXFLAGS/ s;\$; ${cxx_flags};" \
-e "/^CFG_GCCISH_LINK_FLAGS/ s;\$; ${link_flags};" \
\
"$p/$sys"
local t="${WORKDIR}/targets/"
mkdir -p "$t"
local link_flags_vec='[ "-fPIC" ]'
cat >"$t$sys" <<-EOF
{
"data-layout": "$(deref DATA_LAYOUT__$ARCH)",
"llvm_target": "${sys}",
"target_endian": "little",
"target-word-size": "$(deref TARGET_WORD_SIZE__$ARCH)",
"arch": "$ARCH",
"os": "linux",
"linker": "${bare_cc}",
"pre_link_args": ${link_flags_vec},
# post_link_args
# cpu
"features": "$(deref FEATURES__$ARCH)",
"dynamic_linking": true,
"executables": true,
"morestack": true,
# relocation_model
# ...
# is_like_windows
"linker_is_gnu": true,
"has_rpath": true,
# no_compiler_rt
"position_independent_executables": true,
}
EOF
}
do_rust_arch_fixup () {
RUST_BASE_TARGET_SYS="${@rust_triple('${TARGET_ARCH}','${TARGET_VENDOR}','${TARGET_OS}', d)}"
RUST_BASE_BUILD_SYS="${@rust_triple('${BUILD_ARCH}','${BUILD_VENDOR}','${BUILD_OS}', d)}"
RUST_BASE_HOST_SYS="${@rust_triple('${HOST_ARCH}','${HOST_VENDOR}','${HOST_OS}', d)}"
# XXX: these are all hacks around having the variables be shell vars
# instead of bitbake vars. It probably makes sense to convert this
# entire mess into python so we don't have to do this.
HOST_SYS="${HOST_SYS}"
BUILD_SYS="${BUILD_SYS}"
TARGET_SYS="${TARGET_SYS}"
HOST_ARCH="${HOST_ARCH}"
BUILD_ARCH="${BUILD_ARCH}"
TARGET_ARCH="${TARGET_ARCH}"
rust_gen_mk_cfg host
rust_gen_mk_cfg build
rust_gen_mk_cfg target
}
addtask rust_arch_fixup before do_configure after do_patch
addtask do_rust_arch_fixup before do_configure after do_patch
do_configure () {
# FIXME: allow --enable-local-rust
@@ -208,7 +233,7 @@ rust_runmake () {
env
# CFLAGS, LDFLAGS, CXXFLAGS, CPPFLAGS are used by rust's build for a
# wide range of targets (not just HOST). Yocto's settings for them will
# wide range of targets (not just TARGET). Yocto's settings for them will
# be inappropriate, avoid using.
unset CFLAGS
unset LDFLAGS