| #!/usr/bin/env python |
| # Copyright 2018 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. |
| |
| ### Generates documentation for a Rust target |
| |
| import argparse |
| import os |
| import platform |
| import subprocess |
| import sys |
| |
| ROOT_PATH = os.path.abspath(__file__ + "/../../..") |
| CONFIG_PATH = os.path.join(ROOT_PATH, ".config") |
| |
| # Runs the given command and returns its return code and output. |
| def run_command(args, env, cwd): |
| job = subprocess.Popen(args, env=env, cwd=cwd, stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE) |
| stdout, stderr = job.communicate() |
| return (job.returncode, stdout, stderr) |
| |
| def main(): |
| parser = argparse.ArgumentParser("Compiles all third-party Rust crates") |
| parser.add_argument("gn_target", |
| nargs=1, |
| help="GN target to generate a symlink for. \ |
| Use the absolute path to the target \ |
| (relative to $FUCHSIA_DIR). \ |
| For example: //garnet/bin/foo/bar:baz. \ |
| Alternatively, this can be a path to a \ |
| Cargo.toml file of a package for which to \ |
| generate docs.") |
| parser.add_argument("--target", |
| help="Target triple for which this crate is being compiled", |
| default="x86_64-unknown-fuchsia") |
| parser.add_argument("--no-deps", |
| action="store_true", |
| help="Disable building of docs for dependencies") |
| parser.add_argument("--open", |
| action="store_true", |
| help="Open the generated documentation") |
| |
| args = parser.parse_args() |
| |
| out_dir = "" |
| with open(CONFIG_PATH, "r") as config: |
| for line in config.readlines(): |
| if line.startswith("FUCHSIA_BUILD_DIR="): |
| segments = line.split("=") |
| assert(len(segments) == 2) |
| out_dir = segments[1].strip().strip("'") |
| if out_dir == "": |
| print "Invalid fuchsia/.config: no FUCHSIA_BUILD_DIR entry found" |
| |
| gn_target = args.gn_target[0] |
| if gn_target.endswith("Cargo.toml"): |
| manifest_path = os.path.abspath(gn_target) |
| else: |
| gn_target = gn_target.lstrip("/") |
| gn_target_parts = gn_target.split(":", 1) |
| if len(gn_target_parts) == 1: |
| # Turn foo/bar into foo/bar/bar |
| path = os.path.join(gn_target, os.path.basename(gn_target)) |
| elif len(gn_target_parts) == 2: |
| # Turn foo/bar:baz into foo/bar/baz |
| path = gn_target.replace(":", os.sep) |
| else: |
| print "Invalid gn_target: explected at most one colon." |
| return 1 |
| manifest_path = os.path.join(ROOT_PATH, out_dir, "gen", path, "Cargo.toml") |
| |
| env = os.environ.copy() |
| |
| host_platform = "%s-%s" % ( |
| platform.system().lower().replace("darwin", "mac"), |
| { |
| "x86_64": "x64", |
| "aarch64": "arm64", |
| }[platform.machine()], |
| ) |
| |
| # run cargo from third_party/rust-crtaes/rustc_deps which has an appropriate .cargo/config |
| cwd = os.path.join(ROOT_PATH, "third_party", "rust-crates", "rustc_deps") |
| buildtools_dir = os.path.join(ROOT_PATH, "buildtools", host_platform) |
| clang_prefix = os.path.join(buildtools_dir, "clang", "bin") |
| cmake_dir = os.path.join(buildtools_dir, "cmake", "bin") |
| cargo = os.path.join(buildtools_dir, "rust", "bin", "cargo") |
| rustc = os.path.join(buildtools_dir, "rust", "bin", "rustc") |
| rustdoc = os.path.join(buildtools_dir, "rust", "bin", "rustdoc") |
| |
| shared_libs_root = os.path.join(ROOT_PATH, out_dir) |
| sysroot = os.path.join(ROOT_PATH, out_dir, "sdks", "zircon_sysroot", "sysroot") |
| |
| clang_c_compiler = os.path.join(clang_prefix, "clang") |
| |
| env["CARGO_TARGET_LINKER"] = clang_c_compiler |
| env["CARGO_TARGET_X86_64_APPLE_DARWIN_LINKER"] = clang_c_compiler |
| env["CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER"] = clang_c_compiler |
| env["CARGO_TARGET_%s_LINKER" % args.target.replace("-", "_").upper()] = clang_c_compiler |
| if "fuchsia" in args.target: |
| env["CARGO_TARGET_%s_RUSTFLAGS" % args.target.replace("-", "_").upper()] = ( |
| "-Clink-arg=--target=" + args.target + |
| " -Clink-arg=--sysroot=" + sysroot + |
| " -Lnative=" + shared_libs_root |
| ) |
| else: |
| env["CARGO_TARGET_%s_RUSTFLAGS" % args.target.replace("-", "_").upper()] = ( |
| "-Clink-arg=--target=" + args.target |
| ) |
| env["RUSTC"] = rustc |
| env["RUSTDOC"] = rustdoc |
| env["RUST_BACKTRACE"] = "1" |
| env["CC"] = clang_c_compiler |
| if "fuchsia" in args.target: |
| env["CFLAGS"] = "--sysroot=%s -L %s" % (sysroot, shared_libs_root) |
| env["CXX"] = os.path.join(clang_prefix, "clang++") |
| env["AR"] = os.path.join(clang_prefix, "llvm-ar") |
| env["RANLIB"] = os.path.join(clang_prefix, "llvm-ranlib") |
| env["PATH"] = "%s:%s" % (env["PATH"], cmake_dir) |
| |
| call_args = [ |
| cargo, |
| "doc", |
| "--manifest-path=%s" % manifest_path, |
| "--color=always", |
| "--target=%s" % args.target, |
| ] |
| |
| if args.no_deps: |
| call_args.append("--no-deps") |
| |
| if args.open: |
| call_args.append("--open") |
| |
| retcode, stdout, stderr = run_command(call_args, env, cwd) |
| print(stdout + stderr) |
| return retcode |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |