diff --git a/projects/rocprofiler-systems/examples/openmp/target/CMakeLists.txt b/projects/rocprofiler-systems/examples/openmp/target/CMakeLists.txt index 4c9479e240c9..833be351f788 100644 --- a/projects/rocprofiler-systems/examples/openmp/target/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/openmp/target/CMakeLists.txt @@ -70,8 +70,31 @@ set(_LLVM_LIB_HINTS "/opt/rocm/lib/llvm/lib" ) +# Determine LLVM host triple as libomptarget might be installed there. +execute_process( + COMMAND "${OMP_TARGET_COMPILER}" --print-target-triple + OUTPUT_VARIABLE LLVM_HOST_TRIPLE + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + RESULT_VARIABLE _llvm_host_triple_rc +) + +if(NOT _llvm_host_triple_rc EQUAL 0) + set(LLVM_HOST_TRIPLE "") + rocprofiler_systems_message( + FATAL_ERROR + "'${OMP_TARGET_COMPILER} --print-target-triple' failed (exit code ${_llvm_host_triple_rc})" + "This toolchain may be broken." + ) +endif() + # Find libomptarget -find_library(LIBOMPTARGET_SO NAMES omptarget HINTS ${_LLVM_LIB_HINTS}) +find_library( + LIBOMPTARGET_SO + NAMES omptarget + HINTS ${_LLVM_LIB_HINTS} + PATH_SUFFIXES ${LLVM_HOST_TRIPLE} +) if(NOT LIBOMPTARGET_SO) message(FATAL_ERROR "Could not find libomptarget in any of:\n ${_LLVM_LIB_HINTS}") diff --git a/projects/rocprofiler-systems/source/lib/common/CMakeLists.txt b/projects/rocprofiler-systems/source/lib/common/CMakeLists.txt index 14687e6d12c4..41e6d8562e99 100644 --- a/projects/rocprofiler-systems/source/lib/common/CMakeLists.txt +++ b/projects/rocprofiler-systems/source/lib/common/CMakeLists.txt @@ -14,6 +14,42 @@ add_library( ALIAS rocprofiler-systems-common-library ) +# Query clang for host target triple for defines.h +# This is useful when LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON and +# the openmp libraries are installed one level deeper in lib/. +find_program( + amdclang_EXECUTABLE + NAMES amdclang + HINTS ${ROCmVersion_DIR} ${ROCM_PATH} + ENV ROCM_PATH + /opt/rocm + PATH_SUFFIXES bin llvm/bin lib/llvm/bin +) +mark_as_advanced(amdclang_EXECUTABLE) +set(LLVM_HOST_TRIPLE "") +if(amdclang_EXECUTABLE) + execute_process( + COMMAND "${amdclang_EXECUTABLE}" --print-target-triple + OUTPUT_VARIABLE LLVM_HOST_TRIPLE + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _llvm_host_triple_result + ) + if(NOT _llvm_host_triple_result EQUAL 0) + set(LLVM_HOST_TRIPLE "") + rocprofiler_systems_message( + FATAL_ERROR + "'${amdclang_EXECUTABLE} --print-target-triple' failed (exit code ${_llvm_host_triple_result})" + "This toolchain may be broken." + ) + endif() +else() + rocprofiler_systems_message( + WARNING + "Could not find amdclang to determine the LLVM host triple; " + "libomptarget discovery for LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON may not work." + ) +endif() + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/defines.h.in ${CMAKE_CURRENT_BINARY_DIR}/defines.h diff --git a/projects/rocprofiler-systems/source/lib/common/defines.h.in b/projects/rocprofiler-systems/source/lib/common/defines.h.in index 0c563dbf79bf..7080a611db88 100644 --- a/projects/rocprofiler-systems/source/lib/common/defines.h.in +++ b/projects/rocprofiler-systems/source/lib/common/defines.h.in @@ -47,6 +47,8 @@ #define ROCPROFSYS_ROCM_VERSION_MINOR @ROCPROFSYS_ROCM_VERSION_MINOR@ #define ROCPROFSYS_ROCM_VERSION_PATCH @ROCPROFSYS_ROCM_VERSION_PATCH@ +#define ROCPROFSYS_ROCM_LLVM_HOST_TRIPLE "@LLVM_HOST_TRIPLE@" + // these can be set via defining the variable in CMake, e.g.: // cmake -D ROCPROFSYS_CACHELINE_SIZE=N /path/to/source // if not defined when configuring cmake, these values fall back to diff --git a/projects/rocprofiler-systems/source/lib/common/environment.hpp b/projects/rocprofiler-systems/source/lib/common/environment.hpp index ceb15dc04f46..0268bf42ecd5 100644 --- a/projects/rocprofiler-systems/source/lib/common/environment.hpp +++ b/projects/rocprofiler-systems/source/lib/common/environment.hpp @@ -419,7 +419,7 @@ discover_llvm_libdir_for_ompt() const auto rocm_dir = strip(get_env("ROCM_PATH", "/opt/rocm")); const auto rocmv_dir = strip(get_env("ROCmVersion_DIR", "")); - const constexpr auto number_of_candidates = 6; + const constexpr auto number_of_candidates = 8; std::vector candidates; candidates.reserve(number_of_candidates); @@ -439,6 +439,14 @@ discover_llvm_libdir_for_ompt() } push_unique(rocm_dir + "/llvm/lib"); push_unique(rocm_dir + "/lib/llvm/lib"); + + const auto llvm_host_triple = strip(std::string{ ROCPROFSYS_ROCM_LLVM_HOST_TRIPLE }); + if(!llvm_host_triple.empty()) + { + push_unique(rocm_dir + "/lib/llvm/lib/" + llvm_host_triple); + push_unique("/opt/rocm/lib/llvm/lib/" + llvm_host_triple); + } + push_unique("/opt/rocm/llvm/lib"); push_unique("/opt/rocm/lib/llvm/lib"); diff --git a/projects/rocprofiler-systems/tests/pytest/rocprofsys/config.py b/projects/rocprofiler-systems/tests/pytest/rocprofsys/config.py index 114c0a34adab..4ab80c4187aa 100644 --- a/projects/rocprofiler-systems/tests/pytest/rocprofsys/config.py +++ b/projects/rocprofiler-systems/tests/pytest/rocprofsys/config.py @@ -3,6 +3,7 @@ from __future__ import annotations from dataclasses import dataclass, field +from functools import cached_property import getpass import os from pathlib import Path @@ -76,7 +77,8 @@ def capabilities(self) -> SystemCapabilities: self._capabilities = SystemCapabilities.from_config(self) return self._capabilities - def get_llvm_lib_paths(self) -> list[Path]: + @cached_property + def llvm_lib_paths(self) -> list[Path]: """Get list of found ROCm LLVM lib paths. Returns: @@ -89,6 +91,36 @@ def get_llvm_lib_paths(self) -> list[Path]: self.rocm_path / "llvm" / "lib", self.rocm_path / "lib" / "llvm" / "lib", ] + # Determine the per-target runtime subdir used when + # LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON + clang_candidates = [ + self.rocm_path / "bin" / "amdclang", + self.rocm_path / "llvm" / "bin" / "amdclang", + self.rocm_path / "lib" / "llvm" / "bin" / "amdclang", + ] + clang_path = next((c for c in clang_candidates if c.exists()), None) + if clang_path is None: + which_clang = shutil.which("amdclang") + if which_clang: + clang_path = Path(which_clang) + if clang_path is not None: + try: + host_triple = subprocess.run( + [str(clang_path), "--print-target-triple"], + capture_output=True, + text=True, + timeout=10, + check=True, + ).stdout.strip() + except (subprocess.SubprocessError, OSError) as exc: + raise RuntimeError( + f"'{clang_path} --print-target-triple' failed; " + "this suggests a broken toolchain." + ) from exc + if host_triple: + candidates.append( + self.rocm_path / "lib" / "llvm" / "lib" / host_triple + ) for candidate in candidates: if candidate.exists(): found_paths.append(candidate) @@ -113,7 +145,7 @@ def get_library_path(self) -> str: paths.append(existing) # Add ROCm LLVM lib as fallback - for llvm_path in self.get_llvm_lib_paths(): + for llvm_path in self.llvm_lib_paths: paths.append(str(llvm_path)) return ":".join(paths)