Files
TheRock/cmake/therock_subproject_dep_provider.cmake
T
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

186 lines
9.1 KiB
CMake

# Copyright Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT
# find_package dependency provider
# This is injected into sub-projects that contain dependencies. It runs in a
# context with the following variables defined at the top level:
# THEROCK_PROVIDED_PACKAGES: Package names that are to be provided from the
# super-project
# THEROCK_PACKAGE_DIR_${package_name}: Directory in the super-project to
# resolve the dependency.
# THEROCK_IGNORE_PACKAGES: Packages to ignore, even if they are in
# THEROCK_PROVIDED_PACKAGES, falling back to the system resolver.
# THEROCK_PKG_CONFIG_DIRS: Directories to search for .pc files.
# THEROCK_STRICT_PROVIDED_PACKAGES: All packages that the super-project knows
# about. If a sub-project attempts to resolve one of these without a
# proper declared dependency, it will error.
# See: _therock_cmake_subproject_setup_deps which assembles these variables
block(PROPAGATE CMAKE_PREFIX_PATH)
set(prefix_extensions)
if(THEROCK_PKG_CONFIG_DIRS)
foreach(_dir ${THEROCK_PKG_CONFIG_DIRS})
# There is a mismatch between THEROCK_PKG_CONFIG_DIRS, which specifies
# a full path to the .pc file (i.e. /some/path/lib/pkgconfig) versus
# how CMAKE_PREFIX_PATH is parsed for the same. The latter expects each
# path to be to the prefix and it will probe sub-directory 'lib/pkgconfig'
# (actually from an allow list of suitable prefix extensions) to determine
# if the path will be extended and propagated to pkg-config. Therefore,
# we need to back up to the actual prefix path. For super-project
# pkg-config dirs (which is what we are dealing with here), this will
# always be two levels up (i.e. lib/pkgdata). We could add more validation
# of this, but it is actually somewhat open ended to determine *which*
# two levels it is (i.e. lib32 vs lib, share vs lib, etc). But is is
# always two.
cmake_path(GET _dir PARENT_PATH _dir)
cmake_path(GET _dir PARENT_PATH _dir)
list(APPEND prefix_extensions "${_dir}")
endforeach()
message(STATUS "Sub-project pkg-config prefixes: ${prefix_extensions}")
list(APPEND CMAKE_PREFIX_PATH ${prefix_extensions})
endif()
endblock()
macro(therock_dependency_provider method package_name)
cmake_policy(PUSH)
cmake_policy(SET CMP0057 NEW)
if("${package_name}" IN_LIST THEROCK_PROVIDED_PACKAGES AND NOT
"${package_name}" IN_LIST THEROCK_IGNORE_PACKAGES)
cmake_policy(POP)
# It is quite hard to completely neuter find_package so that for an
# arbitrary signature it will only attempt to find from one specified path.
# This is important because it "latches" and if any find_package manages
# to escape to the system, it will likely find a library from outside the
# super-project, which can cause all kinds of hard to diagnose issues.
# For background, read carefully:
# https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search-procedure
# We opt-to rewrite the signature, removing any options that connote an
# implicit search behavior and then rewrite the signature to be explicit.
# We further do this in a function to avoid macro namespace pollution, since
# the find_package itself must be evaluated in the caller-scope.
therock_reparse_super_project_find_package(
"${THEROCK_PACKAGE_DIR_${package_name}}" "${package_name}" ${ARGN})
find_package(${_therock_rewritten_superproject_find_package_sig})
else()
if("${package_name}" IN_LIST THEROCK_STRICT_PROVIDED_PACKAGES AND NOT
"${package_name}" IN_LIST THEROCK_IGNORE_PACKAGES)
cmake_policy(POP)
message(FATAL_ERROR "Project contains find_package(${package_name}) for a package availabe in the super-project but not declared: Add a BUILD_DEPS or RUNTIME_DEPS appropriately")
endif()
cmake_policy(POP)
message(STATUS "Resolving system find_package(${package_name}) (not found in super-project ${THEROCK_PROVIDED_PACKAGES})")
set(_therock_has_preserved_module_path FALSE)
find_package(${package_name} ${ARGN} BYPASS_PROVIDER)
if(_therock_has_preserved_module_path)
set(CMAKE_MODULE_PATH "${_therock_preserved_module_path}")
endif()
endif()
endmacro()
if(THEROCK_USE_SAFE_DEPENDENCY_PROVIDER AND THEROCK_PROVIDED_PACKAGES)
message(STATUS "Resolving packages from super-project: ${THEROCK_PROVIDED_PACKAGES}")
cmake_language(
SET_DEPENDENCY_PROVIDER therock_dependency_provider
SUPPORTED_METHODS FIND_PACKAGE
)
endif()
function(therock_reparse_super_project_find_package superproject_path package_name)
# We parse the arguments we want dropped from the find_package and then use
# what was unparsed.
cmake_parse_arguments(PARSE_ARGV 1 UNUSED
"BYPASS_PROVIDER;CONFIG;MODULE;NO_DEFAULT_PATH;NO_CMAKE_PATH;NO_CMAKE_ENVIRONMENT_PATH;NO_SYSTEM_ENVIRONMENT_PATH;NO_CMAKE_PACKAGE_REGISTRY"
""
"HINTS;PATHS"
)
if(NOT superproject_path)
message(FATAL_ERROR "Super-project package path not found for ${package_name}")
endif()
# The signature of MODULE vs DEFAULT mode is different, so switch.
set(_rewritten ${UNUSED_UNPARSED_ARGUMENTS})
# Some very old code uses explicit MODULE mode, which forces the basic
# signature (*cough* old FindHIP based junk). In this mode, there is no way
# to explicitly indicate a search path in the signature (and other options
# are illegal), so we fork on this and hard code the CMAKE_MODULE_PATH
# in the parent scope, also stashing the original and setting an indicator
# to restore it. This is not *the best* thing to be doing, but since this
# is a controlled ecosystem and used for very old things, we tolerate the
# pitfalls.
if(UNUSED_MODULE)
# Explicit find module.
list(APPEND _rewritten MODULE BYPASS_PROVIDER)
set(_therock_has_preserved_module_path TRUE PARENT_SCOPE)
set(_therock_preserved_module_path "${CMAKE_MODULE_PATH}" PARENT_SCOPE)
set(CMAKE_MODULE_PATH "${superproject_path}" PARENT_SCOPE)
else()
# By default, assume a FULL signature.
if(UNUSED_CONFIG)
list(APPEND _rewritten "CONFIG")
endif()
list(APPEND _rewritten BYPASS_PROVIDER NO_DEFAULT_PATH PATHS ${superproject_path})
endif()
list(JOIN _rewritten " " _rewritten_pretty)
message(STATUS "Resolving super-project find_package(${_rewritten_pretty})")
set(_therock_rewritten_superproject_find_package_sig ${_rewritten} PARENT_SCOPE)
endfunction()
# Action at a distance: sanitizers need to be able to find their runtime libraries,
# so if configuring a sanitizer, we set the THEROCK_INCLUDE_CLANG_RESOURCE_DIR_RPATH
# variable during toolchain setup. Now in the sub-project, we have access to clang
# and can ask it what its resource dir is. We use this to form a proper relative
# path and append it to the default RPATH dirs.
if(THEROCK_INCLUDE_CLANG_RESOURCE_DIR_RPATH)
block(PROPAGATE THEROCK_PRIVATE_INSTALL_RPATH_DIRS THEROCK_PRIVATE_BUILD_RPATH_DIRS)
execute_process(
COMMAND "${CMAKE_CXX_COMPILER}" --print-resource-dir
OUTPUT_VARIABLE _abs_resource_dir
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
# This will yield an absolute path like: /some/long/path/lib/llvm/lib/clang/20
# The version number on the end is all we want as we will form the correct
# prefix relative path from that.
# The actual libraries live under lib/linux in that directory. We shamelessly
# just hardcode "linux" since that is the only system we do RPATH munging for.
cmake_path(GET _abs_resource_dir FILENAME _clang_version)
set(_prefix_resource_dir "lib/llvm/lib/clang/${_clang_version}")
list(APPEND THEROCK_PRIVATE_INSTALL_RPATH_DIRS "${_prefix_resource_dir}/lib/linux")
# Build tree needs absolute paths to the resource dir.
list(APPEND THEROCK_PRIVATE_BUILD_RPATH_DIRS "${_abs_resource_dir}/lib/linux")
message(STATUS "Added clang resource dir to RPATH: ${_prefix_resource_dir} (since sanitizer enabled)")
endblock()
endif()
# Setup THEROCK_SANITIZER_LAUNCHER.
# Used by subprojects to run build-time tools (like Python) with the ASAN runtime preloaded.
# Needed for both ASAN and HOST_ASAN modes.
block(PROPAGATE THEROCK_SANITIZER_LAUNCHER)
set(THEROCK_SANITIZER_LAUNCHER)
if(LINUX AND THEROCK_SANITIZER)
if(THEROCK_SANITIZER STREQUAL "ASAN" OR THEROCK_SANITIZER STREQUAL "HOST_ASAN")
set(_suffix "asan")
elseif(THEROCK_SANITIZER STREQUAL "TSAN" OR THEROCK_SANITIZER STREQUAL "HOST_TSAN")
set(_suffix "tsan")
else()
message(FATAL_ERROR "Unknown Sanitizer: ${THEROCK_SANITIZER}")
endif()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
set(_arch_suffix "x86_64")
else()
message(FATAL_ERROR "Unknown processor ${CMAKE_SYSTEM_PROCESSOR}")
endif()
execute_process(
COMMAND ${CMAKE_CXX_COMPILER} "--print-file-name=libclang_rt.${_suffix}-${_arch_suffix}.so"
OUTPUT_VARIABLE _rt_path
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
set(THEROCK_SANITIZER_LAUNCHER
"${CMAKE_COMMAND}" -E env "LD_PRELOAD=${_rt_path}" --
)
message(STATUS "Sanitizer launcher: ${THEROCK_SANITIZER_LAUNCHER}")
endif()
endblock()