This guide documents how to add third-party dependencies to the TheRock super-project build system.
TheRock is a CMake-based super-project that coordinates building many sub-projects. Third-party dependencies can be integrated using one of three patterns:
- Pattern 1: CMake-Native Libraries - For libraries that use CMake and provide CMake config files
- Pattern 2: Meson-Based Header-Only Libraries - For cross-platform meson libraries that use pkg-config
- Pattern 3: Meson-Based System Dependencies - For OS-specific libraries needing special handling
| Criteria | Pattern 1 (CMake) | Pattern 2 (Meson Header-Only) | Pattern 3 (Meson Sysdeps) |
|---|---|---|---|
| Build System | CMake | Meson | Meson |
| Interface | CMake config (Find*.cmake or *Config.cmake) |
pkg-config (.pc file) |
pkg-config (.pc file) |
| Location | /develop/therock/third-party/ |
/develop/therock/third-party/ |
/develop/therock/third-party/sysdeps/ |
| Cross-platform | Usually | Yes | OS-specific (linux/windows) |
| Examples | eigen, nlohmann-json, fmt | simde | libdrm, numactl, elfutils |
| When to use | Library provides CMake support | Header-only or no CMake support, uses pkg-config | Needs symbol renaming, patching, or OS-specific install |
Each sub-project goes through 4 phases:
- configure: Initial CMake configuration
- build: Compilation (builds the
alltarget) - stage: Local install to
stage/directory - dist: Combined install merging this project's
stage/with all runtime dependencystage/directories
- BUILD_DEPS: Must build/stage before configure phase (compile-time dependencies)
- RUNTIME_DEPS: Must build before AND must be in unified distribution tree at runtime
Dependencies are declared in /develop/therock/core/CMakeLists.txt, NOT in the sub-project's own CMakeLists.txt. This is because TheRock is a super-project that manages all dependency relationships.
Examples: eigen, nlohmann-json, fmt
Create /develop/therock/third-party/<library>/CMakeLists.txt:
# Fetch the source tarball
# NOTE: Start with the original GitHub/upstream URL and add a TODO to mirror to S3.
# The tarball will be uploaded to S3 after initial testing.
therock_subproject_fetch(therock-<library>-sources
CMAKE_PROJECT # Optional: makes CMakeLists.txt visible to super-project
# TODO: Mirror to https://rocm-third-party-deps.s3.us-east-2.amazonaws.com/<library>-<version>.tar.gz
# Originally from: <upstream-url>
URL <github-or-upstream-url>
URL_HASH SHA256=<hash>
)
# Declare the sub-project
therock_cmake_subproject_declare(therock-<library>
BACKGROUND_BUILD # Run in job pool for parallelism
EXCLUDE_FROM_ALL # Don't build by default
NO_MERGE_COMPILE_COMMANDS # Skip compile_commands.json merging
OUTPUT_ON_FAILURE # Suppress output unless failure
EXTERNAL_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/source"
CMAKE_ARGS # Optional: pass arguments to library's CMake
-D<LIBRARY>_BUILD_TESTS=OFF
)
# Provide package for find_package() redirection
therock_cmake_subproject_provide_package(
therock-<library> <PackageName> <relative/path/to/cmake/config>)
# Activate the sub-project
therock_cmake_subproject_activate(therock-<library>)
# Add to third-party meta-target
add_dependencies(therock-third-party therock-<library>)Add to /develop/therock/third-party/CMakeLists.txt:
add_subdirectory(<library>)Example: simde
For meson-based header-only libraries that are cross-platform and don't need the rocm_sysdeps infrastructure.
- pkg-config, not CMake config: Use
INTERFACE_PKG_CONFIG_DIRS, NOTtherock_cmake_subproject_provide_package() - Dual-mode CMakeLists.txt: One file serves as both super-project integration and sub-project build script
- Meson invocation: Must use specific flags for relocatable, arch-neutral builds
- DESTDIR installation: Install using DESTDIR environment variable, not direct prefix
Create /develop/therock/third-party/<library>/CMakeLists.txt:
# Section 1: Super-project integration (when included from TheRock)
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
# CRITICAL: Detect meson in super-project context where venv PATH is available
# The sub-project (Section 2) doesn't have access to the same environment,
# so tool detection MUST happen here and be passed through CMAKE_ARGS.
find_program(MESON_BUILD meson)
if(NOT MESON_BUILD)
message(FATAL_ERROR "Building <library> requires meson (install with: pip install meson)")
endif()
# Fetch the source tarball
set(_source_dir "${CMAKE_CURRENT_BINARY_DIR}/source")
set(_download_stamp "${_source_dir}/download.stamp")
therock_subproject_fetch(therock-<library>-sources
SOURCE_DIR "${_source_dir}"
# TODO: Mirror to https://rocm-third-party-deps.s3.us-east-2.amazonaws.com/<library>-<version>.tar.gz
# Originally from: <upstream-url>
URL <github-or-upstream-url>
URL_HASH SHA256=<hash>
TOUCH "${_download_stamp}"
)
# Declare the sub-project (uses this same CMakeLists.txt as sub-build)
therock_cmake_subproject_declare(therock-<library>
EXTERNAL_SOURCE_DIR .
BINARY_DIR build
NO_MERGE_COMPILE_COMMANDS
BACKGROUND_BUILD
OUTPUT_ON_FAILURE
CMAKE_ARGS
"-DSOURCE_DIR=${_source_dir}"
"-DMESON_BUILD=${MESON_BUILD}" # Pass detected tool path to sub-project
"-DPython3_EXECUTABLE=${Python3_EXECUTABLE}"
INTERFACE_PKG_CONFIG_DIRS
lib/pkgconfig
EXTRA_DEPENDS
"${_download_stamp}"
)
# Note: NO therock_cmake_subproject_provide_package() - library uses pkg-config
therock_cmake_subproject_activate(therock-<library>)
add_dependencies(therock-third-party therock-<library>)
return()
endif()
# Section 2: Sub-project build (invoked by super-project)
cmake_minimum_required(VERSION 3.25)
project(<LIBRARY>_BUILD)
if(NOT MESON_BUILD)
message(FATAL_ERROR "Missing MESON_BUILD from super-project")
endif()
# Meson refuses to build if source dir is subdir of build dir
set(PATCH_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/../patch_source")
add_custom_target(
meson_build ALL
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMAND
# Clean previous build
"${CMAKE_COMMAND}" -E rm -rf -- "${CMAKE_INSTALL_PREFIX}" "${PATCH_SOURCE_DIR}"
COMMAND
# Copy sources (in case we need to patch in the future)
"${CMAKE_COMMAND}" -E copy_directory "${SOURCE_DIR}" "${PATCH_SOURCE_DIR}"
COMMAND
# Meson setup - CRITICAL FLAGS for relocatable builds
"${CMAKE_COMMAND}" -E chdir "${PATCH_SOURCE_DIR}"
"${MESON_BUILD}" setup "${CMAKE_CURRENT_BINARY_DIR}"
--reconfigure
# We generate relocatable, arch neutral directory layouts
--prefix "/"
-Dpkgconfig.relocatable=true
-Dlibdir=lib
# Library-specific options (e.g., disable tests)
-Dtests=false
COMMAND
# Build (may be minimal for header-only)
"${MESON_BUILD}" compile --verbose
COMMAND
# Install using DESTDIR
"${CMAKE_COMMAND}" -E env "DESTDIR=${CMAKE_INSTALL_PREFIX}" --
"${MESON_BUILD}" install
)Always use these flags for relocatable builds:
--prefix "/": Set prefix to root (DESTDIR will provide actual location)-Dpkgconfig.relocatable=true: Makes .pc file use${pcfiledir}for paths-Dlibdir=lib: Ensures libraries go inlib/notlib64/orlib/x86_64-linux-gnu/
After building, verify the integration:
# 1. Check stage directory structure
ls -la /develop/therock-build/third-party/<library>/build/stage/
# Expected structure:
# include/<library>/ # Headers
# lib/pkgconfig/ # .pc file
# 2. Verify pkg-config file is relocatable
cat /develop/therock-build/third-party/<library>/build/stage/lib/pkgconfig/<library>.pc
# Should contain: prefix=${pcfiledir}/../..
# 3. Test pkg-config
PKG_CONFIG_PATH=/develop/therock-build/third-party/<library>/build/stage/lib/pkgconfig \
pkg-config --cflags <library>Add to /develop/therock/third-party/CMakeLists.txt:
add_subdirectory(<library>)Example: libdrm
For system dependencies that need special handling, symbol renaming, or OS-specific installation.
Create /develop/therock/third-party/sysdeps/linux/<library>/CMakeLists.txt with two sections:
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
# Fetch sources
set(_source_dir "${CMAKE_CURRENT_BINARY_DIR}/source")
set(_download_stamp "${_source_dir}/download.stamp")
therock_subproject_fetch(therock-<library>-sources
SOURCE_DIR "${_source_dir}"
URL "https://rocm-third-party-deps.s3.us-east-2.amazonaws.com/<library>-<version>.tar.gz"
URL_HASH "SHA256=<hash>"
TOUCH "${_download_stamp}"
)
# Declare sub-project (uses this same CMakeLists.txt as sub-build)
therock_cmake_subproject_declare(therock-<library>
EXTERNAL_SOURCE_DIR .
BINARY_DIR build
NO_MERGE_COMPILE_COMMANDS
BACKGROUND_BUILD
OUTPUT_ON_FAILURE
CMAKE_ARGS
"-DSOURCE_DIR=${_source_dir}"
"-DMESON_BUILD=${MESON_BUILD}"
"-DPython3_EXECUTABLE=${Python3_EXECUTABLE}"
INSTALL_DESTINATION lib/rocm_sysdeps
INTERFACE_LINK_DIRS lib/rocm_sysdeps/lib
INTERFACE_INSTALL_RPATH_DIRS lib/rocm_sysdeps/lib
INTERFACE_PKG_CONFIG_DIRS lib/rocm_sysdeps/lib/pkgconfig
EXTRA_DEPENDS "${_download_stamp}"
)
therock_cmake_subproject_activate(therock-<library>)
return()
endif()# Sub-project build logic
cmake_minimum_required(VERSION 3.25)
project(<LIBRARY>_BUILD)
# Invoke meson
add_custom_target(meson_build ALL
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMAND "${CMAKE_COMMAND}" -E rm -rf -- "${CMAKE_INSTALL_PREFIX}"
COMMAND "${MESON_BUILD}" setup "${CMAKE_CURRENT_BINARY_DIR}"
--prefix "/"
-Dlibdir=lib
# ... meson options ...
COMMAND "${MESON_BUILD}" compile --verbose
COMMAND "${CMAKE_COMMAND}" -E env "DESTDIR=${CMAKE_INSTALL_PREFIX}" --
"${MESON_BUILD}" install
)Add to /develop/therock/third-party/sysdeps/linux/CMakeLists.txt:
add_subdirectory(<library>)In /develop/therock/CMakeLists.txt, add to the bundled variables section:
set(THEROCK_BUNDLED_<LIBRARY>) # Initialize as empty
if(THEROCK_BUNDLE_SYSDEPS)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(THEROCK_BUNDLED_<LIBRARY> therock-<library>)
endif()
endif()Dependencies are declared in /develop/therock/core/CMakeLists.txt:
therock_cmake_subproject_declare(ROCR-Runtime
...
BUILD_DEPS
therock-<library> # Add your library here
...
)therock_cmake_subproject_declare(ROCR-Runtime
...
RUNTIME_DEPS
${THEROCK_BUNDLED_<LIBRARY>} # Expands to library name or empty string
...
)IMPORTANT: After adding a new dependency, document the canonical way to use it in /develop/therock/docs/development/dependencies.md.
This file provides the standard way for ROCm projects to depend on the library. Add an entry in alphabetical order with:
- Brief description
- Canonical method (find_package or pkg_check_modules)
- Import library name
- Variables provided
- Alternative methods (if any)
- Any special notes
Example for pkg-config based library:
## simde
SIMDe (SIMD Everywhere) is a header-only portability library for SIMD intrinsics.
- Canonical method: `pkg_check_modules(simde REQUIRED IMPORTED_TARGET simde)`
- Import library: `PkgConfig::simde`
- Vars: `simde_INCLUDE_DIRS`
- Alternatives: none
- Note: Header-only library, provides portable SIMD intrinsics (SSE, AVX, NEON, etc.)Example for CMake config based library:
## eigen
- Canonical method: `find_package(Eigen3)`
- Import library: `Eigen3::Eigen`
- Alternatives: noneThis documentation ensures consistent usage across all ROCm projects.
Downloads external content (like FetchContent).
URL: Source tarball URLURL_HASH: SHA256 hash for verificationSOURCE_DIR: Where to extractTOUCH: Stamp file for dependenciesCMAKE_PROJECT: Makes CMakeLists.txt visible to super-project
Main function to declare a sub-project.
EXTERNAL_SOURCE_DIR: Path to sourcesBINARY_DIR: Build directoryBUILD_DEPS: Build-time dependencies (compile-time)RUNTIME_DEPS: Runtime dependencies (must be in dist tree)CMAKE_ARGS: Arguments passed to CMakeINSTALL_DESTINATION: Subdirectory in stage/dist (e.g.,lib/rocm_sysdeps)INTERFACE_LINK_DIRS: Advertise library directories to dependentsINTERFACE_INSTALL_RPATH_DIRS: Advertise rpath directoriesBACKGROUND_BUILD: Run in job pool for parallelismNO_MERGE_COMPILE_COMMANDS: Skip compile_commands.json mergingOUTPUT_ON_FAILURE: Suppress output unless failureEXTRA_DEPENDS: Additional dependencies (e.g., download stamps)
Advertises that this sub-project provides a find_package() package.
- Enables dependency provider to redirect
find_package()calls - Example:
therock_cmake_subproject_provide_package(ROCR-Runtime hsakmt lib/cmake/hsakmt)
Tells super-project to watch source files for changes.
- Without this, changing sources won't trigger rebuild
Finalizes and activates the sub-project.
- Like
FetchContent_MakeAvailable() - Must be called last after all configuration
cmake -B /develop/therock-build -S /develop/therock -GNinja \
-DTHEROCK_AMDGPU_FAMILIES=gfx1201 \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccachecd /develop/therock-build
ninja <component>+expunge && ninja <component>+dist- Dependencies are declared in core/CMakeLists.txt, not in the sub-project's own CMakeLists.txt
- BUILD_DEPS vs RUNTIME_DEPS: Use BUILD_DEPS for header-only libs, RUNTIME_DEPS for shared libraries
- THEROCK_BUNDLED_ pattern*: Required for optional system dependencies
- Download stamps: Use
EXTRA_DEPENDSwith stamp files to ensure fetch completes first - Dual-mode CMakeLists.txt: For meson libraries, guard super-project logic with
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
- Tool detection in super-project: CRITICAL - Detect meson using
find_program()in Section 1 (super-project), NOT in Section 2 (sub-project). The sub-project CMake invocation doesn't have access to the same shell environment/PATH as the super-project. Always pass detected tools via CMAKE_ARGS. - Environment setup: Before building, activate the venv:
source /develop/therock-venv/bin/activate. This provides meson and other build tools. Without it,find_program(meson)will fail even though meson is in requirements.txt. - pkg-config, not CMake: Use
INTERFACE_PKG_CONFIG_DIRS, NOTtherock_cmake_subproject_provide_package()for meson libraries - Critical meson flags: Always use
--prefix "/",-Dpkgconfig.relocatable=true,-Dlibdir=lib - DESTDIR installation: Use
DESTDIR=${CMAKE_INSTALL_PREFIX}when callingmeson install - Source directory location: Meson refuses to build if source dir is a subdirectory of build dir (use PATCH_SOURCE_DIR)
- Verification: Always check that .pc file contains
prefix=${pcfiledir}/../..for relocatability - Testing iterations: Use
ninja <library>+expunge && ninja <library>to fully rebuild from scratch
- No absolute paths in docs: Never use absolute paths like
/develop/therockin documentation files - Avoid find_path: Don't recommend
find_path()for dependencies - it's fragile. Usefind_package()orpkg_check_modules()only - List "none" for alternatives: If there are no good alternatives, explicitly state
- Alternatives: none
- Build system documentation:
/develop/therock/docs/development/build_system.md - Core dependency declarations:
/develop/therock/core/CMakeLists.txt - Third-party examples:
/develop/therock/third-party/ - Sysdeps examples:
/develop/therock/third-party/sysdeps/linux/ - CMake functions:
/develop/therock/cmake/therock_subproject.cmake