aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam C. Foltzer <acfoltzer@galois.com>2018-01-11 16:04:40 -0800
committerAdam C. Foltzer <acfoltzer@galois.com>2018-01-29 15:47:05 -0800
commit1d81efb03d5efee5899db01737880b1b3969e1fc (patch)
tree5333fba87ba73d881364934454ebdaaaf98cc7b0
parent7eb6a2918080fce37df7e6d25194d46ed98f0f35 (diff)
downloadmeson-1d81efb03d5efee5899db01737880b1b3969e1fc.zip
meson-1d81efb03d5efee5899db01737880b1b3969e1fc.tar.gz
meson-1d81efb03d5efee5899db01737880b1b3969e1fc.tar.bz2
Add cross-compilation support for `rustc`
This patch is largely modeled on the relatively-straightforward code for Fortran cross-compilation, so there might be some intricacies missing.
-rw-r--r--cross/ubuntu-armhf.txt1
-rw-r--r--docs/markdown/snippets/rust-cross.md16
-rw-r--r--mesonbuild/backend/ninjabackend.py16
-rw-r--r--mesonbuild/compilers/rust.py15
-rw-r--r--mesonbuild/environment.py29
-rw-r--r--mesonbuild/interpreter.py4
6 files changed, 62 insertions, 19 deletions
diff --git a/cross/ubuntu-armhf.txt b/cross/ubuntu-armhf.txt
index 367eba3..6246ffe 100644
--- a/cross/ubuntu-armhf.txt
+++ b/cross/ubuntu-armhf.txt
@@ -3,6 +3,7 @@
# when cross compiled binaries can't be run we don't do that
c = '/usr/bin/arm-linux-gnueabihf-gcc-7'
cpp = '/usr/bin/arm-linux-gnueabihf-g++-7'
+rust = ['rustc', '--target', 'arm-unknown-linux-gnueabihf', '-C', 'linker=/usr/bin/arm-linux-gnueabihf-gcc-7']
ar = '/usr/arm-linux-gnueabihf/bin/ar'
strip = '/usr/arm-linux-gnueabihf/bin/strip'
pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config'
diff --git a/docs/markdown/snippets/rust-cross.md b/docs/markdown/snippets/rust-cross.md
new file mode 100644
index 0000000..7f18c44
--- /dev/null
+++ b/docs/markdown/snippets/rust-cross.md
@@ -0,0 +1,16 @@
+## Rust cross-compilation
+
+Cross-compilation is now supported for Rust targets. Like other
+cross-compilers, the Rust binary must be specified in your cross
+file. It should specify a `--target` (as installed by `rustup target`)
+and a custom linker pointing to your C cross-compiler. For example:
+
+```
+[binaries]
+c = '/usr/bin/arm-linux-gnueabihf-gcc-7'
+rust = [
+ 'rustc',
+ '--target', 'arm-unknown-linux-gnueabihf',
+ '-C', 'linker=/usr/bin/arm-linux-gnueabihf-gcc-7',
+]
+```
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 77c7d50..e1f3909 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1291,7 +1291,11 @@ int dummy;
# installations
for rpath_arg in rpath_args:
args += ['-C', 'link-arg=' + rpath_arg + ':' + os.path.join(rustc.get_sysroot(), 'lib')]
- element = NinjaBuildElement(self.all_outputs, target_name, 'rust_COMPILER', relsrc)
+ crstr = ''
+ if target.is_cross:
+ crstr = '_CROSS'
+ compiler_name = 'rust%s_COMPILER' % crstr
+ element = NinjaBuildElement(self.all_outputs, target_name, compiler_name, relsrc)
if len(orderdeps) > 0:
element.add_orderdep(orderdeps)
element.add_item('ARGS', args)
@@ -1579,8 +1583,11 @@ int dummy;
outfile.write(restat)
outfile.write('\n')
- def generate_rust_compile_rules(self, compiler, outfile):
- rule = 'rule %s_COMPILER\n' % compiler.get_language()
+ def generate_rust_compile_rules(self, compiler, outfile, is_cross):
+ crstr = ''
+ if is_cross:
+ crstr = '_CROSS'
+ rule = 'rule %s%s_COMPILER\n' % (compiler.get_language(), crstr)
invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()])
command = ' command = %s $ARGS $in\n' % invoc
description = ' description = Compiling Rust source $in.\n'
@@ -1671,8 +1678,7 @@ rule FORTRAN_DEP_HACK
self.generate_vala_compile_rules(compiler, outfile)
return
if langname == 'rust':
- if not is_cross:
- self.generate_rust_compile_rules(compiler, outfile)
+ self.generate_rust_compile_rules(compiler, outfile, is_cross)
return
if langname == 'swift':
if not is_cross:
diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py
index b93289f..d1a05ed 100644
--- a/mesonbuild/compilers/rust.py
+++ b/mesonbuild/compilers/rust.py
@@ -19,9 +19,11 @@ from ..mesonlib import EnvironmentException, Popen_safe
from .compilers import Compiler, rust_buildtype_args
class RustCompiler(Compiler):
- def __init__(self, exelist, version):
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None):
self.language = 'rust'
super().__init__(exelist, version)
+ self.is_cross = is_cross
+ self.exe_wrapper = exe_wrapper
self.id = 'rustc'
def needs_static_linker(self):
@@ -41,7 +43,16 @@ class RustCompiler(Compiler):
pc.wait()
if pc.returncode != 0:
raise EnvironmentException('Rust compiler %s can not compile programs.' % self.name_string())
- if subprocess.call(output_name) != 0:
+ if self.is_cross:
+ if self.exe_wrapper is None:
+ # Can't check if the binaries run so we have to assume they do
+ return
+ cmdlist = self.exe_wrapper + [output_name]
+ else:
+ cmdlist = [output_name]
+ pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ pe.wait()
+ if pe.returncode != 0:
raise EnvironmentException('Executables created by Rust compiler %s are not runnable.' % self.name_string())
def get_dependency_gen_args(self, outfile):
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index e5aa43e..0e5dff0 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -278,6 +278,7 @@ class Environment:
self.default_objc = ['cc']
self.default_objcpp = ['c++']
self.default_fortran = ['gfortran', 'g95', 'f95', 'f90', 'f77', 'ifort']
+ self.default_rust = ['rustc']
self.default_static_linker = ['ar']
self.vs_static_linker = ['lib']
self.gcc_static_linker = ['gcc-ar']
@@ -688,16 +689,24 @@ class Environment:
return ValaCompiler(exelist, version)
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
- def detect_rust_compiler(self):
- exelist = ['rustc']
- try:
- p, out = Popen_safe(exelist + ['--version'])[0:2]
- except OSError:
- raise EnvironmentException('Could not execute Rust compiler "%s"' % ' '.join(exelist))
- version = search_version(out)
- if 'rustc' in out:
- return RustCompiler(exelist, version)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
+ def detect_rust_compiler(self, want_cross):
+ popen_exceptions = {}
+ compilers, ccache, is_cross, exe_wrap = self._get_compilers('rust', 'RUSTC', want_cross)
+ for compiler in compilers:
+ if isinstance(compiler, str):
+ compiler = [compiler]
+ try:
+ p, out = Popen_safe(compiler + ['--version'])[0:2]
+ except OSError as e:
+ popen_exceptions[compiler] = e
+ continue
+
+ version = search_version(out)
+
+ if 'rustc' in out:
+ return RustCompiler(compiler, version, is_cross, exe_wrap)
+
+ self._handle_exceptions(popen_exceptions, compilers)
def detect_d_compiler(self, want_cross):
is_cross = False
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index c759892..fb29fe9 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1992,9 +1992,9 @@ to directly access options of other subprojects.''')
if need_cross_compiler:
cross_comp = self.environment.detect_d_compiler(True)
elif lang == 'rust':
- comp = self.environment.detect_rust_compiler()
+ comp = self.environment.detect_rust_compiler(False)
if need_cross_compiler:
- cross_comp = comp # FIXME, not correct.
+ cross_comp = self.environment.detect_rust_compiler(True)
elif lang == 'fortran':
comp = self.environment.detect_fortran_compiler(False)
if need_cross_compiler: