Files
TheRock/debug-tools/rocgdb/CMakeLists.txt
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

811 lines
31 KiB
CMake

# Copyright Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT
# This is a CMake wrapper to build rocgdb from within TheRock. Since GDB's
# build system is autotools-based, we need the wrapper to call the right
# functions and provide the proper include and library paths.
#
# We also take care of cycling through the available Python versions and
# building gdb against each of those.
# Available defines to be used when building rocgdb:
#
# BUILD_TESTING
#
# Enable integrity tests and installation of ROCgdb's testsuite files.
# Usually ON by default in cmake, unless set otherwise.
#
# If set to ON, adds a number of ROCgdb build integrity tests that will
# validate the expected files exist. It also triggers the installation of
# the ROCgdb testsuite files. If set to OFF, no build integrity tests will
# be included and no testsuite files will be installed.
#
#
# PATCHELF
#
# Contains the path to the patchelf utility. This must be passed so
# post-install RPATH patching can take place.
#
#
# ROCGDB_SOURCE_DIR
#
# Specifies the location of the ROCgdb sources. Used by TheRock to build
# ROCgdb from an alternative source location.
#
#
# ROCM_VERSION
#
# Specifies the ROCM version we are building for. If empty or non-existent
# we default to "ROCm development".
#
#
# SHARED_PYTHON_EXECUTABLES
#
# A semicolon-separated list of paths to Python executables that support
# linking against a shared libpython. If empty or non-existent only a
# Pythonless rocgdb (rocgdb-pynone) will be built. Otherwise one rocgdb
# will be built for each of the Python entries on the list, as long as
# each entry supports linking against libpython.
#
# Example: SHARED_PYTHON_EXECUTABLES="/opt/python-shared/cp310-cp310/bin/python3"
cmake_minimum_required(VERSION 3.25)
project(rocgdb C CXX)
include(ExternalProject)
include(ProcessorCount)
# Function to find a library package and extract its install prefix.
# Uses find_package() which respects CMAKE_PREFIX_PATH and TheRock's
# dependency provider system.
#
# Usage:
# find_library_prefix(<package_name> <target_name> <output_var>)
#
# Example:
# find_library_prefix(gmp gmp::gmp GMP_PREFIX)
#
function(find_library_prefix package_name target_name output_var)
find_package(${package_name} REQUIRED)
if(TARGET ${target_name})
# Extract the library location from the imported target
get_target_property(_lib_location ${target_name} IMPORTED_LOCATION)
if(_lib_location)
# Get the directory containing the library (e.g., .../lib)
cmake_path(GET _lib_location PARENT_PATH _lib_dir)
# Get the install prefix (e.g., .../lib -> ...)
cmake_path(GET _lib_dir PARENT_PATH _prefix)
set(${output_var} "${_prefix}" PARENT_SCOPE)
message(STATUS "Found ${package_name} at prefix: ${_prefix}")
else()
message(FATAL_ERROR "Found ${package_name} target but could not extract location")
endif()
else()
message(FATAL_ERROR "Required package ${package_name} not found.")
endif()
endfunction()
# By default install the ROCgdb testsuite files.
option(ENABLE_TESTS "Enable installation of ROCgdb testsuite files" OFF)
# Upstream build mode: skips AMD-specific files not yet in upstream master
# (NOTICES.txt, roccoremerge program/manpage).
option(ROCGDB_UPSTREAM_BUILD "Building from upstream master (skips AMD-specific files)" OFF)
# When the rocgdb source tree does not carry .github/scripts/test_rocgdb.py
# (e.g. an upstream branch), fetch it from ROCm/ROCgdb amd-staging at configure
# time so that it can be installed into tests/rocgdb for TheRock CI to invoke.
option(ROCGDB_DOWNLOAD_CI_SCRIPT "Download test_rocgdb.py from amd-staging if missing in source tree" OFF)
# Find standard build tools.
find_program(MAKE_EXECUTABLE NAMES make REQUIRED)
ProcessorCount(PAR_JOBS)
# Configure build type flags.
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
# Standard flags are handled by CMAKE_C_FLAGS, CMAKE_C_FLAGS_DEBUG, etc.
# Initialize with base flags and build-type-specific flags.
set(CUSTOM_C_FLAGS "${CMAKE_C_FLAGS}")
set(CUSTOM_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# Append build-type-specific flags.
string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type_upper)
if(_build_type_upper)
string(APPEND CUSTOM_C_FLAGS " ${CMAKE_C_FLAGS_${_build_type_upper}}")
string(APPEND CUSTOM_CXX_FLAGS " ${CMAKE_CXX_FLAGS_${_build_type_upper}}")
endif()
# Set custom flags for Debug builds.
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
string(APPEND CUSTOM_C_FLAGS " -O0 -g3")
string(APPEND CUSTOM_CXX_FLAGS " -O0 -g3")
endif()
# Harden against stack clash attacks (not supported on all platforms).
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
string(APPEND CUSTOM_C_FLAGS " -fstack-clash-protection")
string(APPEND CUSTOM_CXX_FLAGS " -fstack-clash-protection")
endif()
# Compiler commands to chain to autotools.
set(CUSTOM_CC "${CMAKE_C_COMPILER}")
if(CMAKE_C_COMPILER_LAUNCHER)
string(PREPEND CUSTOM_CC "${CMAKE_C_COMPILER_LAUNCHER} ")
endif()
set(CUSTOM_CXX "${CMAKE_CXX_COMPILER}")
if(CMAKE_CXX_COMPILER_LAUNCHER)
string(PREPEND CUSTOM_CXX "${CMAKE_CXX_COMPILER_LAUNCHER} ")
endif()
message(STATUS "Build type set to: ${CMAKE_BUILD_TYPE}")
# amd-dbgapi is always a required dependency for ROCgdb
find_package(amd-dbgapi REQUIRED CONFIG)
# Fetch the install prefixes for the library and executables rocgdb
# depends on. When THEROCK_BUNDLE_SYSDEPS is OFF, these are left empty and
# GDB's configure script discovers the libraries via pkg-config instead.
set(NCURSES_RPATH "")
set(NCURSES_INCLUDE "")
if(THEROCK_BUNDLE_SYSDEPS)
find_library_prefix(gmp gmp::gmp GMP_PREFIX)
find_library_prefix(mpfr mpfr::mpfr MPFR_PREFIX)
find_library_prefix(expat expat::expat EXPAT_PREFIX)
find_library_prefix(ncurses ncurses::ncurses NCURSES_PREFIX)
# We need to explicitly pass ncurses' include path and set the rpath for
# the library. The reason we need to explicitly pass rpath is because gdb's
# configure assumes ncurses is always picked up from the default system
# location, or that the library is always within reach.
#
# Since we're building our own ncurses and it is in a non-standard location,
# the rpath assures the configure tests properly locate the library.
# Extract include and lib directories from the ncurses imported target.
if(TARGET ncurses::ncurses)
get_target_property(_ncurses_includes ncurses::ncurses INTERFACE_INCLUDE_DIRECTORIES)
get_target_property(_ncurses_location ncurses::ncurses IMPORTED_LOCATION)
if(_ncurses_includes)
set(NCURSES_INCLUDE "-I${_ncurses_includes}")
endif()
if(_ncurses_location)
cmake_path(GET _ncurses_location PARENT_PATH _ncurses_lib_dir)
set(NCURSES_RPATH "-Wl,-rpath,${_ncurses_lib_dir}")
endif()
endif()
# Adjust the compilation flags with the bundled ncurses include path.
if(NCURSES_INCLUDE)
set(CUSTOM_C_FLAGS "${CUSTOM_C_FLAGS} ${NCURSES_INCLUDE}")
set(CUSTOM_CXX_FLAGS "${CUSTOM_CXX_FLAGS} ${NCURSES_INCLUDE}")
endif()
endif()
# Add RPATH entries for sanitizer runtime libraries if needed.
# THEROCK_PRIVATE_BUILD_RPATH_DIRS contains absolute paths to directories
# needed during build/configure (e.g., clang sanitizer runtime).
set(SANITIZER_RPATH "")
if(DEFINED THEROCK_PRIVATE_BUILD_RPATH_DIRS AND NOT "${THEROCK_PRIVATE_BUILD_RPATH_DIRS}" STREQUAL "")
foreach(build_rpath_dir ${THEROCK_PRIVATE_BUILD_RPATH_DIRS})
string(APPEND SANITIZER_RPATH "-Wl,-rpath,${build_rpath_dir} ")
endforeach()
string(STRIP "${SANITIZER_RPATH}" SANITIZER_RPATH)
message(STATUS "Adding sanitizer RPATH for configure/build: ${SANITIZER_RPATH}")
endif()
# Adjust LDFLAGS. NCURSES_RPATH and SANITIZER_RPATH are empty when not using bundled sysdeps or sanitizers.
set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${NCURSES_RPATH} ${SANITIZER_RPATH} -Wl,--enable-new-dtags")
# Replace all semicolons (the CMake separator) with colons (the ENV separator).
# We need this to pass it on to rocgdb's configure.
string(REPLACE ";" ":" PKG_CONFIG_PATH_ENV_VAR "${THEROCK_PKG_CONFIG_DIRS}")
# Set conditional configure flags for bundled sysdep prefixes. When using system
# libraries, these are left empty so autotools discovers them via pkg-config.
set(ROCGDB_EXPAT_FLAG "")
set(ROCGDB_GMP_FLAG "")
set(ROCGDB_MPFR_FLAG "")
if(THEROCK_BUNDLE_SYSDEPS)
set(ROCGDB_EXPAT_FLAG "--with-expat-prefix=${EXPAT_PREFIX}")
set(ROCGDB_GMP_FLAG "--with-gmp=${GMP_PREFIX}")
set(ROCGDB_MPFR_FLAG "--with-mpfr=${MPFR_PREFIX}")
endif()
# Build RPATH segments from THEROCK_PRIVATE_INSTALL_RPATH_DIRS if defined.
# These paths are relative to <root>, but need to be relative to <root>/bin.
# If not defined, fall back to hardcoded sysdeps path for backward compatibility.
set(ROCGDB_EXTRA_RPATH_SEGMENTS "")
if(DEFINED THEROCK_PRIVATE_INSTALL_RPATH_DIRS AND NOT "${THEROCK_PRIVATE_INSTALL_RPATH_DIRS}" STREQUAL "")
foreach(rpath_dir ${THEROCK_PRIVATE_INSTALL_RPATH_DIRS})
# Convert path from <root>-relative to <root>/bin-relative by prepending ../
string(APPEND ROCGDB_EXTRA_RPATH_SEGMENTS ":\\\$ORIGIN/../${rpath_dir}")
endforeach()
message(STATUS "RPATH segments from THEROCK_PRIVATE_INSTALL_RPATH_DIRS: ${ROCGDB_EXTRA_RPATH_SEGMENTS}")
elseif(THEROCK_BUNDLE_SYSDEPS)
# Fallback for older builds without THEROCK_PRIVATE_INSTALL_RPATH_DIRS
set(ROCGDB_EXTRA_RPATH_SEGMENTS ":\\\$ORIGIN/../lib/rocm_sysdeps/lib")
endif()
# Set some global variables for the configure/build.
set(ROCGDB_BUG_URL "https://github.com/ROCm-Developer-Tools/ROCgdb/issues")
set(ROCGDB_SEPARATE_DEBUG_INFO_DIR "\\\${prefix}/lib/debug:/usr/lib/debug")
set(ROCGDB_DATA_DIR "\\\${prefix}/share/rocgdb")
set(ROCGDB_TARGETS "x86_64-linux-gnu,amdgcn-amd-amdhsa")
# If the version is not set, set it to a generic value.
if (NOT ROCM_VERSION)
set(ROCM_BUILD_ID "ROCm development")
else()
set(ROCM_BUILD_ID "ROCm-${ROCM_VERSION}")
endif()
# List to accumulate all unique build targets.
set(ALL_ROCGDB_TARGETS)
# Adds a rocgdb build target for a python variant with explicit additional configure flags.
# The special minor_version "none" indicates that the build is without python support.
#
# For variants with minor_version other than "none", libpython_dir must contain
# the path to the shared libpython rocgdb should link against.
macro(add_python_variant minor_version configure_flags libpython_dir)
# Set the name transformation for the rocgdb executable and rocgcore script.
set(ROCGDB_PROGRAM_TRANSFORM_STR "s/^rocgdb$/rocgdb-py${minor_version}/")
# Define a unique name for the build directory.
set(ROCGDB_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/rocgdb-build-py${minor_version}")
# Define a unique name for the intermediate install directory.
set(ROCGDB_INTERMEDIATE_INSTALL_DIR "${ROCGDB_BUILD_DIR}-install")
set(ROCGDB_TARGET_NAME "rocgdb-py${minor_version}")
# If we have a valid libpython_dir, adjust the LDFLAGS for this build
# variant and add an extra RPATH entry for post-install patching.
#
# Skip this for system library directories (under /usr, excluding /usr/local).
# The linker already searches these by default, and explicitly adding them
# via -L pulls in unrelated system static archives (e.g. libiberty.a from
# libiberty-dev) that conflict with GDB's bundled copies. GDB's configure
# finds system libpython on its own via --with-python without needing -L.
# Non-system libpython (custom builds, /opt, /usr/local, etc.) still needs
# the explicit flags since those paths are not in the default search order.
# See https://github.com/ROCm/TheRock/issues/4223
set(ALL_LDFLAGS ${LDFLAGS})
set(LIBPYTHON_RPATH "")
if(NOT "${libpython_dir}" STREQUAL "")
set(_usr_prefix "/usr")
set(_usr_local_prefix "/usr/local")
cmake_path(IS_PREFIX _usr_prefix "${libpython_dir}" NORMALIZE _is_under_usr)
cmake_path(IS_PREFIX _usr_local_prefix "${libpython_dir}" NORMALIZE _is_under_usr_local)
if(_is_under_usr AND NOT _is_under_usr_local)
message(STATUS "-> Skipping extra LDFLAGS for system libpython dir: ${libpython_dir}")
else()
set(LIBPYTHON_LDFLAGS "-L${libpython_dir} -Wl,-rpath,${libpython_dir}")
string(APPEND ALL_LDFLAGS " ${LIBPYTHON_LDFLAGS}")
set(LIBPYTHON_RPATH ":${libpython_dir}")
message(STATUS "-> Extra LDFLAGS: ${LIBPYTHON_LDFLAGS}")
message(STATUS "-> Extra RPATH: ${LIBPYTHON_RPATH}")
endif()
endif()
# These directories are adjusted here so we don't have to escape
# ${prefix} and make it survive across multiple expansions from shells
# cmake and libtool.
set(ROCGDB_HTML_DIR "${ROCGDB_INTERMEDIATE_INSTALL_DIR}/share/html")
set(ROCGDB_PDF_DIR "${ROCGDB_INTERMEDIATE_INSTALL_DIR}/share/doc")
set(ROCGDB_INFO_DIR "${ROCGDB_INTERMEDIATE_INSTALL_DIR}/share/info/rocgdb")
# Build AMD-specific install commands (conditionally included).
set(AMD_SPECIFIC_INSTALL_COMMANDS "")
if(NOT ROCGDB_UPSTREAM_BUILD)
list(APPEND AMD_SPECIFIC_INSTALL_COMMANDS
COMMAND ${CMAKE_COMMAND} -E copy ${ROCGDB_SOURCE_DIR}/gdb/NOTICES.txt ${ROCGDB_INTERMEDIATE_INSTALL_DIR}/share/doc/
)
endif()
add_custom_target("${ROCGDB_TARGET_NAME}"
ALL
VERBATIM
COMMENT "rocgdb (python ${CURRENT_PYTHON_EXECUTABLE})"
# Create the build directory
COMMAND ${CMAKE_COMMAND} -E make_directory "${ROCGDB_BUILD_DIR}"
# Configure
COMMAND
${CMAKE_COMMAND} -E chdir "${ROCGDB_BUILD_DIR}"
${CMAKE_COMMAND} -E env
"CC=${CUSTOM_CC}"
"CXX=${CUSTOM_CXX}"
"PKG_CONFIG_PATH=${PKG_CONFIG_PATH_ENV_VAR}"
"CFLAGS=${CUSTOM_C_FLAGS}"
"CXXFLAGS=${CUSTOM_CXX_FLAGS}"
"LDFLAGS=${ALL_LDFLAGS}"
--
# The actual configure command.
${ROCGDB_SOURCE_DIR}/configure
"--prefix=${ROCGDB_INTERMEDIATE_INSTALL_DIR}"
--program-prefix=roc
"--program-transform-name=${ROCGDB_PROGRAM_TRANSFORM_STR}"
--enable-64-bit-bfd
"--enable-targets=${ROCGDB_TARGETS}"
--enable-tui
"--htmldir=${ROCGDB_HTML_DIR}"
"--pdfdir=${ROCGDB_PDF_DIR}"
"--infodir=${ROCGDB_INFO_DIR}"
--with-amd-dbgapi
"--with-bugurl=${ROCGDB_BUG_URL}"
${ROCGDB_EXPAT_FLAG}
"--with-gdb-datadir=${ROCGDB_DATA_DIR}"
${ROCGDB_GMP_FLAG}
--with-lzma
${ROCGDB_MPFR_FLAG}
"--with-pkgversion=${ROCM_BUILD_ID}"
"--with-separate-debug-dir=${ROCGDB_SEPARATE_DEBUG_INFO_DIR}"
--with-system-zlib
--with-zstd
--disable-gas
--disable-gdbserver
--disable-gdbtk
--disable-gprofng
--disable-ld
--disable-shared
--disable-sim
--without-babeltrace
--without-debuginfod
--without-guile
--without-intel-pt
--without-libunwind-ia64
--without-xxhash
${configure_flags}
# Build
COMMAND
${CMAKE_COMMAND} -E chdir "${ROCGDB_BUILD_DIR}"
${MAKE_EXECUTABLE} -s -j "${PAR_JOBS}"
# Install gdb.
COMMAND
${CMAKE_COMMAND} -E chdir "${ROCGDB_BUILD_DIR}"
${MAKE_EXECUTABLE} -s -C gdb install
# Install gdb docs.
COMMAND
${CMAKE_COMMAND} -E chdir "${ROCGDB_BUILD_DIR}"
${MAKE_EXECUTABLE} -s -C gdb install-html
# Install binutils for coremerge and coremerge manpage.
COMMAND
${CMAKE_COMMAND} -E chdir "${ROCGDB_BUILD_DIR}"
${MAKE_EXECUTABLE} -s -C binutils install
# Create doc directory and add AMD-specific files (NOTICES.txt) if not building upstream.
COMMAND
${CMAKE_COMMAND} -E make_directory ${ROCGDB_INTERMEDIATE_INSTALL_DIR}/share/doc
${AMD_SPECIFIC_INSTALL_COMMANDS}
# Rename rocgcore to rocgcore-py<python version>.
COMMAND
${CMAKE_COMMAND} -E rename ${ROCGDB_INTERMEDIATE_INSTALL_DIR}/bin/rocgcore ${ROCGDB_INTERMEDIATE_INSTALL_DIR}/bin/rocgcore-py${minor_version}
)
list(APPEND ALL_ROCGDB_TARGETS ${ROCGDB_TARGET_NAME})
# We only want to install a subset of the files, so we list them here,
# relative to their intermediate install prefixes.
# For instance, we don't want to include any binutils files other than
# roccoremerge.
# Misc directories.
set(ROCGDB_MISC_DIRS_TO_INSTALL
"include"
"share/doc"
"share/man/man5"
"share/rocgdb"
)
# Executable files.
set(ROCGDB_EXEC_FILES_TO_INSTALL
"bin/rocgcore-py${minor_version}"
"bin/rocgdb-py${minor_version}"
)
# Misc files.
set(ROCGDB_MISC_FILES_TO_INSTALL
"share/info/rocgdb/annotate.info"
"share/info/rocgdb/gdb.info"
"share/man/man1/rocgdb.1"
"share/man/man1/rocgcore.1"
"share/man/man1/rocgdb-add-index.1"
)
# AMD-specific files not yet in upstream master.
if(NOT ROCGDB_UPSTREAM_BUILD)
list(APPEND ROCGDB_EXEC_FILES_TO_INSTALL "bin/roccoremerge")
list(APPEND ROCGDB_MISC_FILES_TO_INSTALL "share/man/man1/roccoremerge.1")
endif()
# Register the final installation step for this variant's files.
# This basically moves the variant files from the intermediate install
# prefix to the final installation location.
foreach(rocgdb_dir ${ROCGDB_MISC_DIRS_TO_INSTALL})
# The last "/" is important, as we want to copy the contents from the
# listed directory into another directory, and not the directory itself.
install(DIRECTORY ${ROCGDB_INTERMEDIATE_INSTALL_DIR}/${rocgdb_dir}/
DESTINATION "${rocgdb_dir}"
USE_SOURCE_PERMISSIONS
COMPONENT rocgdb)
endforeach()
foreach(rocgdb_file ${ROCGDB_EXEC_FILES_TO_INSTALL})
install(PROGRAMS ${ROCGDB_INTERMEDIATE_INSTALL_DIR}/${rocgdb_file}
DESTINATION bin
COMPONENT rocgdb)
endforeach()
foreach(rocgdb_file ${ROCGDB_MISC_FILES_TO_INSTALL})
# Get the directory part of the file.
get_filename_component(file_dir ${rocgdb_file} DIRECTORY)
install(FILES ${ROCGDB_INTERMEDIATE_INSTALL_DIR}/${rocgdb_file}
DESTINATION ${file_dir}
COMPONENT rocgdb)
endforeach()
# Register RPATH patching for this rocgdb variant.
message(STATUS "Registering fixup of ${CMAKE_INSTALL_PREFIX}/bin/rocgdb-py${minor_version}")
install(CODE "execute_process(
COMMAND \"${PATCHELF}\" --set-rpath \"\$ORIGIN${ROCGDB_EXTRA_RPATH_SEGMENTS}${LIBPYTHON_RPATH}\"
\"${CMAKE_INSTALL_PREFIX}/bin/rocgdb-py${minor_version}\"
COMMAND_ERROR_IS_FATAL ANY
)"
COMPONENT rocgdb)
if(BUILD_TESTING)
# Track for build validation.
list(APPEND ROCGDB_BUILD_INTEGRITY_FILES "bin/rocgdb-py${minor_version}")
list(APPEND ROCGDB_BUILD_INTEGRITY_FILES "bin/rocgcore-py${minor_version}")
endif()
endmacro()
# Determine python versions either from the explicit list of dist python executables
# or from the global Python3_EXECUTABLE.
if(SHARED_PYTHON_EXECUTABLES)
message(STATUS "Available python-shared: ${SHARED_PYTHON_EXECUTABLES}")
# Build once for each shared-built python executables we were told to use.
# Note that the build will fail if libpython is not available in any of these.
foreach(CURRENT_PYTHON_EXECUTABLE ${SHARED_PYTHON_EXECUTABLES})
# Query each dist python interpreter for version information.
execute_process(
COMMAND "${CURRENT_PYTHON_EXECUTABLE}" -c "import sys; v=sys.version_info; print(f'{v.major}.{v.minor};{v.major}.{v.minor}.{v.micro}')"
OUTPUT_VARIABLE _python_versions
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
list(GET _python_versions 0 CURRENT_PYTHON_VERSION)
list(GET _python_versions 1 CURRENT_PYTHON_FULL_VERSION)
message(STATUS "Building rocgdb for python ${CURRENT_PYTHON_EXECUTABLE}: Minor=${CURRENT_PYTHON_VERSION}, Full=${CURRENT_PYTHON_FULL_VERSION}")
message(STATUS "-> Found Python ${CURRENT_PYTHON_FULL_VERSION} at ${CURRENT_PYTHON_EXECUTABLE}")
# For each Python that supports linking against a shared libpython we
# fetch the library directory so we can pass a linker flag to rocgdb's
# configure.
execute_process(
COMMAND "${CURRENT_PYTHON_EXECUTABLE}" -c "import sysconfig; libdir=sysconfig.get_config_var('LIBDIR'); print(f'{libdir}')"
OUTPUT_VARIABLE _libpython_dir
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
# Sanity check that we managed to get the libpython path. Otherwise skip
# this particular build.
if(_libpython_dir)
message(STATUS "-> Found libpython path ${_libpython_dir}")
# Add build instructions for this python-specific rocgdb.
add_python_variant("${CURRENT_PYTHON_VERSION}" "--with-python=${CURRENT_PYTHON_EXECUTABLE}" "${_libpython_dir}")
else()
message(STATUS "Failed to extract libpython directory for ${CURRENT_PYTHON_EXECUTABLE}: Skipping")
endif()
endforeach()
endif()
# We always build a rocgdb without python support as fallback.
message(STATUS "Building rocgdb without python support")
add_python_variant("none" "--disable-python" "")
# Add a single custom target in the main project that depends
# on building ALL rocgdb variants.
add_custom_target(build_all_rocgdb ALL DEPENDS ${ALL_ROCGDB_TARGETS})
################################
# ROCgdb script generation step.
################################
# Since we potentially have multiple versions of python, and each rocgdb
# executable links against a specific version of libpython, we have a
# convenience script that automatically detects the version and fires up
# the most appropriate rocgdb executable. This makes the python selection
# process transparent to the end user.
set(ROCGDB_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/rocgdb")
# Install the generated script.
install(PROGRAMS ${ROCGDB_SCRIPT}
DESTINATION bin
COMPONENT rocgdb)
if(BUILD_TESTING)
# Track for build validation.
list(APPEND ROCGDB_BUILD_INTEGRITY_FILES "bin/rocgdb")
endif()
##################################
# ROCgdb executable patching step.
##################################
# Now add targets for each executable we want to patch post-build.
# These will run after the rocgdb build finishes, and will add the
# appropriate RUNPATH entries so the executables can locate their
# required libraries even if they move around.
# List of all the files in bin we need to patch in RUNPATH's.
# This excludes rocgdb executables as we patch those separately.
set(ROCGDB_EXECS_TO_PATCH)
# roccoremerge is only present in ROCm's branch (not yet in upstream master).
if(NOT ROCGDB_UPSTREAM_BUILD)
list(APPEND ROCGDB_EXECS_TO_PATCH "bin/roccoremerge")
endif()
foreach(rocgdb_exec_filename ${ROCGDB_EXECS_TO_PATCH})
set(rocgdb_exec_file "${CMAKE_INSTALL_PREFIX}/${rocgdb_exec_filename}")
message(STATUS "Registering fixup of ${rocgdb_exec_file}")
# Patch in the RUNPATH.
install(CODE "execute_process(
COMMAND \"${PATCHELF}\" --set-rpath \"\$ORIGIN${ROCGDB_EXTRA_RPATH_SEGMENTS}\"
\"${rocgdb_exec_file}\"
COMMAND_ERROR_IS_FATAL ANY
)"
COMPONENT rocgdb)
endforeach()
##################################################
# Build integrity and testsuite installation step.
##################################################
if(BUILD_TESTING)
enable_testing()
list(APPEND ROCGDB_BUILD_INTEGRITY_FILES ${ROCGDB_EXECS_TO_PATCH})
# List of all the other files we expect to be in the installation.
set(ROCGDB_EXPECTED_FILES
"include/gdb/jit-reader.h"
"share/info/rocgdb/gdb.info"
"share/info/rocgdb/annotate.info"
"share/rocgdb/python/gdb/ptwrite.py"
"share/rocgdb/python/gdb/__init__.py"
"share/rocgdb/python/gdb/missing_objfile.py"
"share/rocgdb/python/gdb/xmethod.py"
"share/rocgdb/python/gdb/missing_debug.py"
"share/rocgdb/python/gdb/frames.py"
"share/rocgdb/python/gdb/FrameIterator.py"
"share/rocgdb/python/gdb/prompt.py"
"share/rocgdb/python/gdb/printing.py"
"share/rocgdb/python/gdb/missing_files.py"
"share/rocgdb/python/gdb/disassembler.py"
"share/rocgdb/python/gdb/styling.py"
"share/rocgdb/python/gdb/function/caller_is.py"
"share/rocgdb/python/gdb/function/__init__.py"
"share/rocgdb/python/gdb/function/as_string.py"
"share/rocgdb/python/gdb/function/rocm_get_scaled_float.py"
"share/rocgdb/python/gdb/function/strfns.py"
"share/rocgdb/python/gdb/FrameDecorator.py"
"share/rocgdb/python/gdb/types.py"
"share/rocgdb/python/gdb/printer/__init__.py"
"share/rocgdb/python/gdb/printer/rocm_ocp_mx.py"
"share/rocgdb/python/gdb/unwinder.py"
"share/rocgdb/python/gdb/dap/varref.py"
"share/rocgdb/python/gdb/dap/locations.py"
"share/rocgdb/python/gdb/dap/threads.py"
"share/rocgdb/python/gdb/dap/next.py"
"share/rocgdb/python/gdb/dap/events.py"
"share/rocgdb/python/gdb/dap/__init__.py"
"share/rocgdb/python/gdb/dap/launch.py"
"share/rocgdb/python/gdb/dap/sources.py"
"share/rocgdb/python/gdb/dap/bt.py"
"share/rocgdb/python/gdb/dap/state.py"
"share/rocgdb/python/gdb/dap/typecheck.py"
"share/rocgdb/python/gdb/dap/globalvars.py"
"share/rocgdb/python/gdb/dap/server.py"
"share/rocgdb/python/gdb/dap/evaluate.py"
"share/rocgdb/python/gdb/dap/scopes.py"
"share/rocgdb/python/gdb/dap/frames.py"
"share/rocgdb/python/gdb/dap/startup.py"
"share/rocgdb/python/gdb/dap/disassemble.py"
"share/rocgdb/python/gdb/dap/pause.py"
"share/rocgdb/python/gdb/dap/memory.py"
"share/rocgdb/python/gdb/dap/completions.py"
"share/rocgdb/python/gdb/dap/breakpoint.py"
"share/rocgdb/python/gdb/dap/modules.py"
"share/rocgdb/python/gdb/dap/io.py"
"share/rocgdb/python/gdb/command/__init__.py"
"share/rocgdb/python/gdb/command/pretty_printers.py"
"share/rocgdb/python/gdb/command/frame_filters.py"
"share/rocgdb/python/gdb/command/prompt.py"
"share/rocgdb/python/gdb/command/unwinders.py"
"share/rocgdb/python/gdb/command/xmethods.py"
"share/rocgdb/python/gdb/command/type_printers.py"
"share/rocgdb/python/gdb/command/explore.py"
"share/rocgdb/python/gdb/command/missing_files.py"
"share/rocgdb/syscalls/mips-n64-linux.xml"
"share/rocgdb/syscalls/loongarch-linux.xml"
"share/rocgdb/syscalls/amd64-linux.xml"
"share/rocgdb/syscalls/mips-n32-linux.xml"
"share/rocgdb/syscalls/ppc-linux.xml"
"share/rocgdb/syscalls/riscv-linux.xml"
"share/rocgdb/syscalls/sparc-linux.xml"
"share/rocgdb/syscalls/mips-o32-linux.xml"
"share/rocgdb/syscalls/aarch64-linux.xml"
"share/rocgdb/syscalls/ppc64-linux.xml"
"share/rocgdb/syscalls/netbsd.xml"
"share/rocgdb/syscalls/sparc64-linux.xml"
"share/rocgdb/syscalls/arm-linux.xml"
"share/rocgdb/syscalls/s390-linux.xml"
"share/rocgdb/syscalls/s390x-linux.xml"
"share/rocgdb/syscalls/i386-linux.xml"
"share/rocgdb/syscalls/freebsd.xml"
"share/rocgdb/syscalls/gdb-syscalls.dtd"
"share/rocgdb/system-gdbinit/elinos.py"
"share/rocgdb/system-gdbinit/wrs-linux.py"
"share/man/man5/rocgdbinit.5"
"share/man/man1/rocgdb-add-index.1"
"share/man/man1/rocgcore.1"
"share/man/man1/rocgdb.1"
)
# AMD-specific files not yet in upstream master.
if(NOT ROCGDB_UPSTREAM_BUILD)
list(APPEND ROCGDB_EXPECTED_FILES
"share/doc/NOTICES.txt"
"share/man/man1/roccoremerge.1"
)
endif()
list(APPEND ROCGDB_BUILD_INTEGRITY_FILES ${ROCGDB_EXPECTED_FILES})
# Add build integrity tests to check if we have the files we want.
message(STATUS "BUILD_TESTING set. Adding rocgdb installation integrity tests.")
foreach(rocgdb_file ${ROCGDB_BUILD_INTEGRITY_FILES})
add_test(
NAME rocgdb_install_validation_${CMAKE_INSTALL_PREFIX}/${rocgdb_file}
COMMAND ${CMAKE_COMMAND} -E env
sh -c "test -f ${CMAKE_INSTALL_PREFIX}/${rocgdb_file}"
)
endforeach()
# Also install the required testsuite files so we can run tests later on.
#
# rocgdb's testsuite does not prebuild executables, so it needs to run on
# the target machine.
# Non-executable testsuite files.
set(ROCGDB_TESTSUITE_FILES
"config.guess"
"config.sub"
"contrib/dg-extract-results.py"
"gdb/disable-implicit-rules.mk"
"gdb/silent-rules.mk"
"include/dwarf2.def"
"include/dwarf2.h"
)
# Executable testsuite files.
set(ROCGDB_EXECUTABLE_TESTSUITE_FILES
"contrib/dg-extract-results.sh"
"install-sh"
)
foreach(rocgdb_file ${ROCGDB_TESTSUITE_FILES})
# Get the directory part of the file.
get_filename_component(file_dir ${rocgdb_file} DIRECTORY)
install(FILES ${ROCGDB_SOURCE_DIR}/${rocgdb_file}
DESTINATION tests/rocgdb/${file_dir}
COMPONENT tests)
endforeach()
foreach(rocgdb_file ${ROCGDB_EXECUTABLE_TESTSUITE_FILES})
# Get the directory part of the file.
get_filename_component(file_dir ${rocgdb_file} DIRECTORY)
install(PROGRAMS ${ROCGDB_SOURCE_DIR}/${rocgdb_file}
DESTINATION tests/rocgdb/${file_dir}
COMPONENT tests)
endforeach()
# Testsuite directories.
set(ROCGDB_TESTSUITE_DIRS
"gdb/contrib"
"gdb/features"
"gdb/testsuite"
)
foreach(rocgdb_testsuite_dir ${ROCGDB_TESTSUITE_DIRS})
install(DIRECTORY ${ROCGDB_SOURCE_DIR}/${rocgdb_testsuite_dir}
DESTINATION tests/rocgdb/gdb
COMPONENT tests
USE_SOURCE_PERMISSIONS)
endforeach()
# Install the CI wrapper script that invokes the rocgdb testsuite. This is
# used by TheRock CI. If the script is not in the source tree and
# ROCGDB_DOWNLOAD_CI_SCRIPT is enabled, fetch it from amd-staging.
set(TEST_ROCGDB_SCRIPT "${ROCGDB_SOURCE_DIR}/.github/scripts/test_rocgdb.py")
if(NOT EXISTS "${TEST_ROCGDB_SCRIPT}")
if(ROCGDB_DOWNLOAD_CI_SCRIPT)
set(TEST_ROCGDB_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/test_rocgdb.py")
# The source of truth for the CI script is the one in amd-staging.
set(TEST_ROCGDB_URL "https://raw.githubusercontent.com/ROCm/ROCgdb/amd-staging/.github/scripts/test_rocgdb.py")
# Use curl rather than file(DOWNLOAD): file(DOWNLOAD)'s STATUS is the
# libcurl transfer code, so HTTP 404/500 responses are reported as
# success and the error-page body is written to disk. curl --fail
# returns non-zero on HTTP >= 400, and verifies TLS by default.
find_program(CURL_EXECUTABLE curl REQUIRED)
set(download_success FALSE)
foreach(attempt RANGE 1 3)
message(STATUS "Attempting to download test_rocgdb.py (attempt ${attempt}/3)")
execute_process(
COMMAND "${CURL_EXECUTABLE}"
--fail --silent --show-error --location
--max-time 60
--output "${TEST_ROCGDB_SCRIPT}"
"${TEST_ROCGDB_URL}"
RESULT_VARIABLE curl_result
ERROR_VARIABLE curl_error
)
if(curl_result EQUAL 0)
set(download_success TRUE)
message(STATUS "Successfully downloaded test_rocgdb.py to ${TEST_ROCGDB_SCRIPT}")
break()
else()
message(WARNING "Download attempt ${attempt} failed: ${curl_error}")
file(REMOVE "${TEST_ROCGDB_SCRIPT}")
endif()
endforeach()
if(NOT download_success)
message(FATAL_ERROR "Failed to download test_rocgdb.py after 3 attempts")
endif()
else()
message(FATAL_ERROR "test_rocgdb.py not found at ${TEST_ROCGDB_SCRIPT} and ROCGDB_DOWNLOAD_CI_SCRIPT is OFF. Re-configure with -DTHEROCK_ROCGDB_DOWNLOAD_CI_SCRIPT=ON to fetch it from amd-staging.")
endif()
endif()
install(
PROGRAMS ${TEST_ROCGDB_SCRIPT}
DESTINATION tests/rocgdb
COMPONENT tests
)
# Install the optional xfails ignore list, if present in the sources.
if(EXISTS "${ROCGDB_SOURCE_DIR}/.github/scripts/rocgdb_ignore_list.json")
install(
FILES ${ROCGDB_SOURCE_DIR}/.github/scripts/rocgdb_ignore_list.json
DESTINATION tests/rocgdb
COMPONENT tests
)
else()
message(WARNING "rocgdb tests: xfails ignore list not found at "
"${ROCGDB_SOURCE_DIR}/.github/scripts/rocgdb_ignore_list.json; skipping installation.")
endif()
else()
message(STATUS "rocgdb tests: BUILD_TESTING not set. Skipping installation integrity tests.")
endif()