@@ -41,7 +41,6 @@ This is a **build-only** rule. The combined traceability *test* is owned
4141by the ``dependability_analysis`` rule which wraps this one.
4242"""
4343
44- load ("@trlc//:trlc.bzl" , "TrlcProviderInfo" )
4544load ("//bazel/rules/rules_score:providers.bzl" , "AnalysisInfo" , "ArchitecturalDesignInfo" , "SphinxSourcesInfo" )
4645load ("//bazel/rules/rules_score/private:puml_utils.bzl" , "make_puml_rst_wrappers" )
4746load ("//bazel/rules/rules_score/private:verbosity.bzl" , "VERBOSITY_ATTR" , "get_log_level" )
@@ -129,33 +128,37 @@ def _process_root_causes(ctx):
129128# Private Helpers
130129# ============================================================================
131130
132- def _render_trlc_inc (ctx , src , suffix ):
133- """Render a trlc_requirements target to an ``.inc`` file via trlc_rst.
131+ def _render_trlc_inc (ctx , trlc_files , spec_files , out_name ):
132+ """Render a list of ``.trlc`` source files to an ``.inc`` file via trlc_rst.
134133
135134 The ``.inc`` extension means the file is symlinked into the output
136135 directory (via ``_filter_doc_files``) but is NOT added to any Sphinx
137136 toctree (``_is_document_file`` only matches ``.rst`` / ``.md``).
138137
139138 Args:
140- ctx: Rule context.
141- src: Label carrying TrlcProviderInfo.
142- suffix: Suffix appended to the target name before ``.inc``.
139+ ctx: Rule context.
140+ trlc_files: List of ``.trlc`` File objects to render.
141+ spec_files: List of ``.rsl`` spec File objects needed for TRLC import
142+ resolution (passed as sandbox inputs only).
143+ out_name: Output filename (e.g. ``"failuremodes.inc"``).
143144
144145 Returns:
145- Declared ``.inc`` output File inside ``{label.name}/``.
146+ Declared ``.inc`` output File inside ``{label.name}/``, or ``None``
147+ when ``trlc_files`` is empty.
146148 """
147- trlc_provider = src [TrlcProviderInfo ]
149+ if not trlc_files :
150+ return None
148151 rendered = ctx .actions .declare_file (
149- "{}/{}{}.inc " .format (ctx .label .name , src . label . name , suffix ),
152+ "{}/{}" .format (ctx .label .name , out_name ),
150153 )
151154 args = ctx .actions .args ()
152155 args .add ("--output" , rendered .path )
153156 args .add ("--input-dir" , "." )
154157 args .add ("--title" , "" )
155158 args .add ("--source-files" )
156- args .add_all (trlc_provider . reqs )
159+ args .add_all (trlc_files )
157160 ctx .actions .run (
158- inputs = src [ DefaultInfo ]. files ,
161+ inputs = trlc_files + spec_files ,
159162 outputs = [rendered ],
160163 arguments = [args ],
161164 executable = ctx .executable ._renderer ,
@@ -179,67 +182,50 @@ def _fmea_impl(ctx):
179182 # -------------------------------------------------------------------------
180183 # 1. Render failure modes: TRLC -> .inc via trlc_rst
181184 # -------------------------------------------------------------------------
182- failuremodes_inc = [
183- _render_trlc_inc (ctx , src , "_failuremodes" )
184- for src in ctx .attr .failuremodes
185- ]
185+ spec_files = ctx .files .spec
186+ fm_inc = _render_trlc_inc (ctx , ctx .files .failuremodes , spec_files , "failuremodes.inc" )
187+ failuremodes_inc = [fm_inc ] if fm_inc else []
186188 output_files .extend (failuremodes_inc )
187189
188190 # -------------------------------------------------------------------------
189191 # 2. Render control measures: TRLC -> .inc via trlc_rst
190192 # -------------------------------------------------------------------------
191- controlmeasures_inc = [
192- _render_trlc_inc (ctx , src , "_controlmeasures" )
193- for src in ctx .attr .controlmeasures
194- ]
193+ cm_inc = _render_trlc_inc (ctx , ctx .files .controlmeasures , spec_files , "controlmeasures.inc" )
194+ controlmeasures_inc = [cm_inc ] if cm_inc else []
195195 output_files .extend (controlmeasures_inc )
196196
197197 # -------------------------------------------------------------------------
198- # 3. Run lobster-trlc on TRLC sources -> lobster files
199- # Use TrlcProviderInfo.reqs to check if there are any TRLC sources to
200- # process. Pass DefaultInfo.files as sandbox inputs so that the .rsl
201- # spec files (needed to resolve `import ScoreReq` etc.) are available
202- # alongside the .trlc record files.
198+ # 3. Run lobster-trlc on TRLC sources -> lobster files.
199+ # Spec files must be sandbox inputs so the TRLC parser can resolve
200+ # ``import ScoreReq`` etc.
203201 # -------------------------------------------------------------------------
204- failure_mode_trlc_srcs = []
205- failure_mode_inputs = []
206- for src in ctx .attr .failuremodes :
207- failure_mode_trlc_srcs .extend (src [TrlcProviderInfo ].reqs .to_list ())
208- failure_mode_inputs .extend (src [DefaultInfo ].files .to_list ())
209-
210202 failuremodes_lobster_files = []
211- if failure_mode_trlc_srcs :
203+ if ctx . files . failuremodes :
212204 failuremodes_lobster = ctx .actions .declare_file (
213205 "{}/failuremodes.lobster" .format (ctx .label .name ),
214206 )
215207 args = ctx .actions .args ()
216208 args .add ("--config" , ctx .file ._fm_lobster_config .path )
217209 args .add ("--out" , failuremodes_lobster .path )
218210 ctx .actions .run (
219- inputs = failure_mode_inputs + [ctx .file ._fm_lobster_config ],
211+ inputs = ctx . files . failuremodes + spec_files + [ctx .file ._fm_lobster_config ],
220212 outputs = [failuremodes_lobster ],
221213 executable = ctx .executable ._lobster_trlc ,
222214 arguments = [args ],
223215 progress_message = "lobster-trlc {}" .format (failuremodes_lobster .path ),
224216 )
225217 failuremodes_lobster_files .append (failuremodes_lobster )
226218
227- control_measure_trlc_srcs = []
228- control_measure_inputs = []
229- for src in ctx .attr .controlmeasures :
230- control_measure_trlc_srcs .extend (src [TrlcProviderInfo ].reqs .to_list ())
231- control_measure_inputs .extend (src [DefaultInfo ].files .to_list ())
232-
233219 controlmeasures_lobster_files = []
234- if control_measure_trlc_srcs :
220+ if ctx . files . controlmeasures :
235221 controlmeasures_lobster = ctx .actions .declare_file (
236222 "{}/controlmeasures.lobster" .format (ctx .label .name ),
237223 )
238224 args = ctx .actions .args ()
239225 args .add ("--config" , ctx .file ._cm_lobster_config .path )
240226 args .add ("--out" , controlmeasures_lobster .path )
241227 ctx .actions .run (
242- inputs = control_measure_inputs + [ctx .file ._cm_lobster_config ],
228+ inputs = ctx . files . controlmeasures + spec_files + [ctx .file ._cm_lobster_config ],
243229 outputs = [controlmeasures_lobster ],
244230 executable = ctx .executable ._lobster_trlc ,
245231 arguments = [args ],
@@ -330,14 +316,20 @@ _fmea = rule(
330316 attrs = dict (
331317 {
332318 "failuremodes" : attr .label_list (
333- providers = [TrlcProviderInfo ],
319+ allow_files = [".trlc" ],
334320 mandatory = False ,
335- doc = "Failure modes as trlc_requirements targets (rendered to .inc via trlc_rst) ." ,
321+ doc = "Failure mode ``.trlc`` source files ." ,
336322 ),
337323 "controlmeasures" : attr .label_list (
338- providers = [TrlcProviderInfo ],
324+ allow_files = [".trlc" ],
339325 mandatory = False ,
340- doc = "Control measures as trlc_requirements targets (rendered to .inc via trlc_rst)." ,
326+ doc = "Control measure ``.trlc`` source files." ,
327+ ),
328+ "spec" : attr .label_list (
329+ allow_files = [".rsl" , ".trlc" ],
330+ default = [Label ("//bazel/rules/rules_score/trlc/config:score_requirements_model" )],
331+ doc = "TRLC model specification files (``.rsl``) required for import resolution. " +
332+ "Defaults to the S-CORE requirements model." ,
341333 ),
342334 "root_causes" : attr .label_list (
343335 allow_files = [".puml" , ".plantuml" ],
@@ -407,6 +399,7 @@ _fmea = rule(
407399
408400def fmea (
409401 name ,
402+ spec = None ,
410403 failuremodes = [],
411404 controlmeasures = [],
412405 root_causes = [],
@@ -420,24 +413,28 @@ def fmea(
420413
421414 FTA diagrams passed via ``root_causes`` are preprocessed to inline
422415 ``fta_metamodel.puml`` (hermetic, no ``!include`` at render time) and
423- lobster traceability items are extracted to ``fta .lobster``.
416+ lobster traceability items are extracted to ``root_causes .lobster``.
424417
425418 This is a **build-only** rule. The combined traceability test
426419 (FM + CM + FTA) is owned by the ``dependability_analysis`` that wraps
427420 this target.
428421
429422 Args:
430423 name: Target name.
431- failuremodes: trlc_requirements targets for failure mode records.
432- controlmeasures: trlc_requirements targets for control measure records.
424+ spec: TRLC model specification files (``.rsl``) for resolving imports.
425+ Defaults to the S-CORE requirements model. Override only when using
426+ a custom TRLC schema.
427+ failuremodes: Failure mode ``.trlc`` source files.
428+ controlmeasures: Control measure ``.trlc`` source files.
433429 root_causes: Optional FTA PlantUML diagram files (``.puml`` /
434430 ``.plantuml``) representing the root causes of failure modes.
435- arch_design: Optional architectural_design target for traceability.
431+ arch_design: Optional `` architectural_design`` target for traceability.
436432 visibility: Bazel visibility.
437433 tags: Additional Bazel tags.
438434 """
439435 _fmea (
440436 name = name ,
437+ spec = spec ,
441438 failuremodes = failuremodes ,
442439 controlmeasures = controlmeasures ,
443440 root_causes = root_causes ,
0 commit comments