Functions & API Calls
rebar_compiler_dag:init/4
Purpose: Initialize or restore DAG from disk
Signature:
-spec init(Dir, Compiler, Label, CritMeta) -> Graph when
Dir :: file:filename_all(),
Compiler :: atom(),
Label :: string() | undefined,
CritMeta :: term(),
Graph :: digraph:graph().
Arguments:
Dir: Directory for DAG storage (typically deps_dir)Compiler: Compiler module name (e.g.,rebar_compiler_erl)Label: Optional label (e.g., "apps", "project_apps")CritMeta: Critical metadata for invalidation (compiler version, etc.)
Returns: Digraph handle
Flow:
- Create new acyclic digraph
- Determine DAG file path
- Try to restore from file
- If restoration fails: delete invalid file, return empty graph
- Return graph
DAG File Path:
- With label:
_build/PROFILE/.rebar3/COMPILER/source_LABEL.dag - Without label:
_build/PROFILE/.rebar3/COMPILER/source.dag
rebar_compiler_dag:status/4
Purpose: Quick validation of DAG file without loading
Signature:
-spec status(Dir, Compiler, Label, CritMeta) -> Status when
Dir :: file:filename_all(),
Compiler :: atom(),
Label :: string() | undefined,
CritMeta :: term(),
Status :: valid | bad_format | bad_vsn | bad_meta | not_found.
Returns:
valid: DAG file valid and compatiblebad_format: File corrupted or wrong formatbad_vsn: DAG version mismatch (current: 4)bad_meta: Critical metadata mismatchnot_found: DAG file doesn't exist
Use: Determines if full rebuild needed before actual compilation
rebar_compiler_dag:prune/5
Purpose: Remove deleted files from DAG
Signature:
-spec prune(G, SrcExt, ArtifactExt, Sources, AppPaths) -> ok when
G :: digraph:graph(),
SrcExt :: string(),
ArtifactExt :: [string()],
Sources :: [file:filename()],
AppPaths :: [{AppDir, OutDir}].
Arguments:
G: DAG graphSrcExt: Source extension (e.g., ".erl")ArtifactExt: Artifact extensions (e.g., [".beam"])Sources: Current list of source filesAppPaths: App directories and output directories
Flow:
- Find vertices not in
Sources - For source files: check if in app paths, delete if so
- For header files with no incoming edges: delete
- For deleted sources: delete associated artifacts
- Mark DAG dirty if anything deleted
rebar_compiler_dag:populate_sources/5
Purpose: Add sources and scan their dependencies
Signature:
-spec populate_sources(G, Compiler, InDirs, Sources, DepOpts) -> ok when
G :: digraph:graph(),
Compiler :: module(),
InDirs :: [file:filename()],
Sources :: [file:filename()],
DepOpts :: term().
Arguments:
G: DAG graphCompiler: Compiler module (fordependencies/4callback)InDirs: Include directories to searchSources: Source files to addDepOpts: Options for dependency scanning
Flow:
- Create parallel worker pool
- For each source:
- Check if vertex exists
- Compare timestamps
- If new or modified: queue dependency scan
- If unchanged: skip
- Wait for all scans to complete
- Add dependency edges to graph
- Delete obsolete edges
- Mark dirty if changes made
Parallel Scanning: Uses rebar_parallel for performance
rebar_compiler_dag:populate_deps/3
Purpose: Scan header files for timestamp updates
Signature:
-spec populate_deps(G, SourceExt, ArtifactExts) -> ok when
G :: digraph:graph(),
SourceExt :: string(),
ArtifactExts :: [string()].
Flow:
- Find all vertices that are neither sources nor artifacts (headers)
- Refresh timestamp for each header file
- Update vertex labels
rebar_compiler_dag:propagate_stamps/1
Purpose: Propagate timestamps through dependency chains
Signature:
-spec propagate_stamps(G :: digraph:graph()) -> ok.
Algorithm:
Given: A → B → C → D with timestamps [0, 1, 3, 2]
Process in reverse topological order: [D, C, B, A]
For D (timestamp 2):
Dependencies: none
Keep timestamp: 2
For C (timestamp 3):
Dependencies: [D with timestamp 2]
Max dependency: 2
Current: 3
Keep timestamp: 3 (already newer)
For B (timestamp 1):
Dependencies: [C with timestamp 3]
Max dependency: 3
Current: 1 < 3
Update timestamp: 3
For A (timestamp 0):
Dependencies: [B with timestamp 3]
Max dependency: 3
Current: 0 < 3
Update timestamp: 3
Result: [3, 3, 3, 2]
Why: Ensures dependent files know when their dependencies changed
rebar_compiler_dag:compile_order/4
Purpose: Determine inter-application compilation order
Signature:
-spec compile_order(G, AppDefs, SrcExt, ArtifactExt) -> [AppName] when
G :: digraph:graph(),
AppDefs :: [{AppName, AppPath}],
SrcExt :: string(),
ArtifactExt :: [string()],
AppName :: atom().
Returns: Ordered list of application names
Flow:
- Create new app-level DAG
- For each file dependency edge in G:
- Skip artifact edges
- Resolve both files to apps
- If different apps: add inter-app edge
- Use interleave sort (respects original order + DAG constraints)
- Return sorted app names
- Delete app DAG
Interleave Sort: Preserves rebar.config order while respecting hard dependencies
rebar_compiler_dag:store_artifact/4
Purpose: Track compiled artifact in DAG
Signature:
-spec store_artifact(G, Source, Target, Meta) -> ok when
G :: digraph:graph(),
Source :: file:filename(),
Target :: file:filename(),
Meta :: term().
Arguments:
G: DAG graphSource: Source file pathTarget: Artifact file pathMeta: Artifact metadata (options, versions)
Flow:
- Add artifact vertex with metadata
- Add artifact edge:
Target → Source - Check for duplicate edge (artifact compilation may run multiple times)
- Mark DAG dirty
rebar_compiler_dag:maybe_store/5
Purpose: Save DAG to disk if modified
Signature:
-spec maybe_store(G, Dir, Compiler, Label, CritMeta) -> ok when
G :: digraph:graph(),
Dir :: file:filename_all(),
Compiler :: atom(),
Label :: string() | undefined,
CritMeta :: term().
Flow:
- Check if DAG is dirty
- If dirty:
- Clear dirty bit
- Serialize DAG to binary
- Write to file
- If not dirty: skip save
DAG File Format:
#dag{
vsn = 4,
meta = CritMeta,
vtab = Vertices,
etab = Edges,
ntab = NeighborTable
}
rebar_compiler_dag:terminate/1
Purpose: Clean up in-memory DAG
Signature:
-spec terminate(G :: digraph:graph()) -> true.
Flow: Calls digraph:delete/1
Note: Does not delete disk files