Public Headers Reference
update-public-headers resolves an explicit directory policy into a public include tree and consumer namespace
exports.
See Update Public Headers for the generation workflow.
Global Configuration
The required [Update Public Headers] section lives in tool/conf/tools/update_public_headers.elcl.
There are no command-line path overrides.
--check suppresses all writes and deletions and reports outdated output as a failure.
--jobs (-j) selects 1 to 64 read, parsing and rendering workers.
Without an override, the default uses system::info::logicalCpuCount(), Core’s usable logical CPU count hint.
Text setting |
Default |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Base directories and the mapping file are relative to the selected project. Namespace-header paths are relative to the source base. Source and include trees must not overlap; the mapping file must live outside both trees. Paths use ASCII letters, digits, underscores, dots, hyphens and slash separators, without empty or dot components. Project access rejects paths outside the selected project. Inventory skips links and queues accepted paths for reading during the same generation run, trusting that parent directories are not concurrently replaced. Output access retains separate link and containment checks. Missing output directories are created only during generation.
The following optional settings accept one text value or a list, defaulting to empty:
Excluded Directorieslists directory basenames whose subtrees are excluded from publication and coverage checks.Excluded Headerscontains filename-only publication exclusion globs.Excluded From All Headerscontains filename-only globs excluding headers from every umbrella, while retaining their individual public wrappers.Mergeable Header Nameslists filenames intentionally allowed to forward to multiple source headers.Declared Namespacessupplies additional namespace names relative toBase Namespace.
Generated Markers accepts one text value or a list of line-comment prefixes.
It defaults to "// !!! THIS IS A GENERATED FILE", covering both current and legacy generated headers.
The first marker is emitted in new output; later markers recognize older output during migrations.
Markers must start with // and contain no line breaks.
Recognition examines at most the first ten physical lines of the initial comment banner, allowing a preceding
#pragma once.
Blank lines count toward this limit.
A later marker or text inside a string literal does not establish ownership.
The optional Namespace Aliases section maps base-namespace alias names to qualified names relative to the base.
For example, Sys Info: "system::info" declares the target namespace and exports sys_info.
The production configuration retains the existing aliases for cpp, io, html, punycode, and sys_info.
The optional Header Aliases section contains named entries with Source Header and Include Header paths,
relative to the source and include bases respectively.
Explicit entries also restore missing compatibility wrappers.
The production entry for system/SystemInfo.hpp preserves SystemInfo.hpp independently of the selective system
namespace exports.
Directory Sections
Directory is a required section containing the source-directory tree.
Section names are normalized ELCL names; their lowercase underscore spelling names the directory.
Every non-excluded source directory must be represented, including organizational and structural parent directories.
Configured directories must exist.
Top-level sections establish a domain namespace, default to Flatten: No, use their directory name as the public
target directory, and select *.hpp.
Nested sections inherit publication and namespace settings unless overridden.
Each entry computes its own target directory from its effective Flatten value.
Target-directory overrides are not inherited.
Setting |
Behavior |
|---|---|
|
Boolean, default |
|
Boolean, inherited. |
|
Text overriding this entry’s canonical wrapper directory. When omitted, |
|
Text naming a base-namespace alias. Overrides the namespace-wide import. |
|
Filename-only Core globs selecting published headers. |
|
Filename-only globs removing headers from publication and umbrellas. |
|
Filename-only globs retaining source-shaped canonical paths, without removing publication. |
|
Filename-only globs requiring explicit includes instead of umbrella inclusion. |
|
Explicit names replacing namespace-wide imports; only their owning headers gain the flattened target path. |
Included Symbols requires Flatten: Yes and cannot be combined with Target Namespace.
Directory lists are inherited and replaced by an explicit value.
Global umbrella exclusions apply independently: a header is omitted if either its global or effective directory patterns
match.
A local list cannot cancel a global exclusion.
The production configuration excludes StdFormat.hpp globally and ResourceStorageRegistration.hpp only in the
resource entry.
The latter is an implementation interface published for generated resource code.
Glob settings accept a single text value or a list and use StringPattern::fromGlob against filenames only.
A slash in a pattern is an error.
Generated all.hpp and fwd.hpp files are never discovered as ordinary public headers.
The production exclusions also omit underscore part headers and canonical forward headers.
A new nested namespace clears inherited selective exports and target aliases.
Select Flatten: No when the nested namespace must not inherit flattening.
Specify Target Directory only to override the computed destination, for example "zip" for compression/zip.
Organizational sections need no settings:
[Update Public Headers.Directory.Network]
Flatten: Yes
[Update Public Headers.Directory.Network.Tls]
[Update Public Headers.Directory.Conf]
Flatten: No
[Update Public Headers.Directory.Conf.Vr]
Nested Namespace: Yes
Namespace Verification and Exports
The scanner ignores comments, string and character literals, preprocessor directives, and nested type bodies.
Library namespace declarations must match the configured namespace or an auxiliary child namespace.
Specializations in std and collection headers without declarations are allowed.
The generated namespace-list header is exempt.
Corresponding forward headers are inspected as well.
Selective exports reuse canonical forward headers, but export only the explicitly listed names. Without such a declaration, extraction supports non-template classes and structs and enums with supported built-in or fixed-width integer underlying types. Unsupported aliases, templates, and enum types require a canonical forward header. The generator never includes a full definition header merely to make a selective export available.
Consumer flattening remains controlled by Definitions.hpp.
The generated helper retains the ERBSLAND_CORE_BUILDING_LIBRARY guard; consumers can disable flattening with
ERBSLAND_CORE_DO_NOT_FLATTEN_NS.
The production policy exports only RegEx from re and preserves the selective system exports.
Wrappers, Umbrellas and Updates
Each published header has a canonical wrapper and its source-shaped alias. Existing recognized generated wrappers are retained as aliases while their source remains public. Wrapper paths differing only in ASCII case are rejected. Multiple sources may share a wrapper only when its filename is explicitly mergeable.
Each configured directory receives a source all.hpp containing only its directly selected public headers, excluding
headers matched by global or local umbrella exclusions.
Descendant headers and umbrellas are not collected automatically, regardless of whether the child introduces a C++
namespace or organizes declarations in the same namespace.
Directories without eligible direct headers still receive an empty umbrella.
Ordinary dependencies included by individual headers remain unchanged.
Its preferred public wrapper is all_<source_path>.hpp with slashes replaced by underscores; the nested all.hpp
wrapper remains an alias.
Real namespace destinations also provide an all.hpp alias, such as render/all.hpp.
The universal root all.hpp is not generated.
Each source and include tree is walked once.
The walk records inputs for one bulk WorkerPool::map() operation that reads headers and parses selected source
declarations with bounded worker concurrency.
A second bulk operation parses the corresponding forward headers needed for declaration validation.
The inventory retains shared header text and path metadata for declaration checks, compatibility aliases, ownership
checks and cleanup.
Workers return independent results; the calling thread merges them into ordered indexes and resolves publication
relationships.
Rendering maps independent outputs through a shared, fully configured rendering environment.
Each stage has one future, and its ordered results make generated bytes independent of worker completion order.
Queued and running work drains before preparation returns, including when a worker reports a read, parsing or rendering
error.
Output planning validates each distinct parent directory once and resolves the mapping destination once.
Unchanged outputs reuse the inventory text after reloading their file identity, size and timestamps.
Changed files use the normal confined comparison and atomic replacement path.
Parent creation is deferred until an output needs updating.
Excluded subtrees remain visible to obsolete-umbrella cleanup; other excluded files are not read.
Discovery, namespace checks, collisions and output validation finish before writes start.
Updates use the framework’s atomic per-file replacement and equivalent-text comparison, which ignores line endings and
first-line copyright years.
This includes the mapping file: an existing CRLF file equivalent to the generated LF text retains its contents and
timestamp.
This is not a transaction across every file if an I/O error occurs during writing.
Obsolete public wrappers and source all.hpp umbrellas are removed only when their initial banner matches a
configured marker.
Other source headers, including generated implementation data, are outside this cleanup scope.
Unmanaged output conflicts are rejected, except for the explicitly configured namespace headers adopted during
migration.
Mapping File
New mappings are UTF-8 without a BOM and use LF endings.
Readers also accept CRLF endings, blank lines and comment lines beginning with #.
Every data row contains source;include, without a header row, quoting or metadata.
Both paths are relative to their configured bases and use slash separators.
The restricted path alphabet excludes semicolons and line breaks.
Rows are grouped by source path in ASCII order. The first row of each group is canonical; remaining distinct aliases are sorted. Generated directory umbrellas are included. A merged wrapper has one relationship for each source it forwards to:
network/tls/TlsClientConnection.hpp;TlsClientConnection.hpp
network/tls/TlsClientConnection.hpp;network/tls/TlsClientConnection.hpp
The code-cleanup command uses these canonical paths without narrowing merged wrappers.
Dependency analysis uses source membership from the same file, excluding generated umbrellas from its
regular-public-header counts.
Reusable C++ Tokenizer
erbsland::text::cpp::CppTokenizer streams tokens using StringCharReader captures that share source storage.
next() supplies one token at a time; tokens(source) exposes a CoGenerator owning its source string.
Tokens retain their lexical kind, original spelling and character position.
Whitespace is skipped, while comments, directives, ordinary literals and raw literals remain available to analysis
tools.
Unterminated comments and literals raise ParseError with a code-point position.
See C++ Tokenizer for the public interface.
The tokenizer does not expand macros or select conditional preprocessing branches.
HeaderDeclarations consumes significant tokens directly, tracking namespace scopes without retaining a token list.
Its reusable StringEditor buffer assembles qualified namespace names.
Output templates under tool/resources/headers own include statements, namespace declarations, guards and exports;
the planner supplies structured lists and maps.