| #!/usr/bin/env python |
| # Copyright 2019 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. |
| |
| from collections import OrderedDict |
| from os import path |
| import argparse |
| import json |
| import platform |
| import sys |
| |
| EXTRA_TOOLS = ["cargo", "rls", "rustfmt", "cargo-fmt", "miri"] |
| DEFAULT_TOOLS = ["cargo", "clippy", "src"] |
| |
| FUCHSIA_TRIPLE_TO_ARCH = { |
| "x86_64-fuchsia": "x64", |
| "aarch64-fuchsia": "arm64", |
| } |
| FUCHSIA_TRIPLES = FUCHSIA_TRIPLE_TO_ARCH.keys() |
| FUCHSIA_RUNTIME_ARCHES = ["aarch64", "x86_64"] |
| |
| BUILD_CONFIG = """ |
| [llvm] |
| optimize = true |
| thin-lto = {thinlto} |
| ccache = {gomacc_quote} |
| ninja = true |
| targets = "X86;AArch64;WebAssembly" |
| cflags = "{cflags}" |
| cxxflags = "{cxxflags}" |
| ldflags = "{ldflags}" |
| use-libcxx = true |
| |
| [build] |
| target = [{target}] |
| docs = false |
| extended = true |
| cargo-native-static = true |
| tools = [{tools}] |
| |
| [install] |
| prefix = "{prefix}" |
| sysconfdir = "etc" |
| |
| [rust] |
| optimize = true |
| codegen-units-std = 1 |
| channel = "nightly" |
| lld = true |
| llvm-libunwind = "in-tree" |
| |
| # Enable full debuginfo for libstd. |
| # |
| # For now we only link libstd statically, so this won't affect any DSOs we |
| # ship. |
| debuginfo-level-std = 2 |
| |
| [dist] |
| """ |
| |
| TARGET_CONFIG = """ |
| [target.{triple}] |
| cc = "{cc}" |
| cxx = "{cxx}" |
| ar = "{ar}" |
| ranlib = "{ranlib}" |
| """ |
| |
| |
| def generate_config_toml(args): |
| targets = FUCHSIA_TRIPLES + args.targets.split(",") |
| tools = EXTRA_TOOLS if args.extra_tools_only else args.tools.split(",") |
| |
| def string_list(items): |
| return ", ".join('"%s"' % item for item in items) |
| |
| config_toml = BUILD_CONFIG.format( |
| prefix=args.prefix, |
| gomacc_quote=('"%s"' % path.join(args.goma_dir, "gomacc")) |
| if args.goma_dir |
| else "false", |
| thinlto=str(args.thinlto).lower(), |
| cflags="--sysroot=%s" % args.host_sysroot, |
| cxxflags="--sysroot=%s" % args.host_sysroot, |
| ldflags="--sysroot=%s" % args.host_sysroot |
| + ( |
| " -L%s" % path.join(args.clang_prefix, "lib") |
| if args.is_mac |
| else " -static-libstdc++" |
| ), |
| target=string_list(targets), |
| tools=string_list(tools), |
| ) |
| for target in targets: |
| config_toml += TARGET_CONFIG.format( |
| triple=target, |
| cc=path.join(args.clang_prefix, "bin", "clang"), |
| cxx=path.join(args.clang_prefix, "bin", "clang++"), |
| ar=path.join(args.clang_prefix, "bin", "llvm-ar"), |
| ranlib=path.join(args.clang_prefix, "bin", "llvm-ranlib"), |
| ) |
| if "fuchsia" not in target: |
| config_toml += 'linker = "%s"\n' % path.join( |
| args.clang_prefix, "bin", "clang++" |
| ) |
| print(config_toml) |
| |
| |
| def generate_env(args): |
| env = OrderedDict() |
| env["RUST_BACKTRACE"] = 1 |
| |
| if args.revision: |
| env["CFG_VERSION"] = args.revision |
| |
| for target, gn_arch in FUCHSIA_TRIPLE_TO_ARCH.iteritems(): |
| triple_lower = target.replace("-", "_").lower() |
| triple_upper = triple_lower.upper() |
| env["CC_%s" % triple_lower] = path.join(args.clang_prefix, "bin", "clang") |
| env["CXX_%s" % triple_lower] = path.join(args.clang_prefix, "bin", "clang++") |
| env["CFLAGS_%s" % triple_lower] = "--target=%s --sysroot=%s -I%s" % ( |
| target, |
| path.join(args.sdk_dir, "arch", gn_arch, "sysroot"), |
| path.join(args.sdk_dir, "pkg", "fdio", "include"), |
| ) |
| env["CXXFLAGS_%s" % triple_lower] = "--target=%s --sysroot=%s -I%s" % ( |
| target, |
| path.join(args.sdk_dir, "arch", gn_arch, "sysroot"), |
| path.join(args.sdk_dir, "pkg", "fdio", "include"), |
| ) |
| env["LDFLAGS_%s" % triple_lower] = "--target=%s --sysroot=%s -L%s" % ( |
| target, |
| path.join(args.sdk_dir, "arch", gn_arch, "sysroot"), |
| path.join(args.sdk_dir, "arch", gn_arch, "lib"), |
| ) |
| env["CARGO_TARGET_%s_AR" % triple_upper] = path.join( |
| args.clang_prefix, "bin", "llvm-ar" |
| ) |
| env["CARGO_TARGET_%s_RUSTFLAGS" % triple_upper] = " ".join( |
| [ |
| "-C link-arg=--sysroot=%s" |
| % path.join(args.sdk_dir, "arch", gn_arch, "sysroot"), |
| "-C link-arg=-L%s/lib" |
| % path.join(args.sdk_dir, "arch", gn_arch, "sysroot"), |
| "-C link-arg=-L%s" % path.join(args.sdk_dir, "arch", gn_arch, "lib"), |
| "-C panic=abort", |
| "-C force-unwind-tables=yes", |
| ] |
| ) |
| |
| target_sysroots = { |
| "aarch64-unknown-linux-gnu": args.linux_arm64_sysroot, |
| "x86_64-unknown-linux-gnu": args.linux_amd64_sysroot, |
| } |
| if args.darwin_sysroot: |
| target_sysroots.update( |
| {"x86_64-apple-darwin": args.darwin_sysroot,} |
| ) |
| |
| for target in args.targets.split(","): |
| if "wasm32" in target: |
| # Skip setting sysroots for wasm32. |
| continue |
| sysroot = target_sysroots[target] |
| triple_lower = target.replace("-", "_").lower() |
| triple_upper = triple_lower.upper() |
| env["CC_%s" % triple_lower] = path.join(args.clang_prefix, "bin", "clang") |
| env["CXX_%s" % triple_lower] = path.join(args.clang_prefix, "bin", "clang++") |
| env["CFLAGS_%s" % triple_lower] = "--target=%s --sysroot=%s" % ( |
| target, |
| sysroot, |
| ) |
| env["CXXFLAGS_%s" % triple_lower] = "--target=%s --sysroot=%s" % ( |
| target, |
| sysroot, |
| ) |
| env["LDFLAGS_%s" % triple_lower] = "--target=%s --sysroot=%s" % ( |
| target, |
| sysroot, |
| ) + (" -fuse-ld=lld" if "apple" not in target else "") |
| env["CARGO_TARGET_%s_AR" % triple_upper] = path.join( |
| args.clang_prefix, "bin", "llvm-ar" |
| ) |
| env["CARGO_TARGET_%s_RUSTFLAGS" % triple_upper] = " ".join( |
| ["-C link-arg=--target=%s" % target, "-C link-arg=--sysroot=%s" % sysroot,] |
| + (["-C link-arg=-fuse-ld=lld"] if "apple" not in target else []) |
| ) |
| |
| for key, val in env.iteritems(): |
| if args.eval: |
| print('export %s="%s"' % (key, val)) |
| else: |
| print("%s=%s" % (key, val)) |
| |
| |
| def generate_runtimes_spec(args): |
| runtimes = [] |
| for arch in FUCHSIA_RUNTIME_ARCHES: |
| for dynlink_flags in [[], ["-Cprefer-dynamic"]]: |
| runtime = [] |
| if dynlink_flags: |
| for lib in ["libstd", "libtest"]: |
| runtime.append( |
| { |
| # The runtimes module will expand this wildcard |
| # (it must match exactly one file.) |
| "dist": "rustlib/%s-fuchsia/lib/%s-*.so" % (arch, lib), |
| "name": lib, |
| } |
| ) |
| runtimes.append( |
| { |
| "target": ["%s-unknown-fuchsia" % arch, "%s-fuchsia" % arch], |
| "rustflags": dynlink_flags, |
| "runtime": runtime, |
| } |
| ) |
| print(json.dumps(runtimes)) |
| |
| |
| def main(): |
| is_mac = platform.system() == "Darwin" |
| default_targets = [ |
| "x86_64-unknown-linux-gnu", |
| "aarch64-unknown-linux-gnu", |
| "wasm32-unknown-unknown", |
| ] |
| if is_mac: |
| default_targets.append("x86_64-apple-darwin") |
| |
| parser = argparse.ArgumentParser() |
| subparsers = parser.add_subparsers() |
| parser_config = subparsers.add_parser("config_toml") |
| parser_env = subparsers.add_parser("environment") |
| parser_runtime = subparsers.add_parser("runtime") |
| |
| for subcommand in [parser_config, parser_env]: |
| subcommand.add_argument( |
| "--targets", |
| default=",".join(default_targets), |
| help="comma-separated list of targets to build for, in addition to Fuchsia", |
| ) |
| subcommand.add_argument( |
| "--clang-prefix", help="path to clang toolchain", required=True |
| ) |
| |
| parser_config.add_argument("--prefix", help="installation prefix", required=True) |
| parser_config.add_argument( |
| "--host-sysroot", help="path to host sysroot", required=True |
| ) |
| parser_config.add_argument("--goma-dir", help="path to goma", required=False) |
| parser_config.add_argument( |
| "--thinlto", default=not is_mac, action="store_true", help="enable thinlto" |
| ) |
| parser_config.add_argument( |
| "--extra-tools-only", |
| help="build extra tools (%s); overrides --tools" % ", ".join(EXTRA_TOOLS), |
| default=False, |
| action="store_true", |
| ) |
| parser_config.add_argument( |
| "--tools", |
| help="comma-separated list of tools to build; ignored if --extra-tools-only is used", |
| default=",".join(DEFAULT_TOOLS), |
| ) |
| parser_config.set_defaults(func=generate_config_toml) |
| parser_config.set_defaults(is_mac=is_mac) |
| |
| parser_env.add_argument("--sdk-dir", help="path to Fuchsia SDK", required=True) |
| parser_env.add_argument("--linux-amd64-sysroot", help="path to Linux amd64 sysroot") |
| parser_env.add_argument("--linux-arm64-sysroot", help="path to Linux arm64 sysroot") |
| parser_env.add_argument( |
| "--darwin-sysroot", help="path to Darwin sysroot, if building on Mac" |
| ) |
| parser_env.add_argument("--revision", help="git commit of Rust repository") |
| parser_env.add_argument( |
| "--eval", |
| default=False, |
| action="store_true", |
| help="format output for evaluating in a terminal", |
| ) |
| parser_env.set_defaults(func=generate_env) |
| |
| parser_runtime.set_defaults(func=generate_runtimes_spec) |
| |
| args = parser.parse_args() |
| args.func(args) |
| |
| return 0 |
| |
| |
| if __name__ == "__main__": |
| sys.exit(main()) |