# 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 # https://github.com/rust-lang/rust/issues/64191 aims to make this # 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", ] } }