Bug 41137: Build gcc-cross and tor-expert-bundle for linux-aarch64
Merge Info
Related Issues
Backporting
Timeline
-
Immediate: patchset needed as soon as possible -
Next Minor Stable Release: patchset that needs to be verified in nightly before backport -
Eventually: patchset that needs to be verified in alpha before backport -
No Backport (preferred): patchset for the next major stable
(Optional) Justification
-
Emergency security update: patchset fixes CVEs, 0-days, etc -
Censorship event: patchset enables censorship circumvention -
Critical bug-fix: patchset fixes a bug in core-functionality -
Consistency: patchset which would make development easier if it were in both the alpha and release branches; developer tools, build system changes, etc -
Sponsor required: patchset required for sponsor -
Other: please explain
Issue Tracking
-
Link resolved issues with appropriate Release Prep issue for changelog generation
Review
Request Reviewer
-
Request review from an applications developer depending on modified system: -
NOTE: if the MR modifies multiple areas, please
/ccall the relevant reviewers (since gitlab only allows 1 reviewer) - accessibility : henry
- android : clairehurst, dan
- build system : boklm
- extensions : ma1
- firefox internals (XUL/JS/XPCOM) : ma1
- fonts : pierov
- frontend (implementation) : henry
- frontend (review) : donuts, richard
- localization : henry, pierov
- macos : clairehurst, dan
- nightly builds : boklm
- rebases/release-prep : boklm, dan, ma1, pierov, richard
- security : ma1
- signing : boklm, richard
- updater : pierov
- misc/other : pierov, richard
-
NOTE: if the MR modifies multiple areas, please
Change Description
This MR adds support for building a gcc toolchain and the tor-expert-bundle for linux-aarch64. It does so by
- rationalizing the process of cross-compiling a linux target (
linux-cross) and making it extensible to other archs - adding a
gcc-crossproject - making small changes to
container-image,binutils,openssl,go-bootstrapandgo - building
torforlinux-crosstargets
The gcc-cross and tor-expert-bundle projects, and any project in between, can be built using
./rbm/rbm build $project --target alpha --target torbrowser-linux-$arch
where $arch is one of aarch64 or arm. linux-arm is not within the main scope of this MR, but enabling it only required a couple of minor changes, and it serves as a check that the cross-compilation logic is solid for generic linux targets.
In what follows I will detail the cross-compilation logic and some of the changes contained in this patchset. You can skip the cross-compilation logic if you are not interested, the patchset will still work! But in the future more work is likely to be done on linux-cross targets if this MR is accepted, so it's best if I lay it out here.
Cross-compilation logic
The linux-cross target defines the compiler and the generic configure options for linux cross-compiled targets. When cross-compiling, there are a few things we must take into account:
- we need to build both a native compiler (to build the host tools) and a cross compiler (to build the target binaries)
- some projects are built for the host, others are built for the target, others still are built for the host and will build binaries for the target.
linux-crossneeds a way to select which of the above compilers to use for each project - projects built for the host which build binaries for the target may need both the compilers (e.g.
rustapparently does, whileclangdoesn't while buildingclang, but does while buildingfirefox) - we don't want to build the host tools multiple times (think about
cmake,python, etc.), so their projects must have the native compiler alone among their dependencies
In light of the above, this MR implements linux cross-compilation as follows. First, a copy of the native compiler (and of cross-binutils), separately built as dependencies, are embedded into the cross-compiler artifact. This avoids huge headaches with passing headers and library paths around when building rust and firefox (admittedly outside the scope of this MR, but something we must take into account from the get-go if we don't want to re-write the cross compiler from scratch later).
Second, by default, projects built for the linux-cross target will use the cross-compiler. However, to avoid tens of unmanageable target_replace, projects which only build host tools and whose building does not need the cross compiler are marked with a no_crosscompile variable, and are built using the native compiler. Selecting the native compiler when no_crosscompile: 1 is done automatically by the linux-cross target via the definition of compiler in rbm.conf.
In general, a project should be marked as no_crosscompile if:
- it is built using the
linux-crosstarget - its building requires a compiler, and that compiler is the native compiler
However, this is not enough to comply with point 4. above. The reason for this is Jeremy Rand sneaked in a quite useful change in projects/container-image: in current main, when building for target linux-cross, the build container calls dpkg --add-architecture $debian_arch before installing packages. Since this changes the container's setup and thus its id, all projects built in a container under the linux-cross target in current main, and all projects which depend on such projects, have different ids and will be built twice, whether or not they are actually cross-compiling anything. This includes the host tools.
To fix this, I deactivated dpkg --add-architecture $debian_arch in the container's setup when no_crosscompile is set for the container's parent project. Thanks to this change, to comply with point 4., a project must be marked as no_crosscompile if:
- it is built using the
linux-crosstarget (either directly or indirectly, as a dependence of another project) - its building does not require the cross-compiler
- it is built in a container
On the other hand, it must not be marked as no_crosscompile if it requires the cross-compiler (unless the project's own linux-cross targets defines no_crosscompile: 0 of course).
Details
Some of the changes are explained in the commit messages, in comments or in patch headers. In addition to those:
-
binutilsis the only project in alltor-browser-buildwhich needs to be both compiled and cross-compiled (meaning that it provides cross-binutils) and which does not need a separate build script for cross compilation. It is not natively compiled in this MR, but it will be eventually, when building the browser. It must be called with thelinux-crosstarget when and only when we want cross-binutils -
gccand the crossgcctoolchain are built in completely different ways, so I separated the cross toolchain into agcc-crossproject. As mentioned previously,gcc-crosscontains a copy of the cross binutils and of the native compiler, which are built separately and imported as dependencies - in
gcc-cross, twoglibcpatches are backported to overcome build failures due to linking issues. These are specific tolinux-aarch64, and to this version ofglibc(I chose v2.24 because this is the last version which, when used as part of thegcccross-toolchain, is able to compile binaries which work on Debian Stretch). The*.patchfiles bear the names of the original authors and the hashes of the original commit, so you can easily find them in theglibcgit repo. However I had to refresh them for theglibcversion contained in this MR. In more detail:-
glibc-cross-linux-aarch64.patchovercomesrelocation R_AARCH64_ABS32 against 'a local symbol' can not be used when making a shared object. More info here -
glibc-cross-linux-aarch64-2.patchovercomesrelocation R_AARCH64_ADR_PREL_PG_HI21 against symbol '_dl_argv' which may bind externally can not be used when making a shared object. More info here
-
- there are of course a lot of details regarding how
gcc-crossis built. As a general rule, I started from Jeremy's code (which is still there and makes up for the majority of thegcc-crossbuild script I believe) and changed it until I got a cross compiler which is able to fully build the browser -
(does not apply when building with thego-bootstrapis correctly built once for all targets.gowould be too for alllinuxtargets ifosnamewas not in itsfilename, but I'm not going to change this now because it is outside of the scope of this MRtorbrowser-linux-$archtarget)
How Tested
I tested the gcc-cross compiler by building tor-expert-bundle for both linux-aarch64 and linux-arm. I tested the tor-expert-bundle as part of a full linux-aarch64 build of the Tor Browser using this linux-cross branch, which is a rewrite of !920 (closed) that avoids rebuilding the host tools and that does not contain the native linux-aarch64 build enablement patches. The linux-arm tor-expert-bundle artifact is untested (although I checked that all the binaries contained therein are for the correct architecture).
A note
I talked to Jeremy Rand and, from what I understood, he is fine with me changing his linux-cross code as long as openssl still builds the linux-arm target (i.e. if there are no regressions in the code). This MR builds a full linux-arm tor-expert-bundle (and it's the base for cross-building a whole linux-aarch64 Tor Browser), so I think we're good from this perspective, although as I mentioned those binaries are untested.