blob: 468ba17c44278ae5429f643da7badcdd7a8b7f93 [file] [log] [blame]
# 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.
import("//build/config/clang/clang.gni")
import("//build/fidl/toolchain.gni")
declare_args() {
# Sets a custom base directory for `rustc` and `cargo`.
# This can be used to test custom Rust toolchains.
rustc_prefix = "//buildtools/${host_platform}/rust/bin"
# Sets the default LTO type for rustc bulids.
rust_lto = "unset"
}
template("rustc_third_party_artifact") {
# Dummy build target to match the one in rustc_artifact
build_target_name = "${target_name}_build"
action(build_target_name) {
script = "//build/rust/write_3p_crate_dep_info.py"
forward_variables_from(invoker, [ "crate_name" ])
out_info_path = "${target_out_dir}/${target_name}_info.json"
args = [
# This is a slight lie to the end user-- the crate name that
# users provide and that appears in Cargo.toml is the package name,
# which may be different than the crate name (the thing given to
# --extern). One example of this is the rust-crypto crate,
# whose real crate name is crypto, but which is published under
# the package name rust-crypto.
"--package-name",
crate_name,
"--output",
rebase_path(out_info_path),
]
outputs = [
out_info_path,
]
}
group(target_name) {
public_deps = [
":${build_target_name}",
]
}
}
# Defines a Rust artifact to be built directly with rustc (rather than using cargo)
#
# Only for internal use, supporting rustc_library and rustc_binary.
#
# The arguments are the same as for rustc_library and rustc_binary, with the exception
# of `type`, which must be one of bin/lib/staticlib/proc-macro. This is used to determine
# the kind of artifact that is produced by rustc.
template("rustc_artifact") {
assert(defined(invoker.type),
"Must specify an artifact type (bin/lib/staticlib/proc-macro)")
type = invoker.type
# bin: executable binary application
# lib: intermediate artifact to be used in other Rust programs
# staticlib: a statically-linked system library, generally used for linking Rust into C
# proc-macro: a procedural macro (such as a custom-derive)
assert(
type == "bin" || type == "lib" || type == "staticlib" ||
type == "proc-macro",
"Artifact type must be one of: \"bin\", \"lib\", \"staticlib\", or \"proc-macro\"")
if (type == "lib") {
# For now, lib == rlib, but this could change in future versions of rustc.
# If/when this changes, we will likely want to transition manually rather
# than being automatically changed as a result of a toolchain upgrade.
type = "rlib"
}
if (defined(invoker.name)) {
package_name = invoker.name
} else {
package_name = target_name
}
crate_name = exec_script(
"//build/rust/package_name_to_crate_name.py",
[
"--package-name",
package_name,
],
"trim string"
)
if (defined(invoker.version)) {
version = invoker.version
} else {
version = "0.1.0"
}
assert(
current_os == "mac" || current_os == "linux" || current_os == "fuchsia",
"current_os was neither mac, linux, nor fuchsia")
if (current_os == "mac") {
target_triple = "x86_64-apple-darwin"
assert(current_cpu == "x64")
} else if (current_os == "linux") {
assert(current_cpu == "x64")
target_triple = "x86_64-unknown-linux-gnu"
} else if (current_os == "fuchsia") {
assert(current_cpu == "x64" || current_cpu == "arm64")
if (current_cpu == "x64") {
target_triple = "x86_64-unknown-fuchsia"
} else if (current_cpu == "arm64") {
target_triple = "aarch64-unknown-fuchsia"
}
}
group_deps = []
if (is_debug) {
opt_level = "0"
} else {
opt_level = "z"
}
if (type == "bin") {
if (defined(invoker.with_lto)) {
with_lto = invoker.with_lto
} else if (rust_lto != "unset") {
with_lto = rust_lto
} else if (is_debug) {
with_lto = "none"
} else {
# TODO(tkilbourn): turn this on after gathering more data on impact to build
# speed.
with_lto = "none"
}
} else {
with_lto = "none"
}
assert(
with_lto == "none" || with_lto == "thin" || with_lto == "fat",
"with_lto was neither none, thin, or fat")
# Determine the prefix and extension for the output file based on the crate type
if (type == "bin") {
prefix = ""
extension = ""
root_file = "src/main.rs"
} else if (type == "rlib") {
prefix = "lib"
extension = ".rlib"
root_file = "src/lib.rs"
} else if (type == "staticlib") {
prefix = "staticlib"
extension = ".a"
root_file = "src/lib.rs"
} else if (type == "proc-macro") {
prefix = "macro"
extension = ".so"
root_file = "src/lib.rs"
}
third_party_build = "//third_party/rust-crates/rustc_deps:build-third-party"
third_party_deps_data = "${root_out_dir}/rust_third_party/deps_data.json"
first_party_crate_root = "${root_out_dir}/rust_crates"
output_file = "${first_party_crate_root}/${prefix}${crate_name}${extension}"
output_depfile = "${first_party_crate_root}/${prefix}${crate_name}.d"
test_output_file = "${root_out_dir}/${crate_name}_${invoker.type}_test_rustc"
build_target_name = "${target_name}_build"
group_deps += [ ":${build_target_name}" ]
with_unit_tests = defined(invoker.with_unit_tests) && invoker.with_unit_tests
# Iterate through the deps collecting a list of the outputs
# of their build targets, which will be passed to rustc as
# `--extern` crates.
dep_info_paths = []
if (defined(invoker.deps)) {
foreach(dep, invoker.deps) {
dep_target_name = get_label_info(dep, "name")
dep_dir = get_label_info(dep, "dir")
dep_build_target = "${dep_dir}:${dep_target_name}_build"
dep_out_dir = get_label_info(dep_build_target, "target_out_dir")
dep_info_path = "${dep_out_dir}/${dep_target_name}_build_info.json"
dep_info_paths += [
"--dep-data",
rebase_path(dep_info_path),
]
}
}
if (defined(invoker.source_root)) {
root_file = invoker.source_root
}
root_file = rebase_path(root_file)
cargo_toml_dir = "$target_gen_dir/$target_name"
# Declare the action target that performs the build itself
action(build_target_name) {
script = "//build/rust/build_rustc_target.py"
forward_variables_from(invoker,
[
"deps",
"testonly",
])
if (!defined(deps)) {
deps = []
}
deps += [ third_party_build ]
inputs = [
root_file,
]
depfile = output_depfile
if (defined(invoker.non_rust_deps)) {
public_deps = invoker.non_rust_deps
}
out_info_path = "${target_out_dir}/${target_name}_info.json"
args = [
"--rustc",
rebase_path("$rustc_prefix/rustc"),
"--crate-root",
rebase_path(root_file),
"--cargo-toml-dir",
rebase_path(cargo_toml_dir),
"--crate-type",
type,
"--crate-name",
crate_name,
"--package-name",
package_name,
"--opt-level",
opt_level,
"--depfile",
rebase_path(output_depfile),
"--root-out-dir",
rebase_path(root_out_dir),
"--output-file",
rebase_path(output_file),
"--test-output-file",
rebase_path(test_output_file),
"--target",
target_triple,
"--cmake-dir",
rebase_path("//buildtools/cmake/bin"),
"--shared-libs-root",
rebase_path(
get_label_info("//default($shlib_toolchain)", "root_out_dir")),
"--first-party-crate-root",
rebase_path(first_party_crate_root),
"--third-party-deps-data",
rebase_path(third_party_deps_data),
"--out-info",
rebase_path(out_info_path),
"--version",
version,
]
if (with_lto != "none") {
args += [ "--lto", with_lto ]
}
if (with_unit_tests) {
args += [ "--with-unit-tests" ]
}
if (is_fuchsia) {
deps += [
"//garnet/public/sdk:zircon_sysroot_export",
# These libraries are required by libstd.
"//zircon/public/lib/backtrace",
"//zircon/public/lib/fdio",
"//zircon/public/lib/launchpad",
]
args += [
"--clang_prefix",
rebase_path(clang_prefix, "", root_out_dir),
"--sysroot",
rebase_path("$root_out_dir/sdks/zircon_sysroot/sysroot"),
]
}
args += dep_info_paths
outputs = [
output_file,
]
if (with_unit_tests) {
outputs += [ test_output_file ]
}
}
# Copy binaries and staticlibs out of rust_crates/* into the root dir
# TODO(cramertj) remove and replace with writing directly to the root
# dir once all existing build rules have moved off of using rust_crates/*
if (type == "bin" || type == "staticlib") {
copy_target_name = "${target_name}_copy"
group_deps += [ ":${copy_target_name}" ]
copy(copy_target_name) {
deps = [
":${build_target_name}",
]
sources = [
output_file,
]
outputs = [
"${root_out_dir}/${prefix}${crate_name}${extension}",
]
}
}
cargo_toml_target_name = "${target_name}_cargo"
group_deps += [ ":${cargo_toml_target_name}" ]
action(cargo_toml_target_name) {
script = "//build/rust/write_cargo_toml.py"
forward_variables_from(invoker,
[
"deps",
"testonly",
])
if (!defined(deps)) {
deps = []
}
deps += [ third_party_build ]
if (defined(invoker.non_rust_deps)) {
public_deps = invoker.non_rust_deps
}
args = [
"--out-dir",
rebase_path(cargo_toml_dir),
"--source-root",
root_file,
"--package-name",
package_name,
"--crate-name",
crate_name,
"--crate-type",
type,
"--version",
version,
"--third-party-deps-data",
rebase_path(third_party_deps_data),
]
# list of paths to info about crate dependencies
args += dep_info_paths
outputs = [
"${cargo_toml_dir}/Cargo.toml",
]
}
group(target_name) {
forward_variables_from(invoker, [ "testonly" ])
public_deps = group_deps
}
}