Skip to content

Commit 242a7d3

Browse files
authored
[rules score] Refactor libclang parser and Reuse in unit rule
refactor(cpp/libclang): extract reusable parser action Move the C++ parser action setup into shared Starlark plumbing so it can be reused by both cpp_parser and other Bazel rules. Switch parser outputs from an output directory to explicit class FlatBuffer and optional debug JSON files, and update the Rust CLI and docs to use those paths. test(cpp/libclang): centralize parser integration case wiring Add a shared integration test macro that wires the parser, expected output filegroup, debug JSON provider, and Rust comparison test for each case. Update all parser integration BUILD files to use the macro and make the test framework consume the explicit debug JSON output path. feat(rules_score): generate implementation class FBS in unit rule Wire the libclang C++ parser action into the unit rule for implementation targets that provide parser inputs. Collect generated class diagram FBS files in DefaultInfo, and add the parser toolchain attrs/aspects required by the reused action.
1 parent c310490 commit 242a7d3

43 files changed

Lines changed: 511 additions & 770 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bazel/rules/rules_score/private/unit.bzl

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,32 @@ following S-CORE process guidelines. A unit is the smallest testable
1919
software element with associated design, implementation, and tests.
2020
"""
2121

22+
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
2223
load("@lobster//:lobster.bzl", "subrule_gtest_report")
24+
load("@rules_cc//cc:find_cc_toolchain.bzl", "use_cc_toolchain")
2325
load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
2426
load("@rules_rust//rust:defs.bzl", "rust_common")
2527
load("//bazel/rules/rules_score:providers.bzl", "CcDependencyInfo", "CertifiedScope", "SphinxSourcesInfo", "UnitDesignInfo", "UnitInfo")
28+
load("//cpp/libclang:cpp_parser.bzl", "cpp_parser_action_internal_attrs", "cpp_parser_target_aspects", "has_cpp_parser_inputs", "run_cpp_parser_action")
2629
load(":cc_dependency_aspect.bzl", "cc_dependencies_aspect")
2730

31+
def _run_implementation_cpp_parser(ctx, impl, output_prefix):
32+
return run_cpp_parser_action(
33+
ctx,
34+
target = impl,
35+
output_prefix = output_prefix,
36+
tool = ctx.attr._tool,
37+
libclang = ctx.file._libclang,
38+
llvm_cxx_builtin_include = ctx.attr._llvm_cxx_builtin_include,
39+
llvm_extra_config_site = ctx.attr._llvm_extra_config_site,
40+
log_level = ctx.attr._log_level[BuildSettingInfo].value,
41+
)
42+
43+
def _target_output_prefix(ctx, target):
44+
package_name = target.label.package.replace("/", "_")
45+
target_name = target.label.name.replace("/", "_")
46+
return "{}_{}_{}".format(ctx.label.name, package_name, target_name)
47+
2848
# ============================================================================
2949
# Private Rule Implementation
3050
# ============================================================================
@@ -59,28 +79,41 @@ def _unit_impl(ctx):
5979
design_static_fbs_depset = depset(transitive = design_static_fbs)
6080
design_dynamic_fbs_depset = depset(transitive = design_dynamic_fbs)
6181

82+
# Generate FBS files for implementation targets supported by the libclang parser.
83+
implementation_class_fbs = []
84+
collected_dependent_labels = []
85+
for impl in ctx.attr.implementation:
86+
if CcDependencyInfo in impl:
87+
collected_dependent_labels.append(impl[CcDependencyInfo].dependencies)
88+
89+
if not has_cpp_parser_inputs(impl):
90+
continue
91+
92+
output_prefix = _target_output_prefix(ctx, impl)
93+
parser_outputs = _run_implementation_cpp_parser(ctx, impl, output_prefix)
94+
implementation_class_fbs.append(parser_outputs.class_fbs)
95+
6296
# Run each test executable via subrule_gtest_report and collect the XML outputs
6397
xml_files = []
6498
for test_target in ctx.attr.tests:
65-
pkg = test_target.label.package.replace("/", "_")
66-
test_name = test_target.label.name.replace("/", "_")
67-
unique_name = "{}_{}_{}_gtest_report".format(ctx.label.name, pkg, test_name)
68-
xml = subrule_gtest_report(unique_name, test_target.files_to_run.executable, test_target.default_runfiles.files)
99+
unique_name = "{}_gtest_report".format(
100+
_target_output_prefix(ctx, test_target),
101+
)
102+
xml = subrule_gtest_report(
103+
unique_name,
104+
test_target.files_to_run.executable,
105+
test_target.default_runfiles.files,
106+
)
69107
xml_files.append(xml)
70108

71109
tests_depset = depset(xml_files)
72110

73111
# Combine all files for DefaultInfo
74112
all_files = depset(
75-
xml_files,
113+
xml_files + implementation_class_fbs,
76114
transitive = [design_depset],
77115
)
78116

79-
collected_dependent_labels = []
80-
for impl in ctx.attr.implementation:
81-
if CcDependencyInfo in impl:
82-
collected_dependent_labels.append(impl[CcDependencyInfo].dependencies)
83-
84117
return [
85118
DefaultInfo(files = all_files),
86119
CertifiedScope(transitive_scopes = depset(ctx.attr.scope)),
@@ -104,32 +137,38 @@ def _unit_impl(ctx):
104137
# Rule Definition
105138
# ============================================================================
106139

140+
_unit_attrs = {
141+
"unit_design": attr.label_list(
142+
mandatory = True,
143+
providers = [UnitDesignInfo],
144+
doc = "Unit design artifacts (unit_design targets only)",
145+
),
146+
"implementation": attr.label_list(
147+
mandatory = True,
148+
providers = [[CcInfo], [rust_common.crate_info]],
149+
aspects = [cc_dependencies_aspect] + cpp_parser_target_aspects(),
150+
doc = "Implementation targets (cc_library, cc_binary, rust_library, rust_binary, etc.).",
151+
),
152+
"scope": attr.string_list(
153+
default = [],
154+
doc = "Additional not explicitly named targets which are needed for the unit implementation",
155+
),
156+
"tests": attr.label_list(
157+
mandatory = True,
158+
cfg = "exec",
159+
doc = "Test targets that verify the unit (cc_test, py_test, rust_test, etc.)",
160+
),
161+
}
162+
163+
_unit_attrs.update(cpp_parser_action_internal_attrs())
164+
107165
_unit = rule(
108166
implementation = _unit_impl,
109167
doc = "Defines a software unit with design, implementation, and tests for S-CORE process compliance",
110168
subrules = [subrule_gtest_report],
111-
attrs = {
112-
"unit_design": attr.label_list(
113-
mandatory = True,
114-
providers = [UnitDesignInfo],
115-
doc = "Unit design artifacts (unit_design targets only)",
116-
),
117-
"implementation": attr.label_list(
118-
mandatory = True,
119-
providers = [[CcInfo], [rust_common.crate_info]],
120-
aspects = [cc_dependencies_aspect],
121-
doc = "Implementation targets (cc_library, cc_binary, rust_library, rust_binary, etc.)",
122-
),
123-
"scope": attr.string_list(
124-
default = [],
125-
doc = "Additional not explicitly named targets which are needed for the unit implementation",
126-
),
127-
"tests": attr.label_list(
128-
mandatory = True,
129-
cfg = "exec",
130-
doc = "Test targets that verify the unit (cc_test, py_test, rust_test, etc.)",
131-
),
132-
},
169+
attrs = _unit_attrs,
170+
toolchains = use_cc_toolchain(),
171+
fragments = ["cpp"],
133172
)
134173

135174
# ============================================================================

cpp/libclang/BUILD

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ rust_binary(
3232
data = [
3333
"@llvm_toolchain_llvm//:libclang",
3434
],
35-
env = {
36-
"LIBCLANG_PATH": "$(rootpath @llvm_toolchain_llvm//:libclang)",
37-
},
3835
visibility = ["//visibility:public"],
3936
deps = [
4037
"//cpp/libclang/src/utils",

cpp/libclang/README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ cpp_parser(
2626
extra_args = [
2727
],
2828
target = "//cpp/libclang/integration_test/cases/include_3rdparty",
29-
tool = ":clang_rs_parser",
3029
)
3130
```
3231

@@ -38,9 +37,9 @@ Where:
3837
Expected result:
3938

4039
- Bazel creates parser output artifact:
41-
- `bazel-bin/cpp/libclang/cpp_parser_include_3rdparty_result.fbs.bin`
40+
- `bazel-bin/cpp/libclang/cpp_parser_include_3rdparty_class_diagram.fbs.bin`
4241
- When `emit_debug_json = True`, the parser also writes:
43-
- `bazel-bin/cpp/libclang/cpp_parser_include_3rdparty_result/debug.json`
42+
- `bazel-bin/cpp/libclang/cpp_parser_include_3rdparty_debug.json`
4443

4544
## Configure debug logging
4645

@@ -55,6 +54,6 @@ Accepted values are: `error`, `warn`, `info`, `debug`, `trace`.
5554
## Quick check (optional)
5655

5756
```bash
58-
ls -l bazel-bin/cpp/libclang/cpp_parser_include_3rdparty_result.fbs.bin
59-
ls -l bazel-bin/cpp/libclang/cpp_parser_include_3rdparty_result/debug.json
57+
ls -l bazel-bin/cpp/libclang/integration_test/cases/include_3rdparty/parser_class_diagram.fbs.bin
58+
ls -l bazel-bin/cpp/libclang/integration_test/cases/include_3rdparty/parser_debug.json
6059
```

0 commit comments

Comments
 (0)