Skip to main content

fpp-query

List the files an FPP autocoder would generate, from the syntactic model alone.

An F Prime build autocoder is invoked twice: once at CMake configure time to declare which files it will generate, and once at build time to generate them. The configure-time query runs once per module, needs only the syntax model, and in a Python autocoder is dominated by interpreter and extension-module startup.

On a project with a few hundred .fpp files that is tens of seconds of serial configure time.

fpp-query --rules static-tlm-packet.toml \
          -d "$BUILD" --filenames "$BUILD/names.txt" -- Top/topology.fpp
# static-tlm-packet.toml
[[group]]
node = "DefTopology"
where = '$.is_deployment'
generate = ["StaticTlmPacketAc.cpp"]

The rules file

The file holds the rules; the command line holds the invocation — -d, --filenames, the input files — because those are build paths that change per module while the rules do not.

A file is a list of groups. Each emits <DIR>/<stem><SUFFIX> for every definition of node that satisfies where. Output is sorted and deduplicated across all groups.

Key Meaning
node AST node kind to select, e.g. DefTopology. Required.
where Predicate the definition must satisfy.
name Expression overriding the file stem.
generate Suffixes appended to the stem. Required, non-empty.

One file-wide key sits above the first [[group]]:

Key Meaning
expand Match against the expanded model. Default false.

Write a query as a TOML literal string — where = '$.is_deployment', in single quotes. A query needs " for its own string literals, and a literal string carries those unescaped. A basic string with escapes in it is rejected rather than mis-reported: its decoded text is shorter than what is written, so every caret past the first escape would point at the wrong column.

A misspelled key names the alternatives exactly (unknown field \wheer`, expected one of `node`, `where`, `name`, `generate``), and every diagnostic — a bad kind, a bad suffix, a query that will not parse — carets the offending value at its real line in the file. One run reports every rule the file gets wrong.

The command line

fpp-query [OPTIONS] --rules <FILE> [--] [FILES]...
Option Meaning
--rules <FILE> The TOML rules. Required, except for --json / --fields.
-d, --directory <DIR> Directory the paths are rooted at. Default ..
--filenames <FILE> Write the paths to FILE instead of stdout.
-i, --imports <FILES> Accepted and ignored, so one argv works for both phases.
--json Dump the serialized model — exactly what a query sees.
--fields [KIND] List every kind, or one kind's queryable fields.

That is the whole surface. Rules only ever come from a file, so there are no group flags to order, no shell quoting to get right around a $, and nothing to reconcile when a flag and a file disagree. The trade is that a one-off query needs a file too; --json and --fields are the exploratory modes that do not.

--json and --fields also accept --rules, which is how you see the model a particular rule set reads — including its expand setting.

The stem

By default the stem is the definition's name, prefixed recursively by the names of enclosing components and state machines. Module nesting contributes nothing. This is what fpp-to-cpp does, so the defaults reproduce its filenames:

module M {
  passive component C {
    array A = [3] U32         # C_AArrayAc.hpp
    state machine SM {
      array A = [2] U8        # C_SM_AArrayAc.hpp
      initial enter S
      state S
    }
  }
  array A = [4] U8            # AArrayAc.hpp -- module M is not part of the name
  deployment topology T { }   # TTopologyAc.hpp
}

Reproducing fpp-filenames

Upstream FPP ships an fpp-filenames tool with these rules built in. All six of its modes are expressible here, and ship as presets:

Preset Upstream
presets/autocode.toml no flags
presets/autocode-expanded.toml no flags, from the expanded model
presets/template.toml -t
presets/test.toml -u
presets/test-auto-helpers.toml -u -a
presets/test-template.toml -u -t
presets/test-template-auto-helpers.toml -u -t -a
fpp-query --rules presets/autocode.toml -d "$OUT" -- "$@"

Copy the file into your project and delete the groups you do not want. Its comments explain each rule, and it is the tested spelling of them: tests/filenames.rs runs these presets against upstream's own suite — the models in tests/filenames/ and the .ref.txt reference outputs are copied verbatim from the Scala compiler's compiler/tools/fpp-filenames/test — so the file you copy is the one held to upstream's output byte for byte, not a transcription of it.

The query language

A query is evaluated against one definition at a time. Values are the JSON that fpp_ast's Serialize impls produce — there is no separate reflection layer to drift out of step with the grammar, so a field is queryable exactly when it is serialized. Run --json to see it, or --fields <KIND> <FILES> for one node.

Every definition has an annotations field — {"pre": [...], "post": [...]}, never omitted, empty arrays when there is none — because annotations live in the compiler context keyed by node handle, not as a struct field, and would otherwise be invisible to --json and to $.field navigation. It reaches further than the $@pre/$@post roots below: those only ever read the top-level matched node, while $.members[0].DefComponent.annotations.pre reaches a nested one's.

Roots

Root Value
$ the matched definition
$.field, $.a.b, $.members[0] field navigation
$.annotations.pre, $.annotations.post the matched definition's own annotations, as a real field
$@ every annotation line, @ then @<
$@pre, $@post just one side
$@kind the node kind name, e.g. "DefTopology"
$@file, $@line source file URI, 1-based start line
$@included true when spliced in by an include
$@scope, $@qualified dotted enclosing scope; scope and name
$@stem the default filename stem
$^, $^Kind immediate parent; nearest enclosing Kind

Operators

== != < <= > >= · contains starts_with ends_with matches (glob: *, ?, \) · in · + (concatenation) · && || ! · len() lower() upper() join() replace() · "str" 'str' 42 true false null [a, b]

A list on the left of contains / starts_with / ends_with / matches holds when any element does. == deliberately does not lift, so use in for exact membership.

The evaluator is strict: no truthiness, no cross-type comparison, and navigating into an absent field is an error rather than silently null. A query that quietly evaluated to false would drop a file from the list, and a build output that was declared but never written is far harder to diagnose than an error here. Guard optional fields with != null — && short-circuits.

Checking for an annotation

where = '$@ contains "static-tlm-packetizer"'   # any line containing the tag
where = '"static-tlm-packetizer" in $@'         # one line that is exactly the tag
where = 'len($@) > 0'                           # any annotation at all
where = 'len($@) == 0'                          # none
where = '$@pre matches "static-*"'              # only a `@` line, matched as a glob

Annotation text is what the lexer stores: the @ or @< sigil is stripped and the line trimmed, one list element per line.

More examples

where = '$.kind in ["Active", "Queued"]'   # active or queued components
where = '$.members != null'                # bodied state machines only
where = '!$@included'                      # written here, not pulled in by an include

# Arrays declared inside a state machine
[[group]]
node = "DefArray"
where = '$^DefStateMachine != null'
generate = ["ArrayAc.hpp"]

# Telemetry packet sets, whose name depends on the enclosing topology
[[group]]
node = "SpecTlmPacketSet"
where = '$^DefTopology.is_deployment'
name = '$^DefTopology.name + "_" + $.name'
generate = ["TlmPacketsAc.hpp", "TlmPacketsAc.cpp"]

# Collapse many definitions onto one pair of files
[[group]]
node = "DefConstant"
name = '"FppConstants"'
generate = ["Ac.hpp", "Ac.cpp"]

CMake integration

Replace the configure-time half of an autocoder. The fpp_info / fpp_autocoder_variables calls can be dropped from that half entirely: they exist to produce FPP_IMPORT_FLAGS, which a syntax-only query ignores, and they require the fpp_depend sub-build cache to already exist — itself configure-time cost.

function(static_tlm_packet_setup_autocode MODULE_NAME AC_INPUT_FILES)
    set(NAMES "${CMAKE_CURRENT_BINARY_DIR}/static-tlm-packet-filenames.txt")
    set(RULES "${CMAKE_CURRENT_LIST_DIR}/static-tlm-packet.toml")
    # Editing the rules must re-run configure, or the declared output list goes
    # stale and Ninja reports an output that was never produced.
    set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${RULES}")

    execute_process_or_fail(
        "[static_tlm_packet] could not list generated files for ${MODULE_NAME}"
        "${FPP_QUERY}"
        "--rules" "${RULES}"
        "-d" "${CMAKE_CURRENT_BINARY_DIR}"
        "--filenames" "${NAMES}"
        "--" ${AC_INPUT_FILES}
    )
    file(STRINGS "${NAMES}" GENERATED_CPP)

    if (NOT GENERATED_CPP)
        # Defined-but-empty, not undefined: the autocoder contract requires one of
        # the AUTOCODER_GENERATED_* variables to exist in the caller's scope.
        set(AUTOCODER_GENERATED_BUILD_SOURCES "" PARENT_SCOPE)
        return()
    endif()
    set(AUTOCODER_GENERATED_BUILD_SOURCES "${GENERATED_CPP}" PARENT_SCOPE)

    fpp_info("${MODULE_NAME}" "${AC_INPUT_FILES}")
    fpp_autocoder_variables("${FPP_IMPORTS}")
    add_custom_command(
        OUTPUT ${GENERATED_CPP}
        COMMAND ${STATIC_TLM_PACKETIZER} "-d" "${CMAKE_CURRENT_BINARY_DIR}"
            ${FPP_IMPORT_FLAGS} ${AC_INPUT_FILES}
        DEPENDS ${FILE_DEPENDENCIES} "${STATIC_TLM_PACKETIZER}"
        COMMENT "Generating telemetry packet code for ${MODULE_NAME}"
    )
endfunction()

The generator and the query must agree on the path set exactly, or Ninja reports a declared output that was never produced. This is what the rules file is for: it is one artifact both halves can read, so the build-time generator can derive its own output names from it — tomllib.load in a Python autocoder — rather than keeping a second copy of the same suffixes in sync by hand.

Exit codes and output format

Code Meaning
0 Success. The --filenames file exists, possibly empty. Nothing on stdout or stderr.
1 Diagnostics were emitted: a syntax error, an unresolvable include, or a bad rules file.
2 Usage or I/O failure, including an unreadable --rules file.

No matches is not a failure. A nonzero exit becomes a CMake FATAL_ERROR that aborts configure, and a module with nothing to generate must not do that.

The --filenames file is written unconditionally, including on exit 1, because file(STRINGS) on a missing file is a hard FATAL_ERROR — leaving it out would turn one diagnosable error into two. It holds one absolute path per line, LF-terminated, with no blank lines (a blank line becomes an empty CMake list element, hence an empty add_custom_command(OUTPUT ...) entry). Diagnostics go to stderr, since stdout is where the list goes when --filenames is absent.

Release files for fprime-fpp-query 3.3.24

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fprime-fpp-query 3.3.24
File Size Uploaded
fprime_fpp_query-3.3.24.tar.gz 158.5 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for fprime-fpp-query 3.3.24
File Interpreter ABI Platform
fprime_fpp_query-3.3.24-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
fprime_fpp_query-3.3.24-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
fprime_fpp_query-3.3.24-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 2.8 MB

Release files / fprime_fpp_query-3.3.24.tar.gz

Download URL fprime_fpp_query-3.3.24.tar.gz
Size 158.5 kB
Tags Source
SHA-256 checksum
How to use checksums
2764eacbc3e51664930005919c6415c252584d48c85ba54a5c016f12a1b69cf4
BLAKE2b-256 checksum
How to use checksums
17174246c31a033b1863671316a0480e398f1c5e88dd6593010c4c58d564d227
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / fprime_fpp_query-3.3.24-py3-none-win_amd64.whl

Download URL fprime_fpp_query-3.3.24-py3-none-win_amd64.whl
Size 863.9 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
0b0256657a1c3b8016057e93b2d779a281274945c0655f8fec050b8551682f87
BLAKE2b-256 checksum
How to use checksums
2393fb83456bbc8eecc298bf0484403b83a194a92a863fc398c5bcb9d49f4182
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / fprime_fpp_query-3.3.24-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fprime_fpp_query-3.3.24-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 948.8 kB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
9f5c7194f1279d098e27273986e629e8c328d9b8cbc161d66c6b5a41a1f92667
BLAKE2b-256 checksum
How to use checksums
a4e7dc245baf37930cc0d4d4db70b3b2518d5e8cd2f925b825f8b4fac12e3104
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / fprime_fpp_query-3.3.24-py3-none-macosx_11_0_arm64.whl

Download URL fprime_fpp_query-3.3.24-py3-none-macosx_11_0_arm64.whl
Size 865.0 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
12b61efd6927045436137d942b0d4c132c52249aee5c5fab1e690ef912c02433
BLAKE2b-256 checksum
How to use checksums
5091db3e6dffa57e2196b9d4f35733a6391849cb805c2f71714f511af20fa9cf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

3.3.25

4 release files

This release

3.3.24 This release

4 release files

3.3.23

4 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page