Dependency Analyzers
rsconstruct uses dependency analyzers to scan source files and discover dependencies between files. Analyzers run after processors discover products and add dependency information to the build graph.
How analyzers work
- Product discovery: Processors discover products (source → output mappings).
- Dependency analysis: Analyzers scan source files to find dependencies.
- Graph resolution: Dependencies are added to products for correct build ordering.
Analyzers are decoupled from processors — they operate on any product with matching source files, regardless of which processor created it.
Built-in analyzers
Per-analyzer reference pages:
- cpp — C/C++
#includescanning (invokesgcc/pkg-config) - icpp — C/C++
#includescanning, pure Rust (no subprocess) - python — Python
import/from ... importresolution - markdown — Markdown image and link references
- tera — Tera
{% include %},{% import %},{% extends %}references
Configuration
Analyzers are configured in rsconstruct.toml:
[analyzer]
auto_detect = true # default: true
enabled = ["cpp", "markdown", "python", "tera"] # instances to run
[analyzer.cpp]
include_paths = ["include", "src"]
Only analyzers listed under [analyzer.X] (or enabled) are instantiated — there is no global “all analyzers always run” mode.
Auto-detection
An analyzer runs if:
- It is declared (listed in
enabledor configured via[analyzer.X]). - AND either
auto_detect = false, OR the analyzer detects relevant files in the project.
This mirrors how processors work.
Caching
Analyzer results are cached in the dependency cache (.rsconstruct/deps.redb). On subsequent builds:
- If a source file hasn’t changed, its cached dependencies are used.
- If a source file has changed, dependencies are re-scanned.
- The cache is shared across all analyzers.
Use the analyzers and deps commands to inspect the cache:
rsconstruct analyzers list # list available analyzers
rsconstruct analyzers defconfig cpp # show default config for an analyzer
rsconstruct analyzers add cpp # append [analyzer.cpp] to rsconstruct.toml with comments
rsconstruct analyzers add cpp --dry-run # preview without writing
rsconstruct deps all # show all cached dependencies
rsconstruct deps for src/main.c # show dependencies for specific files
rsconstruct deps clean # clear the dependency cache
Build phases
With --phases, you can see when analyzers run:
rsconstruct --phases build
Output:
Phase: Building dependency graph...
Phase: discover
Phase: add_dependencies # Analyzers run here
Phase: apply_tool_version_hashes
Phase: resolve_dependencies
Use --stop-after add-dependencies to stop after dependency analysis:
rsconstruct build --stop-after add-dependencies
Adding a custom analyzer
Analyzers implement the DepAnalyzer trait:
#![allow(unused)]
fn main() {
pub trait DepAnalyzer: Sync + Send {
fn description(&self) -> &str;
fn auto_detect(&self, file_index: &FileIndex) -> bool;
fn analyze(
&self,
graph: &mut BuildGraph,
deps_cache: &mut DepsCache,
file_index: &FileIndex,
verbose: bool,
) -> Result<()>;
}
}
The analyze method should:
- Find products with relevant source files.
- Scan each source file for dependencies (using the cache when available).
- Add discovered dependencies to the product’s inputs.