Netsuke uses the MiniJinja engine to add dynamic capabilities to your manifest.
Netsuke uses the MiniJinja engine to add dynamic capabilities to your manifest.
Basic Syntax
-
Variables:
{{ my_variable }} -
Expressions:
{{ 1 + 1 }},{{ sources | map('basename') }} -
Control Structures (within specific keys like
foreach,when, or insidemacros):{% if enable %}…{% endif %},{% for item in list %}…{% endfor %}
Important: Structural Jinja ({% %}) is generally not allowed directly
within the YAML structure outside of macros. Logic should primarily be within
string values or dedicated keys like foreach and when.
Processing Order
Netsuke processes the manifest in stages:
-
Initial YAML Parse: Load the raw file into an intermediate structure (like
serde_json::Value). -
Template Expansion (
foreach,when): Evaluateforeachexpressions to generate multiple target definitions. Theitem(and optionalindex) become available in the context. Evaluatewhenexpressions to conditionally include/exclude targets. -
Deserialisation to AST: Convert the expanded intermediate structure into Netsuke's typed Rust structs (
NetsukeManifest,Target, etc.). -
Final Rendering: Render Jinja expressions only within string fields (like
command,description,name,sourcesetc.) using the combined context (globals + target vars + iteration vars).
foreach and when
These keys enable generating multiple similar targets programmatically.
targets:
# Generate a target for each .c file in src/
- foreach: glob('src/*.c') # Jinja expression returning an iterable
# Only include if the filename isn't 'skip.c'
when: item | basename != 'skip.c'
# 'item' and 'index' (0-based) are available in the context
name: "build/{{ item | basename | with_suffix('.o') }}"
rule: compile
sources: "{{ item }}"
vars:
compile_flags: "-O{{ index + 1 }}" # Example using index
-
foreach: A Jinja expression evaluating to a list (or any iterable). A target definition will be generated for each item. -
when(Optional): A Jinja expression evaluating to a boolean. If false, the target generated for the currentitemis skipped.
User-defined Macros
Define reusable Jinja logic in the top-level macros section.
macros: - signature: "cc_cmd(src, obj, flags='')" # Jinja macro signature body: | # Multi-line body {{ cc }} {{ flags }} -c {{ src | shell_escape }} -o {{ obj | shell_escape }} targets: - name: build/main.o command: "{{ cc_cmd('src/main.c', 'build/main.o', flags=cflags) }}" sources: src/main.c