4. Step 4 — Get built and tested on the target platforms#
What it unlocks
Target-platform builds & tests — Your module is actually compiled and tested by the pipelines — built for and deployed to every target platform (Linux x86_64, QNX, AutoSD, EBcLfSA aarch64), offered in the interactive CLI, and exercised by CI. This is the rung that turns a library into something that runs inside the integration images.
The integration provides build definitions for four target images, each built and tested by its own gating CI job — it does not distribute ready-to-flash images; you build them yourself from these definitions. The table lists the platforms, the image target, the runner used to execute it, and the per-platform CI check.
Platform |
Arch |
Image |
Runner |
Build & test workflow |
|---|---|---|---|---|
Linux |
x86_64 |
Docker (runners/docker_x86_64) |
||
QNX 8 |
x86_64 |
QEMU (runners/qemu_x86_64) |
||
Red Hat AutoSD |
x86_64 |
Docker (runners/docker_x86_64) |
||
EB corbos Linux (Safety Apps) |
aarch64 |
QEMU (runners/qemu_aarch64) |
Note
The EB corbos Safety Applications image is special: it runs a high-integrity application demo under additional constraints. Read images/ebclfsa_aarch64/README.md before targeting it.
4.1. Run any image locally in QEMU#
Every image exposes a :run target that boots it in an emulator, so you can
try your module on the real target without hardware:
bazel run //images/linux_x86_64:run
bazel run //images/qnx_x86_64:run
bazel run //images/autosd:run
bazel run //images/ebclfsa_aarch64:run
The QNX and aarch64 images boot under QEMU, which needs a one-time host setup (TUN device, bridge helper, libvirt network). Follow the QEMU runner how-to in runners/qemu_x86_64/README.md before the first run.
4.2. Two ways to get your module onto the images#
There are two ways to make your binary part of the images:
As a showcase (recommended). Bundle your binary once into the aggregate
//showcasespackage; it is then deployed into every image automatically — one change covers all four platforms, and the binary is also offered in the interactive CLI. See Add a runtime showcase below.Directly into each image. Wire the binary into each image’s build description by hand. This is per-image work that you repeat four times (once per image) and is only needed for components that are not run as a CLI showcase — typically a daemon. The
datarouteris integrated this way; see how the QNX image does it in images/qnx_x86_64/build/BUILD (thedataroutersource and theDATAROUTER_PATHmapping). See Deploy a component as part of the platform below. Prefer the showcase route unless you have a reason not to.
4.3. Add a runtime showcase#
A showcase is the vehicle that gets your module onto the platforms: you bundle
a runnable binary, and the aggregate //showcases package is deployed into
every image automatically. You do this once — there is no per-platform work.
There are two patterns under showcases/:
Standalone (showcases/standalone) — bundle a binary that already exists in your module’s repo.
Composed — a small binary defined here that combines several modules.
1. Define the bundle. Add a score_pkg_bundle target. To re-use a binary
that lives in your module:
load("//bazel_common:bundlers.bzl", "score_pkg_bundle")
score_pkg_bundle(
name = "my_module",
bins = ["@score_my_module//examples:my_example"],
config_data = ["//showcases/standalone:my_module.score.json"],
package_dir = "standalone",
)
2. Add a CLI descriptor. Create a *.score.json next to the bundle. The
CLI auto-discovers every *.score.json deployed under /showcases and
offers it in the interactive menu, so no code change to the CLI is required:
{
"name": "My Module Example",
"description": "Demonstrates my_module at runtime",
"apps": [
{
"path": "/showcases/bin/my_example",
"args": [],
"env": {},
"dir": "/showcases/data/my_module"
}
]
}
3. Register the bundle in the top-level showcase package. Add your bundle to
the aggregate score_pkg_bundle in
showcases/BUILD so it is packaged into the images:
score_pkg_bundle(
name = "showcases",
bins = ["//showcases/cli"],
other_package_files = [
"//showcases/standalone:comm_pkg_files",
# ...
"//showcases/standalone:my_module_pkg_files",
],
package_dir = "showcases",
)
Once your bundle is part of //showcases, it is reachable from
//images/<platform>:image and is therefore built by every platform CI
job automatically.
4.4. Deploy a component as part of the platform#
If your component is not a showcase — for example a background daemon that must always be present — it belongs to the deployed platform rather than to the demonstration layer. The image content is split into three layers:
Image (
images/<variant>) — boot, kernel, drivers, rootfs skeleton.Platform (
deploy/) — the S-CORE modules as deployed. This is what a conformance check treats as the system under test.Showcases (
showcases/) — applications that demonstrate and verify the platform, removable without touching the two layers below.
Keep the two apart: a showcase must never ship the component it exercises,
otherwise it verifies the binary it brought along instead of the one the
distribution deployed. The lifecycle module is the illustrative case — the
launch_manager daemon is deployed from deploy/lifecycle, while the
applications it supervises stay in showcases/simple_lifecycle.
1. Package the component. Declare destination path and permissions as a
pkg_files target in deploy/<module>/BUILD. Because the binary is
resolved per platform (not per architecture), one definition serves every
image, and score_rules_imagefs generates the matching mkifs directives
so nothing has to be added to system.build:
# deploy/logging/BUILD
pkg_files(
name = "datarouter_bin",
srcs = ["@score_logging//score/datarouter"],
attributes = pkg_attributes(mode = "0777"),
prefix = "usr/bin/datarouter",
strip_prefix = strip_prefix.files_only(),
)
2. Register it in the platform bundle. Unlike the showcase route this is not per-image work: every image already consumes the aggregate, so adding your target to it is enough.
# deploy/BUILD
pkg_filegroup(
name = "platform_bundle",
srcs = [
# ...
"//deploy/logging:datarouter_bin",
],
visibility = ["//visibility:public"],
)
# images/qnx_x86_64/build/BUILD (already present, shown for context)
qnx_ifs(
name = "init",
srcs = [
# ...
"//deploy:platform_bundle",
],
build_file = "init.build",
extra_build_files = ["system.build"],
)
Note that qnx_ifs rejects anything in srcs that does not provide a
rules_pkg provider, so a plain filegroup or a bare label will not work -
wrap it in pkg_files.
See deploy/README.md for the contract between the platform and the showcase layer, and images/qnx_x86_64/build/BUILD for how an image consumes it.
If your module simply cannot run on a given platform, exclude its targets via
metadata.exclude_test_targets / metadata.extra_test_config in
known_good.json (Step 1) rather than editing the workflow.