read_file
Read C/C++ source files showing only the code that compiles for the current build configuration. Inactive #ifdef branches are blanked to preserve line numbers, giving build-accurate content.
Instructions
Read a complete C/C++ source file with ifdef-filtered content —
only code that actually compiles for the current build configuration.
Inactive #ifdef branches are replaced with blank lines (preserving
original line numbers).
Use this to read a file without leaving the fw-context ecosystem.
Unlike generic file readers, this tool returns build-accurate content:
code gated behind #ifdef BOARD_V2 stays visible only when
BOARD_V2 is actually defined for this build. Line numbers match
the original file — inactive branches appear as blank lines, and the
text spans the whole file, thus lines is the length of the file.
A blank line is an answer, and not a defect: it says that the line is
in a branch the build does not take. When EVERY line of the file is
blank, the dict carries all_lines_inactive and a warning — such
a file holds code, and the active build compiles none of it.
content is bare text by default and carries NO line-number prefix —
unlike the source of get_source, which numbers every line.
Never count the lines here to find a number. Take it from a field
instead: the match_lines of search_bodies or search_content,
the line / end_line of get_source and get_file_map, or
pass line_numbers=True and read the number off the line.
start_line and end_line cut a window out of the file (1-based,
both ends inclusive, 0 = no bound on that side). Reading around a
known line costs a fraction of the whole file — 40 lines around a match
instead of 2000 lines of a header.
A comment and a preprocessor directive are part of the answer. Both
are text that the file holds and the build reads, thus both stay — an
include guard, a #define, and the description of a register in a
vendor header included. A blank line is therefore an inactive line, or
a line that is blank on disk, and nothing else.
For reading a single function body with libclang exact extents use
get_source. For body + callers + callees in one call use
get_symbol_context. For a structural overview without content use
get_file_map. For searching patterns across files use
search_content.
Read-only. No side effects. Falls back to raw disk content (with a
warning) when the indexed files.content column is empty — e.g. on
a legacy index that predates this feature. Run fw-context index
to populate the ifdef-filtered content.
Args:
file_path: Path relative to project root, or just the filename.
E.g. src/main.cpp or main.cpp.
project_root: Project root. Auto-detected if omitted.
project: Project name or project_id — call list_projects to get them. Use
it to ask about a project that is not the project of the current
directory. It is an alternative to project_root, which takes a root
path. Give one of the two, not both.
line_numbers: Prefix every line with its number, right-aligned and
followed by two spaces, as get_source does. Default False.
start_line: First line to return, 1-based inclusive. 0 = file start.
end_line: Last line to return, 1-based inclusive. 0 = file end.
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns:
dict: {file (str), language (str — "c" or "cpp"),
mtime (float), lines (int — total line count of the WHOLE file,
whatever range was asked for),
content (str — the ifdef-filtered text, bare unless
line_numbers was set),
warning (str, optional — when reading from raw disk instead of
indexed content, or when no line of the file is active),
all_lines_inactive (True, optional)}.
``all_lines_inactive`` marks a file that the active build compiles
no line of: every line is inside an inactive ``#if`` branch, thus
``content`` holds the correct number of lines and no text. Without
this field that answer reads as an empty file, and the two mean
opposite things.
A range adds ``start_line`` and ``end_line`` — the first and last
line the ``content`` really holds, after the end was clamped to the
length of the file.
On failure the dict holds only ``error`` with the reason: a
negative bound, an ``end_line`` before ``start_line``, or a
``start_line`` past the end of the file.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| project | No | Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. | |
| variant | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| end_line | No | Last line to return, 1-based inclusive. 0 = to the end of the file. | |
| file_path | Yes | Path to source file — relative to project root or just filename. | |
| start_line | No | First line to return, 1-based inclusive. 0 = from the start of the file. | |
| line_numbers | No | Prefix every line with its line number, like get_source. Default False (bare text). | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |