Source code

Revision control

Copy as Markdown

Other Tools

# Copyright 2021 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This file provides the ability for our C++ toolchain to successfully
# link binaries containing arbitrary Rust code.
#
# By "arbitrary Rust code" I mean .rlib archives full of Rust code, which
# is actually a static archive.
#
# Those static libraries don't link as-is into a final executable because
# they're designed for downstream processing by further invocations of rustc
# which link into a final binary. That final invocation of rustc knows how
# to do two things:
# * Find the Rust standard library.
# * Remap some generic allocator symbols to the specific allocator symbols
# in use.
# This file does both those things. Any C++ target containing Rust .rlibs
# should simply depend on :std within this file and it will be taken care of.
# In practice, this will in future be taken care of by a standard template
# used for each Rust source set, so that a typical user of Rust need not
# think about it.
#
# This is obviously a bit fragile - rustc might do other magic in future.
# But, linking with a final C++ toolchain is something often needed, and
# officially possible.
import("//build/config/compiler/compiler.gni")
import("//build/config/rust.gni")
stdlib_files = [
"std", # List first because it makes depfiles more debuggable (see below)
"addr2line",
"adler",
"alloc",
"cfg_if",
"compiler_builtins",
"core",
"getopts",
"gimli",
"hashbrown",
"libc",
"miniz_oxide",
"object",
"panic_abort",
"panic_unwind",
"proc_macro",
"rustc_demangle",
"std_detect",
"term",
"test",
"unicode_width",
"unwind",
]
if (!use_unverified_rust_toolchain) {
# rlib files which are distributed alongside Rust's prebuilt stdlib, but we
# don't need to pass to the C++ linker because they're used for specialized
# purposes.
skip_stdlib_files = [
"profiler_builtins",
"rustc_std_workspace_alloc",
"rustc_std_workspace_core",
"rustc_std_workspace_std",
]
}
if (toolchain_has_rust) {
action("find_stdlib") {
# Specifics of what we're doing here.
#
# We are using prebuilt Rust rlibs supplied along with the toolchain.
# The Rust standard library consists of rlibs with roughly all the names
# above.
#
# However, their filenames are not predictable, and therefore we can't
# have ninja rules which depend upon them. (gn offers a facility to
# build rules dynamically, but it's frowned upon because a script needs
# to run each time).
#
# Instead therefore we copy these unpredictable .rlib paths to apredictable
# location. That's what this script does. Furthermore, it generates a
# .d file in order to teach Ninja that it only needs to do this copying
# once, unless the source .rlibs change.
#
# The script accepts the list of known libraries and will raise an
# exception if the list on disk differs. (Either 'Found stdlib rlib
# that wasn't expected' or 'We failed to find all expected stdlib
# rlibs').
script = "find_std_rlibs.py"
depfile = "$target_out_dir/stdlib.d"
out_libdir = rebase_path(target_out_dir, root_build_dir)
out_depfile = rebase_path(depfile, root_build_dir)
args = [
"--rust-bin-dir",
rust_prefix,
"--output",
out_libdir,
"--depfile",
out_depfile,
# Due to limitations in Ninja's handling of .d files, we have to pick
# *the first* of our outputs. To make diagnostics more obviously
# related to the Rust standard library, we ensure libstd.rlib is first.
"--depfile-target",
stdlib_files[0],
]
if (!use_unverified_rust_toolchain) {
args += [
"--stdlibs",
string_join(",", stdlib_files),
"--skip",
string_join(",", skip_stdlib_files),
]
}
if (rust_abi_target != "") {
args += [
"--target",
rust_abi_target,
]
}
outputs = []
foreach(lib, stdlib_files) {
outputs += [ "$target_out_dir/lib$lib.rlib" ]
}
}
config("rust_stdlib_config") {
ldflags = []
out_libdir = rebase_path(target_out_dir, root_build_dir)
foreach(lib, stdlib_files) {
this_file = "$out_libdir/lib$lib.rlib"
ldflags += [ this_file ]
}
}
source_set("remap_alloc") {
sources = [
"immediate_crash.h",
"remap_alloc.c",
]
}
group("std") {
all_dependent_configs = [ ":rust_stdlib_config" ]
deps = [
":find_stdlib",
":remap_alloc",
]
}
}