diff --git a/README.md b/README.md index 4bc2c2b..2352d96 100644 --- a/README.md +++ b/README.md @@ -1,248 +1,54 @@ -# S-CORE Bazel C/C++ Toolchain Configuration Repository - -This repository provides the configuration layer for all S-CORE C++ toolchains used in Bazel builds.
-It contains **no compiler binaries**. Instead, it defines: -* Toolchain configurations -* Toolchain rules and extensions for Bzlmod -* Common compiler flags -* Templates for generating toolchain configs -* Package descriptors for external toolchain binaries -* Tests ensuring correct toolchain behavior - -All toolchain binaries (GCC, QCC, etc.) are downloaded through Bazel repositories defined in consuming workspaces.
-This repository is structured and versioned as a Bazel module and is intended to be consumed through MODULE.bazel. - -## Key Goals - -* Provide a centralized, unified configuration source for all C++ toolchains used across S-CORE. -* Enforce consistency through shared flags, templates, and mandatory feature tests. -* Support multiple compilers (GCC, QCC) and multiple platforms (Linux, QNX). -* Ensure reproducible builds across architectures by separating: - * configuration logic (this repo). - * binary/toolchain distributions (external packages). -* Support plug-and-play toolchain activation via Bzlmod extensions. - -## Repository Structure - -```bash -. -│ -├── .github # Configuration directory for GitHub operations. -├── docs # Sphinx documentation sources. -├── examples # Functional examples for toolchain validation. -├── extensions # Module extensions for GCC/QCC toolchains -│ ├── BUILD -│ └── gcc.bzl # Module extension for setting up GCC toolchains in Bazel. -├── packages # Toolchain package descriptors (no binaries) -│ ├── linux/ # Linux toolchain versions (GCC only) -│ ├── qnx/ # QNX SDP/QCC toolchain metadata -│ └── version_matrix.bzl # Supported toolchain version definitions -├── rules # Bazel rule implementations for toolchains -│ ├── BUILD -│ ├── common.bz # Common rules used by all drivers -│ └── gcc.bzl # Module rule for defining GCC toolchains in Bazel. -├── templates # Templates for toolchain definition and configuration -│ ├── linux/ -│ ├── qnx/ -│ ├── BUILD -│ └── BUILD.template -├── tools # Utility scripts (e.g., QNX credential helper) -├── MODULE.bazel # Module declaration for Bzlmod -├── BUILD -├── LICENSE -├── NOTICE -└── README.md -``` - -## Toolchain Model - -This repository does not contain compiler binaries.
-Instead: -- Toolchain **packages** describe how to fetch compiler binaries via `http_archive` or internal artifact storage. -- Toolchain **templates** describe how Bazel should use the binaries. -- Toolchain **rules** and **extensions** generate and register toolchains. -- Toolchain **examples** validate the toolchains. -- This separation provides: - - Hermetic configurations - - Full reproducibility - - Clear ownership boundaries - - Easy addition of new compilers or versions - - -## Using Toolchains in a different Bazel Module - -### GCC Example (Linux x86_64) - -```starlark -bazel_dep(name = "score_cpp_toolchains", version = "0.1.0") -use_extension("@score_cpp_toolchains//extensions:gcc.bzl", "gcc") -gcc( - target_os = "linux", - target_cpu = "x86_64", - version = "12.2.0", - use_default_package = True, -) -use_repo(gcc, "score_gcc_toolchain") -``` - -### QCC Example (QNX ARM64) - -```starlark -bazel_dep(name = "score_cpp_toolchains", version = "0.2.0") -use_extension("@score_cpp_toolchains//extensions:gcc.bzl", "gcc") -gcc( - target_os = "qnx", - target_cpu = "arm64", - sdp_version = "8.0.0", - version = "12.2.0", - use_default_package = True, -) -use_repo(gcc, "score_gcc_qnx_toolchain") -``` - -The registration of toolchains is done by adding command line option `--extra_toolchains=@//:toolchain_name` -In case above this would be: -```bash ---extra_toolchains=@score_gcc_toolchain//:x86_64-linux-gcc-12.2.0 ---extra_toolchains=@score_gcc_qnx_toolchain//:x86_64-qnx-sdp-8.0.0 -``` - -> NOTE: In case that more than one toolchain needs to be defined, the registration must be protected via config flags otherwise
-the first toolchain that matches constraints will be selected by toolchain resolutions. - -## Configuration Flags - -Shared flag sets live under: - -- [linux](templates/linux/cc_toolchain_flags.bzl.template) -- [qnx](templates/qnx/cc_toolchain_config.bzl.template) - -These define: - -- Base C/C++ flags -- Optimization flags -- PIC/PIE handling -- Debug and sanitizer modes -- Linker behavior -- Warning levels - -## Templates - -Templates define how toolchain files are generated: - -- `BUILD.template` -- `cc_toolchain_config.bzl.template` -- `cc_gcov_wrapper.template` -- `cc_toolchain_flags.bzl.template` - -These templates simplify adding: + -- New compiler versions -- New compiler families -- New OS/arch combinations - -## Testing and Validation - -Testing is part of the **integration gate pipeline**. - -## Examples - -Example cover: - -- Simple compilation ( [examples/main.cpp](./examples/main.cpp)) -- Toolchain registration behavior ([examples/.bazelrc](./examples/.bazelrc)) - -# Documentation - -Documentation uses **Sphinx** and lives in `docs/`. (Not yet prepared!) - -# QNX License - -## Local License File - -By default, the QNX toolchain uses `/opt/score_qnx/license/licenses` as the license path. -If you want to change this location, you can override it by setting the `license_path` variable -when calling the `gcc.toolchain(...)` function in your `MODULE.bazel` file. - -**Example:** - -```bazel -gcc.toolchain( - name = "score_qcc_toolchain", - target_os = "qnx", - ... - license_path = "/path/to/your/custom/licenses", -) -``` - -> **TODO:** Is it possible to set this via environment variable? - -## License Servers - -In case you are using a license server for QNX licenses (FLEXlm), you can set the license server information -either locally in your module or centrally in your bazel configuration. -This also applies to floating licenses. - -### Module Local Configuration - -You can set the license server for your toolchains by setting the variables `license_info_variable` and -`license_info_url` when calling the `gcc.toolchain(...)` function in your `MODULE.bazel` file. - -**Example (for QNXLM_LICENSE_FILE variable):** - -```bazel -gcc.toolchain( - name = "score_qcc_toolchain", - target_os = "qnx", - ... - license_info_variable = "QNXLM_LICENSE_FILE", - license_info_url = "@", -) -``` - -### Central Configuration - -In case you want to set the license server for all your bazel projects you can set the -environment variable in your `~/.bazelrc` file: - -**Example (for QNXLM_LICENSE_FILE variable):** - -```bazel -common --action_env=QNXLM_LICENSE_FILE=@ -``` - -In case you do not want to set it for all commands you can also set it per build/test command: - -```bazel -build --action_env=QNXLM_LICENSE_FILE=@ -test --action_env=QNXLM_LICENSE_FILE=@ -``` +# S-CORE Bazel C/C++ Toolchain Configuration Repository -# Adding New Toolchain Versions +This repository contains the configuration layer for S-CORE C and C++ +toolchains used in Bazel builds. It does not ship compiler binaries. Instead, +it defines the metadata, templates, repository rules, module extension logic, +and validation workspace needed to fetch and register external toolchain +packages reproducibly. -1. Update `packages/version_matrix.bzl` -2. Add a package descriptor (e.g., `packages/linux/x86_64/gcc/13.1.0`) -3. Generate configuration from templates -4. Update flags if needed -5. Submit through integration gate +The documentation below is organized around the main subsystems of the +repository: how consumers declare toolchains, how Bazel repositories are +generated, how platform packages are described, how the example workspace +validates the setup, and how QNX-specific authentication and licensing fit in. ---- +## Documentation -# Tools +- [Overview](docs/overview.md) +- [Repository layout](docs/repository_layout.md) +- [Extension API](docs/extension_api.md) +- [Generation flow](docs/generation_flow.md) +- [Examples and validation](docs/examples_and_validation.md) +- [QNX integration](docs/qnx_integration.md) +- [Maintenance](docs/maintenance.md) -Utility scripts such as: +## Quick Summary -``` -tools/qnx_credential_helper.py -``` +**Module:** S-CORE Bazel C/C++ toolchain configurations -are used for repository authentication flows. +**Type:** Bazel module with repository rules, templates, and example validation ---- +**Primary consumer entry point:** `@score_bazel_cpp_toolchains//extensions:gcc.bzl` -# License +**Main validation surface:** `examples/` smoke-test workspace -Distributed under: +## Key Capabilities -- `LICENSE` -- `NOTICE` +- Define Linux and QNX toolchains through a Bzlmod extension. +- Resolve default package metadata through `packages/version_matrix.bzl`. +- Generate toolchain repositories from platform-specific templates. +- Validate toolchain selections through the example workspace test matrix. diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index d07ded8..0000000 --- a/docs/conf.py +++ /dev/null @@ -1,19 +0,0 @@ -# ******************************************************************************* -# Copyright (c) 2026 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0 -# -# SPDX-License-Identifier: Apache-2.0 -# ******************************************************************************* -project = "S-CORE Bazel C/C++ Toolchain configurations" -project_url = "https://eclipse-score.github.io/bazel_cpp_toolchains" -version = "0.1" -extensions = [ - "sphinxcontrib.plantuml", - "score_sphinx_bundle", -] diff --git a/docs/examples_and_validation.md b/docs/examples_and_validation.md new file mode 100644 index 0000000..b2a4eb7 --- /dev/null +++ b/docs/examples_and_validation.md @@ -0,0 +1,82 @@ + + +# Examples And Validation + +## Example Workspace Purpose + +The `examples/` directory is a separate Bazel workspace used as a lightweight +integration test bed for the repository. + +It demonstrates how consumers declare toolchains while also serving as the main +smoke-test surface for validating that the generated toolchains can build and, +where appropriate, run example targets. + +## Important Files + +`examples/MODULE.bazel` + +Declares representative Linux and QNX toolchain repositories and wires the +example workspace back to the local checkout with `local_path_override`. + +`examples/.bazelrc` + +Defines named Bazel configurations that activate the generated toolchains and +platforms. + +`examples/BUILD` + +Contains small C++ targets used to verify compilation, linking, pthread +support, and sanitizer integration. + +`examples/test.sh` + +Matrix runner that maps each configuration name to a small build or test +sequence. + +## Smoke-Test Matrix + +The example workspace currently validates these configuration groups: + +- Linux host toolchains +- Linux cross-compilation toolchains +- runtime-specific Linux toolchains such as AutoSD and EB corbos Linux for Safety Applications +- packaged QNX toolchains + +The smoke-test runner isolates Bazel state per configuration so it does not +rely on `bazel clean --expunge` between cases. + +## Useful Commands + +```bash +cd examples +./test.sh --list +./test.sh host_config_1 +./test.sh --keep-going +``` + +## What The Tests Prove + +The example workspace is not intended to be an exhaustive compiler correctness +suite. Instead, it answers a narrower question: did the configuration +repository produce a usable toolchain definition for each supported scenario? + +In practice this means checking among other things: + +- successful compilation with the selected compiler and sysroot, +- correct toolchain registration and platform matching, +- basic linking behavior, +- feature coverage such as pthread-enabled builds, +- optional sanitizer feature wiring for the local Linux toolchain path. \ No newline at end of file diff --git a/docs/extension_api.md b/docs/extension_api.md new file mode 100644 index 0000000..1c2b6d1 --- /dev/null +++ b/docs/extension_api.md @@ -0,0 +1,116 @@ + + +# Extension API + +## Consumer Entry Point + +Consumers interact with this repository through the `gcc` module extension in +`@score_bazel_cpp_toolchains//extensions:gcc.bzl`. + +Typical usage looks like this: + +```starlark +bazel_dep(name = "score_bazel_cpp_toolchains", version = "0.4.0") + +gcc = use_extension("@score_bazel_cpp_toolchains//extensions:gcc.bzl", "gcc") + +gcc.toolchain( + name = "score_gcc_toolchain", + target_cpu = "x86_64", + target_os = "linux", + version = "12.2.0", + use_default_package = True, +) + +use_repo(gcc, "score_gcc_toolchain") +``` + +## Public Tags + +`gcc.toolchain(...)` + +Declares a toolchain repository to generate. + +`gcc.sdp(...)` + +Declares a package repository explicitly. This is used when the package is not +taken from the default version matrix or when local QNX SDP generation is +required. + +## `gcc.toolchain(...)` Attributes + +Required attributes: + +- `name`: name of the generated repository +- `target_cpu`: target CPU, currently `x86_64` or `aarch64` +- `target_os`: target OS, currently `linux` or `qnx` + +Common package selection attributes: + +- `use_default_package`: resolve package metadata from `packages/version_matrix.bzl` +- `version`: GCC version string for Linux toolchains +- `sdp_version`: QNX SDP version string +- `sdk_version`: alternative SDK identifier used in matrix resolution +- `sdp_to_link`: override the package repository name that the toolchain uses + +Flag and runtime attributes: + +- `extra_compile_flags` +- `extra_c_compile_flags` +- `extra_cxx_compile_flags` +- `extra_link_flags` +- `ld_library_paths` +- `runtime_ecosystem` +- `use_base_constraints_only` + +QNX-specific attributes: + +- `license_path` +- `license_info_variable` +- `license_info_url` + +## `gcc.sdp(...)` Attributes + +The `gcc.sdp` tag defines the package side of the toolchain setup. Important +attributes are: + +- `name`: repository name for the package +- `build_file`: BUILD file that exposes the package contents as Bazel targets +- `url`: url of the archive, +- `sha256`: sha256 of the archive +- `strip_prefix`: extraction prefix for packaged archives + + +## Activation In A Workspace + +Declaring a toolchain repository is not enough on its own. Consumers still need +to activate the generated toolchain during Bazel analysis, typically with a +configuration such as: + +```text +--extra_toolchains=@score_gcc_toolchain//:x86_64-linux-gcc_12.2.0 +``` + +The example workspace under `examples/` provides complete `.bazelrc` +configurations for this activation step. + +## Behavior Notes + +- The extension is intended for the root module. +- When `use_default_package` is enabled, the version matrix can inject extra + include and link flags required by non-standard sysroot layouts. +- QNX toolchains use additional licensing and include-path parameters that do + not apply to Linux toolchains. \ No newline at end of file diff --git a/docs/generation_flow.md b/docs/generation_flow.md new file mode 100644 index 0000000..0ed4f55 --- /dev/null +++ b/docs/generation_flow.md @@ -0,0 +1,92 @@ + + +# Generation Flow + +## End-To-End Flow + +The repository turns a small `MODULE.bazel` declaration into a generated +toolchain repository through these steps: + +1. `extensions/gcc.bzl` collects `gcc.toolchain` and `gcc.sdp` tags. +2. Package metadata is resolved from `packages/version_matrix.bzl` or from an + explicit `gcc.sdp` declaration. +3. `rules/gcc.bzl` renders a BUILD file and configuration files into a new + repository. +4. Platform-specific templates from `templates/linux/` or `templates/qnx/` are + populated with CPU, version, licensing, and flag information. +5. The consuming workspace enables the generated toolchain with + `--extra_toolchains` and compatible platform constraints. + +## Subsystem Roles + +`packages/version_matrix.bzl` + +Defines the supported package matrix. Each entry maps a logical toolchain key +to download metadata and, when needed, extra compiler or linker flags. + +`rules/common.bzl` + +Provides small helpers that convert lists of flags into the Bazel `flag_group` +representation needed by the templates and repository rules. + +`rules/gcc.bzl` + +Generates the toolchain repository. It decides whether Linux or QNX template +content is required, performs placeholder substitution, and emits the final +`BUILD`, `cc_toolchain_config.bzl`, `flags.bzl`, and Linux `gcov` wrapper +files. + +## Template Families + +Linux templates: + +- `templates/linux/cc_toolchain_config.bzl.template` +- `templates/linux/cc_toolchain_flags.bzl.template` +- `templates/linux/cc_gcov_wrapper.template` + +QNX templates: + +- `templates/qnx/cc_toolchain_config.bzl.template` +- `templates/qnx/cc_toolchain_flags.bzl.template` + +Shared template: + +- `templates/BUILD.template` + +## Important Implementation Details + +- Some package definitions rely on the `%{toolchain_pkg}%` placeholder, which + is rewritten to the canonical Bzlmod repository name during repository-rule + generation. +- QNX `aarch64` is mapped internally to `aarch64le` where required by the + underlying SDK layout. +- SDP version `8.0.4` is normalized to `8.0.0` in the generated toolchain + configuration because platform constraint support currently uses the older + identifier. +- Linux toolchains generate an extra `gcov_wrapper` script to work around the + current `rules_cc` coverage integration behavior. + +## Version Matrix Responsibilities + +The version matrix is more than a list of URLs. It is also the place where the +repository centralizes: + +- package build-file selection, +- archive extraction prefixes, +- sysroot-specific compiler flags, +- extra link flags, +- compiler library search paths, +- runtime-ecosystem variants such as AutoSD or EB corbos Linux for Safety Applications. \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index 8ce2ace..0000000 --- a/docs/index.rst +++ /dev/null @@ -1,32 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2026 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* -Bazel C/C++ Toolchain Config Documentation -============================ - -TBD - -.. contents:: Table of Contents - :depth: 2 - :local: - -Purpose -------- -TBD - -Summary -------- - -**Library:** `Score C/C++ Toolchain configurations` - -**Type:** Bazel toolchain configurations \ No newline at end of file diff --git a/docs/maintenance.md b/docs/maintenance.md new file mode 100644 index 0000000..f41ce25 --- /dev/null +++ b/docs/maintenance.md @@ -0,0 +1,62 @@ + + +# Maintenance + +## Adding A New Toolchain Variant + +Adding support for a new toolchain variant usually touches several layers: + +1. add or extend package metadata in `packages/version_matrix.bzl`, +2. add a package BUILD descriptor under `packages/linux/` or `packages/qnx/`, +3. ensure the required template placeholders already exist, or extend the + platform template files, +4. update the example workspace if the new variant should be validated by the + smoke-test matrix, +5. add or update documentation in this Markdown source and the repository README. + +## When To Use The Version Matrix + +Use the version matrix when a package should be part of the supported default +surface for consumers. This gives downstream users a shorter configuration and +centralizes special sysroot flags in one place. + +Use explicit `gcc.sdp(...)` declarations when package metadata is local, +experimental, or intentionally not part of the default support matrix. + +## Common Gotchas + +- runtime-specific toolchains may need extra include and link flags that do not + exist for standard GCC archives, +- QNX `aarch64` naming differs from some underlying SDK paths, +- QNX licensing and authentication requirements live outside Bazel target + analysis and must be configured in the execution environment, +- documentation examples must stay aligned with actual `examples/.bazelrc` + configuration names. + +## Recommended Validation After Changes + +For repository changes that affect toolchain resolution, package metadata, or +template generation, validate with the example workspace: + +```bash +cd examples +./test.sh --list +./test.sh host_config_1 +./test.sh --keep-going +``` + +For documentation-only changes, build or preview the Markdown site to catch +markup and table-of-contents/navigation issues before publishing. \ No newline at end of file diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 0000000..7857e31 --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,67 @@ + + +# Overview + +## Purpose + +The repository separates toolchain *configuration logic* from toolchain +*binary distributions*. + +It exists to answer three practical needs: + +- provide a single Bazel-native way to declare Linux and QNX C/C++ toolchains, +- keep package provenance, compiler flags, and platform constraints consistent, +- validate those toolchains through an example workspace instead of relying on + ad hoc local setup. + +## What The Repository Contains + +The repository does not contain GCC, QCC, or QNX SDK binaries. Instead, it +contains the layers Bazel needs in order to fetch those binaries and expose +them as `cc_toolchain` targets: + +- module extension logic in `extensions/` +- repository rules in `rules/` +- package metadata in `packages/` +- generated-file templates in `templates/` +- authentication helpers in `tools/` +- an example validation workspace in `examples/` + +## Supported Platform Families + +The current repository surface supports these platform families: + +- Linux `x86_64` with packaged GCC toolchains +- Linux `aarch64` with packaged GCC toolchains +- Linux runtime-specific variants such as AutoSD and EB corbos Linux for Safety Applications +- QNX `x86_64` with packaged or locally built SDP-based toolchains +- QNX `aarch64` with packaged or locally built SDP-based toolchains + +## Core Design Model + +The configuration pipeline is intentionally layered: + +1. A consuming project declares toolchains in `MODULE.bazel`. +2. The `gcc` module extension interprets those declarations. +3. Package metadata is resolved from either the default version matrix or a + manually declared package. +4. Repository rules generate a Bazel repository containing the toolchain + definition and platform-specific configuration files. +5. The consuming project activates those toolchains via `--extra_toolchains` + and compatible platform constraints. + +This keeps the consuming workspace small while centralizing platform policy, +default flags, sysroot wiring, and repository authentication behavior. \ No newline at end of file diff --git a/docs/qnx_integration.md b/docs/qnx_integration.md new file mode 100644 index 0000000..12cd058 --- /dev/null +++ b/docs/qnx_integration.md @@ -0,0 +1,52 @@ + + +# QNX Integration + +## Licensing + +QNX toolchains require access to a valid license setup at execution time. The +repository exposes this through toolchain attributes rather than embedding +license material into the package itself. + +Relevant `gcc.toolchain(...)` attributes are: + +- `license_path` +- `license_info_variable` +- `license_info_url` + +The default shared license path is `/opt/score_qnx/license/licenses`. + +## Credential Helper + +Authenticated QNX downloads are handled by the standalone script +`tools/qnx_credential_helper.py`. + +Its purpose is to translate locally available QNX credentials into the cookie +header format expected by `qnx.com` download endpoints. Bazel executes it via +`--credential_helper`; it is not referenced as a Bazel target. + +Supported registration patterns include: + +```text +common --credential_helper=*.qnx.com=/absolute/path/to/qnx_credential_helper.py +common --credential_helper=*.qnx.com=qnx_credential_helper.py +common --credential_helper=*.qnx.com=%workspace%/path/to/qnx_credential_helper.py +``` + +The helper reads credentials in this order: + +- `SCORE_QNX_USER` and `SCORE_QNX_PASSWORD` +- `~/.netrc` entry for `qnx.com` \ No newline at end of file diff --git a/docs/repository_layout.md b/docs/repository_layout.md new file mode 100644 index 0000000..a2818b1 --- /dev/null +++ b/docs/repository_layout.md @@ -0,0 +1,79 @@ + + +# Repository Layout + +## Top-Level Structure + +The repository is organized by subsystem rather than by platform product: + +```text +. +|- docs/ Markdown documentation sources +|- examples/ Example workspace and smoke tests +|- extensions/ Bzlmod extension entry points +|- packages/ Toolchain package descriptors and version matrix +|- rules/ Repository rules and shared helpers +|- templates/ Generated file templates for toolchain repositories +`- tools/ Standalone utility scripts +``` + +## Directory Responsibilities + +`extensions/` + +Hosts the public module extension used by consumers. The main file, +`extensions/gcc.bzl`, defines the tag classes and resolves user declarations +into repository rule invocations. + +`rules/` + +Contains the repository rules that materialize a toolchain repository. +`rules/gcc.bzl` renders BUILD and configuration files from templates. + +`packages/` + +Stores package metadata and BUILD descriptors for supported toolchain +archives. The most important file is `packages/version_matrix.bzl`, which maps +logical toolchain identifiers to URLs, checksums, build files, and any +required extra flags. + +`templates/` + +Holds the template files used by repository rules. These templates are +rendered into the generated toolchain repository and differ between Linux and +QNX because the execution environment, sysroot layout, and licensing model are +different. + +`examples/` + +A standalone Bazel workspace used as an integration surface. It declares +representative toolchain configurations and validates them with a smoke-test +runner. + +`tools/` + +Contains utility scripts that Bazel executes directly, most notably the QNX +credential helper used for authenticated downloads from `qnx.com`. + +## How These Pieces Relate + +Each directory is part of a single flow: + +- `packages/` defines *what* to fetch, +- `templates/` define *what to generate*, +- `rules/` define *how to generate it*, +- `extensions/` define *how consumers ask for it*, +- `examples/` prove that the generated result actually works. \ No newline at end of file