Skip to content

Commit 0438fba

Browse files
MaxIhlenfeldtotavio
authored andcommitted
chromium: Enable Rust
This adds a dependency on OE's Rust recipe, as well as all the necessary changes to make Chromium successfully use that toolchain. Signed-off-by: Max Ihlenfeldt <max@igalia.com>
1 parent ea731e8 commit 0438fba

6 files changed

+419
-6
lines changed

meta-chromium/recipes-browser/chromium/chromium-gn.inc

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ SRC_URI += "\
4545
file://0020-Fix-implicitly-deleted-default-constructor-build-err.patch \
4646
file://0021-Don-t-delete-CrashKeyWithName-dtor.patch \
4747
file://0022-Use-base-ranges-instead-of-std-ranges.patch \
48+
file://0023-Use-the-correct-path-to-libclang_rt.builtins.a.patch \
49+
file://0024-Adjust-the-Rust-build-to-our-needs.patch \
50+
file://0025-Make-toolchain_supports_rust_thin_lto-configurable.patch \
4851
"
4952
# ARM/AArch64-specific patches.
5053
SRC_URI:append:arm = "\
@@ -107,9 +110,11 @@ DEPENDS += " \
107110
pkgconfig-native \
108111
${@bb.utils.contains('DISTRO_FEATURES', 'pulseaudio', 'pulseaudio', '', d)} \
109112
qemu-native \
113+
rust \
114+
rust-native \
110115
virtual/libgl \
111116
"
112-
DEPEND:append:runtime-llvm = " compiler-rt-native libcxx-native"
117+
DEPENDS:append:runtime-llvm = " compiler-rt compiler-rt-native libcxx-native"
113118
DEPENDS:append:libc-musl = " libexecinfo"
114119

115120
LDFLAGS:append:libc-musl = " -lexecinfo"
@@ -306,19 +311,36 @@ GN_ARGS += ' \
306311
gold_path="" \
307312
host_toolchain="//build/toolchain/yocto:yocto_native" \
308313
is_clang=true \
309-
clang_base_path="${@clang_install_path(d)}" \
310314
clang_use_chrome_plugins=false \
311315
target_cpu="${@gn_target_arch_name(d)}" \
312316
v8_snapshot_toolchain="//build/toolchain/yocto:yocto_target" \
313317
'
314318

319+
# Make sure Chromium is able to find clang libraries. See
320+
# 0023-Use-the-correct-path-to-libclang_rt.builtins.a.patch and the
321+
# add_clang_symlink and copy_clang_library tasks for more context.
322+
GN_ARGS += ' \
323+
clang_base_path="${@clang_install_path(d)}" \
324+
clang_version="latest" \
325+
'
326+
315327
# This parameter is added by limit-number-of-LTO-jobs.patch with the default value of 8,
316328
# but we can use whatever user configured in PARALLEL_MAKE
317329
GN_ARGS += 'max_jobs_per_link="${@oe.utils.parallel_make_argument(d, '%d')}"'
318330

319-
# We haven't figured out how to best support Rust yet, so disable it for now.
320-
# See the discussion at https://github.com/OSSystems/meta-browser/issues/723.
321-
GN_ARGS += 'enable_rust=false'
331+
# Use our own toolchain instead of the one upstream provides. See
332+
# //build/config/rust.gni for more details.
333+
# Note: the value of rustc_version doesn't matter, it's only used to ensure all
334+
# Rust code is rebuilt after updating the Rust toolchain. This is irrelevant for
335+
# our build setup, but not setting it leads to an error.
336+
GN_ARGS += ' \
337+
rust_sysroot_absolute="${RECIPE_SYSROOT_NATIVE}/usr" \
338+
rustc_version="custom" \
339+
rust_target_triple_vendor_for_target="${TARGET_VENDOR}" \
340+
'
341+
342+
# This would require the Rust toolchain to use the same LLVM version as clang.
343+
GN_ARGS += 'toolchain_supports_rust_thin_lto=false'
322344

323345
# ARM builds need special additional flags (see ${S}/build/config/arm.gni).
324346
# If we do not pass |arm_arch| and friends to GN, it will deduce a value that
@@ -442,6 +464,42 @@ do_add_nodejs_symlink () {
442464
}
443465
addtask add_nodejs_symlink after do_configure before do_compile
444466

467+
do_add_clang_symlink () {
468+
# Creates a `latest` symlink in the native sysroot's /usr/lib/clang
469+
# directory that points to /usr/lib/clang/$CLANG_VERSION. Chromium manually
470+
# links against libclang_rt.builtins.a and uses the `clang_version` GN
471+
# variable to find it. This allows us to set it to the same value for all
472+
# Yocto releases.
473+
cd "${RECIPE_SYSROOT_NATIVE}/usr/lib/clang"
474+
# find the directory containing the library
475+
for dir in *; do
476+
if [ -n "$(find $dir -name 'libclang_rt.builtins*')" ] ; then
477+
ln -sf "$dir" latest
478+
break
479+
fi
480+
done
481+
}
482+
addtask add_clang_symlink after do_configure before do_compile
483+
484+
do_copy_clang_library () {
485+
# Chromium needs to link against libclang_rt.builtins.a for both host and
486+
# target code, and expects to find both libraries in the same directory
487+
# (thanks to 0023-Use-the-correct-path-to-libclang_rt.builtins.a.patch).
488+
cd "${RECIPE_SYSROOT}"
489+
lib_file="$(find usr/lib/clang -name 'libclang_rt.builtins*')"
490+
lib_dir="$(dirname $lib_file)"
491+
cp "$lib_file" "${RECIPE_SYSROOT_NATIVE}/$lib_dir"
492+
}
493+
addtask copy_clang_library after do_configure before do_compile
494+
495+
do_copy_target_rustlibs () {
496+
# Chromium needs a single Rust sysroot that contains the rustlibs for both
497+
# the host and target, so we copy the target rustlibs to the native sysroot.
498+
rustlib_src_dir="${RECIPE_SYSROOT}/usr/lib/rustlib/${TARGET_ARCH}"*
499+
cp -r $rustlib_src_dir "${RECIPE_SYSROOT_NATIVE}/usr/lib/rustlib"
500+
}
501+
addtask copy_target_rustlibs after do_configure before do_compile
502+
445503
do_configure() {
446504
cd ${S}
447505
python3 ./build/linux/unbundle/replace_gn_files.py --system-libraries ${GN_UNBUNDLE_LIBS}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
From 334f64aafb062324a9124a13855128dfe733c0c2 Mon Sep 17 00:00:00 2001
2+
From: Max Ihlenfeldt <max@igalia.com>
3+
Date: Tue, 19 Dec 2023 12:14:05 +0000
4+
Subject: [PATCH] Use the correct path to libclang_rt.builtins.a
5+
6+
Chromium needs to link against libclang_rt.builtins.a, but it expects
7+
it in a slightly different directory than where it actually is in our
8+
sysroot. Thus, we need adjust the where Chromium looks for the library.
9+
10+
Note that the directory used by this patch is actually independent of
11+
the target architecture. This has the added benefit that we can just
12+
copy the target's libclang_rt.builtins.a to the host's sysroot (to the
13+
same directory where the host's library is). This is necessary because
14+
Chromium needs to link against this library for both host and target
15+
code, but only allows us to specify a single `clang_base_path`.
16+
17+
Upstream-Status: Inappropriate [specific to our sysroot setup]
18+
Signed-off-by: Max Ihlenfeldt <max@igalia.com>
19+
---
20+
build/config/clang/BUILD.gn | 9 +++++----
21+
1 file changed, 5 insertions(+), 4 deletions(-)
22+
23+
diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn
24+
index 46f4de0..ad3bfc4 100644
25+
--- a/build/config/clang/BUILD.gn
26+
+++ b/build/config/clang/BUILD.gn
27+
@@ -122,14 +122,15 @@ template("clang_lib") {
28+
} else if (is_apple) {
29+
_dir = "darwin"
30+
} else if (is_linux || is_chromeos) {
31+
+ _dir = "linux"
32+
if (current_cpu == "x64") {
33+
- _dir = "x86_64-unknown-linux-gnu"
34+
+ _suffix = "-x86_64"
35+
} else if (current_cpu == "x86") {
36+
- _dir = "i386-unknown-linux-gnu"
37+
+ _suffix = "-i386"
38+
} else if (current_cpu == "arm") {
39+
- _dir = "armv7-unknown-linux-gnueabihf"
40+
+ _suffix = "-armhf"
41+
} else if (current_cpu == "arm64") {
42+
- _dir = "aarch64-unknown-linux-gnu"
43+
+ _suffix = "-aarch64"
44+
} else {
45+
assert(false) # Unhandled cpu type
46+
}
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
From f4f50a5de596d13d18f1f9b80f83e446936a4afb Mon Sep 17 00:00:00 2001
2+
From: Max Ihlenfeldt <max@igalia.com>
3+
Date: Tue, 16 Jan 2024 12:29:30 +0000
4+
Subject: [PATCH] Adjust the Rust build to our needs
5+
6+
1. Set `RUSTC_BOOTSTRAP=1` environment variable when calling rustc, to
7+
avoid the need of a nightly Rust toolchain.
8+
2. Copy the target.json file which rustc needs to compile for OE's
9+
custom target triple.
10+
3. Add a rust_target_triple_vendor_for_target GN arg. OE builds the
11+
Rust libraries for the target by using TARGET_VENDOR as the vendor
12+
part for the Rust "target triple", but Chromium assumes the vendor to
13+
always be "-unknown". This new arg lets us override the default when
14+
building target code.
15+
16+
Upstream-Status: Inappropriate [specific to our build setup]
17+
Signed-off-by: Max Ihlenfeldt <max@igalia.com>
18+
---
19+
build/config/rust.gni | 24 +++++++++++++++++------
20+
build/rust/rustc_wrapper.py | 1 +
21+
build/rust/std/BUILD.gn | 33 ++++++++++++++++++++++++--------
22+
build/rust/std/find_std_rlibs.py | 13 ++++++++++---
23+
4 files changed, 54 insertions(+), 17 deletions(-)
24+
25+
diff --git a/build/config/rust.gni b/build/config/rust.gni
26+
index b82ac38..702353e 100644
27+
--- a/build/config/rust.gni
28+
+++ b/build/config/rust.gni
29+
@@ -76,6 +76,11 @@ declare_args() {
30+
# a platform. Mostly applicable to Windows, where new versions can handle ANSI
31+
# escape sequences but it's not reliable in general.
32+
force_rustc_color_output = false
33+
+
34+
+ # Override the vendor part of the Rust target triple (with a leading dash)
35+
+ # used for building target code (not host code). Leave empty to use the
36+
+ # platform default.
37+
+ rust_target_triple_vendor_for_target = ""
38+
}
39+
40+
# Use a separate declare_args so these variables' defaults can depend on the
41+
@@ -189,12 +194,19 @@ if (enable_rust) {
42+
# other toolchains.
43+
rust_abi_target = ""
44+
if (is_linux || is_chromeos) {
45+
+ vendor = "-unknown"
46+
+
47+
+ is_host = current_toolchain == host_toolchain || toolchain_for_rust_host_build_tools
48+
+ if (!is_host && rust_target_triple_vendor_for_target != "") {
49+
+ vendor = rust_target_triple_vendor_for_target
50+
+ }
51+
+
52+
if (current_cpu == "arm64") {
53+
- rust_abi_target = "aarch64-unknown-linux-gnu"
54+
+ rust_abi_target = "aarch64" + vendor + "-linux-gnu"
55+
} else if (current_cpu == "x86") {
56+
- rust_abi_target = "i686-unknown-linux-gnu"
57+
+ rust_abi_target = "i686" + vendor + "-linux-gnu"
58+
} else if (current_cpu == "x64") {
59+
- rust_abi_target = "x86_64-unknown-linux-gnu"
60+
+ rust_abi_target = "x86_64" + vendor + "-linux-gnu"
61+
} else if (current_cpu == "arm") {
62+
if (arm_float_abi == "hard") {
63+
float_suffix = "hf"
64+
@@ -203,13 +215,13 @@ if (is_linux || is_chromeos) {
65+
}
66+
if (arm_arch == "armv7-a" || arm_arch == "armv7") {
67+
# No way to inform Rust about the -a suffix.
68+
- rust_abi_target = "armv7-unknown-linux-gnueabi" + float_suffix
69+
+ rust_abi_target = "armv7" + vendor + "-linux-gnueabi" + float_suffix
70+
} else {
71+
- rust_abi_target = "arm-unknown-linux-gnueabi" + float_suffix
72+
+ rust_abi_target = "arm" + vendor + "-linux-gnueabi" + float_suffix
73+
}
74+
} else {
75+
# Best guess for other future platforms.
76+
- rust_abi_target = current_cpu + "-unknown-linux-gnu"
77+
+ rust_abi_target = current_cpu + vendor + "-linux-gnu"
78+
}
79+
} else if (is_android) {
80+
import("//build/config/android/abi.gni")
81+
diff --git a/build/rust/rustc_wrapper.py b/build/rust/rustc_wrapper.py
82+
index 1c61e9f..5f9556b 100755
83+
--- a/build/rust/rustc_wrapper.py
84+
+++ b/build/rust/rustc_wrapper.py
85+
@@ -158,6 +158,7 @@ def main():
86+
rustc_args = remaining_args[:ldflags_separator]
87+
ldflags = remaining_args[ldflags_separator + 1:rustenv_separator]
88+
rustenv = remaining_args[rustenv_separator + 1:sources_separator]
89+
+ rustenv += ["RUSTC_BOOTSTRAP=1"]
90+
91+
abs_build_root = os.getcwd().replace('\\', '/') + '/'
92+
is_windows = sys.platform == 'win32' or args.target_windows
93+
diff --git a/build/rust/std/BUILD.gn b/build/rust/std/BUILD.gn
94+
index 77f4b8c..8a25798 100644
95+
--- a/build/rust/std/BUILD.gn
96+
+++ b/build/rust/std/BUILD.gn
97+
@@ -188,7 +188,8 @@ if (toolchain_has_rust) {
98+
# our locally-built std. Both reside in root_out_dir: we must only have one of
99+
# each per GN toolchain anyway.
100+
101+
- sysroot_lib_subdir = "lib/rustlib/$rust_abi_target/lib"
102+
+ sysroot_target_subdir = "lib/rustlib/$rust_abi_target"
103+
+ sysroot_lib_subdir = "$sysroot_target_subdir/lib"
104+
105+
if (!rust_prebuilt_stdlib) {
106+
local_rustc_sysroot = "$root_out_dir/local_rustc_sysroot"
107+
@@ -372,12 +373,12 @@ if (toolchain_has_rust) {
108+
rust_abi_target,
109+
]
110+
111+
- outputs = []
112+
+ outputs = [ "$target_out_dir/target.json" ]
113+
foreach(lib, all_stdlibs_to_copy) {
114+
- outputs += [ "$target_out_dir/lib$lib.rlib" ]
115+
+ outputs += [ "$target_out_dir/lib/lib$lib.rlib" ]
116+
}
117+
foreach(lib, extra_sysroot_libs) {
118+
- outputs += [ "$target_out_dir/$lib" ]
119+
+ outputs += [ "$target_out_dir/lib/$lib" ]
120+
}
121+
122+
visibility = [ ":*" ]
123+
@@ -390,8 +391,18 @@ if (toolchain_has_rust) {
124+
"enable_rust=false")
125+
deps = [ ":find_stdlib" ]
126+
sources = get_target_outputs(":find_stdlib")
127+
- outputs =
128+
- [ "$prebuilt_rustc_sysroot/$sysroot_lib_subdir/{{source_file_part}}" ]
129+
+ sources -= [ "$target_out_dir/target.json" ]
130+
+ outputs = [
131+
+ "$prebuilt_rustc_sysroot/$sysroot_lib_subdir/{{source_file_part}}",
132+
+ ]
133+
+
134+
+ visibility = [ ":*" ]
135+
+ }
136+
+
137+
+ copy("prebuilt_rustc_copy_target_json_to_sysroot") {
138+
+ deps = [ ":find_stdlib" ]
139+
+ sources = [ "$target_out_dir/target.json" ]
140+
+ outputs = [ "$prebuilt_rustc_sysroot/$sysroot_target_subdir/target.json" ]
141+
142+
visibility = [ ":*" ]
143+
}
144+
@@ -429,7 +440,10 @@ if (toolchain_has_rust) {
145+
# Use the sysroot generated by :prebuilt_rustc_copy_to_sysroot.
146+
group("stdlib_for_rustc") {
147+
all_dependent_configs = [ ":prebuilt_stdlib_sysroot" ]
148+
- deps = [ ":prebuilt_rustc_copy_to_sysroot" ]
149+
+ deps = [
150+
+ ":prebuilt_rustc_copy_to_sysroot",
151+
+ ":prebuilt_rustc_copy_target_json_to_sysroot",
152+
+ ]
153+
}
154+
155+
# Links the Rust stdlib. Used by targets for which linking is driven by
156+
@@ -439,7 +453,10 @@ if (toolchain_has_rust) {
157+
":prebuilt_stdlib_libs",
158+
":stdlib_public_dependent_libs",
159+
]
160+
- deps = [ ":prebuilt_rustc_copy_to_sysroot" ]
161+
+ deps = [
162+
+ ":prebuilt_rustc_copy_to_sysroot",
163+
+ ":prebuilt_rustc_copy_target_json_to_sysroot",
164+
+ ]
165+
166+
# The host builds tools toolchain supports Rust only and does not use
167+
# the allocator remapping to point it to PartitionAlloc.
168+
diff --git a/build/rust/std/find_std_rlibs.py b/build/rust/std/find_std_rlibs.py
169+
index 386258f..25fdedc 100755
170+
--- a/build/rust/std/find_std_rlibs.py
171+
+++ b/build/rust/std/find_std_rlibs.py
172+
@@ -52,6 +52,8 @@ def main():
173+
rustc_args.extend(["--target", args.target])
174+
rustlib_dir = subprocess.check_output(rustc_args).rstrip().decode()
175+
176+
+ lib_output_dir = os.path.join(args.output, 'lib')
177+
+
178+
# Copy the rlibs to a predictable location. Whilst we're doing so,
179+
# also write a .d file so that ninja knows it doesn't need to do this
180+
# again unless the source rlibs change.
181+
@@ -63,7 +65,7 @@ def main():
182+
# output rlibs for that purpose. If any of the input rlibs change, ninja
183+
# will run this script again and we'll copy them all afresh.
184+
depfile.write(
185+
- "%s:" % (os.path.join(args.output, "lib%s.rlib" % args.depfile_target)))
186+
+ "%s:" % (os.path.join(lib_output_dir, "lib%s.rlib" % args.depfile_target)))
187+
188+
def copy_file(infile, outfile):
189+
depfile.write(f" {infile}")
190+
@@ -117,14 +119,19 @@ def main():
191+
output_filename = f"lib{concise_name}.rlib"
192+
193+
infile = os.path.join(rustlib_dir, f)
194+
- outfile = os.path.join(args.output, output_filename)
195+
+ outfile = os.path.join(lib_output_dir, output_filename)
196+
copy_file(infile, outfile)
197+
198+
for f in extra_libs:
199+
infile = os.path.join(rustlib_dir, f)
200+
- outfile = os.path.join(args.output, f)
201+
+ outfile = os.path.join(lib_output_dir, f)
202+
copy_file(infile, outfile)
203+
204+
+ f = 'target.json'
205+
+ infile = os.path.join(rustlib_dir, '..', f)
206+
+ outfile = os.path.join(args.output, f)
207+
+ copy_file(infile, outfile)
208+
+
209+
depfile.write("\n")
210+
211+

0 commit comments

Comments
 (0)