8.8 KiB
Build Flags
Build flags are system-wide controls that affect how TheRock subprojects are
configured. Each flag creates a THEROCK_FLAG_{NAME} CMake cache variable and
can optionally propagate CMake variables and C preprocessor defines to all or
specific subprojects.
Flags vs Features
| Concept | Purpose | Naming |
|---|---|---|
Features (therock_features.cmake) |
Control which subprojects are included in the build | THEROCK_ENABLE_{NAME} |
Flags (FLAGS.cmake) |
Control how included subprojects are configured | THEROCK_FLAG_{NAME} |
Features are about "what to build". Flags are about "how to build it".
Architecture
FLAGS.cmake Central declarations (project root)
└── therock_declare_flag() → THEROCK_FLAG_{NAME} cache var
└── BRANCH_FLAGS.cmake → Legacy per-branch default overrides
└── BRANCH_CONFIG.json → Per-branch defaults and optional sources
└── therock_finalize_flags() → Propagation data + flag_settings.json
└── therock_report_flags() → Status output
cmake/therock_flag_utils.cmake Processing functions
build_tools/topology_to_cmake.py Generated branch config CMake helpers
cmake/therock_subproject.cmake Injection via project_init.cmake
Propagation Mechanism
Flag effects are injected into subprojects via the generated
project_init.cmake files (the same mechanism used for
THEROCK_DEFAULT_CMAKE_VARS):
- GLOBAL_PROPAGATE_FLAG: Mirrors
THEROCK_FLAG_{NAME}to all subprojects, regardless of whether the flag is enabled or disabled. - GLOBAL_CMAKE_VARS:
VAR=VALUEpairs set in the super-project and propagated to all subprojects when the flag is enabled. - GLOBAL_CPP_DEFINES: Preprocessor defines added to all subprojects
when the flag is enabled via
add_compile_definitions()in project_init.cmake. - CMAKE_VARS:
VAR=VALUEpairs injected only into the listed SUB_PROJECTS when the flag is enabled. - CPP_DEFINES: Preprocessor defines added only to the listed
SUB_PROJECTS when the flag is enabled via
add_compile_definitions().
Structural concerns (conditional subproject inclusion, runtime dependency wiring) remain as explicit conditionals in the consuming CMakeLists.txt files. Flags do not auto-include subprojects.
Declaring a Flag
All flags are declared in FLAGS.cmake at the project root:
therock_declare_flag(
NAME KPACK_SPLIT_ARTIFACTS
DEFAULT_VALUE OFF
DESCRIPTION "Split target-specific artifacts into generic and arch-specific components"
ISSUE "https://github.com/ROCm/TheRock/issues/3448"
CMAKE_VARS
ROCM_KPACK_ENABLED=ON
SUB_PROJECTS
hip-clr
)
Parameters
| Parameter | Required | Description |
|---|---|---|
NAME |
Yes | Unique identifier. Creates THEROCK_FLAG_{NAME} cache variable. |
DEFAULT_VALUE |
Yes | ON or OFF. |
DESCRIPTION |
Yes | Short description shown in CMake cache UI. |
ISSUE |
No | Tracking issue URL. |
GLOBAL_PROPAGATE_FLAG |
No | Mirror THEROCK_FLAG_{NAME} to all subprojects whether enabled or disabled. |
GLOBAL_CMAKE_VARS |
No | VAR=VALUE pairs for all subprojects when enabled. |
GLOBAL_CPP_DEFINES |
No | Preprocessor defines for all subprojects when enabled. |
CMAKE_VARS |
No | VAR=VALUE pairs for listed SUB_PROJECTS only when enabled. |
CPP_DEFINES |
No | Preprocessor defines for listed SUB_PROJECTS when enabled. |
SUB_PROJECTS |
No* | Target names for scoped CMAKE_VARS/CPP_DEFINES. *Required if either is set. |
Using a Flag in CMakeLists.txt
Flags are regular CMake cache variables, so consuming code uses them directly:
if(THEROCK_FLAG_KPACK_SPLIT_ARTIFACTS)
# Conditional subproject inclusion, dependency wiring, etc.
endif()
Branch Configuration
Integration branches can change flag defaults and request optional source sets
by creating a BRANCH_CONFIG.json file in the project root:
{
"flags": {
"INCLUDE_HRX": "ON"
},
"source_sets": ["optional-hrx"],
"artifact_groups": {
"core-runtime": {
"source_sets": ["optional-hrx"]
}
}
}
At configure time, build_tools/topology_to_cmake.py reads
BRANCH_CONFIG.json and generates a therock_apply_branch_config_flags()
macro that calls therock_override_flag_default() for each entry in flags.
FLAGS.cmake invokes that generated macro before therock_finalize_flags().
Explicit -D flags on the cmake command line always take precedence over
branch defaults.
Optional Source Sets
BRANCH_CONFIG.json also controls optional source fetching:
- Top-level
"source_sets"are fetched by the defaultbuild_tools/fetch_sources.pyinvocation when no--stageis specified. "artifact_groups"source sets are fetched whenfetch_sources.py --stageselects a stage containing that artifact group.fetch_sources.py --source-sets <name>can force extra source sets for any invocation.fetch_sources.py --list-source-setslists available source sets, including optional external git checkouts.
Optional external git sources are declared in BUILD_TOPOLOGY.toml source sets
with external_git_sources entries and are fetched under the ignored
optional-sources/ directory. For example:
[source_sets.optional-hrx]
description = "Optional HRX source checkout"
external_git_sources = [
{ name = "hrx", origin = "https://github.com/ROCm/hrx.git", commit = "e642a13425f46bcf909078459dd4e07df0723a0d", path = "optional-sources/hrx" },
]
Legacy Branch Flags
Existing branches can still change flag defaults by creating a
BRANCH_FLAGS.cmake file in the project root:
# BRANCH_FLAGS.cmake
# Override defaults for the kpack-integration branch.
therock_override_flag_default(KPACK_SPLIT_ARTIFACTS ON)
BRANCH_FLAGS.cmake remains supported for compatibility. When both files are
present, BRANCH_CONFIG.json flag defaults are applied after
BRANCH_FLAGS.cmake.
Manifest Integration
Flag states are recorded in the TheRock manifest (share/therock/therock_manifest.json)
under a "flags" key:
{
"the_rock_commit": "abc123...",
"submodules": [...],
"flags": {
"KPACK_SPLIT_ARTIFACTS": false
}
}
This is generated automatically: therock_finalize_flags() writes
flag_settings.json to the build directory, which is passed to
generate_therock_manifest.py via the aux-overlay subproject.
Adding a New Flag
- Add a
therock_declare_flag()call inFLAGS.cmake. - Use
THEROCK_FLAG_{NAME}in the relevant CMakeLists.txt files for structural decisions (conditional subproject inclusion, dependency wiring). - If subprojects need the flag value itself, use
GLOBAL_PROPAGATE_FLAG. If the flag needs to set variables or defines only when enabled, use theCMAKE_VARS,CPP_DEFINES,GLOBAL_CMAKE_VARS, orGLOBAL_CPP_DEFINESparameters. - Run cmake configure and verify the flag report output and, if applicable,
inspect the generated
project_init.cmakefiles.
Alternatives Considered
Plumbing individual flags to subprojects via CMAKE_ARGS
Before the flag system, each flag's effects were manually forwarded to
subprojects in their therock_cmake_subproject_declare() calls. For example,
THEROCK_KPACK_SPLIT_ARTIFACTS required manual -DROCM_KPACK_ENABLED=ON
forwarding to hip-clr. This approach doesn't scale and is error-prone: adding a
new flag requires modifying multiple declaration sites.
Plumbing flags to the manifest generator individually
For manifest integration, each flag could be passed as its own CMake variable to
the aux-overlay subproject, then read by generate_therock_manifest.py. This
was rejected in favor of generating a single flag_settings.json file that is
splat into the manifest, avoiding per-flag plumbing.
Merging flags into the feature system
Flags could be added as a new mode in therock_features.cmake. However,
features and flags serve fundamentally different purposes (inclusion vs
configuration), and mixing them would complicate the feature dependency
resolution logic.