diff --git a/.bazelignore b/.bazelignore index 52a7f545..d3dcf303 100644 --- a/.bazelignore +++ b/.bazelignore @@ -13,3 +13,5 @@ python_basics/integration_tests starpls/integration_tests +# Should be run from its own directory (separate Module) +bazel/rules/rules_score/test diff --git a/.bazelrc b/.bazelrc index 9b663e7c..6d10fbb4 100644 --- a/.bazelrc +++ b/.bazelrc @@ -7,6 +7,11 @@ common --registry=https://bcr.bazel.build common --extra_toolchains=@score_gcc_x86_64_toolchain//:x86_64-linux +# libclang toolchain for the C/C++ parser used by the score rules. Registered +# only for score_tooling's own build (its LLVM is a dev dependency); integrating +# repositories register their own libclang toolchain instead. +common --extra_toolchains=//cpp/libclang:score_tooling_libclang_toolchain + build --java_language_version=17 build --tool_java_language_version=17 build --java_runtime_version=remotejdk_17 diff --git a/.bazelversion b/.bazelversion index 56b6be4e..f9c71a52 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -8.3.1 +8.5.1 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 66745e31..51686a5d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,34 +14,36 @@ name: Run Python Basics Integration and Unit Tests on: pull_request: types: [opened, reopened, synchronize] +concurrency: + group: tests-${{ github.event.pull_request.number || github.run_id }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} +env: + ANDROID_HOME: "" + ANDROID_SDK_ROOT: "" + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: - code: - runs-on: ubuntu-latest + root_workspace_tests: + runs-on: ubuntu-24.04 + permissions: + contents: read + actions: write steps: - name: Checkout repository uses: actions/checkout@v7.0.0 - - name: Install Missing Dependencies - run: | - sudo apt-get update - sudo apt-get install -y libcairo2-dev - - name: Run python_basics integration tests - run: | - cd python_basics/integration_tests - bazel test //... - - name: Run starpls integration tests - run: | - cd starpls/integration_tests - bazel test //... - - name: Run cr_checker unit tests - run: | - cd cr_checker/tests - bazel test //... + - name: Free Disk Space (Ubuntu) + uses: eclipse-score/more-disk-space@v1 + with: + level: 4 + - uses: castler/setup-bazel@cache-optimized + with: + bazelisk-cache: true + disk-cache: root_workspace_tests + repository-cache: true + cache-optimized: true + cache-save: ${{ github.ref == 'refs/heads/main' }} - name: Run coverage module tests run: | bazel test //coverage/tests:all - - name: Run rules_score tests - run: | - bazel test //bazel/rules/rules_score/... - name: Run Plantuml Tooling clippy run: | bazel build //plantuml/... --config=clippy @@ -63,3 +65,61 @@ jobs: - name: Run Libclang Parser Tooling tests run: | bazel test //cpp/libclang/... + integration_tests: + runs-on: ubuntu-24.04 + permissions: + contents: read + actions: write + steps: + - name: Checkout repository + uses: actions/checkout@v7.0.0 + - name: Free Disk Space (Ubuntu) + uses: eclipse-score/more-disk-space@v1 + with: + level: 4 + - uses: castler/setup-bazel@cache-optimized + with: + bazelisk-cache: true + disk-cache: integration_tests + repository-cache: true + cache-optimized: true + cache-save: ${{ github.ref == 'refs/heads/main' }} + - name: Run python_basics integration tests + run: | + cd python_basics/integration_tests + bazel test //... + - name: Run starpls integration tests + run: | + cd starpls/integration_tests + bazel test //... + - name: Run cr_checker unit tests + run: | + cd cr_checker/tests + bazel test //... + rules_score_tests: + runs-on: ubuntu-24.04 + permissions: + contents: read + actions: write + steps: + - name: Checkout repository + uses: actions/checkout@v7.0.0 + - name: Free Disk Space (Ubuntu) + uses: eclipse-score/more-disk-space@v1 + with: + level: 4 + - uses: castler/setup-bazel@cache-optimized + with: + bazelisk-cache: true + disk-cache: rules_score_tests + repository-cache: true + cache-optimized: true + cache-save: ${{ github.ref == 'refs/heads/main' }} + - name: Install Missing Dependencies + run: | + sudo apt-get update + sudo apt-get install -y libcairo2-dev + - name: Run rules_score tests + run: | + cd bazel/rules/rules_score/test + bazel test //... diff --git a/bazel/rules/rules_score/private/sphinx_module.bzl b/bazel/rules/rules_score/private/sphinx_module.bzl index 1a2007f4..ac230727 100644 --- a/bazel/rules/rules_score/private/sphinx_module.bzl +++ b/bazel/rules/rules_score/private/sphinx_module.bzl @@ -414,12 +414,6 @@ def sphinx_module( extension will not be available). visibility: Bazel visibility """ - if graphviz == None: - graphviz = select({ - "//bazel/rules/rules_score:linux_x86_64": "@graphviz_deb//:all", - "//conditions:default": None, - }) - _score_needs( name = name + "_needs", srcs = srcs, diff --git a/bazel/rules/rules_score/private/unit.bzl b/bazel/rules/rules_score/private/unit.bzl index e6869f85..5169923b 100644 --- a/bazel/rules/rules_score/private/unit.bzl +++ b/bazel/rules/rules_score/private/unit.bzl @@ -25,7 +25,7 @@ load("@rules_cc//cc:find_cc_toolchain.bzl", "use_cc_toolchain") load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") load("@rules_rust//rust:defs.bzl", "rust_common") load("//bazel/rules/rules_score:providers.bzl", "CcDependencyInfo", "CertifiedScope", "SphinxSourcesInfo", "UnitDesignInfo", "UnitInfo") -load("//cpp/libclang:cpp_parser.bzl", "cpp_parser_action_internal_attrs", "cpp_parser_target_aspects", "has_cpp_parser_inputs", "run_cpp_parser_action") +load("//cpp/libclang:cpp_parser.bzl", "cpp_parser_action_internal_attrs", "cpp_parser_action_toolchains", "cpp_parser_target_aspects", "has_cpp_parser_inputs", "run_cpp_parser_action") load(":cc_dependency_aspect.bzl", "cc_dependencies_aspect") def _run_implementation_cpp_parser(ctx, impl, output_prefix): @@ -34,9 +34,6 @@ def _run_implementation_cpp_parser(ctx, impl, output_prefix): target = impl, output_prefix = output_prefix, tool = ctx.attr._tool, - libclang = ctx.file._libclang, - llvm_cxx_builtin_include = ctx.attr._llvm_cxx_builtin_include, - llvm_extra_config_site = ctx.attr._llvm_extra_config_site, log_level = ctx.attr._log_level[BuildSettingInfo].value, ) @@ -167,7 +164,7 @@ _unit = rule( doc = "Defines a software unit with design, implementation, and tests for S-CORE process compliance", subrules = [subrule_gtest_report], attrs = _unit_attrs, - toolchains = use_cc_toolchain(), + toolchains = cpp_parser_action_toolchains() + use_cc_toolchain(), fragments = ["cpp"], ) diff --git a/bazel/rules/rules_score/private/verbosity.bzl b/bazel/rules/rules_score/private/verbosity.bzl index b5863eda..a8388e74 100644 --- a/bazel/rules/rules_score/private/verbosity.bzl +++ b/bazel/rules/rules_score/private/verbosity.bzl @@ -44,7 +44,7 @@ load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") # Merge into a rule's attrs dict with ``**VERBOSITY_ATTR``. VERBOSITY_ATTR = { "_verbosity": attr.label( - default = Label("//bazel/rules/rules_score:verbosity"), + default = Label("@score_tooling//bazel/rules/rules_score:verbosity"), doc = "Verbosity level build setting (warn/info/debug).", ), } diff --git a/bazel/rules/rules_score/test/.bazelversion b/bazel/rules/rules_score/test/.bazelversion index 56b6be4e..f9c71a52 100644 --- a/bazel/rules/rules_score/test/.bazelversion +++ b/bazel/rules/rules_score/test/.bazelversion @@ -1 +1 @@ -8.3.1 +8.5.1 diff --git a/bazel/rules/rules_score/test/BUILD b/bazel/rules/rules_score/test/BUILD index d4b879cb..2c0b4e11 100644 --- a/bazel/rules/rules_score/test/BUILD +++ b/bazel/rules/rules_score/test/BUILD @@ -1,3 +1,5 @@ +load("@aspect_rules_py//py:defs.bzl", "py_binary") + # ******************************************************************************* # Copyright (c) 2025 Contributors to the Eclipse Foundation # @@ -26,6 +28,8 @@ load( "unit", "unit_design", ) +load("@score_tooling//bazel/rules/rules_score:sphinx_toolchain.bzl", "sphinx_toolchain") +load("@score_tooling//cpp/libclang:libclang_toolchain.bzl", "libclang_toolchain") load("@trlc//:trlc.bzl", "trlc_requirements", "trlc_requirements_test") load( ":html_generation_test.bzl", @@ -93,6 +97,56 @@ load( package(default_visibility = ["//visibility:public"]) +# ============================================================================ +# Sphinx Toolchain — uses score_docs_as_code so score_metamodel is importable +# ============================================================================ + +exports_files(["template/conf.template.py"]) + +py_binary( + name = "score_build", + srcs = ["@score_tooling//bazel/rules/rules_score:src/sphinx_wrapper.py"], + main = "@score_tooling//bazel/rules/rules_score:src/sphinx_wrapper.py", + package_collisions = "warning", + visibility = ["//visibility:public"], + deps = [ + "@score_docs_as_code//src:plantuml_for_python", + "@score_docs_as_code//src/extensions/score_sphinx_bundle", + "@score_tooling//bazel/rules/rules_score:bazel_sphinx_needs", + "@score_tooling//bazel/rules/rules_score:sphinx_module_ext", + ], +) + +sphinx_toolchain( + name = "score_sphinx_toolchain", + conf_template = "//:template/conf.template.py", + html_merge_tool = "@score_tooling//bazel/rules/rules_score:sphinx_html_merge", + sphinx = ":score_build", +) + +toolchain( + name = "score_toolchain", + toolchain = ":score_sphinx_toolchain", + toolchain_type = "@score_tooling//bazel/rules/rules_score:toolchain_type", +) + +# ============================================================================ +# libclang Toolchain — this integrating repo supplies its own libclang/C++ +# toolchain for the score libclang-based C/C++ parser. +# ============================================================================ +libclang_toolchain( + name = "test_libclang", + cxx_builtin_include = "@llvm_toolchain_llvm//:cxx_builtin_include", + extra_config_site = "@llvm_toolchain_llvm//:extra_config_site", + libclang = "@llvm_toolchain_llvm//:lib/libclang.so", +) + +toolchain( + name = "test_libclang_toolchain", + toolchain = ":test_libclang", + toolchain_type = "@score_tooling//cpp/libclang:libclang_toolchain_type", +) + # ============================================================================ # Test Fixtures - Module Definitions # ============================================================================ @@ -126,15 +180,6 @@ sphinx_module( ], ) -# Test 2: Graphviz Rendering -# Tests hermetic graphviz support via sphinx.ext.graphviz directive -sphinx_module( - name = "graphviz_test_lib", - srcs = glob(["fixtures/graphviz_test/*.rst"]), - index = "fixtures/graphviz_test/index.rst", - sphinx = "@score_tooling//bazel/rules/rules_score:score_build", -) - # Test 3: SEooC (Safety Element out of Context) Module # Tests the score_component macro with S-CORE process artifacts @@ -283,7 +328,7 @@ unit_design( unit( name = "test_unit", testonly = True, - scope = ["//bazel/rules/rules_score/test:mock_lib1"], + scope = ["//:mock_lib1"], tests = [":test_unit_tests"], unit_design = [":test_unit_design"], implementation = [ @@ -709,26 +754,11 @@ aous_rst_sphinx_test( requirements_rst_test_suite(name = "requirements_rst_tests") # ============================================================================ -# Image srcs Tests +# Image srcs Tests (defined in sub-package to avoid workspace-root edge case) # ============================================================================ - -# Fixture: feature_requirements with image_srcs -feature_requirements( - name = "feat_req_with_image", - srcs = ["fixtures/seooc_test/feature_requirements.trlc"], - image_srcs = [ - "fixtures/image_srcs/diagrams/arch.svg", - "fixtures/image_srcs/diagrams/arch.png", - ], - deps = [":asr_trlc"], -) - -image_srcs_sphinx_sources_test( - name = "image_srcs_sphinx_sources_test", - target_under_test = ":feat_req_with_image", -) - -requirements_image_test_suite(name = "requirements_image_tests") +# feat_req_with_image and image_srcs_sphinx_sources_test live in +# //fixtures/image_srcs so that ctx.label.package is non-empty and +# subrule_trlc_image_stage can strip the prefix correctly. # ============================================================================ # Combined Test Suite @@ -745,7 +775,7 @@ requirements_image_test_suite(name = "requirements_image_tests") trlc_requirements( name = "safety_measures_fixtures", srcs = ["fixtures/seooc_test/safety_measures_fixtures.trlc"], - spec = ["//bazel/rules/rules_score/trlc/config:score_requirements_model"], + spec = ["@score_tooling//bazel/rules/rules_score/trlc/config:score_requirements_model"], ) trlc_requirements_test( @@ -757,14 +787,14 @@ py_test( name = "test_safety_analysis_tools", size = "small", srcs = ["test_safety_analysis_tools.py"], - deps = ["//bazel/rules/rules_score:safety_analysis_tools"], + deps = ["@score_tooling//bazel/rules/rules_score:safety_analysis_tools"], ) py_test( name = "test_aou_forwarding_to_lobster", size = "small", srcs = ["test_aou_forwarding_to_lobster.py"], - deps = ["//bazel/rules/rules_score:aou_forwarding_to_lobster"], + deps = ["@score_tooling//bazel/rules/rules_score:aou_forwarding_to_lobster"], ) py_test( @@ -772,7 +802,7 @@ py_test( size = "small", srcs = ["rst_to_trlc_test.py"], main = "rst_to_trlc_test.py", - deps = ["//bazel/rules/rules_score:rst_to_trlc_lib"], + deps = ["@score_tooling//bazel/rules/rules_score:rst_to_trlc_lib"], ) py_test( @@ -787,27 +817,18 @@ py_test( deps = ["@trlc//tools/trlc_rst:trlc_rst_lib"], ) -py_test( - name = "test_graphviz_rendering", - size = "small", - srcs = ["graphviz_render_test.py"], - data = [":graphviz_test_lib"], - main = "graphviz_render_test.py", -) - # Combined test suite for all tests test_suite( name = "all_tests", tests = [ - ":requirements_image_tests", ":requirements_rst_tests", ":seooc_tests", ":sphinx_module_tests", ":test_aou_forwarding_to_lobster", - ":test_graphviz_rendering", ":test_rst_to_trlc", ":test_safety_analysis_tools", ":test_trlc_rst_image_rendering", ":unit_component_tests", + "//fixtures/image_srcs:requirements_image_tests", ], ) diff --git a/bazel/rules/rules_score/test/MODULE.bazel b/bazel/rules/rules_score/test/MODULE.bazel index da96457c..81e40c0c 100644 --- a/bazel/rules/rules_score/test/MODULE.bazel +++ b/bazel/rules/rules_score/test/MODULE.bazel @@ -55,6 +55,8 @@ pip.parse( use_repo(pip, "pip_tooling_test") bazel_dep(name = "score_docs_as_code", version = "3.0.1", dev_dependency = True) + +bazel_dep(name = "googletest", version = "1.17.0.bcr.2") # bazel_dep(name = "score_platform", version = "0.5.0") # bazel_dep(name = "score_process", version = "1.3.2") @@ -68,16 +70,40 @@ register_toolchains( "//:score_toolchain", ) +############################################################################### +# LLVM Toolchain (provides libclang for the score libclang toolchain below) +# +# As an integrating repository, this module supplies its own libclang/C++ +# toolchain instead of relying on score_tooling's (score_tooling declares LLVM +# only as a dev dependency and does not register a libclang toolchain for +# consumers). +############################################################################### +bazel_dep(name = "toolchains_llvm", version = "1.6.0") + +llvm = use_extension( + "@toolchains_llvm//toolchain/extensions:llvm.bzl", + "llvm", +) +llvm.toolchain( + cxx_standard = {"": "c++17"}, + llvm_version = "19.1.7", +) +use_repo(llvm, "llvm_toolchain", "llvm_toolchain_llvm") + +register_toolchains( + "//:test_libclang_toolchain", +) + bazel_dep(name = "trlc", version = "0.0.0") git_override( module_name = "trlc", - commit = "7f06d0396fd0e5f02b657d25700775af5113b7e0", + commit = "c4c531b9d667085daa09dfc1590edacc314bfda4", remote = "https://github.com/bmw-software-engineering/trlc.git", ) bazel_dep(name = "lobster", version = "0.0.0") git_override( module_name = "lobster", - commit = "56881461f9d3fde2918d1731aa5937aaf64cd67c", + commit = "2792e2daee2cf524fdc7b1545fd3537791ebc36c", remote = "https://github.com/bmw-software-engineering/lobster.git", ) diff --git a/bazel/rules/rules_score/test/fixtures/graphviz_test/index.rst b/bazel/rules/rules_score/test/fixtures/graphviz_test/index.rst deleted file mode 100644 index cb44cddb..00000000 --- a/bazel/rules/rules_score/test/fixtures/graphviz_test/index.rst +++ /dev/null @@ -1,35 +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 - # ******************************************************************************* - -Graphviz Rendering Test -======================= - -This document tests the ``sphinx.ext.graphviz`` directive to ensure hermetic graphviz -integration is working correctly. - -Simple DAG ----------- - -.. graphviz:: - :align: center - - digraph { - A -> B; - A -> C; - B -> D; - C -> D; - label = "Simple DAG"; - } - -This graphviz diagram should render as SVG in the produced HTML output. diff --git a/bazel/rules/rules_score/test/fixtures/image_srcs/BUILD b/bazel/rules/rules_score/test/fixtures/image_srcs/BUILD new file mode 100644 index 00000000..d3f9120f --- /dev/null +++ b/bazel/rules/rules_score/test/fixtures/image_srcs/BUILD @@ -0,0 +1,47 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + +# This sub-package exists so that ctx.label.package == "fixtures/image_srcs" +# when feature_requirements stages image files. subrule_trlc_image_stage +# strips package_prefix from short_path to produce package-relative paths +# (e.g. "diagrams/arch.png"); this only works when the package is not the +# workspace root (""). + +load( + "@score_tooling//bazel/rules/rules_score:rules_score.bzl", + "feature_requirements", +) +load( + "//:requirements_image_test.bzl", + "image_srcs_sphinx_sources_test", + "requirements_image_test_suite", +) + +package(default_visibility = ["//visibility:public"]) + +feature_requirements( + name = "feat_req_with_image", + srcs = ["//:fixtures/seooc_test/feature_requirements.trlc"], + image_srcs = [ + "diagrams/arch.svg", + "diagrams/arch.png", + ], + deps = ["//:asr_trlc"], +) + +image_srcs_sphinx_sources_test( + name = "image_srcs_sphinx_sources_test", + target_under_test = ":feat_req_with_image", +) + +requirements_image_test_suite(name = "requirements_image_tests") diff --git a/bazel/rules/rules_score/test/graphviz_render_test.py b/bazel/rules/rules_score/test/graphviz_render_test.py deleted file mode 100644 index 8a92641c..00000000 --- a/bazel/rules/rules_score/test/graphviz_render_test.py +++ /dev/null @@ -1,82 +0,0 @@ -# ******************************************************************************* -# Copyright (c) 2025 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 -# ******************************************************************************* -"""Integration test for hermetic graphviz rendering in sphinx_module. - -Verifies that the sphinx.ext.graphviz extension successfully renders diagrams -to SVG when using hermetic graphviz bundled via download_deb. -""" - -import os -import unittest - - -def _runfile(*parts: str) -> str: - """Locate a file in the Bazel runfiles tree.""" - srcdir = os.environ["TEST_SRCDIR"] - workspace = os.environ.get("TEST_WORKSPACE", "_main") - for candidate in [ - os.path.join(srcdir, workspace, *parts), - os.path.join(srcdir, *parts), - ]: - if os.path.exists(candidate): - return candidate - raise FileNotFoundError( - f"Runfile not found: {os.path.join(*parts)}\n" - f" Searched under TEST_SRCDIR={srcdir}" - ) - - -def _find_generated_html_root() -> str: - """Locate the generated HTML directory for graphviz_test_lib in runfiles. - - Depending on Bazel/runfiles layout, the directory artifact may appear either - at ``.../graphviz_test_lib/html`` or at ``.../graphviz_test_lib``. - """ - for parts in [ - ("bazel/rules/rules_score/test/graphviz_test_lib/html",), - ("bazel/rules/rules_score/test/graphviz_test_lib",), - ]: - try: - root = _runfile(*parts) - except FileNotFoundError: - continue - if os.path.exists(os.path.join(root, "index.html")): - return root - - raise FileNotFoundError( - "Unable to locate generated graphviz_test_lib HTML output in runfiles" - ) - - -class TestGraphvizRendering(unittest.TestCase): - """Verify that sphinx.ext.graphviz renders an SVG artifact.""" - - def test_graphviz_renders_svg(self): - """Test that graphviz output is rendered as SVG in generated HTML.""" - html_dir = _find_generated_html_root() - - svg_files = [ - file_name - for _, _, files in os.walk(html_dir) - for file_name in files - if file_name.endswith(".svg") - ] - - self.assertTrue( - svg_files, - "Generated HTML output should include at least one rendered graphviz SVG artifact", - ) - - -if __name__ == "__main__": - unittest.main() diff --git a/bazel/rules/rules_score/test/trlc_rst_image_rendering_test.py b/bazel/rules/rules_score/test/trlc_rst_image_rendering_test.py index 2f9d81bf..ee755455 100644 --- a/bazel/rules/rules_score/test/trlc_rst_image_rendering_test.py +++ b/bazel/rules/rules_score/test/trlc_rst_image_rendering_test.py @@ -48,19 +48,11 @@ def setUp(self): self._tmpdir = tempfile.mkdtemp() self._out = os.path.join(self._tmpdir, "output.rst") self._fixture_trlc = _runfile( - "bazel", - "rules", - "rules_score", - "test", "fixtures", "image_requirements", "image_requirements.trlc", ) self._fixture_rsl = _runfile( - "bazel", - "rules", - "rules_score", - "test", "fixtures", "image_requirements", "schema.rsl", diff --git a/cpp/libclang/BUILD b/cpp/libclang/BUILD index 63d6a81b..fa3f8ef9 100644 --- a/cpp/libclang/BUILD +++ b/cpp/libclang/BUILD @@ -12,6 +12,7 @@ # ******************************************************************************* load("@bazel_skylib//rules:common_settings.bzl", "string_flag") load("@rules_rust//rust:defs.bzl", "rust_binary") +load(":libclang_toolchain.bzl", "libclang_toolchain") string_flag( name = "log_level", @@ -26,12 +27,37 @@ string_flag( visibility = ["//visibility:public"], ) +# Toolchain type that supplies libclang + the C++ include paths to the parser. +# score_tooling does not register a libclang toolchain for consumers; each +# integrating repository registers its own so it controls which libclang and +# C++ standard library the parser resolves against. +toolchain_type( + name = "libclang_toolchain_type", + visibility = ["//visibility:public"], +) + +# Default libclang toolchain used by score_tooling's own build. It wraps the +# LLVM installation that score_tooling declares as a dev dependency and is +# registered via score_tooling's .bazelrc (--extra_toolchains), so it is NOT +# inherited by repositories that depend on score_tooling. +libclang_toolchain( + name = "score_tooling_libclang", + cxx_builtin_include = "@llvm_toolchain_llvm//:cxx_builtin_include", + extra_config_site = "@llvm_toolchain_llvm//:extra_config_site", + libclang = "@llvm_toolchain_llvm//:lib/libclang.so", + visibility = ["//visibility:public"], +) + +toolchain( + name = "score_tooling_libclang_toolchain", + toolchain = ":score_tooling_libclang", + toolchain_type = ":libclang_toolchain_type", + visibility = ["//visibility:public"], +) + rust_binary( name = "clang_rs_parser", srcs = ["src/main.rs"], - data = [ - "@llvm_toolchain_llvm//:libclang", - ], visibility = ["//visibility:public"], deps = [ "//cpp/libclang/src/utils", diff --git a/cpp/libclang/cpp_parser.bzl b/cpp/libclang/cpp_parser.bzl index cbeab836..4e84ed95 100644 --- a/cpp/libclang/cpp_parser.bzl +++ b/cpp/libclang/cpp_parser.bzl @@ -14,6 +14,7 @@ load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain", "use_cc_toolchain") load("@rules_cc//cc/common:cc_common.bzl", "cc_common") load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") +load(":libclang_toolchain.bzl", "LIBCLANG_TOOLCHAIN_TYPE") # Providers and aspects used to adapt C/C++ targets for the parser action. @@ -145,26 +146,21 @@ def cpp_parser_action_internal_attrs(): cfg = "exec", doc = "Internal libclang-based parser backend.", ), - "_libclang": attr.label( - allow_single_file = True, - default = "@llvm_toolchain_llvm//:lib/libclang.so", - ), - "_llvm_cxx_builtin_include": attr.label( - default = "@llvm_toolchain_llvm//:cxx_builtin_include", - doc = "LLVM toolchain filegroup containing the libc++ header directory (include/c++) " + - "and the clang resource include directory (lib/clang//include).", - ), - "_llvm_extra_config_site": attr.label( - default = "@llvm_toolchain_llvm//:extra_config_site", - doc = "LLVM toolchain filegroup containing the arch-specific __config_site file " + - "(include//c++/v1/__config_site) used to locate the ABI include path.", - ), "_log_level": attr.label( default = Label("//cpp/libclang:log_level"), doc = "Build setting that controls clang_rs_parser log level.", ), } +def cpp_parser_action_toolchains(): + """Return toolchain types required by run_cpp_parser_action callers. + + Rules that call run_cpp_parser_action must declare these toolchains so the + integrating repository's libclang toolchain is resolved for the action. + """ + + return [LIBCLANG_TOOLCHAIN_TYPE] + # Parser action implementation. def _detect_standard_from_flags(ctx): @@ -260,9 +256,6 @@ def run_cpp_parser_action( target, output_prefix, tool, - libclang, - llvm_cxx_builtin_include, - llvm_extra_config_site, log_level, extra_args = [], emit_debug_json = False): @@ -270,9 +263,13 @@ def run_cpp_parser_action( The target must be analyzed with cpp_parser_target_aspects() before this helper is called. Use has_cpp_parser_inputs() when the caller accepts mixed - implementation target types. + implementation target types. The calling rule must declare the toolchains + returned by cpp_parser_action_toolchains(). """ + libclang_info = ctx.toolchains[LIBCLANG_TOOLCHAIN_TYPE].libclang_info + libclang = libclang_info.libclang + class_fbs_output = ctx.actions.declare_file( "{}_{}".format(output_prefix, "class_diagram.fbs.bin"), ) @@ -299,8 +296,8 @@ def run_cpp_parser_action( target_compilation_flags_list = target[CompilationFlagsInfo].flags.to_list() - cxx_builtin_include_files = llvm_cxx_builtin_include.files.to_list() - extra_config_site_files = llvm_extra_config_site.files.to_list() + cxx_builtin_include_files = libclang_info.cxx_builtin_include.to_list() + extra_config_site_files = libclang_info.extra_config_site.to_list() llvm_include_args = _collect_required_llvm_include_args(cxx_builtin_include_files, extra_config_site_files) parser_extra_args = [ @@ -360,9 +357,6 @@ def _cpp_parser_impl(ctx): target = ctx.attr.target, output_prefix = ctx.label.name, tool = ctx.attr._tool, - libclang = ctx.file._libclang, - llvm_cxx_builtin_include = ctx.attr._llvm_cxx_builtin_include, - llvm_extra_config_site = ctx.attr._llvm_extra_config_site, log_level = ctx.attr._log_level[BuildSettingInfo].value, extra_args = ctx.attr.extra_args, emit_debug_json = ctx.attr.emit_debug_json, @@ -403,6 +397,6 @@ _cpp_parser_attrs.update(cpp_parser_action_internal_attrs()) cpp_parser = rule( implementation = _cpp_parser_impl, attrs = _cpp_parser_attrs, - toolchains = use_cc_toolchain(), + toolchains = cpp_parser_action_toolchains() + use_cc_toolchain(), fragments = ["cpp"], ) diff --git a/cpp/libclang/libclang_toolchain.bzl b/cpp/libclang/libclang_toolchain.bzl new file mode 100644 index 00000000..b7de1528 --- /dev/null +++ b/cpp/libclang/libclang_toolchain.bzl @@ -0,0 +1,70 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + +"""Toolchain definition that supplies libclang and the C++ include paths. + +score_tooling does not hard-code a specific LLVM installation for the libclang +based C++ parser. Instead, each integrating repository registers its own +`libclang_toolchain`, so it can decide which libclang/C++ standard library the +parser resolves against. +""" + +LIBCLANG_TOOLCHAIN_TYPE = "//cpp/libclang:libclang_toolchain_type" + +LibclangToolchainInfo = provider( + doc = "libclang shared library and C++ include directories for the parser.", + fields = { + "libclang": "libclang shared library File loaded by the parser at runtime.", + "cxx_builtin_include": "depset of files exposing the libc++ header directory " + + "(include/c++) and the clang resource include directory " + + "(lib/clang//include).", + "extra_config_site": "depset of files exposing the arch-specific __config_site " + + "(include//c++/v1/__config_site) used to locate the " + + "ABI include path.", + }, +) + +def _libclang_toolchain_impl(ctx): + return [ + platform_common.ToolchainInfo( + libclang_info = LibclangToolchainInfo( + libclang = ctx.file.libclang, + cxx_builtin_include = depset(ctx.files.cxx_builtin_include), + extra_config_site = depset(ctx.files.extra_config_site), + ), + ), + ] + +libclang_toolchain = rule( + implementation = _libclang_toolchain_impl, + doc = "Provides libclang and the C++ include directories required by the parser.", + attrs = { + "libclang": attr.label( + allow_single_file = True, + mandatory = True, + doc = "libclang shared library (e.g. lib/libclang.so).", + ), + "cxx_builtin_include": attr.label( + allow_files = True, + mandatory = True, + doc = "Filegroup with the libc++ header directory (include/c++) and the " + + "clang resource include directory (lib/clang//include).", + ), + "extra_config_site": attr.label( + allow_files = True, + mandatory = True, + doc = "Filegroup with the arch-specific __config_site file " + + "(include//c++/v1/__config_site).", + ), + }, +) diff --git a/python_basics/.bazelversion b/python_basics/.bazelversion index 2bf50aaf..f9c71a52 100644 --- a/python_basics/.bazelversion +++ b/python_basics/.bazelversion @@ -1 +1 @@ -8.3.0 +8.5.1