blob: 7bc78c821e49c4a8bed5cb6e6d4c040651864335 [file] [log] [blame]
#!/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())