First Eclipse S-CORE Module#

Before starting, ensure you are an official contributor to the Eclipse S-CORE project. Otherwise, you will not have the required permissions. Instructions can be found in Actions to ensure Proper Contribution Attribution in Eclipse S-CORE.

Once you have created an Eclipse account, accepted the Eclipse Contributor Agreement (ECA), and linked your GitHub account with your Eclipse account, contact one of the Eclipse S-CORE Project Leads (listed at the official Eclipse SDV S-CORE webpage). They will add you to the list of the official contributors of the Eclipse S-CORE GitHub organization.

The recommended communication channel to approach Eclipse S-CORE project leads is the project lead circle Slack channel in the Eclipse SDV Slack workspace.

Note

You do not need an own repository to follow this guide: the running example, the platform info service and its consumer, lives in the reference integration. The following sections describe what you need when you contribute your own module.

Creating a Repository for Your Module#

After becoming part of the Eclipse S-CORE GitHub organization, you can request a repository for your module. Repository creation follows Eclipse organizational rules. Most configuration is handled via otterdog configuration located in:

Create a fork of this repository and modify the file:

Add your repository definition next to the existing ones. Module repositories are declared with newDependableElementRepo: it creates the repository from the module template, enables GitHub Pages for the documentation and sets up the GitHub environment for the QNX builds. Incubation repositories additionally set subcategory = "incubation":

newDependableElementRepo('lifecycle') {
  description: "Repository for the lifecycle feature",
},

newDependableElementRepo('my_module') {
  description: "Repository for my module",
},

newDependableElementRepo('inc_someip_gateway', subcategory = "incubation") {
  description: "Incubation repository for SOME/IP gateway feature",
},

Then, create a PR in the eclipse-score/.eclipsefdn repository. The PR must be approved by:

  • Eclipse S-CORE project lead

  • Eclipse Foundation Security Team, which is the code owner of the otterdog configuration

Tip

To speed up approval, mention both groups in your PR comment:

@eclipse-score/automotive-score-project-leads
@eclipse-score/eclipsefdn-security

Please approve.

Repository Layout#

Once merged, your new repository will appear in the Eclipse S-CORE GitHub organization repositories overview.

New repositories are based on the Eclipse S-CORE module template. Its README.md explains how to build and test the template; the expected folder structure is described in module folder structure. Below is an overview of the most relevant files and folders.

File / folder

Content

.github/workflows/

CI/CD workflows, based on the reusable workflows of cicd-workflows

.devcontainer/

Development container based on the common S-CORE devcontainer image

.vscode/

Recommended VS Code settings, extensions and snippets

docs/

Module documentation (rst), e.g. module, feature and component documents, release notes and verification report

score/

Source code, unit tests and component integration tests, e.g. score/component_example

examples/

Examples and their documentation

.bazelrc, score.bazelrc/

Bazel configuration incl. the S-CORE build configurations per target platform

MODULE.bazel, BUILD

Bazel module definition and top-level targets

project_config.bzl

Project metadata used by shared Bazel macros

LICENSE, NOTICE, REUSE.toml, LICENSES/

License and copyright information

.github/workflows/#

Contains the CI/CD workflows, e.g. pre-commit checks, license check and documentation build. They are described in the CI/CD workflows chapter.

.devcontainer and .vscode#

.devcontainer/ references the common S-CORE devcontainer image, which contains all required tools pre-installed. Open the repository with the VS Code Dev Containers extension and select Reopen in Container to skip manual toolchain setup entirely.

.vscode/ provides the Eclipse S-CORE recommended VS Code setup, including code completion patterns for requirements and architecture in .vscode/restructuredtext.code-snippets.

docs#

Place all module documentation here in rst format. The documentation generation chapter shows how it is built.

Tip

We try to describe the most common workflows for developers. It is worth checking them.

score/#

Source files, unit tests and component integration tests of the module, one folder per component, e.g. score/<component_name>/. Feature integration tests of the module are placed in score/tests/. The folder determines the test level, see module folder structure.

.bazelrc#

Defines the Bazel configuration of the module. Important entries in the .bazelrc file include:

1common --registry=https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/
2common --registry=https://bcr.bazel.build
3
4# Import toolchain bazelrc file
5try-import %workspace%/score.bazelrc/score_toolchain.bazelrc
  • Line 1 points to the Eclipse S-CORE Bazel registry, where all official versions of Eclipse S-CORE modules are published.

  • Line 2 points to the Bazel Central Registry, where common Bazel modules are made available for everyone.

  • Line 5 imports the S-CORE build configurations, e.g. --config=score-linux-x86_64 or --config=score-qnx-x86_64. They select the target platform and the matching toolchains and are explained in the building source code chapter.

This means, once we reference a dependency in our module, Bazel will search for it in one of these two registries.

MODULE.bazel#

This file turns your repository into a Bazel module. The template starts with a minimal module declaration:

1module(name = "score_module_template")

Rename the module and replace score_module_template by your module name. According to Eclipse S-CORE’s naming convention, all module names must start with the score_ prefix, e.g. score_my_module. The version is not maintained in MODULE.bazel: it is taken from the release tag (vX.Y.Z, following semantic versioning) when the release is added to the Bazel registry. Other modules can depend on a released version of your module with bazel_dep only after it was published in the Eclipse S-CORE Bazel registry; before that, they need a git_override.

Next, the template declares dependencies to modules that are publicly available in the Bazel Central Registry, e.g. for unit test execution with GoogleTest:

1# Add GoogleTest dependency
2bazel_dep(name = "googletest", version = "1.17.0.bcr.2", dev_dependency = True)
3
4# Rust rules for Bazel
5bazel_dep(name = "rules_rust", version = "0.70.0")
6
7# C/C++ rules for Bazel
8bazel_dep(name = "rules_cc", version = "0.2.18")

Then follow the dependencies to Eclipse S-CORE modules that are used during development (excerpt):

 1# tooling
 2bazel_dep(name = "score_tooling", version = "1.3.1", dev_dependency = True)
 3
 4# docs-as-code
 5bazel_dep(name = "score_docs_as_code", version = "8.7.0")
 6bazel_dep(name = "score_process_description", version = "2.2.1")
 7
 8# Provide the tools from the devcontainer to Bazel
 9bazel_dep(name = "score_devcontainer", version = "1.12.0", dev_dependency = True)
10bazel_dep(name = "score_cpp_policies", version = "0.1.2", dev_dependency = True)
  • score_tooling: enables tooling checks such as copyright, formatting and license verification.

  • score_docs_as_code and score_process_description: enable documentation builds with Sphinx and sphinx-needs and the references to the process description.

  • score_devcontainer: makes the tools of the devcontainer available to Bazel.

  • score_cpp_policies: provides the shared C++ quality rules, e.g. compiler warnings, sanitizers and clang-tidy. For Rust code, score_rust_policies provides the shared Clippy configuration.

The last part of the template, marked S-CORE Toolchains (DO NOT MODIFY), registers the S-CORE toolchains from score_bazel_cpp_toolchains and score_toolchains_rust for all supported target platforms. It is explained in the building source code chapter.

Finally, add the S-CORE modules your code uses. The platform info example uses mw::com from score_communication, the CRC32 calculation and argument handling from score_baselibs and mw::log from score_logging:

1bazel_dep(name = "score_communication", version = "0.6.0")
2bazel_dep(name = "score_baselibs", version = "0.2.17")
3bazel_dep(name = "score_logging", version = "0.2.6")

The available versions can be looked up in the Bazel registry UI. Choose versions that fit to each other and to the toolchains of your module: the versions above work with score_bazel_cpp_toolchains 1.0.5, which the template uses at the time of writing. Check the MODULE.bazel of a module version in the registry to see which versions it depends on. If Bazel reports “the root module requires module version X, but got Y in the resolved dependency graph”, another module needs a newer version of this dependency; update the version in your MODULE.bazel accordingly. Bazel modules don’t make transitive dependencies available to your code: list every module whose targets you use directly in your BUILD files.

Tip

Working across multiple modules and repositories can be challenging. Use the following approach during development:

  • use git_override() if you want to use a version of another module that is currently not officially available in the Bazel registry.

  • use local_path_override() if you want to use your local version of the module, e.g. during active development.

  • use the command line option --override_module=<module>=<path> (e.g. with bazel build) to try out a local checkout without changing MODULE.bazel.

BUILD#

The Bazel BUILD file contains the main Bazel targets on the top level of the module:

1load("@score_docs_as_code//:docs.bzl", "docs")
2load("@score_tooling//:defs.bzl", "copyright_checker", "dash_license_checker", "setup_starpls", "use_format_targets")
3load("//:project_config.bzl", "PROJECT_CONFIG")

First, we load Bazel rules and macros implemented in the Eclipse S-CORE context from the modules that we’ve defined as dependencies in the MODULE.bazel file, e.g. eclipse-score/docs-as-code.

 1copyright_checker(
 2    name = "copyright",
 3    srcs = [
 4        "score",
 5        "//:BUILD",
 6        "//:MODULE.bazel",
 7    ],
 8    config = "@score_tooling//cr_checker/resources:config",
 9    template = "@score_tooling//cr_checker/resources:templates",
10    visibility = ["//visibility:public"],
11)
12
13dash_license_checker(
14    src = "//examples:cargo_lock",
15    file_type = "",  # let it auto-detect based on project_config
16    project_config = PROJECT_CONFIG,
17    visibility = ["//visibility:public"],
18)
19
20# Add target for formatting checks
21use_format_targets()

Second, we define the targets for the copyright check (bazel run //:copyright.check), the license check with the Eclipse Dash license tool and the formatting check (bazel test //:format.check), based on Bazel rules implemented in the eclipse-score/tooling module.

1docs(
2    project = "Module Template Project",
3    project_url = "https://eclipse-score.github.io/module_template/",
4    source_dir = "docs",
5)

Finally, the docs macro creates all documentation targets for the rst files located in the docs folder and all its subfolders. This functionality is implemented in eclipse-score/docs-as-code and described in the documentation generation chapter.

project_config.bzl#

Every Eclipse S-CORE module provides a project_config.bzl file in its root directory. This file declares project-level metadata that is consumed by shared Bazel macros such as dash_license_checker.

A minimal example:

1PROJECT_CONFIG = {
2    "asil_level": "QM",        # Safety level: "QM", "ASIL-A", "ASIL-B", "ASIL-C", "ASIL-D"
3    "source_code": ["cpp"],    # Languages used: "cpp", "rust", or both
4}

The asil_level documents the safety level of the module. The source_code list is evaluated by dash_license_checker: if no file_type is given, it determines which dependency file is scanned (e.g., Cargo.lock for Rust, requirements.txt for Python).

Tip

Start with "asil_level": "QM" during initial development. The level can be raised once the module’s safety concept is established.