Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 34 additions & 79 deletions .github/workflows/qnx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
name: Bazel Build (QNX)
permissions:
contents: read
actions: write
on:
pull_request:
types: [opened, reopened, synchronize]
Expand All @@ -23,86 +20,44 @@ on:
merge_group:
types: [checks_requested]
workflow_call:
workflow_dispatch:
jobs:
qnx-build:
name: Build and Test ${{ matrix.bazel-config }}
runs-on: ${{ vars.runner_labels_ghub_standard_x64 && fromJSON(vars.runner_labels_ghub_standard_x64) || vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-24.04' }}
permissions:
contents: read
pull-requests: read
# Bazel test targets live in the separate `tests` module, so run all Bazel
# commands from that directory. `defaults.run.working-directory` applies to
# `run:` steps only; `uses:` action steps still execute from the repo root.
defaults:
run:
working-directory: ./tests
name: Build and Test ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- bazel-config: x86_64-qnx
bazel-test-target: "//:all_tests"
- bazel-config: aarch64-qnx
bazel-test-target: "//:all_tests"
- name: toolchain-qnx-tests-x86_64
bazel-config: x86_64-qnx
working-directory: "./tests/"
bazel-target: "//:all_tests"
bazel-disk-cache: toolchain-qnx-tests-x86_64
bazel-test-target: >-
//:all_tests
- name: toolchain-qnx-tests-aarch64
bazel-config: aarch64-qnx
working-directory: "./tests/"
bazel-target: "//:all_tests"
bazel-disk-cache: toolchain-qnx-tests-aarch64
bazel-test-target: >-
//:all_tests
extra-bazel-test-flags: "--test_timeout=120,600,1800,7200" # Increase test timeout due to QEMU emulation
steps:
- uses: eclipse-score/more-disk-space@6a3b48901846bf7f8cc985925157d71a8973e61f # v1
with:
level: 2
- name: Checkout repository (Handle all events)
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
ref: ${{ github.head_ref || github.event.pull_request.head.ref || github.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
- uses: eclipse-score/cicd-actions/unblock-user-namespace-for-linux-sandbox@30ed908edcf367bc38ebff5b386a244f9b6417a7 # 2025-06-04
- name: Setup QNX SDP usage
uses: eclipse-score/cicd-actions/setup-qnx-sdp@a2b3c36fc7d1b9d03880d19935c7ac9cfffe58c6 # 2026-05-19
with:
qnx-license: ${{ secrets.SCORE_QNX_LICENSE }}
qnx-user: ${{ secrets.SCORE_QNX_USER }}
qnx-password: ${{ secrets.SCORE_QNX_PASSWORD }}
qnx-credential-helper: .github/tools/qnx_credential_helper.py
qnx-license-dir: /opt/score_qnx/license
- name: Build with QNX toolchain
run: |
set -euo pipefail

bazel build --config ${{ matrix.bazel-config }} \
--credential_helper=*.qnx.com="${QNX_CREDENTIAL_HELPER}" -- \
//:all_tests
- name: Install qemu
run: |
sudo apt-get update
sudo apt-get install -y qemu-system
- name: Enable KVM group permissions
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0660", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
sudo chown "$USER":kvm /dev/kvm && sudo chmod 0660 /dev/kvm
- name: Test with QNX toolchain
run: |
set -euo pipefail

bazel test --config ${{ matrix.bazel-config }} \
--test_output=errors \
--credential_helper=*.qnx.com="${QNX_CREDENTIAL_HELPER}" ${{ matrix.extra-bazel-test-flags }} -- \
${{ matrix.bazel-test-target }}
- name: Coverage smoke test with QNX toolchain
run: |
set -euo pipefail

bazel coverage --config ${{ matrix.bazel-config }} \
--combined_report=lcov \
--credential_helper=*.qnx.com="${QNX_CREDENTIAL_HELPER}" -- \
//feature_verification:coverage_test
- name: Dump test logs on failure
if: failure()
run: |
echo "===== Bazel test logs ====="
# `bazel-testlogs` is a convenience symlink in the workspace root (./tests).
find -L bazel-testlogs -name 'test.log' -print | while read -r log; do
echo ""
echo "----- ${log} -----"
cat "${log}"
done
uses: eclipse-score/cicd-workflows/.github/workflows/qnx-build.yml@f606cc0c3fccd3e85dcc6d112f3f1f9aed7efdb8 # main on 2026-11-06
permissions:
contents: read
pull-requests: read
with:
bazel-target: ${{ matrix.bazel-target }}
bazel-config: ${{ matrix.bazel-config }}
bazel-test-target: ${{ matrix.bazel-test-target }}
test-log-artifact-name: qnx-testlogs-${{ matrix.bazel-disk-cache }}-${{ github.run_attempt }}
credential-helper: ".github/tools/qnx_credential_helper.py"
bazel-disk-cache: ${{ matrix.bazel-disk-cache }}
working-directory: ${{ matrix.working-directory }}
extra-bazel-test-flags: ${{ matrix.extra-bazel-test-flags }}
secrets:
score-qnx-license: ${{ secrets.SCORE_QNX_LICENSE }}
score-qnx-user: ${{ secrets.SCORE_QNX_USER }}
score-qnx-password: ${{ secrets.SCORE_QNX_PASSWORD }}
qnx-sdp-github-token: ${{ secrets.SCORE_BOT_QNX_PKG_PAT }}
9 changes: 7 additions & 2 deletions docs/extension_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,12 @@ Common package selection attributes:
- `sdk_version`: SDK version info variable, an alternative identifier used in
matrix resolution.
- `sdp_to_link`: name of the toolchain package to be linked with this
toolchain, default set to toolchain name + `_pkg`.
toolchain. For default QNX packages, the extension uses a name based on the
version-matrix entry so toolchains for different CPUs share one package
repository (for example, QNX SDP 8.0.5 uses
`qnx_sdp_8_0_5_pkg`). This default package is private and available only to
S-CORE committers; other users must provide their own compatible package via
`gcc.sdp(...)`. Other default packages use toolchain name + `_pkg`.
- `use_system_toolchain`: TBD.

Flag and runtime attributes:
Expand Down Expand Up @@ -161,7 +166,7 @@ No `--credential_helper` is needed for these URLs.
```starlark
gcc.sdp(
name = "my_qnx_sdp_pkg",
build_file = "@score_bazel_cpp_toolchains//packages/qnx/x86_64/sdp/8.0.0:sdp.BUILD",
build_file = "//toolchains:qnx_sdp.BUILD",
sha256 = "<sha256 of the asset>",
type = "tar.gz",
url = "https://api.github.com/repos/<owner>/<repo>/releases/assets/<id>",
Expand Down
2 changes: 1 addition & 1 deletion docs/generation_flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Shared templates (used by both Linux and QNX):
centralized in the `_normalize_cpu()` helper. Linux toolchain binaries use
the CPU name unchanged (e.g., `aarch64-unknown-linux-gnu-gcov`).
- SDP version mapping is handled through `SDP_VERSION_MAPPING` in
`rules/common.bzl`. Currently, SDP version `8.0.4` is mapped to `8.0.0`
`rules/common.bzl`. Currently, SDP version `8.0.5` is mapped to `8.0.0`
because platform constraint support uses the older identifier. This mapping
is configurable for future extensibility.
- Linux toolchains generate an extra `gcov_wrapper` script to work around the
Expand Down
137 changes: 65 additions & 72 deletions docs/qnx_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ gcc.toolchain(
name = "qnx_toolchain",
target_cpu = "x86_64", # or "aarch64"
target_os = "qnx",
sdp_version = "8.0.0",
use_default_package = True, # only if you're using reference integration QNX SDP package provided by QNX for S-CORE.
sdp_version = "8.0.5",
use_default_package = True, # available to S-CORE committers only
license_path = "/path/to/your/qnx/license", # default location `/opt/score_qnx/license/licenses`
)

Expand All @@ -64,70 +64,88 @@ supported values are:

| `sdp_version` | Package selected | Platform and toolchain label used today |
|---------------|------------------|------------------------------------------|
| `8.0.0` | QNX SDP 8.0.0 | `sdp_8.0.0` |
| `8.0.4` | QNX SDP 8.0.4 | `sdp_8.0.0` |
| `8.0.5` | QNX SDP 8.0.5 | `sdp_8.0.0` |

QNX SDP 8.0.4 currently uses the `sdp_8.0.0` platform constraint because
`bazel_platforms` does not yet define an `sdp_8.0.4` constraint. Therefore, an
8.0.4 toolchain still has `sdp_8.0.0` in its generated Bazel label. The archive
selected by `sdp_version` is nevertheless the actual 8.0.4 archive.
QNX SDP 8.0.5 uses the `sdp_8.0.0` platform constraint because
`bazel_platforms` does not define an `sdp_8.0.5` constraint. Therefore, an
8.0.5 toolchain still has `sdp_8.0.0` in its generated Bazel label. The archive
selected by `sdp_version` is nevertheless the actual 8.0.5 archive.

The download and platform constraint are resolved separately. The archive is
looked up in `packages/version_matrix.bzl` under the real version key, such as
`x86_64-qnx-sdp_8.0.4`. The constraint and generated toolchain label use the
version after `SDP_VERSION_MAPPING` in `rules/common.bzl` is applied, which
currently maps `8.0.4` to `8.0.0`.

When adding a future patch release, such as 8.0.5, add the corresponding
`x86_64-qnx-sdp_8.0.5` and `aarch64-qnx-sdp_8.0.5` entries to
`packages/version_matrix.bzl` with the new URL, SHA-256 digest, and strip
prefix. If the SDP still uses the `qnx8.0.0` target triple and GCC 12.2.0,
reuse the existing `packages/qnx/<cpu>/sdp/8.0.0/sdp.BUILD` descriptor and add
`"8.0.5": "8.0.0"` to `SDP_VERSION_MAPPING`. If the SDK layout or compiler
version changes, add a new package BUILD directory instead. If the release
needs a distinct platform constraint, add that constraint and its platforms to
`bazel_platforms` as well.

To use QNX SDP 8.0.4 instead, change only the version in the toolchain
declaration:
looked up in `packages/version_matrix.bzl` under the real version key. QNX SDP
packages shared across CPUs use a CPU-independent key, such as
`qnx-sdp_8.0.5`; Linux package keys continue to include the CPU. The constraint
and generated toolchain label use the version after `SDP_VERSION_MAPPING` in
`rules/common.bzl` is applied, which currently maps `8.0.5` to `8.0.0`.
Both QNX toolchains referencing the same matrix entry also share one generated
package repository, so the archive is declared and extracted only once.

For example, with `target_os = "qnx"` and `sdp_version = "8.0.5"`, enabling
`use_default_package` looks up the `qnx-sdp_8.0.5` matrix entry and generates
the package repository `qnx_sdp_8_0_5_pkg`. The repository name comes from the
matrix key, not the toolchain's `name` or `target_cpu`. Thus x86_64 and aarch64
toolchain declarations for this SDP both link the same `@qnx_sdp_8_0_5_pkg`;
their generated toolchain repositories remain separate and retain their
declared names.

The default SDP 8.0.5 archive is hosted in a private GitHub release and is
available only to S-CORE committers. If you are not an S-CORE committer, you
cannot fetch this default package even if you have a valid QNX license. Create
and host your own SDP package archive, including a BUILD file compatible with
this toolchain, and declare it with `gcc.sdp(...)`. Set
`use_default_package = False` and point `sdp_to_link` at the package name:

```starlark
gcc.sdp(
name = "my_qnx_sdp_pkg",
build_file = "//toolchains:qnx_sdp.BUILD",
sha256 = "<sha256 of your archive>",
type = "tar.gz",
url = "https://your-artifact-host/qnx_sdp.tar.gz",
)

gcc.toolchain(
name = "qnx_toolchain",
target_cpu = "x86_64", # or "aarch64"
target_cpu = "x86_64", # or "aarch64"
target_os = "qnx",
sdp_version = "8.0.4",
use_default_package = True,
license_path = "/path/to/your/qnx/license",
sdp_version = "8.0.5", # use the version packaged in your archive
sdp_to_link = "my_qnx_sdp_pkg",
use_default_package = False,
)
```

If both SDP versions are needed in the same workspace, declare them with
different repository names so that either one can be selected explicitly:
When adding a future patch release, add one version-matrix entry for a shared
QNX package, keyed by `qnx-sdp_<version>`, with its URL, SHA-256 digest, and
strip prefix. If the SDP still uses the `qnx8.0.0` target triple and GCC
12.2.0, reuse the existing `packages/qnx/sdp/8.0/sdp.BUILD` descriptor and add
the version mapping to `SDP_VERSION_MAPPING`. If the SDK layout or compiler
version changes, add a new package BUILD descriptor instead. If the release
needs a distinct platform constraint, add that constraint and its platforms to
`bazel_platforms` as well.

For builds targeting both CPUs, declare a toolchain for each CPU. Both can
link the shared default QNX package:

```starlark
gcc.toolchain(
name = "qnx_800_toolchain",
name = "qnx_x86_64_toolchain",
target_cpu = "x86_64",
target_os = "qnx",
sdp_version = "8.0.0",
sdp_version = "8.0.5",
use_default_package = True,
)

gcc.toolchain(
name = "qnx_804_toolchain",
target_cpu = "x86_64",
name = "qnx_aarch64_toolchain",
target_cpu = "aarch64",
target_os = "qnx",
sdp_version = "8.0.4",
sdp_version = "8.0.5",
use_default_package = True,
)

use_repo(gcc, "qnx_800_toolchain", "qnx_804_toolchain")
```

Use the corresponding generated repository in each Bazel configuration. Do
not register both toolchains in the same configuration: they currently have
the same target compatibility constraints.
The package repository is `@qnx_sdp_8_0_5_pkg` for both. Select the matching
CPU-specific generated toolchain repository in each Bazel configuration.

#### Step 2: Add Bazel Configuration

Expand All @@ -146,20 +164,6 @@ build:aarch64-qnx --sandbox_writable_path=/var/tmp

> NOTE: Configuration variables are just an example, it's not mandatory to use exact configuration variables.

The platform label remains `sdp_8.0.0` when selecting the 8.0.4 package. If
both versions are declared as in Step 1, separate configurations can select
them as follows:

```text
# QNX SDP 8.0.0
build:x86_64-qnx-800 --platforms=@score_bazel_platforms//:x86_64-qnx-sdp_8.0.0-posix
build:x86_64-qnx-800 --extra_toolchains=@qnx_800_toolchain//:x86_64-qnx-sdp_8.0.0

# QNX SDP 8.0.4
build:x86_64-qnx-804 --platforms=@score_bazel_platforms//:x86_64-qnx-sdp_8.0.0-posix
build:x86_64-qnx-804 --extra_toolchains=@qnx_804_toolchain//:x86_64-qnx-sdp_8.0.0
```

Notice that the generated target uses an underscore in `sdp_8.0.0`; a label
such as `x86_64-qnx-sdp-8.0.0` does not exist.

Expand Down Expand Up @@ -198,15 +202,15 @@ gcc.toolchain(
name = "qnx_x86_64",
target_cpu = "x86_64",
target_os = "qnx",
sdp_version = "8.0.0",
sdp_version = "8.0.5",
use_default_package = True,
)

gcc.toolchain(
name = "qnx_aarch64",
target_cpu = "aarch64",
target_os = "qnx",
sdp_version = "8.0.0",
sdp_version = "8.0.5",
use_default_package = True,
)
```
Expand Down Expand Up @@ -319,18 +323,7 @@ cc_binary(

You can verify the toolchain by building with explicit platform and toolchain selection:

For **x86_64-qnx with QNX SDP 8.0.0**:
```bash
bazel build \
--platforms=@score_bazel_platforms//:x86_64-qnx-sdp_8.0.0-posix \
--extra_toolchains=@qnx_toolchain//:x86_64-qnx-sdp_8.0.0 \
//:hello_qnx
```

For **x86_64-qnx with QNX SDP 8.0.4**, use `sdp_version = "8.0.4"` in
`MODULE.bazel`. The platform and generated toolchain target still use the
`sdp_8.0.0` label:

For **x86_64-qnx with QNX SDP 8.0.5**:
```bash
bazel build \
--platforms=@score_bazel_platforms//:x86_64-qnx-sdp_8.0.0-posix \
Expand Down Expand Up @@ -508,7 +501,7 @@ gcc.toolchain(
name = "qnx_toolchain",
target_cpu = "x86_64",
target_os = "qnx",
sdp_version = "8.0.0",
sdp_version = "8.0.5",
use_default_package = True,
license_path = "/path/to/your/license/file",
)
Expand All @@ -524,7 +517,7 @@ gcc.toolchain(
name = "qnx_toolchain",
target_cpu = "x86_64",
target_os = "qnx",
sdp_version = "8.0.0",
sdp_version = "8.0.5",
use_default_package = True,
license_path = "/path/to/your/license/file",
license_info_url = "https://your-license-server.com/qnx-license",
Expand Down Expand Up @@ -614,7 +607,7 @@ bazel test --config=aarch64-qnx //...

When adapting the template above for your module, consider:

- [ ] **Replace SDP version**: Set `sdp_version` to the exact SDP package version; for SDP 8.0.4, keep the `sdp_8.0.0` platform/toolchain label until an `sdp_8.0.4` constraint is available
- [ ] **Replace SDP version**: Set `sdp_version` to the exact SDP package version; SDP 8.0.5 uses the `sdp_8.0.0` platform/toolchain label
- [ ] **Update paths**: Adapt default paths and examples to your environment conventions
- [ ] **Update configuration variables**: Adapt configuration variables to your moodule configurations
- [ ] **Add module-specific targets**: Include examples of building your actual targets, not just generic `//...`
Expand Down
Loading
Loading