Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

316 lines
14 KiB
Markdown

# TheRock Build System Manual
The ROCm distribution consists of many component projects that form a DAG
consisting of build and runtime dependencies between projects. Each individual
sub-project is CMake based and dependencies between them are generally
resolved via `find_package`. This means that it is possible to build each
project in isolation.
However, working with the individual pieces is not well suited for many tasks,
most notably CI and full-stack development workflows. TheRock provides a CMake
base super-project and monorepo like organization of the source and build to
make building and testing more of a one stop shop.
## Terminology
*Super-Project*
- This refers to `TheRock` project itself as the container of sub-projects.
*Sub-Project*
- Each individual piece or standalone dependency of the ROCm system is
referred to as a sub-project.
*Build Phases*
- Each sub-project is built in several phases: `configure`, `build`, `stage`,
and `dist`.
- Inter-project dependencies are taken at a build phase
granularity, allowing a degree of parallelism in the case of a more
limited dependency.
- For each project in the tree, a specific phase can
be built interactively by appending `+phase` to the sub-project's target
name.
*Build Dependency*
- If a sub-project dependency is a build dependency, it is not required to be
co-resident in a unified install tree in order to function.
*Runtime Dependency*
- If a sub-project is a runtime dependency that all/part of it must be
co-resident in the unified install tree of the depending project in order
to function.
*Utility Targets*
- Sub-projects may expose additional utility targets that can be accessed as
`+utility`. Currently, this just includes `+expunge`, which removes all
configured/built files related to the sub-project.
*Stamps*
- All Build Phases depend on a set of stamp files and produce a stamp file
named `phase.stamp`. This produces a worst-case ordering DAG between
phases. If a stamp file is removed (manually or via `clean`), the phase
and all of its dependencies will re-run, regardless of whether any sources
changed.
## Directory Layout
While the namespace of sub-projects is flat (every sub-project is a CMake target
name and therefore must be globally unique), the repository itself is organized
into a hierarchy with individual sub-projects at the leaves. Since the `ninja`
build system has good scoping of parts of the build by sub-directory (via the
implicit `all` pseudo-target), this provides some developer ergonomics, allowing
easy partial builds/cleans or deletions of parts of the build tree while
working.
Sub-project directories:
- [`base/`](/base/) : Utility sub-projects that are dependency free or minimally
co-dependent, providing core dependencies for the rest of the system.
- [`compiler/`](/compiler/) : Compiler sub-projects, most notably the
[AMD-LLVM](https://github.com/ROCm/llvm-project) build, `hipcc`, etc.
- [`core/`](/core/) : Core runtime sub-projects, including the low-level
[ROCR-Runtime](https://github.com/ROCm/ROCR-Runtime) and
higher level HIP runtimes.
- [`comm-libs/`](/comm-libs/) : Communication library sub-projects, including
[rccl](https://github.com/ROCm/rccl)
- [`storage-libs/`](/storage-libs/) : Storage library sub-projects, including
[hipFile](https://github.com/ROCm/rocm-systems/tree/develop/projects/hipfile)
- [`math-libs/`](/math-libs/) : Math library sub-projects, including `math-libs/BLAS` for
[Basic Linear Algebra Subprogram](https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms)
projects like [hipBLASLt](https://github.com/ROCm/hipBLASLt).
- [`ml-libs/`](/ml-libs/) : Machine learning library sub-projects like
[MIOpen](https://github.com/ROCm/MIOpen).
- [`media-libs/`](/media-libs/) : Media decoding library sub-projects like
[rocDecode](https://github.com/ROCm/rocm-systems/tree/develop/projects/rocdecode)
and [rocJPEG](https://github.com/ROCm/rocm-systems/tree/develop/projects/rocjpeg).
- [`profiler/`](/profiler/) : Profiler sub-projects
Note that there is nothing in the build system which ensures naming consistency,
however, we try to name leaf directories after their global sub-project
target name (i.e. `ROCR-Runtime` or `amd-llvm`) and if possible, the `project()`
name of the sub-project itself, if that is something we control. Consistency
just makes everyone's lives easier, even at the expense of sometimes not
having a naming/capitalization convention that is uniform.
## Build Directory Layout
Each sub-project, by default, uses a standard directory layout for its build:
- `build/` : The `CMAKE_BINARY_DIR` for the project, containing the
`CMakeCache.txt`, etc. Once an initial super-project build is performed,
developers can interact directly with the CMake build here if they prefer to
work on a single component. The `configure` phase populates this directory
by running the initial `cmake` configure. The `build` phase compiles the
`all` target.
- `stage/` : Local staging install directory for the sub-project. The
sub-projects install components (or just default install) will populate
this directory during the `stage` build phase. Note that for sub-projects
with runtime deps, this will be a "torn" directory in that it may contain
shared libraries whose dependencies cannot be found because their RPATH is
configured for the standard directory layout, which presumes that the project
is bundled with its runtime deps.
- `dist/` : This is populated by the `dist` build phase by hard linking (or
copying if hard-links are not possible) the cone of all runtime dep project's
`stage/` and this project's `stage/` directory contents. In this way, each
individual project's `dist/` directory should consist of a self-contained
slice that is relocatable and usable (for testing, etc). Top-level
distributions are created in this same way by having runtime deps on all
relevant sub-projects. Keeping sub-projects isolated in this way aids in
testing, especially to ensure that dependencies are declared and layered
properly.
- `_init.cmake` : Generated as part of the super-project to set all necessary
CMake settings to build the sub-project. This is injected at configure time
via the
[`CMAKE_PROJECT_TOP_LEVEL_INCLUDES`](https://cmake.org/cmake/help/latest/variable/CMAKE_PROJECT_TOP_LEVEL_INCLUDES.html)
facility and serves some other ancillary functions as well:
- Loads sub-project specific `pre` and `post` CMake file for further
sub-project customization needed as part of the integrated whole.
- Installs a [CMake dependency provider](https://cmake.org/cmake/help/latest/command/cmake_language.html#dependency-providers)
which rewrites `find_package` calls for any packages provided as part
of super-project deps appropriately.
- `_toolchain.cmake` : Generated as part of the super-project to configure the
toolchain used to build the sub-project. This is injected at configure time
via the
[`CMAKE_TOOLCHAIN_FILE`](https://cmake.org/cmake/help/latest/variable/CMAKE_TOOLCHAIN_FILE.html)
facility and allows for sub-projects to use compilers and settings which
differ from the host toolchain, e.g. building with the AMD version of `clang`
instead of the host `clang` on Linux or the host MSVC on Windows.
- Note that a number of sub-projects provide their own toolchain files, one
per platform, like
[`rocPRIM/toolchain-linux.cmake`](https://github.com/ROCm/rocPRIM/blob/develop/toolchain-linux.cmake)
and
[`rocPRIM/toolchain-windows.cmake`](https://github.com/ROCm/rocPRIM/blob/develop/toolchain-windows.cmake).
In TheRock we generate a single toolchain file dynamically that is used for
the current platform.
- `stamp/` : Directory of `{phase}.stamp` files that are used to control
build sequencing.
## CMake Configuration Options
### `THEROCK_DEV_PROJECTS`
Subprojects that opt in to source file globbing even when otherwise skipped
(e.g. `-DTHEROCK_DEV_PROJECTS=amd-llvm`).
## Developer Cookbook
TheRock aims to not just be a CI tool but to be a daily driver for developer
and end-users who wish to consume a source build of ROCm. This section contains
some advice that may help such users be more productive.
### Building part of the tree
Ninja's built-in directory scoping allows easy partial-builds:
Example:
```
ninja compiler/amd-llvm/all
```
Dependencies are tracked so if building a leaf project, it will build projects
it depends on. Note that there is an implicit `all` target at each directory
level, so the path can be arbitrarily fine-grained.
Similarly, cleaning the super-project and configure state can be done with:
```
ninja -t clean compiler/amd-llvm/all
```
Note that this will just clean the stamp files and byproducts that the
super-project knows about, causing a subsequent build to perform all build
phases regardless of whether any contents changed. Notably at present, this
does not clean the built files (this may change in the future), so a subsequent
build will still use CMake's own cache to avoid a full rebuild.
Sometimes a sub-project just needs to be removed entirely and rebuilt from
scratch. For this, you can do it the manual way via
`rm -Rf compiler/amd-llvm; cmake .` (note that if using a big hammer like this,
you need to regenerate the super-project build system because you just deleted
part of it). Or you can invoke the expunge sub-target:
```
ninja amd-llvm+expunge
```
## Build Topology
TheRock uses a declarative topology file (`BUILD_TOPOLOGY.toml` in the repository
root) to define the relationships between build artifacts. This file serves as
the single source of truth for:
1. **CMake Feature Generation**: During CMake configure, the topology is parsed
to automatically generate `THEROCK_ENABLE_*` feature flags for each artifact.
This replaces manual `therock_add_feature()` calls for artifact-mapped features.
1. **CI/CD Pipeline Sharding**: The topology defines which artifacts belong to
which build stages, enabling the CI system to fetch only the required
dependencies from artifact storage before each build stage.
### Topology Structure
The topology has a three-level hierarchy:
- **Build Stages**: CI/CD pipeline jobs (e.g., `compiler-runtime`, `math-libs`)
- **Artifact Groups**: Logical groupings with shared dependencies (e.g., `hip-runtime`)
- **Artifacts**: Individual build outputs (e.g., `core-hip`, `blas`, `miopen`)
### Key Files
- `BUILD_TOPOLOGY.toml` - The topology definition (see inline documentation)
- `build_tools/_therock_utils/build_topology.py` - Python parser and utilities
- `build_tools/topology_to_cmake.py` - Generates CMake includes from topology
### Naming Conventions
| Field | Convention | Example |
| ----------------- | -------------------------- | ----------------- |
| Entity names | lowercase-with-hyphens | `core-runtime` |
| `feature_name` | UPPERCASE_WITH_UNDERSCORES | `CORE_RUNTIME` |
| `feature_group` | UPPERCASE_WITH_UNDERSCORES | `CORE` |
| `type` values | lowercase | `target-specific` |
| `platform` values | lowercase | `windows` |
### Validation
Run validation without generating output:
```bash
python build_tools/topology_to_cmake.py --validate-only
```
Print the dependency graph as JSON:
```bash
python build_tools/topology_to_cmake.py --print-graph
```
## Adding Sub-Projects
The entire sub-project facility is defined in
[`cmake/therock_subproject.cmake`](/cmake/therock_subproject.cmake)
and it may be useful to refer to that if doing anything advanced. This section
attempts to document the basics.
> [!TIP]
> These instructions assume the source directory is already populated.<br>
> You may want to first follow
> [Git Maintenance Chores: Adding a new submodule](./git_chores.md#adding-a-new-submodule).
Consider an example that is typical. This is taken from the tree but annotated
with comments, describing what is going on.
```cmake
# Create a CMake target named `ROCR-Runtime` and set it up as a sub-project.
# This will also cause phase specific convenience targets like
# `ROCR-Runtime+build` to be created. Additional calls are needed to further
# set up the sub-project, and the sequence must terminate with a call to
# `therock_cmake_subproject_activate()`
# Specific settings used here:
# * EXTERNAL_SOURCE_DIR: Tells the system that the sources are located
# somewhere else (in this case within the same subdirectory).
# * CMAKE_ARGS: Additional arguments to pass to CMake. This is in addition
# to a number of default arguments.
# * BUILD_DEPS: Sub-projects that must be built and staged before this
# project's configure phase can run.
# * RUNTIME_DEPS: Sub-projects that should be considered a BUILD_DEP and
# also are required to be in a unified distribution tree at runtime.
therock_cmake_subproject_declare(ROCR-Runtime
EXTERNAL_SOURCE_DIR "ROCR-Runtime"
CMAKE_ARGS
"-DBUILD_SHARED_LIBS=ON"
BUILD_DEPS
amd-llvm
RUNTIME_DEPS
rocprofiler-register
)
# By default, the super-project treats the sources for the sub-project like a
# black box. This means that if you change the sources and rebuild, nothing
# will happen (unless if you clean or invoke the sub-project build directly).
# This directive tells the super-project that it should rebuild if C source
# files in any of the given sub-directories are modified.
therock_cmake_subproject_glob_c_sources(ROCR-Runtime
SUBDIRS
libhsakmt
runtime
)
# Tells the build system that this sub-project is expected to produce two
# `find_package` packages for consumers. The path is relative to the unified
# install directory layout.
therock_cmake_subproject_provide_package(ROCR-Runtime hsakmt lib/cmake/hsakmt)
therock_cmake_subproject_provide_package(ROCR-Runtime hsa-runtime64 lib/cmake/hsa-runtime64)
# Activates the sub-project once all customization is done. This is analogous
# to `FetchContent_MakeAvailable()` for that facility.
therock_cmake_subproject_activate(ROCR-Runtime)
```