pax_global_header00006660000000000000000000000064150742311700014512gustar00rootroot0000000000000052 comment=f7500bb3f8d51a82bb602ca5537c10c0fa20c6a9 rocm-core-rocm-7.1.0/000077500000000000000000000000001507423117000143435ustar00rootroot00000000000000rocm-core-rocm-7.1.0/.azuredevops/000077500000000000000000000000001507423117000167705ustar00rootroot00000000000000rocm-core-rocm-7.1.0/.azuredevops/rocm-ci.yml000066400000000000000000000011631507423117000210450ustar00rootroot00000000000000resources: repositories: - repository: pipelines_repo type: github endpoint: ROCm name: ROCm/ROCm variables: - group: common - template: /.azuredevops/variables-global.yml@pipelines_repo trigger: batch: true branches: include: - master paths: exclude: - 'CHANGELOG.md' - 'CODEOWNERS' - 'copyright' - 'README.txt' pr: autoCancel: true branches: include: - master paths: exclude: - 'CHANGELOG.md' - 'CODEOWNERS' - 'copyright' - 'README.txt' drafts: false jobs: - template: ${{ variables.CI_COMPONENT_PATH }}/rocm-core.yml@pipelines_repo rocm-core-rocm-7.1.0/.github/000077500000000000000000000000001507423117000157035ustar00rootroot00000000000000rocm-core-rocm-7.1.0/.github/palamida.yml000066400000000000000000000001241507423117000201730ustar00rootroot00000000000000disabled: false scmId: gh-emu-rocm branchesToScan: - amd-staging - amd-mainline rocm-core-rocm-7.1.0/.github/workflows/000077500000000000000000000000001507423117000177405ustar00rootroot00000000000000rocm-core-rocm-7.1.0/.github/workflows/kws-caller.yml000066400000000000000000000006611507423117000225320ustar00rootroot00000000000000name: Rocm Validation Suite KWS on: push: branches: [amd-staging, amd-mainline] pull_request: types: [opened, synchronize, reopened] workflow_dispatch: jobs: kws: if: ${{ github.event_name == 'pull_request' }} uses: AMD-ROCm-Internal/rocm_ci_infra/.github/workflows/kws.yml@mainline secrets: inherit with: pr_number: ${{github.event.pull_request.number}} base_branch: ${{github.base_ref}} rocm-core-rocm-7.1.0/.github/workflows/rocm_ci_caller.yml000066400000000000000000000036461507423117000234310ustar00rootroot00000000000000name: ROCm CI Caller on: # Commenting below to avoid re-runs of amd smi for trivial rebases pull_request: branches: [release/rocm-rel-*, amd-mainline] types: [opened, reopened, synchronize] push: branches: [amd-mainline] workflow_dispatch: issue_comment: types: [created] jobs: call-workflow: if: github.event_name != 'issue_comment' ||(github.event_name == 'issue_comment' && github.event.issue.pull_request && (startsWith(github.event.comment.body, '!verify') || startsWith(github.event.comment.body, '!verify release') || startsWith(github.event.comment.body, '!verify retest'))) uses: AMD-ROCm-Internal/rocm_ci_infra/.github/workflows/rocm_ci.yml@mainline secrets: inherit with: input_sha: ${{github.event_name == 'pull_request' && github.event.pull_request.head.sha || (github.event_name == 'push' && github.sha) || (github.event_name == 'issue_comment' && github.event.issue.pull_request.head.sha) || github.sha}} input_pr_num: ${{github.event_name == 'pull_request' && github.event.pull_request.number || (github.event_name == 'issue_comment' && github.event.issue.number) || 0}} input_pr_url: ${{github.event_name == 'pull_request' && github.event.pull_request.html_url || (github.event_name == 'issue_comment' && github.event.issue.pull_request.html_url) || ''}} input_pr_title: ${{github.event_name == 'pull_request' && github.event.pull_request.title || (github.event_name == 'issue_comment' && github.event.issue.pull_request.title) || ''}} repository_name: ${{ github.repository }} base_ref: ${{github.event_name == 'pull_request' && github.event.pull_request.base.ref || (github.event_name == 'issue_comment' && github.event.issue.pull_request.base.ref) || github.ref}} trigger_event_type: ${{ github.event_name }} comment_text: ${{ github.event_name == 'issue_comment' && github.event.comment.body || '' }} rocm-core-rocm-7.1.0/CHANGELOG.md000066400000000000000000000013201507423117000161500ustar00rootroot00000000000000Change Logs for rocm-core ROCm6.4.1 release - Added changelog.debian and copyright for debian packages. ROCm6.3.0 release - Enabled Support for CMAKE Module Config. ROCm6.1.0 release - Added new API to get ROCm install Path (getROCmInstallPath()) at runtime using dlinfo of rocm-core Target Library. ROCm6.0.0 release - Added script to convert RUNPATH in libraries and binaries to RPATH. - Disabled ROCm file reorg backward compatibility ROCm5.6.0 release - Added initial support for Adress Sanitizer(ASAN) enabled builds. - Full support of ASAN will be coming in later release ROCm5.5.0 release - Added module file support for ROCm. - From ROCm5.5.0 release ROCm module files can be loaded as rocm/5.5.0 rocm-core-rocm-7.1.0/CMakeLists.txt000066400000000000000000000350731507423117000171130ustar00rootroot00000000000000################################################################################ ## ## MIT License ## ## Copyright (c) 2017 - 2023 Advanced Micro Devices, Inc. All rights Reserved. ## ## Permission is hereby granted, free of charge, to any person obtaining a copy ## of this software and associated documentation files (the "Software"), to deal ## in the Software without restriction, including without limitation the rights ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ## copies of the Software, and to permit persons to whom the Software is ## furnished to do so, subject to the following conditions: ## ## The above copyright notice and this permission notice shall be included in all ## copies or substantial portions of the Software. ## ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. ## ################################################################################ cmake_minimum_required( VERSION 3.16 ) set( CORE_TARGET "rocm-core" ) project( ${CORE_TARGET} CXX ) ## Define Lib Target Name and Lib Target Install Dir to be available to c++ source add_definitions( -DTARGET_LIBRARY_NAME=\"${CORE_TARGET}\" -DTARGET_LIBRARY_INSTALL_DIR=\"${CMAKE_INSTALL_LIBDIR}\" ) ## Build Type Settings set( CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." ) ## Verbose output. set( CMAKE_VERBOSE_MAKEFILE on ) include( GNUInstallDirs ) if(ENABLE_ASAN_PACKAGING) # Only libraries required for ASAN Package set( CPACK_COMPONENTS_ALL CORE_ASAN ) set( COMP_TYPE "CORE_ASAN" ) set( PKG_DESCRIPTION "ROCm AddressSanitizer Instrumented Runtime software stack" ) set( CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DOCDIR}-asan" ) else() if(BUILD_SHARED_LIBS) set( CPACK_COMPONENTS_ALL CORE_RUNTIME ) set( COMP_TYPE "CORE_RUNTIME" ) set( PKG_DESCRIPTION "ROCm Runtime software stack" ) else() set( CPACK_COMPONENTS_ALL CORE_STATIC ) set( STATIC_COMP_TYPE "CORE_STATIC" ) set( PKG_DESCRIPTION "ROCm Static software stack" ) endif() endif() include( utils.cmake ) #Parse Version message( STATUS "ROCM_VERSION = ${ROCM_VERSION}" ) parse_rocm_version( ${ROCM_VERSION} ) set( CPACK_PACKAGING_INSTALL_PREFIX "/opt/rocm" CACHE PATH "default cpack directory" ) set( BUILD_SHARED_LIBS ON CACHE BOOL "Build shared library (.so) or not." ) set( CPACK_GENERATOR "TGZ;DEB;RPM" CACHE STRING "package types to be produced " ) set( LICENSE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md" CACHE PATH "Path to License File in source dir" ) set( BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR} ) set( EXTENDED_PACKAGE_DESCRIPTION "ROCM-CORE package helps to get ROCm release version,get install path. It is also important to note that ROCM-CORE takes the role as a base component on which all of ROCm can depend, to make it easy to remove all of ROCm with a package manager." ) set( BUILD_ENABLE_LINTIAN_OVERRIDES OFF CACHE BOOL "Enable/Disable Lintian Overrides" ) set( BUILD_DEBIAN_PKGING_FLAG OFF CACHE BOOL "Internal Status Flag to indicate Debian Packaging Build" ) ## Set variables set_variables() set( SO_MAJOR "1") set( SO_MINOR "0" ) if( NOT DEFINED BUILD_ID ) set( BUILD_ID "9999") endif() #Add the libpatch version if available if( DEFINED VERSION_POINT ) set( PACKAGE_BUILD_INFO "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_POINT}.${VERSION_COMMIT_COUNT}-${BUILD_ID}-${VERSION_HASH}" ) message ( STATUS "PACKAGE_BUILD_INFO ${PACKAGE_BUILD_INFO}" ) else () set( PACKAGE_BUILD_INFO "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_COMMIT_COUNT}-${BUILD_ID}-${VERSION_HASH}" ) endif() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/rocmmod.in ${BUILD_DIR}/rocmmod @ONLY ) # Setting Permission 0755 for pre/post install scripts configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/rocm-core.postinst ${BUILD_DIR}/postinst FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE @ONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/rocm-core.prerm ${BUILD_DIR}/prerm FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE @ONLY ) #Generate BUILD_INFO configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/rocm_version.h.in ${BUILD_DIR}/rocm_version.h @ONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/rocm_getpath.h.in ${BUILD_DIR}/rocm_getpath.h @ONLY ) #Make the rocmlib set( SRCS rocm_version.cpp rocm_getpath.cpp) add_library( ${CORE_TARGET} ${SRCS} ) set( CXX_FLAGS ${CXX_FLAGS} -g -fPIC -fvisibility=hidden -W -Wall -Wextra -Wno-unused-parameter -Wformat-security -Wundef -Wshadow -Wpointer-arith -Wcast-qual -Wmissing-declarations -Wredundant-decls -Wunreachable-code -std=c++11 ) set( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,nodelete -Wl,-no-undefined" ) target_include_directories( ${CORE_TARGET} PRIVATE ${BUILD_DIR} ) if(BUILD_SHARED_LIBS) target_link_libraries( ${CORE_TARGET} PRIVATE dl ) endif() ## Set the VERSION and SOVERSION values set( SO_VERSION_STRING "${SO_MAJOR}.${SO_MINOR}.${ROCM_LIBPATCH_VERSION}" ) set_property( TARGET ${CORE_TARGET} PROPERTY VERSION "${SO_VERSION_STRING}" ) set_property( TARGET ${CORE_TARGET} PROPERTY SOVERSION "${SO_MAJOR}" ) #Add the libpatch version if available to the version file if( DEFINED VERSION_POINT ) file ( WRITE "${CMAKE_CURRENT_BINARY_DIR}/version" "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_POINT}\n" ) else() file ( WRITE "${CMAKE_CURRENT_BINARY_DIR}/version" "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}\n" ) endif() ## Support for Static and Shared Target Packaging if(BUILD_SHARED_LIBS) install ( FILES ${BUILD_DIR}/version DESTINATION .info COMPONENT CORE_RUNTIME ) # Target Library needs to installed/packaged to same destination # in both ASAN and nonASAN Shared library builds install ( TARGETS ${CORE_TARGET} EXPORT rocmCoreTargets DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${COMP_TYPE} ) install ( FILES ${BUILD_DIR}/rocm_version.h ${BUILD_DIR}/rocm_getpath.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocm-core COMPONENT CORE_RUNTIME ) install ( PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/runpath_to_rpath.py DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/rocm-core COMPONENT CORE_RUNTIME ) install ( FILES ${BUILD_DIR}/rocmmod DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT CORE_RUNTIME ) else() install ( FILES ${BUILD_DIR}/version DESTINATION .info COMPONENT ${STATIC_COMP_TYPE} ) install ( TARGETS ${CORE_TARGET} EXPORT rocmCoreTargets DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${STATIC_COMP_TYPE} ) install ( FILES ${BUILD_DIR}/rocm_version.h ${BUILD_DIR}/rocm_getpath.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocm-core COMPONENT ${STATIC_COMP_TYPE} ) install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/runpath_to_rpath.py DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/rocm-core COMPONENT ${STATIC_COMP_TYPE} ) install ( FILES ${BUILD_DIR}/rocmmod DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${STATIC_COMP_TYPE} ) endif() ## Cmake module config file configurations set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/" CACHE INTERNAL "Default module path.") ## Export the package for use from the build-tree ## (this registers the build-tree with a global CMake-registry) export(PACKAGE ${CORE_TARGET}) set(CONF_LIB_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") ## Create the rocm-core-config.cmake and rocm-core-config-version files include(CMakePackageConfigHelpers) set(CONFIG_PACKAGE_INSTALL_DIR ${CONF_LIB_DIR}/cmake/${CORE_TARGET}) set(LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") set(BIN_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}") set(PKG_MAINTAINER_NM "ROCm Dev Support") set(PKG_MAINTAINER_EMAIL "rocm-dev.support@amd.com") ## Generate Config File for rocm-core configure_package_config_file( ${CMAKE_MODULE_PATH}/${CORE_TARGET}-config.cmake.in ${BUILD_DIR}/${CORE_TARGET}-config.cmake INSTALL_DESTINATION ${CONFIG_PACKAGE_INSTALL_DIR} PATH_VARS LIB_INSTALL_DIR INCLUDE_INSTALL_DIR BIN_INSTALL_DIR ) ## Generate config Version File for rocm-core write_basic_package_version_file( ${BUILD_DIR}/${CORE_TARGET}-config-version.cmake VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" COMPATIBILITY SameMajorVersion) ## Install the rocm-core-config.cmake and rocm-core-config-version.cmake install(FILES "${PROJECT_BINARY_DIR}/${CORE_TARGET}-config.cmake" "${PROJECT_BINARY_DIR}/${CORE_TARGET}-config-version.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${CORE_TARGET}" COMPONENT ${COMP_TYPE}) ## Install the export set for use with the install-tree install(EXPORT rocmCoreTargets DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${CORE_TARGET}" COMPONENT ${COMP_TYPE}) ## Packaging directives set ( CPACK_PACKAGE_VENDOR "Advanced Micro Devices, Inc." ) set ( CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR} ) set ( CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR} ) set ( CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH} ) set ( CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}" ) set ( CPACK_PACKAGE_CONTACT "${PKG_MAINTAINER_NM} <${PKG_MAINTAINER_EMAIL}>" ) set ( CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PKG_DESCRIPTION}" ) set ( CPACK_RESOURCE_FILE_LICENSE "${LICENSE_FILE}" ) ## packaging variables if ( DEFINED ROCM_LIBPATCH_VERSION ) set ( CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}.${ROCM_LIBPATCH_VERSION}" ) message ( STATUS "Using CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}" ) endif() ## Debian package specific variables set ( CPACK_DEB_COMPONENT_INSTALL ON ) set ( CPACK_DEBIAN_CORE_RUNTIME_PACKAGE_NAME "${CORE_TARGET}" ) # ASAN package name set ( CPACK_DEBIAN_CORE_ASAN_PACKAGE_NAME ${CORE_TARGET}-asan ) # STATIC package name - For Now, No change for static package Name from default set ( CPACK_DEBIAN_CORE_STATIC_PACKAGE_NAME ${CORE_TARGET} ) message ( STATUS "Using CPACK_DEBIAN_PACKAGE_RELEASE ${CPACK_DEBIAN_PACKAGE_RELEASE}" ) set ( CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT" ) # Debian specific packaging configuration if(COMP_TYPE) configure_debian_pkg( ${CORE_TARGET} ${COMP_TYPE} ${CPACK_PACKAGE_VERSION} ${PKG_MAINTAINER_NM} ${PKG_MAINTAINER_EMAIL} ) elseif(STATIC_COMP_TYPE) configure_debian_pkg( ${CORE_TARGET} ${STATIC_COMP_TYPE} ${CPACK_PACKAGE_VERSION} ${PKG_MAINTAINER_NM} ${PKG_MAINTAINER_EMAIL} ) endif() ## RPM package specific variables set ( CPACK_RPM_COMPONENT_INSTALL ON ) set ( CPACK_RPM_CORE_RUNTIME_PACKAGE_NAME "${CORE_TARGET}" ) # ASAN package name set ( CPACK_RPM_CORE_ASAN_PACKAGE_NAME ${CORE_TARGET}-asan ) # STATIC package name - For Now, No change for static package Name from default set ( CPACK_RPM_CORE_STATIC_PACKAGE_NAME ${CORE_TARGET} ) ## 'dist' breaks manual builds on debian systems due to empty Provides execute_process( COMMAND rpm --eval %{?dist} RESULT_VARIABLE PROC_RESULT OUTPUT_VARIABLE EVAL_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE ) if ( PROC_RESULT EQUAL "0" AND NOT EVAL_RESULT STREQUAL "" ) string ( APPEND CPACK_RPM_PACKAGE_RELEASE "%{?dist}" ) endif() message(STATUS "Using CPACK_RPM_PACKAGE_RELEASE: ${CPACK_RPM_PACKAGE_RELEASE}") set ( CPACK_RPM_FILE_NAME "RPM-DEFAULT" ) # #!/usr/bin/env is converted to /usr/libexec/platform-python in some OS like RHEL # Prevent the modification of python interpreter directives in runpath_to_rpath.py set( CPACK_RPM_SPEC_MORE_DEFINE "\n%undefine __brp_mangle_shebangs") # Debian Lintian Fix - Add Dependency for Python Script delivered set( DEB_DEPENDS_STRING "python3, libc6" ) # Debian package specific variables set ( CPACK_DEBIAN_PACKAGE_DEPENDS ${DEB_DEPENDS_STRING} ) set ( CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/ROCm/rocm-core" ) set ( CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${BUILD_DIR}/postinst;${BUILD_DIR}/prerm" ) set ( CPACK_DEBIAN_CORE_RUNTIME_PACKAGE_DEPENDS ${DEB_DEPENDS_STRING} ) set ( CPACK_DEBIAN_CORE_ASAN_PACKAGE_DEPENDS ${CORE_TARGET} ) set ( CPACK_DEBIAN_CORE_RUNTIME_PACKAGE_CONTROL_EXTRA "${CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA}" ) set ( CPACK_DEBIAN_CORE_STATIC_PACKAGE_CONTROL_EXTRA "${CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA}" ) set ( CPACK_DEBIAN_PACKAGE_DESCRIPTION "${EXTENDED_PACKAGE_DESCRIPTION}" ) ## RPM package specific variables set ( CPACK_RPM_PACKAGE_REQUIRES ${RPM_DEPENDS_STRING} ) set ( CPACK_RPM_PACKAGE_LICENSE "MIT" ) set ( CPACK_RPM_CORE_ASAN_PACKAGE_REQUIRES ${CORE_TARGET} ) set ( CPACK_RPM_CORE_RUNTIME_POST_INSTALL_SCRIPT_FILE "${BUILD_DIR}/postinst" ) set ( CPACK_RPM_CORE_RUNTIME_POST_UNINSTALL_SCRIPT_FILE "${BUILD_DIR}/prerm" ) set ( CPACK_RPM_CORE_STATIC_POST_INSTALL_SCRIPT_FILE "${BUILD_DIR}/postinst" ) set ( CPACK_RPM_CORE_STATIC_POST_UNINSTALL_SCRIPT_FILE "${BUILD_DIR}/prerm" ) set ( CPACK_RPM_PACKAGE_DESCRIPTION "${EXTENDED_PACKAGE_DESCRIPTION}" ) if ( DEFINED CPACK_PACKAGING_INSTALL_PREFIX ) set ( CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX} ${CPACK_PACKAGING_INSTALL_PREFIX}/.info" ) endif() # Backward compatibility support for deprecated package rocm-clang-ocl # TODO: To be removed after two releases set(CPACK_DEBIAN_RUNTIME_PACKAGE_REPLACES "rocm-clang-ocl") set(CPACK_DEBIAN_RUNTIME_PACKAGE_CONFLICTS "rocm-clang-ocl") set(CPACK_RPM_RUNTIME_PACKAGE_OBSOLETES "rocm-clang-ocl") # Custom installation for Debian Lintian File if( BUILD_ENABLE_LINTIAN_OVERRIDES STREQUAL "ON" AND BUILD_DEBIAN_PKGING_FLAG STREQUAL "ON") set( OVERRIDE_FILE "${CMAKE_BINARY_DIR}/DEBIAN/${DEB_OVERRIDES_INSTALL_FILENM}" ) if(COMP_TYPE) set( OVERRIDE_TEMP_INSTALL_LOC "/_CPack_Packages/Linux/DEB/${CORE_TARGET}-${CPACK_PACKAGE_VERSION}-Linux/${COMP_TYPE}" ) elseif(STATIC_COMP_TYPE) set( OVERRIDE_TEMP_INSTALL_LOC "/_CPack_Packages/Linux/DEB/${CORE_TARGET}-${CPACK_PACKAGE_VERSION}-Linux/${STATIC_COMP_TYPE}" ) endif() set(CPACK_INSTALL_COMMANDS "${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}${OVERRIDE_TEMP_INSTALL_LOC}${DEB_OVERRIDES_INSTALL_PATH}" "${CMAKE_COMMAND} -E copy ${OVERRIDE_FILE} ${CMAKE_BINARY_DIR}${OVERRIDE_TEMP_INSTALL_LOC}${DEB_OVERRIDES_INSTALL_PATH}" ) endif() ## Include packaging include ( CPack ) rocm-core-rocm-7.1.0/CODEOWNERS000066400000000000000000000001021507423117000157270ustar00rootroot00000000000000* @nunnikri @frepaul @raramakr @ashutom @amd-isparry @arvindcheru rocm-core-rocm-7.1.0/CONTRIBUTING.md000066400000000000000000000144121507423117000165760ustar00rootroot00000000000000# ROCM-CORE Contributing Guide To ensure the quality of the ROCM-CORE code base, the ROCM-CORE team has established a code review process to inform developers of the steps that are required to shepherd a change-set into the repository. #### Table Of Contents [How to get started](#How-to-get-started) [How do I contribute?](#how-do-i-contribute) * [Reporting Issues](#reporting-issues) * [Creating a Pull Request](#Creating-a-Pull-Request) [Responsibility of the Author](#Responsibility-of-the-Author) [Responsibility of the Reviewer](#Responsibility-of-the-Reviewer) [The Review](#the-review) [References](#References) ## How to get started rocm-core is a utility which can be used to get ROCm release version. It also provides the Lmod modules files for the ROCm release. getROCmVersion function provides the ROCm version. ## How do I contribute ### Deliverables All contributions you make will be under the [MIT Software License](copyright). For each new file in repository, Please include the licensing header ``` /******************************************************************************* * * MIT License * * Copyright (c) 20xx Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * *******************************************************************************/ ``` ### Formatting the code All the code is formatted using `clang-format`. To format a file, use: ```shell clang-format-10 -style=file -i ``` ### Reporting Issues We use [GitHub Issues](https://github.com/ROCm/rocm-core/issues) to track public **bugs** and **enhancement requests**. #### Bugs Please follow the template below to report any bugs found in ROCM-CORE: 1. Description: ***Please be clear and descriptive*** 2. How to Reproduce the issue: * Hardware Information: * Docker environment or Software Version: * Expected behavior: * Actual behavior: 3. Any additional information: #### Enhancement Requests Please follow the template below to report any enhancement requests for ROCM-CORE: 1. Description: ***Please be clear and descriptive*** 2. Value and Motivation: * Feature and functionalities enabled: * Any alternatives: 3. Any additional information: The author must set labels (and assigns a milestone) according to his/her own understanding. Other contributors can change these values if they disagree. That being said, adding a small comment explaining the motivation is highly recommended. In this way, we keep the process flexible while cultivating mutual understanding. [**Note**] Most likely, the labels like "bug", "feature" or "complexity*" would not be changed. However, "value*" or "urgency*" might be from mutual understanding. ### Creating a Pull Request No changes are allowed to be directly committed to the develop branch of the ROCM-CORE repository. All authors are required to develop their change sets on a separate branch and then create a pull request (PR) to merge their changes into the develop branch. Once a PR has been created, a developer must choose two reviewers to review the changes made. The first reviewer should be a technical expert in the portion of the library that the changes are being made in. You can find a list of these experts in [CODEOWNERS](CODEOWNERS) list. The second reviewer should be a peer reviewer. This reviewer can be any other ROCM-CORE developer. ## Responsibility of the Author The author of a PR is responsible for: * Writing clear, well documented code * Meeting expectations of code quality * Verifying that the changes do not break current functionality * Writing tests to ensure code coverage * Report on the impact to performance ## Responsibility of the Reviewer Each reviewer is responsible for verifying that the changes are clearly written in keeping with the coding styles of the library, are documented in a way that future developers will be able to understand the intent of the added functionality, and will maintain or improve the overall quality of the codebase. Reviewer's task checklist: 1. Has the PR passed? 2. Does the PR consist of a well-organized sequence of small commits, each of which is designed to make one specific feature or fix ? 3. Does the PR only include a reviewable amount of changes? Or it is a consolidation of already reviewed small batches? e.g. break it into smaller testable and reviewable tasks instead of a huge chunk at once. 4. Does the PR have sufficient documentation and easy to read and understand, feasible for test and future maintainence, related docs already in place? if API or functionality has changed? 5. For bugfixes and new features, new regression test created? 6. Is every PR associated with a ticket or issue number for tracking purposes? ## The Review During the review, reviewers will look over the changes and make suggestions or requests for changes. In order to assist the reviewer in prioritizing their efforts, authors can take the following actions: * Set the urgency and value labels * Set the milestone where the changes need to be delivered * Describe the testing procedure and post the measured effect of the change * Remind reviewers via email if a PR needs attention * If a PR needs to be reviewed as soon as possible, explain to the reviewers why a review may need to take priority ## References 1. [ROCM-CORE Readme](README.md) rocm-core-rocm-7.1.0/DEBIAN/000077500000000000000000000000001507423117000152655ustar00rootroot00000000000000rocm-core-rocm-7.1.0/DEBIAN/changelog.in000066400000000000000000000002631507423117000175450ustar00rootroot00000000000000@DEB_PACKAGE_NAME@ (@DEB_PACKAGE_VERSION@) stable; urgency=low * ROCm Runtime software stack Base Package. -- @DEB_MAINTAINER_NAME@ <@DEB_MAINTAINER_EMAIL@> @DEB_TIMESTAMP@ rocm-core-rocm-7.1.0/DEBIAN/copyright.in000066400000000000000000000025241507423117000176300ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: @DEB_PACKAGE_NAME@ Upstream-Contact: @DEB_MAINTAINER_NAME@ <@DEB_MAINTAINER_EMAIL@> Source: https://github.com/ROCm/@DEB_PACKAGE_NAME@ Files: * License: @DEB_LICENSE@ Copyright: @DEB_COPYRIGHT_YEAR@ Advanced Micro Devices, Inc. All rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rocm-core-rocm-7.1.0/DEBIAN/overrides.in000066400000000000000000000002431507423117000176160ustar00rootroot00000000000000@DEB_OVERRIDES_INSTALL_FILENM@: no-copyright-file @DEB_OVERRIDES_INSTALL_FILENM@: debian-changelog-file-missing @DEB_OVERRIDES_INSTALL_FILENM@: dir-or-file-in-opt rocm-core-rocm-7.1.0/LICENSE.md000066400000000000000000000020701507423117000157460ustar00rootroot00000000000000MIT License Copyright (C) Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rocm-core-rocm-7.1.0/README.md000066400000000000000000000203171507423117000156250ustar00rootroot00000000000000# ROCM-CORE Introduction ROCM-CORE is a package which can be used to get ROCm release version, get ROCm install path information etc. It is also important to note that ROCM-CORE takes the role as a base component on which all of ROCm can depend, to make it easy to remove all of ROCm with a package manager. getROCmVersion function provides the ROCm version. It also provides an example Lmod modules files for the ROCm release. Lmod module files can be loaded with the following commands. ``` shell module load rocm/x.y or module load rocm ``` You can find sources and binaries in our [GitHub repository](https://github.com/ROCm/rocm-core). > [!NOTE] > As with all ROCm projects, the documentation is open source. For more information, see [Contribute to ROCm documentation](https://rocm.docs.amd.com/en/latest/contribute/contributing.html). ## Installing ROCM-CORE Before we proceed with how to install, take a look on references given below to understand System requirements, ROCm Installation prerequisites, ROCm package repository set up etc. ### Prerequisite References * Refer [System Requirements](https://rocm.docs.amd.com/projects/install-on-linux/en/docs-6.2.2/reference/system-requirements.html#supported-gpus) * Refer [ROCm installation for Linux](https://rocm.docs.amd.com/projects/install-on-linux/en/docs-6.2.2/index.html) * A [ROCm](https://rocm.docs.amd.com/)-enabled platform * To be noted that ROCM-CORE library primarily depends on having the C library available for the respective platform. ### Installing with pre-built packages You can install ROCM-CORE on Ubuntu using ```shell apt-get install rocm-core ``` ## Building ROCM-CORE from source You can build ROCM-CORE form source First, get the sources from repository. ```shell git clone https://github.com/ROCm/rocm-core.git ``` Go to Root Directory, create a build directory: ```shell cd rocm-core; mkdir build; cd build ``` Next, configure CMake. Invoke cmake with the following variables define as deemed fit ```shell cmake -S $PWD/../ -B . \ -DCMAKE_VERBOSE_MAKEFILE=1 \ -DCMAKE_INSTALL_PREFIX=./ \ -DROCM_VERSION="6.4.0" \ .. ``` >[!NOTE] >When specifying the path for the `CMAKE_PREFIX_PATH` variable, **do not** use the tilde (`~`) >shorthand to represent the home directory. ### Setting up install locations By default, the install location is set to `/opt/rocm`. You can change this using `CMAKE_INSTALL_PREFIX`: ```shell cmake -DCMAKE_INSTALL_PREFIX= .. ``` where rocm-core-install-path is "./" in the cmake configure command shared above. ### Install Once cmake configuration successfully completed, from the same build directory run build, install targets ```shell cmake --build . -- cmake --build . -- install ``` ### Package Generated Once cmake configuration and build successfully completed from the same build directory trigger package generation ```shell cmake --build . -- package ``` Once successfull execution of above command "rocm-core" RPM/DEBIAN packages will be generated (ex:rocm-core_6.4.0.60400-22.04_amd64.deb, rocm-core-6.4.0.60400-x86_64.rpm). The contents of the "rocm-core" package will include the following files: ```shell Debian Package Sample: $ dpkg -I rocm-core_6.4.0.60400-crdnnh.15158~22.04_amd64.deb new debian package, version 2.0. size 13986 bytes: control archive=2083 bytes. 305 bytes, 10 lines control 917 bytes, 11 lines md5sums 2871 bytes, 75 lines * postinst #!/bin/bash 873 bytes, 32 lines * prerm #!/bin/bash Architecture: amd64 Description: ROCm Runtime software stack Homepage: https://github.com/ROCm/rocm-core Maintainer: ROCm Dev Support Package: rocm-core Priority: optional Section: devel Version: 6.4.0.60400-crdnnh.15158~22.04 Installed-Size: 125 $ dpkg -c rocm-core_6.4.0.60400-crdnnh.15158~22.04_amd64.deb drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/ drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/ drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/.info/ -rw-r--r-- root/root 12 2024-11-22 10:37 ./opt/rocm-6.4.0/.info/version drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/include/ drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/include/rocm-core/ -rw-r--r-- root/root 2801 2024-11-22 10:37 ./opt/rocm-6.4.0/include/rocm-core/rocm_getpath.h -rw-r--r-- root/root 2440 2024-11-22 10:37 ./opt/rocm-6.4.0/include/rocm-core/rocm_version.h drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/ drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/cmake/ drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/cmake/rocm-core/ -rw-r--r-- root/root 2878 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/cmake/rocm-core/rocm-core-config-version.cmake -rw-r--r-- root/root 1590 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/cmake/rocm-core/rocm-core-config.cmake -rw-r--r-- root/root 842 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/cmake/rocm-core/rocmCoreTargets-release.cmake -rw-r--r-- root/root 3774 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/cmake/rocm-core/rocmCoreTargets.cmake lrwxrwxrwx root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/librocm-core.so -> librocm-core.so.1 lrwxrwxrwx root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/librocm-core.so.1 -> librocm-core.so.1.0.60400 -rw-r--r-- root/root 16640 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/librocm-core.so.1.0.60400 -rw-r--r-- root/root 550 2024-11-22 10:37 ./opt/rocm-6.4.0/lib/rocmmod drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/libexec/ drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/libexec/rocm-core/ -rw-r--r-- root/root 8208 2024-11-22 10:34 ./opt/rocm-6.4.0/libexec/rocm-core/runpath_to_rpath.py drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/share/ drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/share/doc/ drwxr-xr-x root/root 0 2024-11-22 10:37 ./opt/rocm-6.4.0/share/doc/rocm-core/ -rw-r--r-- root/root 1113 2024-11-22 10:34 ./opt/rocm-6.4.0/share/doc/rocm-core/LICENSE.txt RPM Package Sample: $ rpm -qip rocm-core-6.4.0.60400-crdnnh.15158.el8.x86_64.rpm Name : rocm-core Version : 6.4.0.60400 Release : crdnnh.15158.el8 Architecture: x86_64 Install Date: (not installed) Group : unknown Size : 37096 License : MIT Signature : (none) Source RPM : rocm-core-6.4.0.60400-crdnnh.15158.el8.src.rpm Build Date : Fri 22 Nov 2024 10:41:01 AM PST Build Host : 514dbdf6c195 Relocations : /opt/rocm-6.4.0 Vendor : Advanced Micro Devices, Inc. Summary : ROCm Runtime software stack Description : DESCRIPTION =========== This is an installer created using CPack (https://cmake.org). No additional installation instructions provided. $ rpm -qlp rocm-core-6.4.0.60400-crdnnh.15158.el8.x86_64.rpm /opt/rocm-6.4.0 /opt/rocm-6.4.0/.info /opt/rocm-6.4.0/.info/version /opt/rocm-6.4.0/include /opt/rocm-6.4.0/include/rocm-core /opt/rocm-6.4.0/include/rocm-core/rocm_getpath.h /opt/rocm-6.4.0/include/rocm-core/rocm_version.h /opt/rocm-6.4.0/lib /opt/rocm-6.4.0/lib/cmake /opt/rocm-6.4.0/lib/cmake/rocm-core /opt/rocm-6.4.0/lib/cmake/rocm-core/rocm-core-config-version.cmake /opt/rocm-6.4.0/lib/cmake/rocm-core/rocm-core-config.cmake /opt/rocm-6.4.0/lib/cmake/rocm-core/rocmCoreTargets-release.cmake /opt/rocm-6.4.0/lib/cmake/rocm-core/rocmCoreTargets.cmake /opt/rocm-6.4.0/lib/librocm-core.so /opt/rocm-6.4.0/lib/librocm-core.so.1 /opt/rocm-6.4.0/lib/librocm-core.so.1.0.60400 /opt/rocm-6.4.0/lib/rocmmod /opt/rocm-6.4.0/libexec /opt/rocm-6.4.0/libexec/rocm-core /opt/rocm-6.4.0/libexec/rocm-core/runpath_to_rpath.py /opt/rocm-6.4.0/share /opt/rocm-6.4.0/share/doc /opt/rocm-6.4.0/share/doc/rocm-core /opt/rocm-6.4.0/share/doc/rocm-core/LICENSE.txt ``` ## ROCM-CORE Library ROCM-CORE Library generated will be found in lib directory of the rocm-core package generated. ```shell find . -name "librocm-core.so.*" ``` ### Sample Usage of APIs provided by rocm-core Library #### Get ROCm Version For getting ROCm Version make use of getROCMVersion() API. Sample Usage Example as shown below. ```C // Usage : int mj=0,mn=0,p=0,ret=0; ret=getROCMVersion(&mj,&mn,&p); if(ret !=VerSuccess ) // error occured ``` rocm-core-rocm-7.1.0/cmake_modules/000077500000000000000000000000001507423117000171535ustar00rootroot00000000000000rocm-core-rocm-7.1.0/cmake_modules/rocm-core-config.cmake.in000066400000000000000000000013221507423117000237110ustar00rootroot00000000000000# - Config file for the rocm-core package # It defines the following variables # ROCM_CORE_INCLUDE_DIR - include directories for rocm-core # ROCM_CORE_LIB_DIR - libraries to link against # ROCM_PATH - Install Base Location for ROCM. @PACKAGE_INIT@ # Compute paths set_and_check(rocm_core_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") set_and_check(ROCM_CORE_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") set_and_check(rocm_core_LIB_DIR "@PACKAGE_LIB_INSTALL_DIR@") set_and_check(ROCM_CORE_LIB_DIR "@PACKAGE_LIB_INSTALL_DIR@") set_and_check(ROCM_PATH "${PACKAGE_PREFIX_DIR}") get_filename_component(ROCM_CORE_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) include("${ROCM_CORE_CMAKE_DIR}/rocmCoreTargets.cmake") rocm-core-rocm-7.1.0/rdhc/000077500000000000000000000000001507423117000152635ustar00rootroot00000000000000rocm-core-rocm-7.1.0/rdhc/README.md000066400000000000000000000053401507423117000165440ustar00rootroot00000000000000# rdhc Rocm Deployment Health Check Tool ## Features of the ROCm Deployment Health Check Tool 1. **Cross-Platform Support**: Works on Ubuntu, RHEL, and SLES distributions 2. **Comprehensive Testing**: - Default tests (GPU presence, driver status, rocminfo, rocm-smi) - Library dependency verification - Check some kernel parameters and ENV variables presence - Component-specific tests - Build and test the test program available from rocm-examples git repo dynamically. 3. **Dynamic Component Detection**: Identifies installed ROCm components using distribution-specific package manager commands 4. **Flexible Reporting**: - Pretty table output for terminal display - JSON export for further analysis or integration 5. **Configurable Verbosity**: Through command-line options (`-v` for verbose, `-s` for silent) ## Install dependency pip packages ```bash sudo pip3 install -r requirements.txt ``` ## Usage ```bash ./rdhc.py -h usage: sudo -E rdhc.py [options] ROCm Deployment Health Check Tool optional arguments: -h, --help show this help message and exit --quick Run quick tests only (default) --all Default tests + Compile and executes simple program for each component. -v, --verbose Enable verbose output -s, --silent Silent mode (errors only) -j FILE, --json FILE Export results to JSON file -d DIR, --dir DIR Directory path for temporary files (default: /tmp/rdhc/) Usage examples: # Run quick test (default tests only) sudo -E ./rdhc.py # Run all tests including compile and execute the rocm-example program for each component sudo -E ./rdhc.py --all # Run all tests with verbose output sudo -E ./rdhc.py --all -v # Enable verbose output sudo -E ./rdhc.py -v # Run in silent mode (only errors shown) sudo -E ./rdhc.py -s # Export results to a specific JSON file sudo -E ./rdhc.py --all --json rdhc-results.json # Specify a directory for temp files and logs (default: /tmp/rdhc/) sudo -E ./rdhc.py -d /home/user/rdhc-dir/ ``` ## RDHC Environment VARIABLES RDHC tool will use the following ENV varaibles and act accordingly if they are set. ```bash # ROCm installation path can be set by the below ENV varaible. Default is "/opt/rocm/" export ROCM_PATH="/opt/rocm" # For library dependency validation, the lib search depth can be set by the below ENV. # Default is full depth. It checks for all the lib files in ROCM_PATH/lib/ folder recursively. export LIBDIR_MAX_DEPTH="" # if you want to check the libs only from the ROCM_PATH/lib/ folder set the depth as 1. export LIBDIR_MAX_DEPTH=1 ``` The tool is designed to be easily extended with additional component tests by adding new test methods following the naming convention `test_check_component_name()`. rocm-core-rocm-7.1.0/rdhc/rdhc.py000077500000000000000000002352201507423117000165640ustar00rootroot00000000000000#!/usr/bin/env python3 import os import subprocess import logging import json import argparse import glob import re import yaml import textwrap from enum import Enum from prettytable import PrettyTable # Define test status enum class TestStatus(Enum): PASS = "PASS" FAIL = "FAIL" NOT_INSTALLED = "NOT INSTALLED" NOT_TESTED = "NOT TESTED" def run_command(command, shell=False): """Run a command and return stdout, stderr, and return code""" try: if isinstance(command, str) and not shell: command = command.split() process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell, universal_newlines=True ) stdout, stderr = process.communicate() return stdout, stderr, process.returncode except Exception as e: logging.error(f"Error executing command: {command}, error: {str(e)}") return "", str(e), 1 def generate_table_report(results): """Generate a pretty table report of test results""" table = PrettyTable() table.title = "RDHC Test Results" table.field_names = ["Test Name", "Description", "Status", "Details"] table.align = "l" # Left align all columns # Standard test descriptions descriptions = { "gpu_presence": "Check for AMD GPUs in the system", "amdgpu_driver": "Check if AMDGPU driver is working properly", "rocminfo": "Check if rocminfo is working properly", "amd_smi": "Check if amd-smi is working properly", "lib_dependencies": "Check rocm libraries runtime dependencies" } for test_name, result in results.items(): # For component tests, create a standard description if test_name.startswith("rocm-") or test_name.startswith("hip-"): description = f"Verify {test_name} usability" else: description = descriptions.get(test_name, f"Check {test_name} usability") table.add_row([ test_name, description, result["status"], result["reason"][:50] + "..." if len(result["reason"]) > 50 else result["reason"] ]) return table def generate_table_system_info(system_info): """Generate a pretty table report of amdgpu driver information""" table = PrettyTable() table.align = "l" # Left align all columns table.title = "General Information" table.header = False # No header row # If system_info is empty, add a placeholder row if not system_info: table.add_row(["No information available", "N/A"]) else: for key, value in system_info.items(): # Add a row for each key-value pair table.add_row([key, value]) return table def generate_table_gpu_info(gpu_info_dict): """Generate a pretty table report of GPU information""" # Create a function to flatten the nested dictionary def flatten_dict(d, parent_key='', sep=':'): items = [] for k, v in d.items(): new_key = parent_key + sep + k if parent_key else k if isinstance(v, dict): items.extend(flatten_dict(v, new_key, sep=sep).items()) else: items.append((new_key, v)) return dict(items) # create the table table = PrettyTable() table.title = "GPU Device Information" table.align = "l" # Left align all columns col_width = 25 # Maximum width for each column # Flatten each GPU dictionary flattened_gpus = {} for gpu_key, gpu_data in gpu_info_dict.items(): flattened_gpus[gpu_key] = flatten_dict(gpu_data) # Get all unique keys across all GPUs while preserving order all_keys = [] for gpu_data in flattened_gpus.values(): for key in gpu_data.keys(): if key not in all_keys: all_keys.append(key) # table.field_names = ["##, "Property", "GPU_O", "GPU_1", ...."] table.field_names = ["##", "Property"] + list(flattened_gpus.keys()) # Add rows to the table for idx, key in enumerate(all_keys): row = [idx, key] # Add row number as first column for gpu_key in flattened_gpus.keys(): # row.append(flattened_gpus[gpu_key].get(key, "N/A")) value = flattened_gpus[gpu_key].get(key, "N/A") # Convert to string if not already value_str = str(value) # print(f"Processing key: {key}, value_str: {value_str} ; value :{value}") # Apply text wrapping if value exceeds max_width if len(value_str) > col_width: wrapped_value = textwrap.fill(value_str, width=col_width) row.append(wrapped_value) else: row.append(value_str) table.add_row(row) return table def generate_table_firmware_info(firmware_info): """Generate a pretty table report of amdgpu firmware version informations""" gpu_dict = firmware_info # Create a flattened table with FW_ID as rows and GPUs as columns table = PrettyTable() table.align = "l" # Left align all columns table.title = "AMDGPU Firmware Version Information" # table.field_names = ["##, "FW_ID", "GPU_O", "GPU_1", ...."] table.field_names = ["##","FW_ID"] + list(gpu_dict.keys()) # Get all firmware IDs while preserving order fw_ids = [] for gpu_key, gpu_data in gpu_dict.items(): for fw_key, fw_data in gpu_data['FW_LIST'].items(): if fw_data['FW_ID'] not in fw_ids: fw_ids.append(fw_data['FW_ID']) # Add rows to the table for idx, fw_id in enumerate(fw_ids): row = [idx, fw_id] # Add row number and FW_ID as first two columns for gpu_key in gpu_dict.keys(): # Find the version for this firmware ID in this GPU version = "N/A" for fw_key, fw_data in gpu_dict[gpu_key]['FW_LIST'].items(): if fw_data['FW_ID'] == fw_id: version = fw_data['FW_VERSION'] break row.append(version) table.add_row(row) return table def export_to_json(results, filename): """Export test results to a JSON file""" try: with open(filename, 'w') as f: json.dump(results, f, indent=4) logging.info(f"Results exported to {filename}") return True except Exception as e: logging.error(f"Error exporting results to JSON: {e}") return False class ROCMHealthCheck: def __init__(self, logger=None): if logger is None: self.logger = logging.getLogger("RDHC") self.logger.setLevel(logging.INFO) else: self.logger = logger # List of all possible ROCm components to check self.all_components = [ "hipcc", "hip-runtime-amd", "hipblas", "hipfft", "hipcub-dev", "hipsolver", "rocblas", "rocfft", "rocprim-dev" , "rocrand", "rocsolver", "rocsparse", "rocthrust-dev", "miopen-hip", "applications" ] # Components to exclude from testing self.exclude_list = ["rocm-utils", "rocm-cmake"] # Categorized rocm-example targets self.rocm_examples_targets = {} # Store system & amdgpu driver information self.system_info = {} self.gpu_info_dict = {} self.gpus = [] self.fw_info = "" self.gpu_fw_info_dict = {} self.amdgpu_firmware_info = {} # Store test results self.results = {} # Get ROCM version self.rocm_version_str = self.get_rocm_version() self.rocm_version_num = self.get_rocm_version_num() self.logger.info(f"ROCm version string: {self.rocm_version_str}") self.logger.info(f"ROCm version number: {self.rocm_version_num}") self.system_info["ROCm version"] = self.rocm_version_str # Find installed components self.installed_components = self.get_installed_components() self.logger.info(f"Installed components: {self.installed_components}") def get_rocm_version(self): """Get the ROCm version string from /opt/rocm/.info/version""" try: rocm_path = os.environ.get("ROCM_PATH", "/opt/rocm") with open(f"{rocm_path}/.info/version", "r") as f: return f.read().strip() except Exception as e: self.logger.error(f"Error reading ROCm version: {e}") return "Unknown" def get_rocm_version_num(self): """Convert version string (e.g., '6.4.0-15121') to numeric format (e.g., '60400')""" try: if self.rocm_version_str == "Unknown": return "00000" # Extract version numbers using regex (e.g., "6.4.0" from "6.4.0-15121") match = re.match(r"(\d+)\.(\d+)\.(\d+)", self.rocm_version_str) if match: major, minor, patch = match.groups() # Format as XXYYZZ return f"{major.zfill(1)}{minor.zfill(2)}{patch.zfill(2)}" return "00000" except Exception as e: self.logger.error(f"Error processing ROCm version number: {e}") return "00000" def detect_os_type(self): """Detect the operating system type""" if os.path.exists("/etc/os-release"): with open("/etc/os-release") as f: os_info = f.read().lower() if "ubuntu" in os_info: return "ubuntu" elif "rhel" in os_info or "centos" in os_info or\ "fedora" in os_info or "almalinux" in os_info or\ "azurelinux" in os_info: return "rhel" elif "sles" in os_info or "suse" in os_info: return "sles" # Default to ubuntu if can't determine return "ubuntu" def get_installed_components(self): """Get list of installed ROCm components based on OS type and installation method""" installed = [] package_installed = [] folder_installed = [] # First, try to detect components via package managers os_type = self.detect_os_type() package_installed = self._get_components_from_packages(os_type) # If no packages found, or if ROCM_PATH points to a non-standard location, # check for folder-based installation if not package_installed: rocm_path = os.environ.get("ROCM_PATH", "/opt/rocm") folder_installed = self._get_components_from_folders(rocm_path) # Log the detection method used if package_installed: installed = package_installed self.logger.info(f"Detected components for a quick test via package manager: {len(package_installed)}") elif folder_installed: installed = folder_installed self.logger.info(f"Detected components for a quick test via folder structure: {len(folder_installed)}") else: self.logger.warning("!!! No ROCm components detected via packages or folders.") return installed def _get_components_from_packages(self, os_type): """Get installed components from package managers""" installed = [] for component in self.all_components: if os_type == "ubuntu": stdout, _, ret_code = run_command(f"dpkg -l {component}*", shell=True) if ret_code == 0 and "ii" in stdout: # Extract exact package name from dpkg output for line in stdout.split("\n"): if line.strip().startswith("ii"): parts = line.split() if len(parts) > 1 and parts[1].startswith(component): installed.append(parts[1]) break elif os_type == "rhel": stdout, _, ret_code = run_command(f"rpm -q {component}", shell=True) if ret_code == 0: # Extract package name from rpm output for line in stdout.split("\n"): if component in line: installed.append(line.strip()) break elif os_type == "sles": stdout, _, ret_code = run_command(f"zypper se -i {component}", shell=True) if ret_code == 0 and "i | " in stdout: # Extract package name from zypper output for line in stdout.split("\n"): if "i | " in line and component in line: parts = line.split("|") if len(parts) > 1: installed.append(parts[1].strip()) break return installed def _get_components_from_folders(self, rocm_path): """Get available components from ROCm folder structure""" installed = [] if not os.path.exists(rocm_path): self.logger.debug(f"ROCm path does not exist: {rocm_path}") return installed # Define component detection strategies component_detection = { "hipcc": [ f"{rocm_path}/bin/hipcc" ], "hip-runtime-amd": [ f"{rocm_path}/lib/libamdhip64.so*" ], "hipblas": [ f"{rocm_path}/lib/libhipblas.so*" ], "hipfft": [ f"{rocm_path}/lib/libhipfft.so*" ], "hipcub-dev": [ f"{rocm_path}/include/hipcub/hipcub.hpp" ], "hipsolver": [ f"{rocm_path}/lib/libhipsolver.so*" ], "rocblas": [ f"{rocm_path}/lib/librocblas.so*" ], "rocfft": [ f"{rocm_path}/lib/librocfft.so*" ], "rocprim-dev": [ f"{rocm_path}/include/rocprim/rocprim.hpp" ], "rocrand": [ f"{rocm_path}/lib/librocrand.so*" ], "rocsolver": [ f"{rocm_path}/lib/librocsolver.so*" ], "rocsparse": [ f"{rocm_path}/lib/librocsparse.so*" ], "rocthrust-dev": [ f"{rocm_path}/include/thrust", f"{rocm_path}/lib/cmake/rocthrust" ], "miopen-hip": [ f"{rocm_path}/lib/libMIOpen.so*", f"{rocm_path}/bin/MIOpenDriver" ] } # Check each component for component in self.all_components: if component in component_detection: component_found = False detection_paths = component_detection[component] for path_pattern in detection_paths: # Use glob to handle wildcards like *.so* matching_paths = glob.glob(path_pattern) if matching_paths: # Check if any matching path actually exists for path in matching_paths: if os.path.exists(path): installed.append(component) component_found = True self.logger.debug(f"Found {component} at: {path}") break if component_found: break elif os.path.exists(path_pattern): installed.append(component) component_found = True self.logger.debug(f"Found {component} at: {path_pattern}") break return installed def test_GPUPresence(self): """Test if AMD GPU is present in the system""" # AMD GPUs PCI class codes: 03xx (Display controllers ), 12xx (Processing accelerators) # use class codes also to identify AMD GPUs stdout, _, ret_code = run_command( "lspci -d 1002: -nn | grep -Ei \ 'Display controller|Processing accelerators|\[03[[:xdigit:]]{2}\]|\[12[[:xdigit:]]{2}\]' ",\ shell=True) gpu_hw = stdout.strip() if ret_code == 0 and gpu_hw: self.logger.debug(f"--Found AMD GPU(s): \n{gpu_hw}") return TestStatus.PASS.value, "Found AMD GPU(s)." return TestStatus.FAIL.value, "No AMD GPU detected." def test_amdgpu_driver(self): """Test if AMDGPU driver is installed and working properly""" issues = [] all_checks_passed = True # Check if amdgpu driver is loaded stdout, _, ret_code = run_command("lsmod | grep amdgpu", shell=True) if ret_code != 0 or not stdout.strip(): return TestStatus.FAIL.value, "AMDGPU driver module is not loaded." # Check DKMS status self.logger.info("--Checking DKMS status for amdgpu driver...") # Get current running kernel version stdout, stderr, ret_code = run_command("uname -r", shell=True) if ret_code != 0: self.logger.debug(f"----Failed to get Linux kernel version") current_kernel = stdout.strip() stdout, stderr, ret_code = run_command("dkms status", shell=True) stdout = stdout.strip() if ret_code != 0: self.logger.debug(f"----Failed to check DKMS status") else: if current_kernel: # Highlight the dkms status with "*" for the current kernel installed dkms_output = [] for line in stdout.split('\n'): if "amdgpu" in line and current_kernel in line: dkms_output.append(f"{line.strip()} *") else: dkms_output.append(line.strip()) self.system_info["dkms status"] = "\n".join(dkms_output) else: self.system_info["dkms status"] = stdout if "amdgpu" in stdout and "installed" in stdout: self.logger.debug("--AMDGPU DKMS module is installed.") else: all_checks_passed = False issues.append("AMDGPU DKMS driver not found or not installed.") # Check driver initialization state self.logger.info("--Checking AMDGPU driver initialization state...") init_state_checked = False if os.path.exists("/sys/module/amdgpu/initstate"): try: with open("/sys/module/amdgpu/initstate", "r") as f: init_state = f.read().strip() if init_state: self.logger.debug(f"--AMDGPU init state: {init_state}") init_state_checked = True else: all_checks_passed = False issues.append("AMDGPU driver not initialized properly.") #self.logger.debug("--AMDGPU driver not initialized properly.") except Exception as e: all_checks_passed = False issues.append(f"Could not read AMDGPU init state: {e}") else: all_checks_passed = False issues.append("AMDGPU init state file not found.") # Check power management # cat /sys/class/drm/card*/device/pp_dpm_sclk => "If it exists and returns a value, # then power management is enabled. That means the driver loaded and is using features # from firmware which is a safe indicator that things are working properly. self.logger.info("--Checking power management status...") sclk_files = glob.glob("/sys/class/drm/card*/device/pp_dpm_sclk") if sclk_files: sclk_checked = False for sclk_file in sclk_files: try: with open(sclk_file, "r") as f: sclk_info = f.read().strip() if sclk_info: self.logger.debug(f"--Power management is enabled. \n {sclk_file}: \n {sclk_info}") sclk_checked = True break except Exception as e: self.logger.warning(f"!!! Could not read {sclk_file}: \n {e}") if not sclk_checked: all_checks_passed = False issues.append("Power management not enabled.") else: all_checks_passed = False issues.append("No power management files found.") if all_checks_passed: return TestStatus.PASS.value, "AMDGPU driver is fully functional." else: # Driver is loaded but with issues self.logger.error(f"--AMDGPU driver loaded but with issues: {', --'.join(issues)}") return TestStatus.PASS.value, f"AMDGPU driver loaded but with issues." def test_rocminfo(self): """Test if rocminfo works properly""" stdout, stderr, ret_code = run_command("rocminfo") if ret_code != 0: self.logger.error(f"--rocminfo command failed: \n{stderr}") return TestStatus.FAIL.value, f"rocminfo command failed." # Check if GPU agents are detected if "Device Type" in stdout: gpu_count = stdout.count("Device Type: GPU") cpu_count = stdout.count("Device Type: CPU") self.logger.info(f"--rocminfo detected {gpu_count} GPU agent(s) and {cpu_count} CPU agent(s).") return TestStatus.PASS.value, f"rocminfo detected {gpu_count} GPU agent(s) and {cpu_count} CPU agent(s)." else: return TestStatus.FAIL.value, "rocminfo executed but no GPU agents detected." def test_rocm_agent_enumerator(self): """Test if rocm_agent_enumerator works properly""" stdout, stderr, ret_code = run_command("rocm_agent_enumerator") if ret_code != 0: self.logger.error(f"--rocm_agent_enumerator command failed: \n{stderr}") return TestStatus.FAIL.value, f"rocm_agent_enumerator command failed." # Check if GPU agents are detected if "gfx" in stdout: agents = ", ".join(stdout.splitlines()) self.logger.info(f"--Detected gpu agents: {agents}") self.system_info["GPU Arch "] = stdout.splitlines()[0] # Store first line as detected agents return TestStatus.PASS.value, f"Detected gpus: {agents}." else: self.logger.error("--rocm_agent_enumerator executed but no GPU agents detected.") return TestStatus.FAIL.value, "rocm_agent_enumerator executed but no GPU agents detected." def test_amd_smi(self): """Test if amd-smi works properly. Get all GPU related information using amd-smi command. """ results = {} # Test basic amd-smi command stdout, stderr, ret_code = run_command("amd-smi version") self.logger.debug(f"--amd-smi version: \n {stdout.strip()}") if ret_code != 0: self.logger.error(f"--amd-smi command failed: \n{stderr}") return TestStatus.FAIL.value, f"amd-smi command failed: {stderr}" # Test list options and save the data for report stdout, stderr, ret_code = run_command("amd-smi list") stdout = stdout.strip() if ret_code == 0 and stdout: self.logger.debug(f"amd-smi list : \n {stdout}") results["list"] = "Passed" self.gpu_info_dict = self._convert_string_to_dict(stdout) else: self.logger.warning(f"!!! amd-smi list failed: {stderr}") results["list"] = "Failed" # Test static options and save the data for report smi_static_dict = {} stdout, stderr, ret_code = run_command("amd-smi static --asic --bus --vbios --driver --vram") stdout = stdout.strip() if ret_code == 0 and stdout: self.logger.debug(f"amd-smi static : \n {stdout}") results["static"] = "Passed" smi_static_dict = self._convert_string_to_dict(stdout) else: self.logger.warning(f"!!! amd-smi static failed: {stderr}") results["static"] = "Failed" # Update static information in gpu_info_dict if smi_static_dict: for gpu_key, gpu_data in self.gpu_info_dict.items(): if gpu_key in smi_static_dict: # Merge static information into the existing GPU data gpu_data.update(smi_static_dict[gpu_key]) # Check firmware option stdout, stderr, ret_code = run_command("amd-smi firmware") stdout = stdout.strip() if ret_code == 0 and stdout: self.logger.debug(f"amd-smi firmware: \n {stdout}") results["firmware"] = "Passed" # Store firmware info in gpu_fw_info_dict # Format the string to make it valid YAML self.gpu_fw_info_dict = self._convert_string_to_dict(stdout) else: self.logger.warning(f"!!! amd-smi firmware failed: {stderr}") results["firmware"] = "Failed" # Check if any tests failed if "Failed" in results.values(): self.logger.error(f"Some amd-smi commands failed: {results}") return TestStatus.FAIL.value, f"Some amd-smi commands failed: {results}" return TestStatus.PASS.value, f"amd-smi tests passed: {', '.join(k for k in results.keys())}" def _convert_string_to_dict(self, stdout_str): """Convert a string to a valid YAML format and return as a dictionary""" # Format the string to make it valid YAML # Need to add quotes around the GPU key to make it a string try: # Replace 'GPU: 0' with 'GPU_0:' to make it a valid YAML key valid_yaml_str = re.sub(r'GPU: (\d+)', r'"GPU_\1":', stdout_str) # Use a custom loader to preserve all values as strings class StringPreservingLoader(yaml.SafeLoader): pass # Override the resolver to treat all scalar values as strings def string_constructor(loader, node): return str(loader.construct_scalar(node)) # Register our custom string constructor for all scalar values StringPreservingLoader.add_constructor( yaml.resolver.Resolver.DEFAULT_SCALAR_TAG, string_constructor ) # Disable YAML's type inference by overriding all the resolvers # This will prevent YAML from identifying hex/integers/etc. StringPreservingLoader.yaml_implicit_resolvers = {} # Parse YAML with our custom loader return yaml.load(valid_yaml_str, StringPreservingLoader) except yaml.YAMLError as e: self.logger.error(f"Error converting string to YAML: {e}") return {} def test_check_lib_dependencies(self): """Check library dependencies of installed ROCm components""" # Determine ROCm installation path rocm_path = os.environ.get("ROCM_PATH", "/opt/rocm") rocm_lib_path = os.path.join(rocm_path, "lib") max_depth = os.environ.get("LIBDIR_MAX_DEPTH", "") self.logger.debug(f"-- Env LIBDIR_MAX_DEPTH = {max_depth}") max_depth_arg = f"-maxdepth {max_depth}" if max_depth else "" if not os.path.exists(rocm_lib_path): self.logger.error(f"!!! ROCm library path not found: {rocm_lib_path}") return TestStatus.FAIL.value, "ROCm library path not found." # Get list of libraries in the ROCm path stdout, stderr, ret_code = run_command(f"find {rocm_lib_path} {max_depth_arg} -name '*.so*'", shell=True) if ret_code != 0: self.logger.error(f"--Error finding libraries in {rocm_lib_path}: \n{stderr}") return TestStatus.FAIL.value, f"Error finding libraries: {stderr}" libraries = stdout.strip().split('\n') if not libraries: self.logger.warning("!!! No libraries found in ROCm library path.") return TestStatus.NOT_TESTED.value, "No libraries found in ROCm library path." # Check libraries in the ROCm library path # Check its dependencies as well. self.logger.info(f"--Checking {len(libraries)} library files in ROCm library path: {rocm_lib_path}...") self.logger.info(f"--Checking shared library dependencies and its linked path...") missing_deps, wrong_path_warnings = self._check_rocm_libs_dependency(libraries, rocm_lib_path) # Log any warnings about libraries linked outside of ROCm library path if wrong_path_warnings: self.logger.warning(f"!!! Found {len(wrong_path_warnings)} warnings : rocm library path linked to outside of ROCm lib PATH. \n") self.logger.debug(f"!!! : \n{json.dumps(wrong_path_warnings, indent=2)}") # If there are any missing dependencies, log them and return failure if missing_deps: self.logger.error(f"!!! Found library dependency issues: \n{json.dumps(missing_deps, indent=2)}") return TestStatus.FAIL.value, f"Found library dependency issues." if wrong_path_warnings: return TestStatus.PASS.value, f"{len(wrong_path_warnings)} Path warnings are found. But all library dependencies are satisfied." else: return TestStatus.PASS.value, "All library dependencies are satisfied." def _check_rocm_libs_dependency(self, libraries, rocm_lib_path): missing_deps = {} wrong_path_warnings = {} # get the actual rocm lib path without symlink real_rocm_lib_path = os.path.realpath(rocm_lib_path) # create a list of rocm libraries basenames rocm_lib_basenames = [os.path.basename(lib) for lib in libraries] # Check each library with ldd for lib in libraries: missing = [] path_warnings = [] if not os.path.exists(lib): continue if os.path.islink(lib): # Resolve symlink to get actual library path rplib = os.path.realpath(lib) if not os.path.exists(rplib): self.logger.debug(f"!!! Library symlink {lib} points to a non-existent file <{rplib}>.") continue # Check if the symlink is within the ROCm library path if not (rplib.startswith(real_rocm_lib_path) or rplib.startswith(rocm_lib_path)): wrong_path_warnings[lib] = f"Library symlink pointing to ->{rplib} ; outside of ROCm library path {rocm_lib_path}." self.logger.debug(f"!!! Library symlink {lib}->{rplib} ; pointing outside of ROCm library path {rocm_lib_path}.") continue stdout, stderr, ret_code = run_command(f"ldd {lib}", shell=True) # Check if its not a dynamic library if "not a dynamic executable" in stderr: continue if ret_code != 0: missing_deps[lib] = f"Error running ldd: {stderr}" continue self.logger.debug(f"----Checking dependencies & link paths for {lib}...") # Parse ldd output for any libraries that are not found in the system # and for any linked libraries that are not in the ROCm library path and raise the warning. for line in stdout.splitlines(): if "not found" in line: missing.append(line.strip()) elif "=>" in line: # Ex: "libamdhip64.so => /opt/rocm/lib/libamdhip64.so (0x00007f8c3c000000)" # Check if the library is outside of the ROCm library path parts = line.split("=>") if len(parts) > 1: dep_lib = parts[0].strip() dep_lib_path = parts[1].strip().split()[0] # dep_lib_path can be relative path, so we need to resolve it # Check if the link is relative or absolute if not os.path.isabs(dep_lib_path): # If it's relative, resolve it against the library path # normalize the path to remove any redundant separators dep_lib_path = os.path.normpath(os.path.join(os.path.dirname(lib), dep_lib_path)) # check if the lib is a ROCm library, else # skip the check if dep_lib in rocm_lib_basenames: # If the dependency path is not within the ROCm library path, raise a warning # Check if dep_lib_path starts with rocm_lib_path(/opt/rocm/lib/) or real_rocm_lib_path(/opt/rocm-7.0.0/lib/) without symlink. if not (dep_lib_path.startswith(rocm_lib_path) or dep_lib_path.startswith(real_rocm_lib_path)): # self.logger.debug(f"!!! Library {dep_lib} is linked to {dep_lib_path} which is outside of ROCm library path {rocm_lib_path}.") path_warnings.append(f"Library {dep_lib} is linked to {dep_lib_path} which is outside of ROCm library path {rocm_lib_path}.") if missing: missing_deps[lib] = missing if path_warnings: wrong_path_warnings[lib] = path_warnings return missing_deps, wrong_path_warnings def test_check_kernel_parameters(self): """Check ROCm-related environment variables and system settings""" self.logger.info("--Checking kernel params/environment settings for ROCm...") warnings = 0 errors = 0 # 1. Check kernel parameters using data-driven approach self.logger.info("----Checking kernel parameters...") # Define kernel parameter checks kernel_param_checks = [ { "name": "numa_balancing", "description": "numa_balancing setting", "file_path": "/proc/sys/kernel/numa_balancing", "expected_value": "0", "check_type": "file_content", # file_content or cmdline_param "error_message": "numa_balancing is not disabled. For optimal performance, set numa_balancing=0", "warning_message": None, "is_error": True # True for error, False for warning }, { "name": "amd_iommu", "description": "amd_iommu & iommu settings", "file_path": "/proc/cmdline", "expected_value": "amd_iommu=on", "check_type": "cmdline_param", "error_message": "amd_iommu=on is not set in kernel parameters", "warning_message": None, "is_error": True }, { "name": "iommu", "description": "amd_iommu & iommu settings", "file_path": "/proc/cmdline", "expected_value": "iommu=pt", "check_type": "cmdline_param", "error_message": "iommu=pt is not set in kernel parameters", "warning_message": None, "is_error": True }, { "name": "pci_realloc", "description": "pci=realloc=off settings", "file_path": "/proc/cmdline", "expected_value": "pci=realloc=off", "check_type": "cmdline_param", "error_message": "pci=realloc=off is not set in kernel parameters", "warning_message": None, "is_error": True }, { "name": "cwsr_enable", "description": "Compute Wavefront Save and Restore [CWSR] settings", "file_path": "/sys/module/amdgpu/parameters/cwsr_enable", "expected_value": "0", "check_type": "file_content", "error_message": None, "warning_message": "amdgpu.cwsr_enable is set, should be 0 for optimal performance", "is_error": False } ] # Process each kernel parameter check for check in kernel_param_checks: self.logger.info(f"------Checking {check['description']}...") try: actual_value = None # Read the file if it exists if os.path.exists(check['file_path']): with open(check['file_path'], 'r') as f: file_content = f.read().strip() actual_value = file_content # Evaluate the check check_passed = False if actual_value is not None: if check['check_type'] == 'file_content': check_passed = (actual_value == check['expected_value']) elif check['check_type'] == 'cmdline_param': check_passed = (check['expected_value'] in actual_value) # Handle failed checks if not check_passed: if check['is_error'] and check['error_message']: self.logger.error(f"!!! {check['error_message']}") errors += 1 elif not check['is_error'] and check['warning_message']: self.logger.warning(f"!!! {check['warning_message']}") warnings += 1 except Exception as e: self.logger.warning(f"!!! Error checking {check['name']}: {str(e)}") warnings += 1 # 2. Check Large BAR is enabled - should be enabled for better performance self.logger.info("----Checking Large BAR setting...") try: large_bar_enabled = True error, warning = self._check_large_bar() errors += error warnings += warning except Exception as e: self.logger.warning(f"!!! Error checking BAR setting for GPU devices: {str(e)}") warnings += 1 # Return results if errors > 0: return TestStatus.FAIL.value, f"{errors} Errors & {warnings} warnings detected in kernel parameters/environment settings." elif warnings > 0: return TestStatus.PASS.value, f"{warnings} warnings detected in kernel parameters/environment settings." else: return TestStatus.PASS.value, "All kernel parameters/environment settings for ROCm appear to be configured correctly" def _check_large_bar(self): """Check if Large BAR is enabled for all GPUs in the system""" # read the GPUs VRAM total size from /sys/class/drm/card*/device/mem_info_vram_total # read the CPUs VRAM visible size from /sys/class/drm/card*/device/mem_info_vis_vram_total # if it has the same value, then large BAR is enabled. # Check this for all the GPUs in the system errors = 0 warnings = 0 # Get all GPU devices gpu_devices = glob.glob("/sys/class/drm/card*/device") if not gpu_devices: self.logger.error("!!! No GPU devices found.") errors += 1 return errors, warnings for device_path in gpu_devices: card_num = os.path.basename(os.path.dirname(device_path)) vram_total_path = os.path.join(device_path, "mem_info_vram_total") vis_vram_total_path = os.path.join(device_path, "mem_info_vis_vram_total") unique_id_path = os.path.join(device_path, "unique_id") if not os.path.exists(vram_total_path) or not os.path.exists(vis_vram_total_path): self.logger.debug(f"!!! VRAM info files not found for {card_num}. Skipping...") continue try: with open(vram_total_path, 'r') as f: vram_total = int(f.read().strip()) with open(vis_vram_total_path, 'r') as f: vis_vram_total = int(f.read().strip()) with open(unique_id_path, 'r') as f: unique_id = f.read().strip() # Format memory values for display vram_total_mb = vram_total / (1024*1024) vis_vram_total_mb = vis_vram_total / (1024*1024) if vram_total != vis_vram_total: self.logger.warning(f"!!! Large BAR is not enabled for {card_num}[SerialNo:{unique_id}]. VRAM total: {vram_total_mb}MB, VRAM total Visible to CPU: {vis_vram_total_mb}MB") warnings += 1 else: self.logger.info(f"Large BAR is enabled for {card_num}[SerialNo:{unique_id}]. VRAM total: {vram_total_mb}MB, VRAM total Visible to CPU: {vis_vram_total_mb}MB") except Exception as e: self.logger.error(f"!!! Error reading VRAM info for {device_path}: {str(e)}") errors += 1 return errors, warnings def test_check_env_variables(self): """Check ROCm-related environment variables settings""" # Check ROCm-related environment variables self.logger.info("--Checking environment variables...") warnings = 0 rocm_env_vars = { # List of ROCM stack related ENV variables here # if possible with its recommended value. # TODO : Need a single source of truth for these ENV variables. # have it in a yaml or json file and read it here } # Check if any of these variables are present found_env_vars = [] missing_env_vars = [] for var, default_val in rocm_env_vars.items(): if var in os.environ: found_env_vars.append(f"{var}={os.environ[var]}") else: missing_env_vars.append(f"{var} (recommended: {default_val})") if found_env_vars: self.logger.info(f"------Found ROCm environment variables:\n {', '.join(found_env_vars)}") if missing_env_vars: self.logger.warning(f"!!! Missing some recommended ROCm environment variables: {', '.join(missing_env_vars)}") warnings += 1 # Look for any ROCm-related environment variables not in our list additional_rocm_vars = [] # TODO: Make this list more comprehensive based on actual ROCm environment variables rocm_env_key_words = ['ROCM', 'HIP', 'HSA', 'ROCR', 'AMD', 'GPU', 'CL_', 'OPENCL', 'MIOPEN', 'ROCBLAS', 'ROCSPARSE', 'ROCALUTION', 'ROCSOLVER', 'ROCRAND' ] # TODO: Optimize this search to avoid multiple loop search. for var in os.environ: if any(x in var.upper() for x in rocm_env_key_words): if var not in rocm_env_vars: additional_rocm_vars.append(f"{var}={os.environ[var]}") if additional_rocm_vars: self.logger.warning(f"!!! Additional ROCm-related environment variables set :\n {'; '.join(additional_rocm_vars)}") warnings += 1 # Return results if warnings > 0: return TestStatus.PASS.value, f"{warnings} warnings detected in ENV settings." else: return TestStatus.PASS.value, "All ROCm environment settings appear to be set correctly" def _get_nic_brands(self, nic_cards): """Extract unique NIC brands from the list of NIC cards""" nic_brands = set() for card in nic_cards: # Use regex to extract brand name after the controller type # Pattern: controller type [code]: Brand Name ... match = re.search(r'(?:Ethernet controller|Network controller|Infiniband controller)\s*\[\w+\]:\s*(\w+)', card, re.IGNORECASE) if match: brand = match.group(1) nic_brands.add(brand) # Convert to list for easier handling nic_brands_list = list(nic_brands) return nic_brands_list[0] if nic_brands_list else None def _check_nic_drivers(self, nic_brand): """Check for specific NIC drivers based on the detected NIC brand Args: nic_brand (str): The detected NIC brand (e.g., "Mellanox", "Broadcom", "HPE") Returns: tuple: (nic_drivers_found, driver_issues) - lists of found drivers and issues """ nic_drivers_found = [] driver_issues = [] if not nic_brand: driver_issues.append("No NIC brand provided for driver check") return nic_drivers_found, driver_issues # Define driver mapping for different NIC brands driver_mapping = { "Mellanox": { "modules": ["mlx5_core", "mlx5_ib", "mlx4_core", "mlx4_ib"], "name": "Mellanox" }, "Broadcom": { "modules": ["bnxt_en", "bnxt_re"], "name": "Broadcom" }, "HPE": { "modules": ["cxi_core", "cxi_eth", "cxi_user"], "name": "HPE-Cassini" }, "Cray": { "modules": ["cxi_core", "cxi_eth", "cxi_user"], "name": "HPE-Cassini" }, "Cassini": { "modules": ["cxi_core", "cxi_eth", "cxi_user"], "name": "HPE-Cassini" }, "Intel": { "modules": ["i40e", "ice", "ixgbe", "igb", "e1000e"], "name": "Intel" } } # Get driver configuration for the detected brand driver_config = driver_mapping.get(nic_brand) if not driver_config: driver_issues.append(f"No driver configuration found for NIC brand: {nic_brand}") self.logger.warning(f"!!! No driver configuration found for NIC brand: {nic_brand}") return nic_drivers_found, driver_issues # Check if the specified drivers are loaded for module in driver_config["modules"]: stdout_mod, _, ret_mod = run_command(f"lsmod | grep {module}", shell=True) if ret_mod == 0 and stdout_mod.strip(): driver_name = f"{driver_config['name']}-{module}" nic_drivers_found.append(driver_name) self.logger.debug(f"--------{nic_brand} driver {module} is loaded") # Check if any drivers were found for this brand if not nic_drivers_found: driver_issues.append(f"{nic_brand} NIC present but drivers not loaded") self.logger.warning(f"!!! {nic_brand} NIC detected but drivers ({', '.join(driver_config['modules'])}) not loaded") return nic_drivers_found, driver_issues def _check_system_limits_configuration(self): """Check /etc/security/limits.conf for proper ulimit settings Returns: int: Number of warnings found """ warnings = 0 limits_conf_path = "/etc/security/limits.conf" self.logger.info("----Checking system limits configuration in /etc/security/limits.conf...") if not os.path.exists(limits_conf_path): self.logger.warning(f"!!! {limits_conf_path} not found. Cannot verify system-wide limit settings.") return 1 try: with open(limits_conf_path, 'r') as f: lines = f.readlines() except Exception as e: self.logger.warning(f"!!! Error reading {limits_conf_path}: {e}") return 1 # Initialize tracking variables found_limits = { 'soft_memlock': None, 'hard_memlock': None, 'soft_nofile': None, 'hard_nofile': None } # Parse non-commented lines for line_num, line in enumerate(lines, 1): line = line.strip() # Skip empty lines and comments if not line or line.startswith('#'): continue # Split line into parts (domain, type, item, value) parts = line.split() if len(parts) < 4: continue domain, limit_type, item, value = parts[0], parts[1], parts[2], parts[3] # Check for our target limits if limit_type == 'soft' and item == 'memlock': found_limits['soft_memlock'] = value self.logger.info(f"--------Found soft memlock: {value} (line {line_num})") elif limit_type == 'hard' and item == 'memlock': found_limits['hard_memlock'] = value self.logger.info(f"--------Found hard memlock: {value} (line {line_num})") elif limit_type == 'soft' and item == 'nofile': found_limits['soft_nofile'] = value self.logger.info(f"--------Found soft nofile: {value} (line {line_num})") elif limit_type == 'hard' and item == 'nofile': found_limits['hard_nofile'] = value self.logger.info(f"--------Found hard nofile: {value} (line {line_num})") # Check memlock limits (should be 'unlimited') for limit_key in ['soft_memlock', 'hard_memlock']: if found_limits[limit_key] is None: warnings += 1 limit_type = limit_key.split('_')[0] self.logger.warning(f"!!! Missing {limit_type} memlock setting in {limits_conf_path}") self.logger.warning(f"!!! Add: * {limit_type} memlock unlimited") elif found_limits[limit_key] != 'unlimited': warnings += 1 limit_type = limit_key.split('_')[0] self.logger.warning(f"!!! {limit_type} memlock is set to '{found_limits[limit_key]}', should be 'unlimited'") self.logger.warning(f"!!! Change to: * {limit_type} memlock unlimited") # Check nofile limits (should be >= 1048576) for limit_key in ['soft_nofile', 'hard_nofile']: if found_limits[limit_key] is None: warnings += 1 limit_type = limit_key.split('_')[0] self.logger.warning(f"!!! Missing {limit_type} nofile setting in {limits_conf_path}") self.logger.warning(f"!!! Add: * {limit_type} nofile 1048576") else: try: nofile_value = int(found_limits[limit_key]) if nofile_value < 1048576: warnings += 1 limit_type = limit_key.split('_')[0] self.logger.warning(f"!!! {limit_type} nofile is set to {nofile_value}, should be >= 1048576") self.logger.warning(f"!!! Change to: * {limit_type} nofile 1048576") except ValueError: warnings += 1 limit_type = limit_key.split('_')[0] self.logger.warning(f"!!! {limit_type} nofile has invalid value '{found_limits[limit_key]}', should be >= 1048576") self.logger.warning(f"!!! Change to: * {limit_type} nofile 1048576") return warnings def test_check_multinode_cluster_readiness(self): """Test if this node is enabled for multinode cluster""" self.logger.info("--Checking if this node is enabled for multinode cluster...") errors = 0 warnings = 0 cluster_readiness_issues = [] # 1. Check if mpirun command is in the PATH environment self.logger.info("----Checking MPI availability...") stdout, stderr, ret_code = run_command("which mpirun") if ret_code != 0: warnings += 1 self.logger.warning("!!! mpirun is not found in PATH. Install OpenMPI or MPICH.") else: # Get MPI version for additional info stdout_ver, _, _ = run_command("mpirun --version") mpi_version = stdout_ver.split('\n')[1] if stdout_ver else "Unknown version" self.logger.info(f"------Found MPI: {mpi_version}") # 2. Check if network cards (NICs) are present in hardware list self.logger.info("----Checking for network interface cards...") nic_brand = None nic_cards, stderr, ret_code = run_command("lspci -nn | grep -i 'ethernet\|network\|infiniband'", shell=True) if ret_code != 0 or not nic_cards.strip(): errors += 1 cluster_readiness_issues.append("No network cards found in hardware") self.logger.error("!!! No Ethernet/Network cards found in the system. This node cannot work as part of a multinode cluster setup.") else: nic_cards = nic_cards.strip().split('\n') self.logger.info(f"------Found {len(nic_cards)} network card(s)") for idx, card in enumerate(nic_cards): self.logger.debug(f"--------NIC {idx}: {card.strip()}") nic_brand = self._get_nic_brands(nic_cards) if nic_brand: self.logger.info(f"------Detected NIC brand: {nic_brand}") else: self.logger.warning("!!! Could not extract brand names from NIC information") # 3. Check for specific NIC drivers (Mellanox, Broadcom, HPE Cray/Cassini) self.logger.info("----Checking NIC drivers...") nic_drivers_found, driver_issues = self._check_nic_drivers(nic_brand) if nic_drivers_found: self.logger.info(f"------Active NIC drivers: {', '.join(nic_drivers_found)}") else: errors += 1 cluster_readiness_issues.append("No high-performance NIC drivers loaded") self.logger.error("!!! No high-performance NIC drivers detected") # Add driver issues to warnings count warnings += len([issue for issue in driver_issues if "not loaded" in issue]) # 4. # Check for RDMA kernel modules self.logger.info("----Checking RDMA kernel modules...") rdma_modules = ["rdma_cm", "ib_core", "ib_uverbs", "rdma_ucm"] rdma_modules_loaded = [] for module in rdma_modules: stdout_mod, _, ret_mod = run_command(f"lsmod | grep {module}", shell=True) if ret_mod == 0 and stdout_mod.strip(): rdma_modules_loaded.append(module) if rdma_modules_loaded: self.logger.info(f"------RDMA modules loaded: {', '.join(rdma_modules_loaded)}") else: errors += 1 cluster_readiness_issues.append("RDMA modules not loaded.") self.logger.error("!!! No RDMA kernel modules detected") # 5. Check RDMA link status self.logger.info("----Checking RDMA link...") stdout_rdma, stderr, ret_code = run_command("rdma link", shell=True) if ret_code == 0 and stdout_rdma.strip(): self.logger.info(f"------: \n{stdout_rdma.strip()}") else: warnings += 1 self.logger.warning("!!! No RDMA links detected. This may affect performance in a multinode cluster setup.") # 6 Check ulimit settings self.logger.info("----Checking ulimit settings...") ulimit_warnings = self._check_system_limits_configuration() if ulimit_warnings == 0: self.logger.info(f"------All required limits are properly configured for ulimit.") else: warnings += ulimit_warnings self.logger.warning(f"!!! Found {warnings} limit configuration issues for ulimit.") self.logger.warning(f"!!! Note: Recommended to set the [ulimit -n 1048576 and ulimit -l unlimited] ") # 7. Final assessment based on all checks self.logger.info("----Final multinode cluster readiness assessment...") # Performance warnings performance_warnings = [] if not nic_drivers_found: performance_warnings.append("No high-performance NIC drivers") if not rdma_modules_loaded: performance_warnings.append("RDMA modules not loaded") # Generate final result if errors: error_msg = f"Multinode cluster readiness check failed with {errors} errors. Issues: {'; '.join(cluster_readiness_issues)}" self.logger.error(f"!!! {error_msg}") return TestStatus.FAIL.value, error_msg elif warnings: warning_msg = f"Found {len(nic_cards)} NICs and Found {warnings} warnings." self.logger.warning(f"!!! {warning_msg}") return TestStatus.PASS.value, warning_msg else: success_msg = f"Found {len(nic_cards)} NICs and required drivers are loaded." self.logger.info(f" {success_msg}") return TestStatus.PASS.value, success_msg # Example component specific tests (these should be customized for each component) def test_check_hipcc(self): """Test hipcc package""" # Check if hipcc is available stdout, stderr, ret_code = run_command("which hipcc") if ret_code != 0: return TestStatus.FAIL.value, "hipcc not found in PATH." # Check version of hipcc stdout, stderr, ret_code = run_command("hipcc --version") if ret_code != 0: return TestStatus.FAIL.value, f"hipcc version check failed: {stderr}" # Build and test a simple program # test_target_name = "hip_bit_extract" test_target_name = self._get_build_target("hipcc", 0) return self._build_target_and_run("hipcc", test_target_name) def test_check_hip_runtime_amd(self): """Test hip-runtime-amd package""" test_target_name = "hip_runtime_compilation" # test_target_name = self._get_build_target("hip-runtime-amd", 0) return self._build_target_and_run("hip-runtime-amd", test_target_name) def test_check_hipblas(self): """Test hipblas package""" # test_target_name = "hipblas_gemm_strided_batched" test_target_name = self._get_build_target("hipblas", 0) return self._build_target_and_run("hipblas", test_target_name) def test_check_hipfft(self): """Test hipfft package""" # test_target_name = "hipfft_plan_d2z" test_target_name = self._get_build_target("hipfft", 0) return self._build_target_and_run("hipfft", test_target_name) def test_check_hipcub_dev(self): """Test hipcub-dev package""" # test_target_name = "hipcub_device_radix_sort" test_target_name = self._get_build_target("hipcub-dev", 0) return self._build_target_and_run("hipcub-dev", test_target_name) def test_check_hipsolver(self): """Test hipsolver package""" # test_target_name = "hipsolver_gels" test_target_name = self._get_build_target("hipsolver", 0) return self._build_target_and_run("hipsolver", test_target_name) def test_check_rocblas(self): """Test rocblas package""" # test_target_name = "rocblas_axpy" test_target_name = self._get_build_target("rocblas", 0) return self._build_target_and_run("rocblas", test_target_name) def test_check_rocfft(self): """Test rocfft package""" # test_target_name = "rocfft_callback" test_target_name = self._get_build_target("rocfft", 0) return self._build_target_and_run("rocfft", test_target_name) def test_check_rocprim_dev(self): """Test rocprim package""" # test_target_name = "rocprim_block_sum" test_target_name = self._get_build_target("rocprim-dev", 0) return self._build_target_and_run("rocprim-dev", test_target_name) def test_check_rocrand(self): """Test rocrand package""" # test_target_name = "rocrand_simple_distributions_cpp" test_target_name = self._get_build_target("rocrand", 0) return self._build_target_and_run("rocrand", test_target_name) def test_check_rocsolver(self): """Test rocsolver package""" # test_target_name = "rocsolver_getf2" test_target_name = self._get_build_target("rocsolver", 0) return self._build_target_and_run("rocsolver", test_target_name) def test_check_rocsparse(self): """Test rocsparse package""" # test_target_name = "rocsparse_bsrmv" test_target_name = self._get_build_target("rocsparse", 0) return self._build_target_and_run("rocsparse", test_target_name) def test_check_rocthrust_dev(self): """Test rocthrust package""" #test_target_name = "rocthrust_norm" test_target_name = self._get_build_target("rocthrust-dev", 0) return self._build_target_and_run("rocthrust-dev", test_target_name) def _get_build_target(self, comp_name, item_index=0): """Get a build target for the specified component. Args: comp_name (str): Component name (e.g., rocblas, hipfft) item_index (int, optional): Index of target to retrieve. Defaults to 0. Returns: str or None: Target name at the specified index or None if not found """ # Handle special cases for component name mapping component_mapping = { "hipcc": "hip", "hip-runtime-amd": "hip", "hipcub-dev": "hipcub", "rocprim-dev": "rocprim", "rocthrust-dev": "rocthrust", # Add more mappings as needed } # Get the actual component key to use comp_key = component_mapping.get(comp_name, comp_name) # Check if the component exists and has targets if comp_key in self.rocm_examples_targets and len(self.rocm_examples_targets[comp_key]) > item_index: return self.rocm_examples_targets[comp_key][item_index] return None def _build_target_and_run(self, comp_name, test_target_name): """Build and run a specific target from rocm-examples Args: comp_name: Component name (e.g., 'rocblas', 'hipfft') test_target_name: Target name for cmake/ctest (e.g., 'rocblas_axpy') Returns: tuple: (TestStatus, message) """ self.logger.info(f"--Checking {comp_name} with a simple program [{test_target_name}]...") stdout, stderr, ret_code = run_command( f"cmake --build build --target {test_target_name}; ctest --test-dir build -R \"^{test_target_name}$\"", shell=True) self.logger.debug(f"\n{stdout.strip()}") if ret_code != 0: self.logger.error(f"--Failed to compile rocm-examples ({test_target_name}): \n{stderr}") return TestStatus.FAIL.value, f"{comp_name} check failed: {stderr}" else: self.logger.debug(f"--Successfully executed {test_target_name}.") return TestStatus.PASS.value, f"{comp_name} is working." def test_check_miopen_hip(self): """Test miopen-hip package""" # Find ROCM path rocm_path = os.environ.get("ROCM_PATH", "/opt/rocm") miopen_driver = os.path.join(rocm_path, "bin", "MIOpenDriver") # Check if MIOpenDriver exists if not os.path.exists(miopen_driver): return TestStatus.NOT_INSTALLED.value, "MIOpenDriver not found" self.logger.info("--Checking MIOpen with MIOpenDriver utility...") test_results = [] # Test 1: Simple convolution test self.logger.debug("----Checking MIOpen convolution with default parameters...") conv_cmd = f"{miopen_driver} conv" stdout, stderr, ret_code = run_command(conv_cmd, shell=True) if ret_code != 0: self.logger.error(f"!!!! MIOpen convolution test failed: \n{stderr}") test_results.append(("Convolution", False, stderr)) else: self.logger.debug("----MIOpen convolution test passed.") test_results.append(("Convolution", True, "")) # Test 2: Pooling test self.logger.debug("----Checking MIOpen pooling with default parameters...") pool_cmd = f"{miopen_driver} pool" stdout, stderr, ret_code = run_command(pool_cmd, shell=True) if ret_code != 0: self.logger.error(f"!!!! MIOpen pooling test failed: \n{stderr}") test_results.append(("Pooling", False, stderr)) else: self.logger.debug("----MIOpen pooling test passed.") test_results.append(("Pooling", True, "")) # Test 3: Activation test self.logger.debug("----Checking MIOpen activation test with default parameters...") activ_cmd = f"{miopen_driver} activ -m relu" stdout, stderr, ret_code = run_command(activ_cmd, shell=True) if ret_code != 0: self.logger.error(f"!!!! MIOpen activation test failed: \n{stderr}") test_results.append(("Activation", False, stderr)) else: self.logger.debug("----MIOpen activation test passed.") test_results.append(("Activation", True, "")) # Evaluate overall results failed_tests = [test[0] for test in test_results if not test[1]] if failed_tests: return TestStatus.FAIL.value, f"MIOpen tests failed for: {', '.join(failed_tests)}" else: return TestStatus.PASS.value, "MIOpen is working correctly for basic operations" def test_component(self, component): """Test a specific component by dynamically calling the appropriate test function""" test_method_name = f"test_check_{component.replace('-', '_').replace('+', '_plus_')}" test_method = getattr(self, test_method_name, None) if component in self.exclude_list: return TestStatus.NOT_TESTED.value, f"{component} is in exclude list." if component not in self.installed_components: return TestStatus.NOT_INSTALLED.value, f"{component} is not installed." if test_method: return test_method() else: # Default test for components without specific tests return self.test_check_basic_component(component) def test_check_basic_component(self, component): """Basic test for components without specific test methods""" # Check if component packge files installed # TODO return TestStatus.PASS.value, f"{component} is installed but no specific test available." def run_default_tests(self): """Run the default set of tests""" results = {} # Test 1: GPU Presence self.logger.info("Running test: GPU Presence...") status, reason = self.test_GPUPresence() results["gpu_presence"] = {"status": status, "reason": reason} # Test 2: AMDGPU Driver self.logger.info("Running test: AMDGPU Driver...") status, reason = self.test_amdgpu_driver() results["amdgpu_driver"] = {"status": status, "reason": reason} # Test 3: Kernel Parameters self.logger.info("Running test: Kernel Parameters...") status, reason = self.test_check_kernel_parameters() results["kernel_parameters"] = {"status": status, "reason": reason} # Test 4: rocminfo self.logger.info("Running test: rocminfo...") status, reason = self.test_rocminfo() results["rocminfo"] = {"status": status, "reason": reason} # Test 5: rocm_agent_enumerator self.logger.info("Running test: rocm_agent_enumerator...") status, reason = self.test_rocm_agent_enumerator() results["rocm_agent_enumerator"] = {"status": status, "reason": reason} # Test 6: amd-smi self.logger.info("Running test: amd-smi...") status, reason = self.test_amd_smi() results["amd_smi"] = {"status": status, "reason": reason} # Test 7: Library Dependencies self.logger.info("Running test: Library Dependencies...") status, reason = self.test_check_lib_dependencies() results["lib_dependencies"] = {"status": status, "reason": reason} # Test 8: Environment Variables self.logger.info("Running test: ENV variables...") status, reason = self.test_check_env_variables() results["env_variables"] = {"status": status, "reason": reason} # Test 9: Multinode cluster readiness self.logger.info("Running test: Multinode cluster readiness...") status, reason = self.test_check_multinode_cluster_readiness() results["Multinode_Readiness"] = {"status": status, "reason": reason} return results def run_component_tests(self): """Run tests for installed components""" results = {} for component in self.installed_components: if component not in self.exclude_list: self.logger.info(f"Running component test: {component}...") status, reason = self.test_component(component) results[component] = {"status": status, "reason": reason} return results def run_applications_tests(self): """Run tests for applications in rocm-examples""" results = {} # Check if rocm-examples targets are available if not self.rocm_examples_targets: return {"applications": {"status": TestStatus.NOT_TESTED.value, "reason": "No rocm-examples targets available for applications."}} # Run tests for each application target for target in self.rocm_examples_targets.get("applications", []): self.logger.info(f"Running application test: [ {target} ]...") status, reason = self._build_target_and_run(target, target) results[target] = {"status": status, "reason": reason} return results def run_tests(self, run_all=False, temp_dir="/tmp/rdhc/"): """Run tests based on the run_all flag""" # Always run default tests self.results = self.run_default_tests() # Run component tests if run_all is True if run_all: # Clone and configure rocm-examples repository if its not already done. # self.logger.info("Cloning rocm-examples repository...") # Store original directory original_dir = os.getcwd() try: # Ensure temp directory exists os.makedirs(temp_dir, exist_ok=True) # Check if rocm-examples already exists examples_dir = os.path.join(temp_dir, "rocm-examples") if not os.path.exists(examples_dir): # Navigate to temp directory os.chdir(temp_dir) # Clone repository self.logger.info("Cloning rocm-examples repository...") stdout, stderr, ret_code = run_command( "git clone https://github.com/ROCm/rocm-examples.git", shell=True) if ret_code != 0: self.logger.error(f"Failed to clone rocm-examples: \n{stderr}") else: self.logger.info("Successfully cloned rocm-examples repository.") else: self.logger.info("rocm-examples repository already exists, skipping git clone.") # Navigate to the repository directory os.chdir(examples_dir) # Check if build directory exists if not os.path.exists(os.path.join(examples_dir, "build")): # Configure with cmake self.logger.info("Configuring rocm-examples with cmake...") stdout, stderr, ret_code = run_command( "cmake -S . -B build") if ret_code != 0: self.logger.error(f"Failed to configure rocm-examples: \n{stderr}") else: self.logger.info("Successfully configured rocm-examples.") else: self.logger.info("rocm-examples build directory already exists, skipping cmake configuration.") # Get the avilabale build targets dynamically. self.logger.info("Retrieving available build targets...") stdout, stderr, ret_code = run_command( "cmake --build build --target help", shell=True) if ret_code != 0: self.logger.error(f"Failed to retrieve build targets: \n{stderr}") else: # Parse the output to find targets self.rocm_examples_targets = self._parse_rocm_example_targets(stdout) self.logger.debug(f"Available build targets from rocm-examples source:\n{json.dumps(self.rocm_examples_targets, indent=2)}") except Exception as e: self.logger.error(f"Error during rocm-examples setup: \n{str(e)}") finally: # Run component tests component_results = self.run_component_tests() self.results.update(component_results) # Run Simple Application tests app_results = self.run_applications_tests() self.results.update(app_results) # Return to original directory os.chdir(original_dir) return self.results def _parse_rocm_example_targets(self, cmake_target_help_output): """Parse cmake target help output and categorize targets by component. Args: cmake_target_help_output (str): Output from 'cmake --build build --target help' Returns: dict: Dictionary with component names as keys and lists of targets as values """ # Initialize the result dictionary component_targets = {} # Split the output into lines lines = cmake_target_help_output.strip().split('\n') # Process each line for line in lines: line = line.strip() if not line.startswith("..."): continue # Remove the "..." prefix target = line.replace("...", "").strip() # Skip special targets without underscore if "_" not in target: continue # Skip certain special targets if target in ["list_install_components", "edit_cache", "rebuild_cache"]: continue # Extract component name (part before the first underscore) component = target.split("_")[0] # Add target to the appropriate component list if component not in component_targets: component_targets[component] = [] component_targets[component].append(target) return component_targets # ======================================================================================= def setup_logger(verbose=False, silent=False): """Setup the logger with appropriate log level""" log_level = logging.ERROR if silent else (logging.DEBUG if verbose else logging.INFO) logger = logging.getLogger("RDHC") logger.setLevel(log_level) # Clear any existing handlers for handler in logger.handlers[:]: logger.removeHandler(handler) # Console handler console_handler = logging.StreamHandler() console_handler.setLevel(log_level) # Format formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') console_handler.setFormatter(formatter) # Add handler to logger logger.addHandler(console_handler) return logger def main(): # Parse command line arguments parser = argparse.ArgumentParser(description="ROCm Deployment Health Check Tool", formatter_class=argparse.RawDescriptionHelpFormatter, usage="sudo -E ./rdhc.py [options]", epilog="Usage examples:\n"+ "# Run quick test (default tests only)\n" + "sudo -E ./rdhc.py\n" + "\n"+ "# Run all tests including compile and execute the rocm-example program for each component\n"+ "sudo -E ./rdhc.py --all\n" + "\n"+ "# Run all tests with verbose output\n" + "sudo -E ./rdhc.py --all -v\n" + "\n"+ "# Enable verbose output\n" + "sudo -E ./rdhc.py -v\n" + "\n"+ "# Run in silent mode (only errors shown)\n" + "sudo -E ./rdhc.py -s\n" + "\n"+ "# Export results to a specific JSON file\n" + "sudo -E ./rdhc.py --all --json rdhc-results.json\n" + "\n"+ "# Specify a directory for temp files and logs (default: /tmp/rdhc/)\n" + "sudo -E ./rdhc.py -d /home/user/rdhc-dir/\n" + " ", ) parser.add_argument("--quick", action="store_true", help="Run quick tests only (default)") parser.add_argument("--all", action="store_true", help="Default tests + Compile and executes simple program for each component.") parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose output") parser.add_argument("-s", "--silent", action="store_true", help="Silent mode (errors only)") parser.add_argument("-j", "--json", metavar="FILE", help="Export results to JSON file", default="rdhc_results.json") parser.add_argument("-d", "--dir", metavar="DIR", help="Directory path for temporary files (default: /tmp/rdhc/)", default="/tmp/rdhc/") args = parser.parse_args() # Setup logger logger = setup_logger(args.verbose, args.silent) # Ensure temp directory exists temp_dir = args.dir try: os.makedirs(temp_dir, exist_ok=True) logger.debug(f"Using temporary directory: {temp_dir}") except Exception as e: logger.error(f"Failed to create temporary directory {temp_dir}: {e}") logger.info("Falling back to current directory") temp_dir = "./" # Create the health check instance health_check = ROCMHealthCheck(logger) # Run tests with the temp_dir health_check.run_tests(run_all=args.all, temp_dir=temp_dir) # Generate and print report print("\nROCm Deployment Health Check Results:") health_check.system_info["RDHC directory"] = temp_dir health_check.system_info["Json output file"] = args.json table = generate_table_system_info(health_check.system_info) print(table) if health_check.gpu_info_dict: table = generate_table_gpu_info(health_check.gpu_info_dict) print(table) if health_check.gpu_fw_info_dict: table = generate_table_firmware_info(health_check.gpu_fw_info_dict) print(table) table = generate_table_report(health_check.results) print(table) # Export results to JSON if requested if args.json: # If json path is not absolute, place it in the specified temp directory json_path = args.json if not os.path.isabs(json_path): json_path = os.path.join(temp_dir, json_path) logger.info(f"Exporting results to JSON file: {json_path}") # Create a combined data dictionary with all information combined_data = { "system_info": health_check.system_info, "gpu_info": health_check.gpu_info_dict, "firmware_info": health_check.gpu_fw_info_dict, "test_results": health_check.results } export_to_json(combined_data, json_path) if __name__ == "__main__": main() rocm-core-rocm-7.1.0/rdhc/requirements.txt000066400000000000000000000000421507423117000205430ustar00rootroot00000000000000prettytable>=3.14.0 PyYAML>=5.4.1 rocm-core-rocm-7.1.0/rocm-core.postinst000077500000000000000000000060031507423117000200400ustar00rootroot00000000000000#!/bin/bash set -e do_update_alternatives(){ # skip update if program doesn't exist command -v update-alternatives >/dev/null || return 0 local altscore now now=$(date -u +%s) # Number of seconds since 1 Jan 1970 # The reason for this approach rather than using the build number # is to allow for jobs from different builds. In one build job the # job number might be at 1200, whilst in a release job the number # may be only 1. This approach assums that if you install a build # with a different semantic version then the highest is the # desired one, but if you install two with the same semver then # the newest is the desired version. # Build up a score. It needs to fit in 32 bits altscore=$((@VERSION_MAJOR@ - 3)) altscore=$((altscore * 14 + @VERSION_MINOR@)) # Allow up to 14 minor altscore=$((altscore * 14 + @VERSION_PATCH@)) # Allow up to 14 patch # So far if the version is less than 9 we have a number (altscore) # that is less than 1175. 2**31/1175 is about 1.8 million. So # multiply altscore by 1,000,000 and add in a factor of how many # minutes have passed from an arbitary point in time (1,600,000,000 # seconds after 1 Jan 1970 or Sep 13 12:26:40 2020) on the # basis that no one is going to be installing a new version more # often than every minute. This does get things wrong if a million # minutes pass and you are downgrading, but the chances of someone # waiting almost 2 years between installing a version and the # previous patch level is small. altscore=$((altscore*1000000+(now-1600000000)/60)) # Update the /opt/rocm symlink # For custom location installation of rpm package, /opt/rocm symlink is not required # TBD: For custom location installation of deb package. if [[ ${ID_LIKE:-$ID} == "debian" ]] || [[ "$RPM_INSTALL_PREFIX0" == "/opt/rocm-"* ]] ; then update-alternatives --install "/opt/rocm" "rocm" "@CPACK_PACKAGING_INSTALL_PREFIX@" "$altscore" fi for loc in "/usr/share/modules/modulefiles" "/usr/local/Modules/modulefiles" "/usr/share/Modules/modulefiles" "/usr/share/Modules/3.2.10/modulefiles" do if [ -d "$loc" ] then mkdir -p "$loc/rocm" if [[ ${ID_LIKE:-$ID} == "debian" ]] ; then update-alternatives --install "$loc/rocm/@ROCM_VERSION@" "rocmmod@ROCM_VERSION@" "@CPACK_PACKAGING_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/rocmmod" "$altscore" else update-alternatives --install "$loc/rocm/@ROCM_VERSION@" "rocmmod@ROCM_VERSION@" "$RPM_INSTALL_PREFIX0/@CMAKE_INSTALL_LIBDIR@/rocmmod" "$altscore" fi break; fi done true } if [ -e /etc/os-release ] && source /etc/os-release && [[ ${ID_LIKE:-$ID} == "debian" ]] then case "$1" in (configure) do_update_alternatives ;; (abort-upgrade|abort-remove|abort-deconfigure) echo "$1" ;; (*) exit 0 ;; esac else do_update_alternatives fi rocm-core-rocm-7.1.0/rocm-core.prerm000077500000000000000000000017211507423117000173040ustar00rootroot00000000000000#!/bin/bash set -e do_update_alternatives(){ # skip update if program doesn't exist command -v update-alternatives >/dev/null || return 0 # Update the /opt/rocm symlink if [[ ${ID_LIKE:-$ID} == "debian" ]] || [[ "$RPM_INSTALL_PREFIX0" == "/opt/rocm-"* ]] ; then update-alternatives --remove "rocm" "@CPACK_PACKAGING_INSTALL_PREFIX@" fi if [[ ${ID_LIKE:-$ID} == "debian" ]] ; then update-alternatives --remove "rocmmod@ROCM_VERSION@" "@CPACK_PACKAGING_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/rocmmod"|| true else update-alternatives --remove "rocmmod@ROCM_VERSION@" "$RPM_INSTALL_PREFIX0/@CMAKE_INSTALL_LIBDIR@/rocmmod"|| true fi } if [ -e /etc/os-release ] && source /etc/os-release && [[ ${ID_LIKE:-$ID} == "debian" ]] then case "$1" in (remove | upgrade) do_update_alternatives ;; (purge) ;; (*) exit 0 ;; esac else do_update_alternatives fi rocm-core-rocm-7.1.0/rocm_getpath.cpp000066400000000000000000000126351507423117000175320ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////////// // // MIT License // // Copyright (c) 2017 - 2024 Advanced Micro Devices, Inc. All rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // //////////////////////////////////////////////////////////////////////////////// #include #include #include /* PATH_MAX */ #include #include #include #include "rocm_getpath.h" /* Macro for NULL CHECK */ #define NULL_CHECK(ptr) if(!ptr) return PathIncorrecPararmeters; /* Target Library Install Dir */ #define TARGET_LIB_INSTALL_DIR TARGET_LIBRARY_INSTALL_DIR /* Target Library Name Buf Size */ #define LIBRARY_FILENAME_BUFSZ (PATH_MAX+1) /* Internal Function to get Base Path - Ref from Icarus Logic*/ static int getROCmBase(char *buf); /* Public Function to get the ROCm Install Base Path // Argument1 (out) : InstallPath (char** pointer which will return InstallPath found) // Argument2 (out) : InstallPathLen (Pointer to integer (size of InstallPath) returned) // Usage : // char *installPath=NULL; // int installPathLen = 0; // installStatus = getROCmInstallPath( &installPath, &installPathLen ); // if(installStatus !=PathSuccess ){ // error occured // ... // } // free(installPath); //caller must free allocated memory after usage. // ... */ PathErrors_t getROCmInstallPath( char** InstallPath, unsigned int *InstallPathLen ) { NULL_CHECK(InstallPath); NULL_CHECK(InstallPathLen); int ret = PathErrorMAX; char *bufPtr = (char *)NULL; unsigned int bufSz = 0; bufPtr = (char *)malloc( LIBRARY_FILENAME_BUFSZ * sizeof(char) ); memset( bufPtr, 0, LIBRARY_FILENAME_BUFSZ ); *InstallPathLen = 0; *InstallPath = NULL; ret = getROCmBase(bufPtr); if (0 > ret){ free(bufPtr); return (PathErrors_t)ret; } else if (0 == ret){ free(bufPtr); return PathFailedToGetBase; } else{ bufSz = ret;//additional char for null termination } *InstallPath = bufPtr; *InstallPathLen = bufSz; return PathSuccess; } /* General purpose function that fills the directory to find rocm related stuff */ /* returns the offset into the buffer for the terminating NUL or -1 for error */ /* The buffer should be at least PATH_MAX */ static int getROCmBase(char *buf) { int len=0; char *envStr=NULL; char libFileName[LIBRARY_FILENAME_BUFSZ]; char *end=NULL; // Check Environment Variable is set for ROCM // install base path, then use it directly. if ((envStr = getenv("ROCM_PATH"))) { /* User space override, essentially just copied through as long as it is not too long */ len = strlen(envStr); if (len > 0) { if (envStr[len] == '/') { /* Already has at least one terminating */ len--; } if (len > PATH_MAX-1 ) { return PathValuesTooLong; } strncpy(buf, envStr, len); buf[len]='/'; buf[len+1]='\0'; /* Length of string including trailing '/' */ return len+1; } } // If Environment Variable is not set // use dl APIs to get target lib path // and get rocm base install path using the lib Path. #if BUILD_SHARED_LIBS sprintf(libFileName, "lib%s.so", TARGET_LIBRARY_NAME); void *handle=dlopen(libFileName,RTLD_NOW); if (!handle){ /* We can't find the library */ return PathLinuxRuntimeErrors; } /* Variable to hold the return value from dlinfo */ struct link_map *map = (struct link_map*)NULL; /* Query the runtime linker */ dlinfo(handle,RTLD_DI_LINKMAP,&map); if (map ->l_name && realpath(map ->l_name,buf)) { /* Get Library Directory Path */ char *end = strrchr(buf, '/'); if (end && end > buf) { *end = '\0'; } } else{ /* If l_name is NULL or realpath() failed * Close handle before return error */ dlclose(handle); return PathLinuxRuntimeErrors; } dlclose(handle); /* find the start of substring TARGET_LIB_INSTALL_DIR * To strip down Path up to Parent Directory of TARGET_LIB_INSTALL_DIR. */ end=strstr(buf, TARGET_LIB_INSTALL_DIR); if( NULL == end ){ /* We can't find the library install directory*/ return PathLinuxRuntimeErrors; } *end = '\0'; #endif /* Length of Path String up to Parent Directoy (ROCm Base Path) * with trailing '/'.*/ len = strlen(buf); return len; } rocm-core-rocm-7.1.0/rocm_getpath.h.in000066400000000000000000000053661507423117000176070ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////////// //// //// MIT License //// //// Copyright (c) 2017 - 2024 Advanced Micro Devices, Inc. All rights Reserved. //// //// Permission is hereby granted, free of charge, to any person obtaining a copy //// of this software and associated documentation files (the "Software"), to deal //// in the Software without restriction, including without limitation the rights //// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell //// copies of the Software, and to permit persons to whom the Software is //// furnished to do so, subject to the following conditions: //// //// The above copyright notice and this permission notice shall be included in all //// copies or substantial portions of the Software. //// //// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE //// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE //// ////////////////////////////////////////////////////////////////////////////////// #ifndef _ROCM_GETPATH_H_ #define _ROCM_GETPATH_H_ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define LIB_API_PUBLIC __attribute__ ((visibility ("default"))) /* Get Library Target Build Type */ #cmakedefine01 BUILD_SHARED_LIBS /* Return Status Flag Definitions*/ typedef enum { PathSuccess=0, PathIncorrecPararmeters = -994, PathValuesNotDefined = -995, PathValuesTooLong = -996, PathFailedToGetBase = -997, PathLinuxRuntimeErrors = -998, PathErrorMAX = -999 //This should always be last value in the enumerations } PathErrors_t; // API for getting the ROCmInstallPath // Return val : PathErrors_t (API execution status) // Argument1 (out) : InstallPath (char** pointer which will return InstallPath found ) // Argument2 (out) : InstallPathLen (Pointer to integer (size of InstallPath) returned) // Usage : // char *installPath=NULL; // int installPathLen = 0; // installStatus = getROCmInstallPath( &installPath, &installPathLen ); // if(installStatus !=PathSuccess ){ // error occured // ... // } // free(installPath); //caller must free allocated memory after usage. // ... // } LIB_API_PUBLIC PathErrors_t getROCmInstallPath(char **InstallPath, unsigned int *InstallPathLen) __attribute__((nonnull)) ; #ifdef __cplusplus } // end extern "C" block #endif #endif //_ROCM_GETPATH_H_ header guard rocm-core-rocm-7.1.0/rocm_version.cpp000066400000000000000000000033671507423117000175650ustar00rootroot00000000000000/* Copyright © Advanced Micro Devices, Inc., or its affiliates. SPDX-License-Identifier: MIT */ #include "rocm_version.h" #include #include #include #define NULL_CHECK(ptr) if(!ptr) return VerIncorrecPararmeters; #define CHECK_AND_REPORT_API_RESULT(val) do { \ if(VerSuccess != val) { \ const char *ErrStrings[VerErrorMAX]= { "VerSuccess", "VerIncorrecPararmeters", "VerValuesNotDefined" }; \ fprintf(stderr, " API returned : %s \n", ErrStrings[val]); \ fflush(stderr); \ return val; \ } \ }while(0); VerErrors getROCmVersion(unsigned int* Major, unsigned int* Minor, unsigned int* Patch) { NULL_CHECK(Major) NULL_CHECK(Minor) NULL_CHECK(Patch) *Major=ROCM_VERSION_MAJOR; *Minor=ROCM_VERSION_MINOR; *Patch=ROCM_VERSION_PATCH; return VerSuccess; } static VerErrors getBuildInfoLen( int* InfoStrlen ) { NULL_CHECK(InfoStrlen); #if defined(ROCM_BUILD_INFO) *InfoStrlen = 1 + strlen(ROCM_BUILD_INFO);//additional char for null termination #else return VerValuesNotDefined; #endif //end defination checker return VerSuccess; } static VerErrors getBuildInfo( char* InfoString, int len ) { NULL_CHECK(InfoString); #if defined(ROCM_BUILD_INFO) snprintf(InfoString, len, "%s", ROCM_BUILD_INFO); #else return VerValuesNotDefined; #endif //end defination checker return VerSuccess; } VerErrors printBuildInfo() { int lenstr=0; VerErrors apiret=VerSuccess; apiret=getBuildInfoLen(&lenstr); CHECK_AND_REPORT_API_RESULT(apiret); char* cstr=(char*) malloc(lenstr*sizeof(char)); apiret=getBuildInfo(cstr,lenstr); CHECK_AND_REPORT_API_RESULT(apiret); printf("\n Build Info of lib = [%s] \n",cstr); free(cstr); return VerSuccess; } rocm-core-rocm-7.1.0/rocm_version.h.in000066400000000000000000000046611507423117000176350ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////////// // // MIT License // // Copyright (c) 2017 - 2023 Advanced Micro Devices, Inc. All rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // //////////////////////////////////////////////////////////////////////////////// #ifndef _ROCM_VERSION_H_ #define _ROCM_VERSION_H_ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define LIB_API_PUBLIC __attribute__ ((visibility ("default"))) #define ROCM_VERSION_MAJOR @VERSION_MAJOR@ #define ROCM_VERSION_MINOR @VERSION_MINOR@ #define ROCM_VERSION_PATCH @VERSION_PATCH@ #define ROCM_BUILD_INFO "@PACKAGE_BUILD_INFO@" typedef enum { VerSuccess=0, VerIncorrecPararmeters, VerValuesNotDefined, VerErrorMAX //This should always be last value in the enumerations } VerErrors; // API for getting the verion // Return val : VerErros : API execution status. The parameters are valid only when the exetution status is SUCCESS==0 LIB_API_PUBLIC VerErrors getROCmVersion(unsigned int* Major, unsigned int* Minor, unsigned int* Patch) __attribute__((nonnull)) ; // Usage : // int mj=0,mn=0,p=0,ret=0; // ret=getROCMVersion(&mj,&mn,&p); // if(ret !=VerSuccess ) // error occured // // check for the values and // //API for building build info on console LIB_API_PUBLIC VerErrors printBuildInfo(); #ifdef __cplusplus } // end extern "C" block #endif #endif //_ROCM_VERSION_H_ header guard rocm-core-rocm-7.1.0/rocmmod.in000066400000000000000000000012461507423117000163360ustar00rootroot00000000000000#%Module ####################################################################### ## ## Rocm module ## Copyright © Advanced Micro Devices, Inc., or its affiliates. ## SPDX-License-Identifier: MIT ## module-whatis "Adds ROCm binary paths to your environment variable" proc ModulesHelp { } { puts stderr "\tThe ROCM Module." } set ROOT [file normalize [file dirname [file normalize ${ModulesCurrentModulefile}/__]]/../..] prepend-path PATH "${ROOT}/@CMAKE_INSTALL_BINDIR@:${ROOT}/lib/llvm/bin" prepend-path MANPATH "${ROOT}/@CMAKE_INSTALL_MANDIR@:${ROOT}/lib/llvm/share/man1" prepend-path CMAKE_PREFIX_PATH "${ROOT}" setenv ROCM_PATH "${ROOT}" setenv HIP_PATH "${ROOT}" rocm-core-rocm-7.1.0/runpath_to_rpath.py000066400000000000000000000200201507423117000202700ustar00rootroot00000000000000#!/usr/bin/env python3 ################################################################################ ## ## MIT License ## ## Copyright (c) 2017 - 2023 Advanced Micro Devices, Inc. All rights Reserved. ## ## Permission is hereby granted, free of charge, to any person obtaining a copy ## of this software and associated documentation files (the "Software"), to deal ## in the Software without restriction, including without limitation the rights ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ## copies of the Software, and to permit persons to whom the Software is ## furnished to do so, subject to the following conditions: ## ## The above copyright notice and this permission notice shall be included in all ## copies or substantial portions of the Software. ## ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. ## ################################################################################ import os import sys import subprocess import argparse import pathlib import re try: from elftools.elf.elffile import ELFFile from elftools.elf.dynamic import DynamicSection from elftools.common.exceptions import ELFError from elftools.elf.dynamic import ENUM_D_TAG except ImportError: print("Error : pyelftools failed to import.\n" "Run \'pip3 install pyelftools\' to install the prerequisite\n") def update_rpath(search_path, excludes) : ''' Function helps to change DT_RUNPATH in libraries and binaries in search_path to DT_RPATH. Its done with the following steps : 1. Check all if the file is an ELF except in excludes folder 2. Find the DT_RUNPATH tag and its offset from file. 3. Toggle the DT_RUNPATH(0x1d) tag byte to DT_RPATH(0xf) and write back to file ''' for path, dirs, files in os.walk(search_path, topdown=True, followlinks=True): dirs[:] = [d for d in dirs if d not in excludes] print( dirs ) for filename in files: filename = os.path.join(path, filename) print("Opening file ", filename) # Open the file and check if its ELF file try : with open(filename, 'rb+') as file: elffile = ELFFile(file) # Find the dynamic section and look for DT_RUNPATH tag section = elffile.get_section_by_name('.dynamic') if not section: break n = 0 for tag in section.iter_tags(): # DT_RUNPATH tag found. Toggle the byte to DT_RPATH if tag.entry.d_tag == 'DT_RUNPATH': offset = section.header.sh_offset + n* section._tagsize section.stream.seek(offset) section.stream.write(bytes([ENUM_D_TAG['DT_RPATH']])) # DT_PATH print("DT_RUNPATH changed to DT_RPATH ") break # DT_RUNPATH tag not found. Loop to the next tag n = n + 1 except ELFError: print("Discarding file as its not an ELF file", filename) continue except FileNotFoundError: print("Discarding file with bad links", filename) continue except OSError: print("Discarding file with OS error", filename) continue except Exception as ex: print("Discarding file ", filename, ex) continue def update_config_file(cfg_path): ''' Function helps to update rocm llvm config file to default to DT_RPATH. ''' print("Updating cfg file in", cfg_path) config_file_exist = os.path.exists(cfg_path) if config_file_exist: print("cfg file exist in path, going ahead with update ") search_str = "enable-new-dtags" replace_str = "disable-new-dtags" try: # Read contents from file as a single string file_string = '' with open(cfg_path, 'r') as f: file_string = f.read() # Use RE package for string replacement file_string = (re.sub(search_str, replace_str, file_string)) # Write contents back to file. Using mode 'w' truncates the file. with open(cfg_path, 'w') as f: f.write(file_string) except Exception as ex: print("Couldnt update rocm.cfg file. ", ex) else: print("Config path doesnt exist", cfg_path) def update_compiler_config(search_path): ''' Function search for rocm llvm config(rocm.cfg) file in the search_path folder. If the config file is not foung search in ROCM_PATH. Once the config file is found, update llvm config to default to DT_RPATH ''' cfg_file_name = "rocm.cfg" found_cfg = False print("Searching for ", cfg_file_name) for path, dirs, files in os.walk(search_path): # Search for rocm.cfg in the search path and default to DT_RPATH if cfg_file_name in files: cfg_path = os.path.join(path, cfg_file_name) print(" Found cfg file cfg_path") found_cfg = True update_config_file(cfg_path) # Continue with the search as there could be cfg files in llvm and llvm/alt continue; if found_cfg: return # rocm.cfg config file not found in search path. Search in the ROCM_PATH. print(cfg_file_name, " not found in search_path. Trying to search in ROCM_PATH") try : rocm_path = os.environ["ROCM_PATH"] print(" Found ROCM_PATH trying for rocm.cfg") # There are multiple possible paths for cfg file. # ROCM_PATH/llvm/bin and ROCM_PATH/lib/llvm/bin. Also alt location update_config_file(rocm_path + "/llvm/bin/" + cfg_file_name) update_config_file(rocm_path + "/llvm/alt/bin/" + cfg_file_name) update_config_file(rocm_path + "/lib/llvm/bin/" + cfg_file_name) update_config_file(rocm_path + "/lib/llvm/alt/bin/" + cfg_file_name) # Found config file. Change default DT_RUNPATH setting to DT_RPATH except Exception as ex: print("ROCM_PATH not found ", ex) def main(): # The script expect a search folder as parameter. It finds all ELF files and updates RPATH argparser = argparse.ArgumentParser( usage='usage: %(prog)s ', description='Find the ELF files in the specified folder and convert the RUNPATH to RPATH. \n', add_help=False, prog='runpath_to_rpath.py') argparser.add_argument('searchdir', nargs='?', type=pathlib.Path, default=None, help='Folder to search for ELF file. \nPlease note: Any folder with name llvm in that path will be discarded') argparser.add_argument('-h', '--help', action='store_true', dest='help', help='Display this information') args = argparser.parse_args() if args.help or not args.searchdir: argparser.print_help() sys.exit(0) # pyelftools is a mandatory requirement for this script. Exit if requirement is not met if 'ELFFile' not in globals(): print('Please install pyelftools using \'pip3 install pyelftools\' ' + 'before using the script : runpath_to_rpath.py') sys.exit(0) # Find the elf files in the serach path and update DT_RUNPATH to DT_RPATH # SWDEV-467155 : remove the exclusion of llvm folder excludes = [] update_rpath(args.searchdir, excludes) # Update rocm clang configs to default to DT_RPATH update_compiler_config(args.searchdir) print("Done with rpath update") if __name__ == "__main__": main() rocm-core-rocm-7.1.0/utils.cmake000066400000000000000000000301701507423117000165060ustar00rootroot00000000000000################################################################################ ## ## MIT License ## ## Copyright (c) 2017 - 2023 Advanced Micro Devices, Inc. All rights Reserved. ## ## Permission is hereby granted, free of charge, to any person obtaining a copy ## of this software and associated documentation files (the "Software"), to deal ## in the Software without restriction, including without limitation the rights ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ## copies of the Software, and to permit persons to whom the Software is ## furnished to do so, subject to the following conditions: ## ## The above copyright notice and this permission notice shall be included in all ## copies or substantial portions of the Software. ## ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. ## ################################################################################ ## Parses the VERSION_STRING variable and places ## the first, second and third number values in ## the major, minor and patch variables. function( parse_rocm_version VERSION_STRING ) string ( FIND ${VERSION_STRING} "-" STRING_INDEX ) if ( ${STRING_INDEX} GREATER -1 ) math ( EXPR STRING_INDEX "${STRING_INDEX} + 1" ) string ( SUBSTRING ${VERSION_STRING} ${STRING_INDEX} -1 VERSION_BUILD ) endif () string ( REGEX MATCHALL "[0123456789]+" VERSIONS ${VERSION_STRING} ) list ( LENGTH VERSIONS VERSION_COUNT ) if ( ${VERSION_COUNT} GREATER 0) list ( GET VERSIONS 0 MAJOR ) set ( VERSION_MAJOR ${MAJOR} PARENT_SCOPE ) set ( TEMP_VERSION_STRING "${MAJOR}" ) endif () if ( ${VERSION_COUNT} GREATER 1 ) list ( GET VERSIONS 1 MINOR ) set ( VERSION_MINOR ${MINOR} PARENT_SCOPE ) set ( TEMP_VERSION_STRING "${TEMP_VERSION_STRING}.${MINOR}" ) endif () if ( ${VERSION_COUNT} GREATER 2 ) list ( GET VERSIONS 2 PATCH ) set ( VERSION_PATCH ${PATCH} PARENT_SCOPE ) set ( TEMP_VERSION_STRING "${TEMP_VERSION_STRING}.${PATCH}" ) endif () if ( ${VERSION_COUNT} GREATER 3 ) list ( GET VERSIONS 3 POINT ) set ( VERSION_POINT ${POINT} PARENT_SCOPE ) set ( TEMP_VERSION_STRING "${TEMP_VERSION_STRING}.${POINT}" ) endif () if ( DEFINED VERSION_BUILD ) set ( VERSION_BUILD "${VERSION_BUILD}" PARENT_SCOPE ) endif () set ( VERSION_STRING "${TEMP_VERSION_STRING}" PARENT_SCOPE ) endfunction () ## Sets cmake variables which can be derived from existing function( set_variables ) set( VERSION_COMMIT_COUNT 0 ) set( VERSION_HASH "unknown" ) find_program( GIT NAMES git ) if( GIT ) # Get branch commit (common ancestor) of current branch and master branch. execute_process(COMMAND git merge-base HEAD origin/HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_MERGE_BASE OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE RESULT ) if( ${RESULT} EQUAL 0 ) # Count commits from branch point. execute_process(COMMAND git rev-list --count ${GIT_MERGE_BASE}..HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE VERSION_COMMIT_COUNT OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE RESULT ) if(NOT ${RESULT} EQUAL 0 ) set( VERSION_COMMIT_COUNT 0 ) endif() endif() # Get current short hash. execute_process(COMMAND git rev-parse --short HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE VERSION_HASH OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE RESULT ) if( ${RESULT} EQUAL 0 ) # Check for dirty workspace. execute_process(COMMAND git diff --quiet WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} RESULT_VARIABLE RESULT ) if(${RESULT} EQUAL 1) set(VERSION_HASH "${VERSION_HASH}-dirty") endif() else() set( VERSION_HASH "unknown" ) endif() endif() #set libpatch version if(NOT DEFINED ENV{ROCM_LIBPATCH_VERSION}) set(ROCM_LIBPATCH_VERSION "${VERSION_MAJOR}") string(LENGTH ${VERSION_MINOR} LENSTR) if(LENSTR EQUAL 1) # length of version cannot be zero hence it would be 1 or greater set(ROCM_LIBPATCH_VERSION "${ROCM_LIBPATCH_VERSION}0${VERSION_MINOR}") else() # length is greater than 1 set(ROCM_LIBPATCH_VERSION "${ROCM_LIBPATCH_VERSION}${VERSION_MINOR}") endif() string(LENGTH ${VERSION_PATCH} LENSTR) if(LENSTR EQUAL 1) # length of version cannot be zero hence it would be 1 or greater set(ROCM_LIBPATCH_VERSION "${ROCM_LIBPATCH_VERSION}0${VERSION_PATCH}") else() # length is greater than 1 set(ROCM_LIBPATCH_VERSION "${ROCM_LIBPATCH_VERSION}${VERSION_PATCH}") endif() set(ROCM_LIBPATCH_VERSION "${ROCM_LIBPATCH_VERSION}" PARENT_SCOPE ) else() set (ROCM_LIBPATCH_VERSION $ENV{ROCM_LIBPATCH_VERSION} PARENT_SCOPE ) endif() if ( DEFINED ENV{CPACK_RPM_PACKAGE_RELEASE} ) set ( CPACK_RPM_PACKAGE_RELEASE ${CPACK_RPM_PACKAGE_RELEASE} PARENT_SCOPE ) else() set ( CPACK_RPM_PACKAGE_RELEASE "local" PARENT_SCOPE ) endif() if ( DEFINED ENV{CPACK_DEBIAN_PACKAGE_RELEASE} ) set ( CPACK_DEBIAN_PACKAGE_RELEASE ${CPACK_DEBIAN_PACKAGE_RELEASE} PARENT_SCOPE ) else() set ( CPACK_DEBIAN_PACKAGE_RELEASE "local" PARENT_SCOPE ) endif() set( VERSION_COMMIT_COUNT "${VERSION_COMMIT_COUNT}" PARENT_SCOPE ) set( VERSION_HASH "${VERSION_HASH}" PARENT_SCOPE ) set( VERSION_BUILD "${VERSION_BUILD}" PARENT_SCOPE ) message(STATUS "VERSION_MAJOR : ${VERSION_MAJOR}" ) message(STATUS "VERSION_MINOR : ${VERSION_MINOR}" ) message(STATUS "VERSION_PATCH : ${VERSION_PATCH}" ) message(STATUS "VERSION_POINT : ${VERSION_POINT}" ) message(STATUS "ROCM_LIBPATCH_VERSION : ${ROCM_LIBPATCH_VERSION}" ) message(STATUS "VERSION_COMMIT_COUNT : ${VERSION_COMMIT_COUNT}" ) message(STATUS "VERSION_HASH : ${VERSION_HASH}" ) message(STATUS "VERSION_BUILD : ${VERSION_BUILD}" ) message(STATUS "CPACK_DEBIAN_PACKAGE_RELEASE : ${CPACK_DEBIAN_PACKAGE_RELEASE}" ) message(STATUS "CPACK_RPM_PACKAGE_RELEASE : ${CPACK_RPM_PACKAGE_RELEASE}" ) endfunction() ## Configure Copyright File for Debian Package function( configure_debian_pkg PACKAGE_NAME_T COMPONENT_NAME_T PACKAGE_VERSION_T MAINTAINER_NM_T MAINTAINER_EMAIL_T) # Check If Debian Platform find_file (DEBIAN debian_version debconf.conf PATHS /etc) if(DEBIAN) set( BUILD_DEBIAN_PKGING_FLAG ON CACHE BOOL "Internal Status Flag to indicate Debian Packaging Build" FORCE ) set_debian_pkg_cmake_flags( ${PACKAGE_NAME_T} ${PACKAGE_VERSION_T} ${MAINTAINER_NM_T} ${MAINTAINER_EMAIL_T} ) # Create debian directory in build tree file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/DEBIAN") # Configure the copyright file configure_file( "${CMAKE_SOURCE_DIR}/DEBIAN/copyright.in" "${CMAKE_BINARY_DIR}/DEBIAN/copyright" @ONLY ) # Install copyright file install ( FILES "${CMAKE_BINARY_DIR}/DEBIAN/copyright" DESTINATION "${CMAKE_INSTALL_DOCDIR}" COMPONENT ${COMPONENT_NAME_T} ) # Configure the changelog file configure_file( "${CMAKE_SOURCE_DIR}/DEBIAN/changelog.in" "${CMAKE_BINARY_DIR}/DEBIAN/changelog.Debian" @ONLY ) if( BUILD_ENABLE_LINTIAN_OVERRIDES ) if(NOT BUILD_SHARED_LIBS) string(FIND ${DEB_OVERRIDES_INSTALL_FILENM} "static" OUT_VAR1) if(OUT_VAR1 EQUAL -1) set( DEB_OVERRIDES_INSTALL_FILENM "${DEB_OVERRIDES_INSTALL_FILENM}-static" ) endif() else() if(ENABLE_ASAN_PACKAGING) string( FIND ${DEB_OVERRIDES_INSTALL_FILENM} "asan" OUT_VAR2) if(OUT_VAR2 EQUAL -1) set( DEB_OVERRIDES_INSTALL_FILENM "${DEB_OVERRIDES_INSTALL_FILENM}-asan" ) endif() endif() endif() set( DEB_OVERRIDES_INSTALL_FILENM "${DEB_OVERRIDES_INSTALL_FILENM}" CACHE STRING "Debian Package Lintian Override File Name" FORCE) # Configure the changelog file configure_file( "${CMAKE_SOURCE_DIR}/DEBIAN/overrides.in" "${CMAKE_BINARY_DIR}/DEBIAN/${DEB_OVERRIDES_INSTALL_FILENM}" FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ @ONLY ) endif() # Install Change Log find_program ( DEB_GZIP_EXEC gzip ) if(EXISTS "${CMAKE_BINARY_DIR}/DEBIAN/changelog.Debian" ) execute_process( COMMAND ${DEB_GZIP_EXEC} -f -n -9 "${CMAKE_BINARY_DIR}/DEBIAN/changelog.Debian" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/DEBIAN" RESULT_VARIABLE result OUTPUT_VARIABLE output ERROR_VARIABLE error ) if(NOT ${result} EQUAL 0) message(FATAL_ERROR "Failed to compress: ${error}") endif() install ( FILES "${CMAKE_BINARY_DIR}/DEBIAN/${DEB_CHANGELOG_INSTALL_FILENM}" DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${COMPONENT_NAME_T}) endif() else() # License file install ( FILES ${LICENSE_FILE} DESTINATION ${CMAKE_INSTALL_DOCDIR} RENAME LICENSE.md COMPONENT ${COMPONENT_NAME_T}) endif() endfunction() # Set variables for changelog and copyright # For Debian specific Packages function( set_debian_pkg_cmake_flags DEB_PACKAGE_NAME_T DEB_PACKAGE_VERSION_T DEB_MAINTAINER_NM_T DEB_MAINTAINER_EMAIL_T ) # Setting configure flags set( DEB_PACKAGE_NAME "${DEB_PACKAGE_NAME_T}" CACHE STRING "Debian Package Name" ) set( DEB_PACKAGE_VERSION "${DEB_PACKAGE_VERSION_T}" CACHE STRING "Debian Package Version String" ) set( DEB_MAINTAINER_NAME "${DEB_MAINTAINER_NM_T}" CACHE STRING "Debian Package Maintainer Name" ) set( DEB_MAINTAINER_EMAIL "${DEB_MAINTAINER_EMAIL_T}" CACHE STRING "Debian Package Maintainer Email" ) set( DEB_COPYRIGHT_YEAR "2025" CACHE STRING "Debian Package Copyright Year" ) set( DEB_LICENSE "MIT" CACHE STRING "Debian Package License Type" ) set( DEB_CHANGELOG_INSTALL_FILENM "changelog.Debian.gz" CACHE STRING "Debian Package ChangeLog File Name" ) if( BUILD_ENABLE_LINTIAN_OVERRIDES ) set( DEB_OVERRIDES_INSTALL_FILENM "${DEB_PACKAGE_NAME}" CACHE STRING "Debian Package Lintian Override File Name" ) set( DEB_OVERRIDES_INSTALL_PATH "/usr/share/lintian/overrides/" CACHE STRING "Deb Pkg Lintian Override Install Loc" ) endif() # Get TimeStamp find_program( DEB_DATE_TIMESTAMP_EXEC date ) set ( DEB_TIMESTAMP_FORMAT_OPTION "-R" ) execute_process ( COMMAND ${DEB_DATE_TIMESTAMP_EXEC} ${DEB_TIMESTAMP_FORMAT_OPTION} OUTPUT_VARIABLE TIMESTAMP_T ) set( DEB_TIMESTAMP "${TIMESTAMP_T}" CACHE STRING "Current Time Stamp for Copyright/Changelog" ) message(STATUS "DEB_PACKAGE_NAME : ${DEB_PACKAGE_NAME}" ) message(STATUS "DEB_PACKAGE_VERSION : ${DEB_PACKAGE_VERSION}" ) message(STATUS "DEB_MAINTAINER_NAME : ${DEB_MAINTAINER_NAME}" ) message(STATUS "DEB_MAINTAINER_EMAIL : ${DEB_MAINTAINER_EMAIL}" ) message(STATUS "DEB_COPYRIGHT_YEAR : ${DEB_COPYRIGHT_YEAR}" ) message(STATUS "DEB_LICENSE : ${DEB_LICENSE}" ) message(STATUS "DEB_TIMESTAMP : ${DEB_TIMESTAMP}" ) message(STATUS "DEB_CHANGELOG_INSTALL_FILENM : ${DEB_CHANGELOG_INSTALL_FILENM}" ) endfunction()