aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2018-02-04 00:44:09 +0200
committerGitHub <noreply@github.com>2018-02-04 00:44:09 +0200
commitbfa6c8d0747b4fb355f8e953448385c51574a965 (patch)
tree7941592be47ca899144e5d6868164d1f399add70
parent8fe816101467e66792251b4f57e0ddddb537764a (diff)
parent281294286e1126ef0945ddedd4f577b01f28bc8b (diff)
downloadmeson-bfa6c8d0747b4fb355f8e953448385c51574a965.zip
meson-bfa6c8d0747b4fb355f8e953448385c51574a965.tar.gz
meson-bfa6c8d0747b4fb355f8e953448385c51574a965.tar.bz2
Merge pull request #2938 from acfoltzer/rust-cross-merge
Add cross-compilation support for `rustc`
-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
-rw-r--r--test cases/rust/4 polyglot/meson.build2
7 files changed, 63 insertions, 20 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 d9c56df..35e697c 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1292,7 +1292,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)
@@ -1580,8 +1584,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'
@@ -1672,8 +1679,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 4737dd3..52c670a 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 9c2a6b9..2273b71 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1994,9 +1994,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:
diff --git a/test cases/rust/4 polyglot/meson.build b/test cases/rust/4 polyglot/meson.build
index a20d766..b7eef57 100644
--- a/test cases/rust/4 polyglot/meson.build
+++ b/test cases/rust/4 polyglot/meson.build
@@ -1,5 +1,5 @@
project('rust and c polyglot executable', 'c', 'rust')
-l = library('stuff', 'stuff.rs', install : true)
+l = library('stuff', 'stuff.rs', rust_crate_type: 'cdylib', install : true)
e = executable('prog', 'prog.c', link_with : l, install : true)
test('polyglottest', e)