summaryrefslogtreecommitdiff
path: root/build/moz.configure/rust.configure
diff options
context:
space:
mode:
Diffstat (limited to 'build/moz.configure/rust.configure')
-rw-r--r--build/moz.configure/rust.configure166
1 files changed, 166 insertions, 0 deletions
diff --git a/build/moz.configure/rust.configure b/build/moz.configure/rust.configure
new file mode 100644
index 0000000000..261768f640
--- /dev/null
+++ b/build/moz.configure/rust.configure
@@ -0,0 +1,166 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+option('--enable-rust', help='Include Rust language sources')
+
+@depends('--enable-rust')
+def rust_compiler_names(value):
+ if value:
+ return ['rustc']
+
+@depends('--enable-rust')
+def cargo_binary_names(value):
+ if value:
+ return ['cargo']
+
+rustc = check_prog('RUSTC', rust_compiler_names, allow_missing=True)
+cargo = check_prog('CARGO', cargo_binary_names, allow_missing=True)
+
+@depends_if(rustc)
+@checking('rustc version', lambda info: info.version)
+def rustc_info(rustc):
+ out = check_cmd_output(rustc, '--version', '--verbose').splitlines()
+ info = dict((s.strip() for s in line.split(':', 1)) for line in out[1:])
+ return namespace(
+ version=Version(info.get('release', '0')),
+ commit=info.get('commit-hash', 'unknown'),
+ )
+
+@depends_if(cargo)
+@checking('cargo support for --frozen')
+@imports('subprocess')
+@imports('os')
+def cargo_supports_frozen(cargo):
+ try:
+ lines = subprocess.check_output(
+ [cargo, 'help', 'build']
+ ).splitlines()
+ supported = any(' --frozen' in l for l in lines)
+ if 'MOZ_AUTOMATION' in os.environ and not supported:
+ die('cargo in automation must support --frozen')
+ return supported
+ except subprocess.CalledProcessError as e:
+ die('Failed to call cargo: %s', e.message)
+
+set_config('MOZ_CARGO_SUPPORTS_FROZEN', cargo_supports_frozen)
+
+@depends('--enable-rust', rustc, rustc_info)
+@imports(_from='textwrap', _import='dedent')
+def rust_compiler(value, rustc, rustc_info):
+ if value:
+ if not rustc:
+ die(dedent('''\
+ Rust compiler not found.
+ To compile rust language sources, you must have 'rustc' in your path.
+ See https//www.rust-lang.org/ for more information.
+ '''))
+ version = rustc_info.version
+ min_version = Version('1.10')
+ if version < min_version:
+ die(dedent('''\
+ Rust compiler {} is too old.
+ To compile Rust language sources please install at least
+ version {} of the 'rustc' toolchain and make sure it is
+ first in your path.
+ You can verify this by typing 'rustc --version'.
+ '''.format(version, min_version)))
+ return True
+
+set_config('MOZ_RUST', rust_compiler)
+
+@depends(rust_compiler, rustc, target, cross_compiling)
+@imports('os')
+@imports('subprocess')
+@imports(_from='mozbuild.configure.util', _import='LineIO')
+@imports(_from='mozbuild.shellutil', _import='quote')
+@imports(_from='tempfile', _import='mkstemp')
+def rust_target(rust_compiler, rustc, target, cross_compiling):
+ if rust_compiler:
+ # Rust's --target options are similar to, but not exactly the same
+ # as, the autoconf-derived targets we use. An example would be that
+ # Rust uses distinct target triples for targetting the GNU C++ ABI
+ # and the MSVC C++ ABI on Win32, whereas autoconf has a single
+ # triple and relies on the user to ensure that everything is
+ # compiled for the appropriate ABI. We need to perform appropriate
+ # munging to get the correct option to rustc.
+ #
+ # The canonical list of targets supported can be derived from:
+ #
+ # https://github.com/rust-lang/rust/tree/master/mk/cfg
+
+ # Avoid having to write out os+kernel for all the platforms where
+ # they don't differ.
+ os_or_kernel = target.kernel if target.kernel == 'Linux' and target.os != 'Android' else target.os
+ rustc_target = {
+ # DragonFly
+ ('x86_64', 'DragonFly'): 'x86_64-unknown-dragonfly',
+ # FreeBSD
+ ('x86', 'FreeBSD'): 'i686-unknown-freebsd',
+ ('x86_64', 'FreeBSD'): 'x86_64-unknown-freebsd',
+ # NetBSD
+ ('x86_64', 'NetBSD'): 'x86_64-unknown-netbsd',
+ # OpenBSD
+ ('x86_64', 'OpenBSD'): 'x86_64-unknown-openbsd',
+ # Linux
+ ('x86', 'Linux'): 'i586-unknown-linux-gnu',
+ # Linux
+ ('x86_64', 'Linux'): 'x86_64-unknown-linux-gnu',
+ # OS X and iOS
+ ('x86', 'OSX'): 'i686-apple-darwin',
+ ('x86', 'iOS'): 'i386-apple-ios',
+ ('x86_64', 'OSX'): 'x86_64-apple-darwin',
+ # Android
+ ('x86', 'Android'): 'i686-linux-android',
+ ('arm', 'Android'): 'armv7-linux-androideabi',
+ # Windows
+ # XXX better detection of CXX needed here, to figure out whether
+ # we need i686-pc-windows-gnu instead, since mingw32 builds work.
+ ('x86', 'WINNT'): 'i686-pc-windows-msvc',
+ ('x86_64', 'WINNT'): 'x86_64-pc-windows-msvc',
+ }.get((target.cpu, os_or_kernel), None)
+
+ if rustc_target is None:
+ die("Don't know how to translate {} for rustc".format(target.alias))
+
+ # Check to see whether our rustc has a reasonably functional stdlib
+ # for our chosen target.
+ target_arg = '--target=' + rustc_target
+ in_fd, in_path = mkstemp(prefix='conftest', suffix='.rs')
+ out_fd, out_path = mkstemp(prefix='conftest', suffix='.rlib')
+ os.close(out_fd)
+ try:
+ source = 'pub extern fn hello() { println!("Hello world"); }'
+ log.debug('Creating `%s` with content:', in_path)
+ with LineIO(lambda l: log.debug('| %s', l)) as out:
+ out.write(source)
+
+ os.write(in_fd, source)
+ os.close(in_fd)
+
+ cmd = [
+ rustc,
+ '--crate-type', 'staticlib',
+ target_arg,
+ '-o', out_path,
+ in_path,
+ ]
+ def failed():
+ die('Cannot compile for {} with {}'.format(target.alias, rustc))
+ check_cmd_output(*cmd, onerror=failed)
+ if not os.path.exists(out_path) or os.path.getsize(out_path) == 0:
+ failed()
+ finally:
+ os.remove(in_path)
+ os.remove(out_path)
+ # This target is usable.
+ return rustc_target
+
+set_config('RUST_TARGET', rust_target)
+
+# Until we remove all the other Rust checks in old-configure.
+add_old_configure_assignment('MOZ_RUST', rust_compiler)
+add_old_configure_assignment('RUSTC', rustc)
+add_old_configure_assignment('RUST_TARGET', rust_target)