1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
# 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",
]
}
}
|