How to Integrate a New Module into the Reference Integration#

This guide explains how to add a new S-CORE module to the reference_integration repository, using scrample as a concrete example. Scrample is a minimal “Hello World” logging application with both a C++ and a Rust implementation, demonstrating mw::log integration across both languages.

Background: Why known_good.json?#

Each S-CORE module lives in its own Git repository and evolves independently. The reference integration continuously validates that a specific combination of module versions builds and tests successfully together – the so-called known-good state.

Keeping this state in a dedicated JSON file instead of directly in Bazel’s MODULE.bazel serves several purposes:

  • Single source of truth. All version pins, repository URLs, and integration metadata (test exclusions, language info, Bazel patches) are in one place and machine-readable. Tooling such as CI pipelines, workspace generators, and the Bazel module generator all consume the same data.

  • Separation of concerns. known_good.json is the what (which commit of which module), while the generated .MODULE.bazel file is the how (the Bazel-specific syntax). Keeping them separate avoids manual errors in Bazel syntax and keeps the intent readable without Bazel knowledge.

  • Tooling support. Because the version data is structured JSON, it can be consumed by additional scripts:

    • scripts/known_good/override_known_good_repo.py – pins individual modules to a different commit (e.g. for testing a PR) without touching the canonical file.

    • scripts/known_good/known_good_to_workspace_metadata.py – generates the workspace manager file (.gita-workspace.csv) used to clone all module repositories locally.

    • scripts/known_good/update_module_from_known_good.py – regenerates the Bazel MODULE.bazel files.

  • Reproducibility. Every entry is pinned to a full SHA-1 commit hash, making the integrated state fully reproducible regardless of branch tip movements.

Overview#

There are two files that together define which modules are integrated:

  • ``known_good.json`` – the single source of truth for all module versions (Git hashes, repository URLs, and metadata such as test configuration). This file is edited manually.

  • ``bazel_common/score_modules_<category>.MODULE.bazel`` – generated from known_good.json by a script. Do not edit this file manually.

The general workflow is:

  1. Add the new module entry to known_good.json.

  2. Run the generation script to update the .MODULE.bazel file.

  3. Optionally add a standalone showcase so the module appears in the S-CORE CLI.

Step 1 – Add the module to known_good.json#

Open known_good.json and add your module under the appropriate category. There are currently two categories:

  • target_sw – modules that are part of the target software stack (deployed on the target platform, e.g. C++ / Rust runtime components).

  • tooling – build and development tooling modules.

Scrample is a target_sw module, so its entry goes under that key. The hash is the full SHA-1 commit of the version to integrate – in this case the head commit of PR #31:

"score_scrample": {
    "repo": "https://github.com/eclipse-score/scrample.git",
    "hash": "32abf22969081a7c4a97733cf6d1b88b9e0c9d55",
    "metadata": {
        "code_root_path": "//src_rust/...",
        "langs": ["cpp", "rust"]
    }
}

Note

code_root_path points to the Bazel target pattern used for test discovery. For scrample the Rust sources live under src_rust/, so that is specified explicitly instead of the default //score/....

Metadata fields explained#

Field

Required

Description

repo

yes

HTTPS URL to the Git repository (ending in .git).

hash

yes

Full SHA-1 commit hash of the version to integrate.

bazel_patches

no

List of Bazel label paths to .patch files that are applied to the module source before building (patch_strip = 1).

metadata.code_root_path

no

Bazel target pattern for the module’s source root. Defaults to //score/....

metadata.langs

no

Languages present in the module: "cpp", "rust", or both. Defaults to ["cpp", "rust"].

metadata.extra_test_config

no

Additional flag values passed to test runs.

metadata.exclude_test_targets

no

Bazel target patterns excluded from CI test runs (e.g. known-failing or platform-specific tests).

metadata.rust_coverage_config

no

Rust coverage profile name. Defaults to "ferrocene-coverage". Set to null to disable Rust coverage for this module.

Step 2 – Regenerate the .MODULE.bazel file#

After editing known_good.json, run the generation script:

python3 scripts/known_good/update_module_from_known_good.py --override-type git

This regenerates bazel_common/score_modules_target_sw.MODULE.bazel with the correct bazel_dep and git_override blocks for every module listed in known_good.json. For scrample the result looks like:

bazel_dep(name = "score_scrample")
git_override(
    module_name = "score_scrample",
    commit = "32abf22969081a7c4a97733cf6d1b88b9e0c9d55",
    remote = "https://github.com/eclipse-score/scrample.git",
)

Alternatively, use the VS Code task:

  • Terminal -> Run Task… -> “Switch Bazel modules to git_overrides”

Note

For local cross-module development, use --override-type local_path so Bazel picks up a local checkout instead of downloading from Git. See the repository README for the full workspace setup procedure.

Step 3 – Add a standalone showcase (optional)#

If the module provides runnable example binaries, expose them to the S-CORE CLI by adding files under showcases/standalone/.

``showcases/standalone/scrample.score.json`` – describes the examples shown in the interactive CLI menu. Scrample ships both a C++ and a Rust binary, so both are listed as separate entries:

[
    {
        "name": "Scrample C++ Hello World",
        "description": "Hello World logging example using score::mw::log in C++",
        "apps": [
            {
                "path": "/showcases/bin/scrample_cpp",
                "args": [],
                "env": {}
            }
        ]
    },
    {
        "name": "Scrample Rust Hello World",
        "description": "Hello World logging example using score_log in Rust",
        "apps": [
            {
                "path": "/showcases/bin/scrample_rust",
                "args": [],
                "env": {}
            }
        ]
    }
]

``showcases/standalone/BUILD`` – add a score_pkg_bundle entry that bundles both binaries and the JSON config file:

score_pkg_bundle(
    name = "scrample",
    bins = [
        "@score_scrample//src_cpp:scrample_cpp",
        "@score_scrample//src_rust:scrample_rust",
    ],
    config_data = ["//showcases/standalone:scrample.score.json"],
    package_dir = "standalone",
)

``showcases/BUILD`` – reference the new _pkg_files target in the top-level showcases bundle so it ends up in every image:

score_pkg_bundle(
    name = "showcases",
    bins = ["//showcases/cli"],
    other_package_files = [
        "//showcases/standalone:comm_pkg_files",
        "//showcases/standalone:kyron_pkg_files",
        "//showcases/standalone:scrample_pkg_files",   # added
        "//showcases/orchestration_persistency:orch_per_pkg_files",
        "//showcases/simple_lifecycle:simple_lifecycle_pkg_files",
    ],
    package_dir = "showcases",
)

The CLI auto-detects all *.score.json files at runtime, so no further registration is needed.

Step 4 – Verify the integration#

Run a Bazel build for the new module to confirm the integration is working:

bazel build @score_scrample//src_cpp:scrample_cpp @score_scrample//src_rust:scrample_rust

Optional – Add Bazel patches#

If the module’s upstream BUILD files need adjustments (e.g. to expose internal targets for integration testing), add patch files under patches/<module_name>/ and reference them in the bazel_patches list in known_good.json.

Patches must be in unified diff format and are applied with patch -p1:

git diff HEAD > patches/scrample/001-fix-visibility.patch

Add a BUILD file in patches/scrample/ that exports the patch files:

# patches/scrample/BUILD
exports_files(glob(["*.patch"]))

Then reference them in known_good.json:

"score_scrample": {
    "repo": "https://github.com/eclipse-score/scrample.git",
    "hash": "32abf22969081a7c4a97733cf6d1b88b9e0c9d55",
    "bazel_patches": [
        "//patches/scrample:001-fix-visibility.patch"
    ],
    "metadata": {
        "code_root_path": "//src_rust/...",
        "langs": ["cpp", "rust"]
    }
}

Testing the integration end-to-end with score_starter#

Once the module is integrated and the showcase configured, the full end-to-end test is done via the interactive launcher score_starter included in the repository root.

  1. Start the launcher from the repository root:

    ./score_starter
    

    A text menu appears listing all available image targets:

    Use up/down arrows to navigate, Enter to run, q to quit
    
      Run QNX x86_64 QEMU
    > Run Linux x86_64 Docker
      Run Elektrobit corbos Linux for Safety Applications aarch64 QEMU
      Run Autosd x86_64 QEMU
      Exit
    
  2. Select the target image with the arrow keys and press Enter. For a quick local check, choose “Run Linux x86_64 Docker”. Bazel will build the full image (first run may take several minutes) and launch a Docker container with the S-CORE CLI.

    Note

    The Linux image requires Docker to be running on the host. For QNX or AutoSD, additional toolchain licenses and QEMU networking setup are required – see the respective README files under images/ and runners/.

  3. The S-CORE CLI starts automatically inside the container. It scans all *.score.json files and presents a multi-select menu of all available examples. Both scrample entries appear automatically:

    Select examples to run:
      [ ] Communication Sender Receiver Example
      [ ] Kyron basic example
      [ ] Kyron select example
      [ ] Kyron safety task example
      [ ] Scrample C++ Hello World      <- scrample entries
      [ ] Scrample Rust Hello World     <- scrample entries
      [ ] ...
    
  4. Select the example with Space, confirm with Enter. The CLI launches the selected binary and streams its output to the terminal. For scrample the expected output is:

    2026/05/22 12:00:00.0000000 00000000 000 ECU1 SCRM scra log info verbose 1 Hello from SCRAMPLE!