| # 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/buildbucket_util", |
| "fuchsia/cipd_platform", |
| "fuchsia/git", |
| "fuchsia/goma", |
| "fuchsia/macos_sdk", |
| "fuchsia/nullcontext", |
| "fuchsia/status_check", |
| "fuchsia/toolchain", |
| "fuchsia/upload", |
| "recipe_engine/cipd", |
| "recipe_engine/context", |
| "recipe_engine/file", |
| "recipe_engine/json", |
| "recipe_engine/path", |
| "recipe_engine/platform", |
| "recipe_engine/properties", |
| "recipe_engine/python", |
| "recipe_engine/raw_io", |
| "recipe_engine/step", |
| ] |
| |
| PACKAGES = ["rust", "rust_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): |
| use_goma = ( |
| not api.platform.arch == "arm" and api.platform.bits == 64 |
| ) and not api.platform.is_win |
| if use_goma: |
| api.goma.ensure() |
| goma_context = api.goma.build_with_goma |
| else: |
| goma_context = api.nullcontext |
| |
| if not revision: |
| revision = api.git.get_remote_branch_head(repository, branch) |
| |
| host_platform = api.cipd_platform.name |
| |
| use_breakpad = host_platform == "linux-amd64" |
| |
| with api.step.nest("ensure_packages"): |
| with api.context(infra_steps=True): |
| pkgs = api.cipd.EnsureFile() |
| pkgs.add_package("infra/3pp/tools/cmake/${platform}", "version:3.13.5") |
| pkgs.add_package("infra/3pp/tools/ninja/${platform}", "version:1.9.0") |
| pkgs.add_package("infra/3pp/tools/swig/${platform}", "version:4.0.2") |
| pkgs.add_package("fuchsia/third_party/clang/${platform}", "integration") |
| pkgs.add_package("fuchsia/sysroot/linux-amd64", "latest", "linux-amd64") |
| pkgs.add_package("fuchsia/sysroot/linux-arm64", "latest", "linux-arm64") |
| # We don't have SDK for linux-arm64 or win, but we only need sysroot. |
| if ( |
| api.platform.arch == "arm" and api.platform.bits == 64 |
| ) or api.platform.is_win: |
| pkgs.add_package("fuchsia/sdk/core/linux-amd64", "latest", "sdk") |
| else: |
| pkgs.add_package("fuchsia/sdk/core/${platform}", "latest", "sdk") |
| if use_breakpad: |
| pkgs.add_package( |
| "fuchsia/tools/breakpad/${platform}", "latest", "breakpad" |
| ) |
| 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["start_dir"].join("staging") |
| 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(), goma_context(): |
| if api.platform.name == "linux": |
| host_sysroot = cipd_dir.join(host_platform) |
| elif api.platform.name == "mac": |
| # TODO(fxbug.dev/3043): Eventually use our own hermetic sysroot as for Linux. |
| step_result = api.step( |
| "xcrun", |
| ["xcrun", "--sdk", "macosx", "--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=[ |
| "config_toml", |
| "--targets", |
| ",".join(targets), |
| "--clang-prefix", |
| cipd_dir, |
| "--prefix", |
| pkg_dir, |
| "--host-sysroot", |
| host_sysroot, |
| ] |
| + (["--goma-dir", api.goma.goma_dir] if use_goma else []) |
| + (["--extra-tools-only"] if package == "rust_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=[ |
| "environment", |
| "--targets", |
| ",".join(targets), |
| "--clang-prefix", |
| cipd_dir, |
| "--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], |
| ) |
| |
| runtime_result = api.python( |
| "generate runtime spec", |
| api.resource("generate_config.py"), |
| args=["runtime"], |
| stdout=api.json.output(), |
| ) |
| api.toolchain.strip_runtimes( |
| name="generate runtime.json", |
| spec=runtime_result.stdout, |
| path=pkg_dir.join("lib"), |
| build_id_subpath="debug/.build-id", |
| readelf=cipd_dir.join("bin", "llvm-readelf"), |
| objcopy=cipd_dir.join("bin", "llvm-objcopy"), |
| dump_syms=( |
| cipd_dir.join("breakpad", "dump_syms", "dump_syms") |
| if use_breakpad |
| else None |
| ), |
| ) |
| |
| isolated = 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) |
| |
| if not api.buildbucket_util.is_tryjob: |
| api.upload.cipd_package( |
| "fuchsia/third_party/%s/${platform}" % package, |
| pkg_dir, |
| [api.upload.DirectoryPath(pkg_dir)], |
| {"git_revision": revision}, |
| repository=repository, |
| extra_tags={"version": version}, |
| ) |
| |
| builders = { |
| "linux-amd64": ( |
| "rust_toolchain.fuchsia-arm64-debug", |
| "rust_toolchain.fuchsia-arm64-release", |
| "rust_toolchain.fuchsia-x64-debug", |
| "rust_toolchain.fuchsia-x64-release", |
| ), |
| "mac-amd64": ("rust_toolchain.fuchsia-host-mac",), |
| } |
| if package == "rust" and host_platform in builders: |
| # Do a full integration build. This will use the just-built toolchain |
| # to build all of Fuchsia to check whether there are any regressions. |
| api.toolchain.trigger_build( |
| "rust_toolchain", |
| repository, |
| revision, |
| isolated, |
| builders=builders[host_platform], |
| ) |
| |
| |
| def GenTests(api): |
| revision = "75b05681239cb309a23fcb4f8864f177e5aa62da" |
| for platform in ("linux", "mac"): |
| for package in ("rust", "rust_tools"): |
| for arch in ("intel", "arm") if platform == "linux" else ("intel",): |
| yield ( |
| api.status_check.test("%s_%s_%s" % (package, arch, platform)) |
| + api.platform.name(platform) |
| + api.platform.arch(arch) |
| + api.properties(package=package) |
| + api.git.get_remote_branch_head("git ls-remote", revision) |
| + api.step_data("generate runtime spec", stdout=api.json.output([])) |
| ) |
| yield ( |
| api.status_check.test("%s_%s_%s_new" % (package, arch, platform)) |
| + api.platform.name(platform) |
| + api.platform.arch(arch) |
| + api.properties(package=package) |
| + api.git.get_remote_branch_head("git ls-remote", revision) |
| + api.step_data("generate runtime spec", stdout=api.json.output([])) |
| + api.step_data( |
| "cipd.cipd search fuchsia/third_party/%s/${platform} " % package |
| + "git_revision:" |
| + revision, |
| api.json.output({"result": []}), |
| ) |
| ) |