Jinja Templating in Netsuke

Updated Nov 24, 2025

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 inside macros): {% 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:

  1. Initial YAML Parse: Load the raw file into an intermediate structure (like serde_json::Value).

  2. Template Expansion (foreach, when): Evaluate foreach expressions to generate multiple target definitions. The item (and optional index) become available in the context. Evaluate when expressions to conditionally include/exclude targets.

  3. Deserialisation to AST: Convert the expanded intermediate structure into Netsuke's typed Rust structs (NetsukeManifest, Target, etc.).

  4. Final Rendering: Render Jinja expressions only within string fields (like command, description, name, sources etc.) 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 current item is 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