blob: aa4f36cc8bf6984236d86b0eb655bff31e12663a [file] [log] [blame]
# Copyright 2017 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for building Rust toolchain."""
from recipe_engine.config import Enum
from recipe_engine.recipe_api import Property
import re
DEPS = [
'fuchsia/git',
'fuchsia/gitiles',
'fuchsia/goma',
'fuchsia/jiri',
'fuchsia/macos_sdk',
'fuchsia/upload',
'recipe_engine/cipd',
'recipe_engine/context',
'recipe_engine/isolated',
'recipe_engine/json',
'recipe_engine/path',
'recipe_engine/platform',
'recipe_engine/properties',
'recipe_engine/python',
'recipe_engine/raw_io',
'recipe_engine/file',
'recipe_engine/step',
'recipe_engine/url',
]
PLATFORM_TO_TRIPLE = {
'linux-amd64': 'x86_64-unknown-linux-gnu',
'linux-arm64': 'aarch64-unknown-linux-gnu',
'mac-amd64': 'x86_64-apple-darwin',
}
PLATFORMS = PLATFORM_TO_TRIPLE.keys()
PACKAGES = ['rust', 'rust_extra_tools']
PROPERTIES = {
'repository':
Property(
kind=str,
help='Git repository URL',
default='https://fuchsia.googlesource.com/third_party/rust'),
'branch':
Property(kind=str, help='Git branch', default='refs/heads/master'),
'revision':
Property(kind=str, help='Revision', default=None),
'package':
Property(
kind=Enum(*PACKAGES), help='Which package to build',
default='rust'),
}
def RunSteps(api, repository, branch, revision, package):
api.goma.ensure()
if not revision:
revision = api.gitiles.refs(repository).get(branch, None)
# TODO: factor this out into a host_build recipe module.
host_platform = '%s-%s' % (api.platform.name.replace('win', 'windows'), {
'intel': {
32: '386',
64: 'amd64',
},
'arm': {
32: 'armv6',
64: 'arm64',
},
}[api.platform.arch][api.platform.bits])
with api.step.nest('ensure_packages'):
with api.context(infra_steps=True):
pkgs = api.cipd.EnsureFile()
pkgs.add_package('infra/cmake/${platform}', 'version:3.9.2')
pkgs.add_package('infra/ninja/${platform}', 'version:1.8.2')
pkgs.add_package('infra/swig/${platform}', 'version:3.0.12')
pkgs.add_package('fuchsia/third_party/clang/${platform}', 'goma')
pkgs.add_package('fuchsia/sysroot/linux-amd64', 'latest', 'linux-amd64')
pkgs.add_package('fuchsia/sysroot/linux-arm64', 'latest', 'linux-arm64')
pkgs.add_package('fuchsia/sdk/core/${platform}', 'latest', 'sdk')
cipd_dir = api.path['start_dir'].join('cipd')
api.cipd.ensure(cipd_dir, pkgs)
sdk_dir = cipd_dir.join('sdk')
with api.context(infra_steps=True):
rust_dir = api.path['start_dir'].join('rust')
api.git.checkout(repository, rust_dir, ref=revision, recursive=True)
# build rust
staging_dir = api.path.mkdtemp('rust')
build_dir = staging_dir.join('build')
api.file.ensure_directory('build', build_dir)
pkg_dir = staging_dir.join('rust')
api.file.ensure_directory('create pkg_dir', pkg_dir)
with api.macos_sdk(), api.goma.build_with_goma():
host_triple = PLATFORM_TO_TRIPLE[host_platform]
if api.platform.name == 'linux':
host_sysroot = cipd_dir.join(host_platform)
elif api.platform.name == 'mac':
# TODO(IN-148): Eventually use our own hermetic sysroot as for Linux.
step_result = api.step(
'xcrun', ['xcrun', '--show-sdk-path'],
stdout=api.raw_io.output(name='sdk-path', add_output_log=True),
step_test_data=lambda: api.raw_io.test_api.stream_output(
'/some/xcode/path'))
host_sysroot = step_result.stdout.strip()
else: # pragma: no cover
assert False, 'unsupported platform'
targets = [
'x86_64-unknown-linux-gnu',
'aarch64-unknown-linux-gnu',
'wasm32-unknown-unknown',
]
if api.platform.is_mac:
targets.append('x86_64-apple-darwin')
config_file = 'config.toml'
api.python(
'generate config.toml',
api.resource('generate_config.py'),
args=[
'--targets',
','.join(targets),
'--clang-prefix',
cipd_dir,
'config_toml',
'--prefix',
pkg_dir,
'--host-sysroot',
host_sysroot,
'--goma-dir',
api.goma.goma_dir,
] + (['--extra-tools-only'] if package == 'rust_extra_tools' else []),
stdout=api.raw_io.output(leak_to=build_dir.join(config_file)))
env_data = api.python(
'generate environment',
api.resource('generate_config.py'),
args=[
'--targets',
','.join(targets),
'--clang-prefix',
cipd_dir,
'environment',
'--sdk-dir',
sdk_dir,
'--revision',
revision,
# TODO(tmandry): Switch to multiarch so these don't need to be separate
'--linux-amd64-sysroot',
cipd_dir.join('linux-amd64'),
'--linux-arm64-sysroot',
cipd_dir.join('linux-arm64'),
] + (['--darwin-sysroot', host_sysroot] if api.platform.is_mac else []),
stdout=api.raw_io.output(name='environment', add_output_log=True),
step_test_data=lambda: api.raw_io.test_api.stream_output(
'RUST_BACKTRACE=1'))
env = {}
for line in env_data.stdout.splitlines():
key, value = line.split('=', 1)
env[key] = value
env_prefixes = {'PATH': [cipd_dir, cipd_dir.join('bin')]}
with api.context(cwd=build_dir, env=env, env_prefixes=env_prefixes):
api.python(
'rust install',
rust_dir.join('x.py'),
args=['install', '--config', config_file])
api.upload.upload_isolated(pkg_dir)
# package rust
step_result = api.step(
'rust version', [pkg_dir.join('bin', 'rustc'), '--version'],
stdout=api.raw_io.output(),
step_test_data=lambda: api.raw_io.test_api.stream_output(
'rustc 1.19.0-nightly (75b056812 2017-05-15)'))
m = re.search(r'rustc ([0-9a-z.-]+)', step_result.stdout)
assert m, 'Cannot determine Rust version'
version = m.group(1)
api.upload.cipd_package(
'fuchsia/%s/${platform}' % package,
pkg_dir, [api.upload.DirectoryPath(pkg_dir)], {'git_revision': revision},
repository=repository,
extra_tags={'version': version})
def GenTests(api):
revision = '75b05681239cb309a23fcb4f8864f177e5aa62da'
for platform in ('linux', 'mac'):
for package in ('rust', 'rust_extra_tools'):
yield (api.test('%s_%s' % (package, platform)) +
api.platform.name(platform) + api.properties(package=package) +
api.gitiles.refs('refs', ('refs/heads/master', revision)))
yield (api.test('%s_%s_new' % (package, platform)) +
api.platform.name(platform) + api.properties(package=package) +
api.gitiles.refs('refs', ('refs/heads/master', revision)) +
api.step_data(
'cipd.cipd search fuchsia/%s/${platform} ' % package +
'git_revision:' + revision, api.json.output({'result': []})))