common/config.h remains the single source of truth for BE config declarations:
- config names
- config types
- default values
- comments that describe the config
The generated config_<domain>_fwd.h headers exist only to expose selected CONF_* declarations to consumers
without forcing them to include all of common/config.h.
We do this for two reasons:
common/config.his large and widely included. Any direct include expands rebuild fanout when the file changes.- We do not want multiple hand-maintained config declaration files. That would split the source of truth and make defaults, types, and comments drift.
The current design keeps config.h authoritative and derives smaller forward headers from it:
common/config.h: authoritative declarationscommon/config.cpp: definitionscommon/config_fwd_headers_manifest.json: selects which configs belong to which forward headerbuild-support/gen_config_fwd_headers.py: generates the committedconfig_<domain>_fwd.hfiles
The generator preserves comments, declaration order, and surrounding preprocessor guards from config.h. By default it
only rewrites a generated file when the content actually changes, so unchanged forward headers keep their timestamps
and do not trigger needless recompiles. Use --force only when you intentionally want to rewrite the generated files.
- Do not hand-edit
config_<domain>_fwd.h. - Add or modify config declarations only in
common/config.hor a config fragment it includes. - Prefer including
common/config_<domain>_fwd.hinstead ofcommon/config.hin headers and reusable.cppfiles. - Reuse an existing domain header when the config fits that domain; otherwise add a new generated domain header through the manifest instead of adding an ad-hoc manual declaration header.
common/config.cppis the definition owner and should continue to includeconfigbase_impl.hbeforeconfig.h.
From the repo root:
- Add the new
CONF_*entry inbe/src/common/config.hor an existing local config fragment. - Decide whether the config should be exposed through an existing
config_<domain>_fwd.h. - If needed, update
be/src/common/config_fwd_headers_manifest.json.- Add the config name to an existing header entry if the domain already fits.
- Add a new header entry only when the config does not fit an existing domain cleanly.
- Regenerate forward headers:
python3 build-support/gen_config_fwd_headers.py- Update consumers to include the appropriate
common/config_<domain>_fwd.hinstead ofcommon/config.h. - Run the guardrails:
python3 build-support/gen_config_fwd_headers.py --check
bash build-support/check_common_config_header_includes.shThe preferred answer is "almost never" for new code.
Current legacy direct includes are tracked in the allowlist enforced by
build-support/check_common_config_header_includes.sh, but new direct includes should be treated as exceptions that
need strong justification. If you think a new direct include is necessary, first check whether:
- an existing
config_<domain>_fwd.hcan be reused - the manifest can be extended
- a new generated domain header would be cleaner
The migration path is to keep shrinking the allowlist over time, not to add new long-term direct includes.