Skip to content

Commit e7b2553

Browse files
committed
Add QEMU user space emulator wrapper for aarch64 testing
1 parent 6951cd2 commit e7b2553

File tree

4 files changed

+118
-1
lines changed

4 files changed

+118
-1
lines changed

.bazelrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ build:bl-aarch64-linux --config=_bl_toolchain_common
4747
build:bl-aarch64-linux --platforms=@score_bazel_platforms//:aarch64-linux-gcc_12.2.0-posix
4848
build:bl-aarch64-linux --extra_toolchains=@score_gcc_aarch64_toolchain//:aarch64-linux-gcc_12.2.0-posix
4949
test:bl-aarch64-linux --config=_bl_common
50+
test:bl-aarch64-linux --run_under=//:qemu_aarch64
5051

5152

5253
# Target configuration for CPU:x86-64|OS:QNX build (do not use it in case of system toolchains!)

BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
load("@score_docs_as_code//:docs.bzl", "docs")
1515
load("@score_tooling//:defs.bzl", "copyright_checker", "use_format_targets")
16+
load(":qemu.bzl", "qemu_aarch64")
1617

1718
docs(
1819
data = [
@@ -38,3 +39,5 @@ copyright_checker(
3839
)
3940

4041
use_format_targets()
42+
43+
qemu_aarch64()

README.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,28 @@ Use the same command as for x86_64 Linux, but replace `--config=bl-x86_64-linux`
8585
> [!NOTE]
8686
> AArch64 Linux support is currently experimental. Some targets may not build successfully.
8787
88+
#### Executing Cross-Compiled Tests with QEMU
89+
90+
When cross-compiling for AArch64, test binaries cannot run natively on an x86_64 host. They are executed locally using [QEMU user-mode emulation](https://www.qemu.org/docs/master/user/main.html).
91+
92+
**Prerequisite:** Install the `qemu-user-static` package on your host system:
93+
94+
```bash
95+
sudo apt install qemu-user-static # Debian/Ubuntu
96+
```
97+
98+
Verify the installation:
99+
100+
```bash
101+
qemu-aarch64 --version
102+
```
103+
104+
Running tests:
105+
106+
```bash
107+
bazel test --config=bl-aarch64-linux //score/...
108+
```
109+
88110
#### Building for x86_64 QNX 8.0 SDP
89111

90112
```bash
@@ -125,4 +147,4 @@ Access the documentation at `_build/index.html` in your browser.
125147

126148
- **GitHub Issues**: [Report bugs or request features](https://github.com/eclipse-score/baselibs/issues).
127149
- **GitHub Discussions**: [Ask questions and share ideas](https://github.com/orgs/eclipse-score/discussions/categories/base-libs-ft).
128-
- **Communication and Coordination**: See the [pinned discussion](https://github.com/orgs/eclipse-score/discussions/1223) for details on communication channels and project coordination.
150+
- **Communication and Coordination**: See the [pinned discussion](https://github.com/orgs/eclipse-score/discussions/1223) for details on communication channels and project coordination.

qemu.bzl

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
"""
15+
Rule for creating a QEMU user-mode emulation wrapper script.
16+
17+
QEMU user-mode emulation allows running Linux executables compiled for one CPU
18+
architecture on a host with a different CPU architecture (e.g. running aarch64
19+
binaries on an x86_64 host). The generated script is intended to be used with
20+
Bazel's --run_under flag to transparently execute cross-compiled test binaries.
21+
22+
The sysroot path is passed to QEMU via the -L flag so that the emulator can
23+
locate the target architecture's shared libraries at runtime.
24+
25+
Prerequisites:
26+
The QEMU user-mode emulator for the target architecture must be installed on
27+
the host system and available on $PATH. For example, to emulate aarch64
28+
binaries on Debian/Ubuntu, install the ``qemu-user-static`` package.
29+
"""
30+
31+
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
32+
33+
def _qemu_emulator_wrapper_impl(ctx):
34+
# Get sysroot from explicit attr or from the CC toolchain
35+
if ctx.attr.sysroot:
36+
sysroot = ctx.attr.sysroot[DefaultInfo].files.to_list()[0].path
37+
else:
38+
cc_toolchain = ctx.attr._cc_toolchain[cc_common.CcToolchainInfo]
39+
sysroot = cc_toolchain.sysroot
40+
41+
script = ctx.actions.declare_file(ctx.label.name)
42+
ctx.actions.write(
43+
output = script,
44+
content = """#!/bin/bash
45+
set -euo pipefail
46+
# Resolve symlinks to find the real execroot, then locate the sysroot.
47+
REAL_SCRIPT="$(readlink -f "$0")"
48+
EXECROOT="${{REAL_SCRIPT%/bazel-out/*}}"
49+
exec qemu-{arch} -L "$EXECROOT/{sysroot}" "$@"
50+
""".format(
51+
arch = ctx.attr.arch,
52+
sysroot = sysroot,
53+
),
54+
is_executable = True,
55+
)
56+
57+
return [DefaultInfo(executable = script)]
58+
59+
qemu_emulator_wrapper = rule(
60+
implementation = _qemu_emulator_wrapper_impl,
61+
attrs = {
62+
"arch": attr.string(
63+
mandatory = True,
64+
doc = "Target CPU architecture (e.g. 'aarch64').",
65+
),
66+
"sysroot": attr.label(
67+
mandatory = False,
68+
doc = "Label pointing to the sysroot directory that is passed to QEMU. If not provided, uses the CC toolchain's sysroot.",
69+
),
70+
"_cc_toolchain": attr.label(
71+
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
72+
),
73+
},
74+
executable = True,
75+
doc = "Generates a wrapper script for running tests under qemu with the correct sysroot.",
76+
)
77+
78+
def qemu_aarch64(name = "qemu_aarch64", sysroot = None, **kwargs):
79+
"""Convenience macro for creating a QEMU aarch64 emulator wrapper.
80+
81+
Args:
82+
name: Optional name of the wrapper target.
83+
sysroot: Optional sysroot label.
84+
**kwargs: Additional arguments passed to qemu_emulator_wrapper.
85+
"""
86+
qemu_emulator_wrapper(
87+
name = name,
88+
arch = "aarch64",
89+
sysroot = sysroot,
90+
**kwargs
91+
)

0 commit comments

Comments
 (0)