# Copyright (c) 2025-2026 Advanced Micro Devices, Inc. # SPDX-License-Identifier: MIT cmake_minimum_required(VERSION 3.22) set(_RJ_ROCM_PATH_EXPLICIT OFF) if(DEFINED ROCM_PATH AND NOT "${ROCM_PATH}" STREQUAL "") set(_RJ_ROCM_PATH_EXPLICIT ON) elseif(DEFINED ENV{ROCM_PATH} AND NOT "$ENV{ROCM_PATH}" STREQUAL "") set(_RJ_ROCM_PATH_EXPLICIT ON) set(ROCM_PATH "$ENV{ROCM_PATH}" CACHE PATH "Path to the ROCm installation") elseif(IS_DIRECTORY "/opt/rocm") set(ROCM_PATH "/opt/rocm" CACHE PATH "Path to the ROCm installation") endif() if(_RJ_ROCM_PATH_EXPLICIT AND NOT IS_DIRECTORY "${ROCM_PATH}") message(FATAL_ERROR "ROCM_PATH must be set to a valid directory") endif() unset(_RJ_ROCM_PATH_EXPLICIT) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(rj_default_compiler) project(rocm_jit_suite VERSION 0.3.0) include(rj_version) # Generate compile_commands.json for clangd, clang-tidy, and other tooling that # needs the exact compiler invocations from the configured build tree. set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Default install prefix to /opt/rocm, matching other ROCm projects. if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND ROCM_PATH) set(CMAKE_INSTALL_PREFIX "${ROCM_PATH}" CACHE PATH "" FORCE) endif() include(CTest) set(CMAKE_CXX_STANDARD 20) set(CMAKE_POSITION_INDEPENDENT_CODE ON) # Hide symbols by default so the shared library (librocjitsu.so) exports only its # intended ABI. set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) find_package(Threads REQUIRED) # GCC 14+ emits false-positive -Wuninitialized on reinterpret_cast # member access in the autogenerated ISA encoding constructors. The pointer is # always initialized from a constructor argument, but GCC's alias analysis # misattributes the access to an uninitialized offset within `this`. if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "14" ) add_compile_options(-Wno-uninitialized) endif() # HSA/KFD headers (local copies from rocr-runtime). set(HSA_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/lib/rocjitsu/external_headers/hsa_headers" ) # DRM/amdgpu UAPI headers (vendored kernel ABI, MIT-licensed). Lets the # interposer service the amdgpu DRM ioctl surface using the real kernel structs # instead of hand-mirrored copies, without depending on libdrm library types. set(DRM_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/lib/rocjitsu/external_headers/drm_headers/linux/uapi/drm" ) include(rj_log) # Install directory variables are used by subdirectories that add install rules. include(GNUInstallDirs) include(rj_sanitizers) # Sanitizer and static analysis options. option(RJ_ENABLE_ASAN "Enable AddressSanitizer" OFF) option(RJ_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer" OFF) option(RJ_ENABLE_TSAN "Enable ThreadSanitizer" OFF) option(RJ_ENABLE_MSAN "Enable MemorySanitizer" OFF) set(RJ_SANITIZER_RUNTIME "AUTO" CACHE STRING "Sanitizer runtime linkage policy (AUTO, SHARED, or STATIC)" ) set_property(CACHE RJ_SANITIZER_RUNTIME PROPERTY STRINGS AUTO SHARED STATIC) string(TOUPPER "${RJ_SANITIZER_RUNTIME}" RJ_SANITIZER_RUNTIME) set(_rj_sanitizer_runtime_values AUTO SHARED STATIC) if(NOT RJ_SANITIZER_RUNTIME IN_LIST _rj_sanitizer_runtime_values) message( FATAL_ERROR "RJ_SANITIZER_RUNTIME must be AUTO, SHARED, or STATIC; got " "'${RJ_SANITIZER_RUNTIME}'." ) endif() unset(_rj_sanitizer_runtime_values) option(RJ_CLANG_TIDY "Enable clang-tidy static analysis" OFF) option( RJ_ENABLE_EXPENSIVE_CHECKS "Enable expensive exhaustive test suites (MFMA/WMMA SIMD bit-exactness)" OFF ) option(RJ_INSTALL_TESTS "Install rocjitsu test binaries" OFF) option( LTO "Enable link-time optimization (IPO) for Release / RelWithDebInfo" OFF ) set(_rj_sanitizer_kinds) if(RJ_ENABLE_ASAN) list(APPEND _rj_sanitizer_kinds address) endif() if(RJ_ENABLE_UBSAN) list(APPEND _rj_sanitizer_kinds undefined) endif() if(RJ_ENABLE_TSAN) list(APPEND _rj_sanitizer_kinds thread) endif() if(RJ_ENABLE_MSAN) list(APPEND _rj_sanitizer_kinds memory) endif() list(LENGTH _rj_sanitizer_kinds _rj_sanitizer_count) set(RJ_SANITIZER_USE_SHARED OFF) if(LTO) if(_rj_sanitizer_count GREATER 0) message(FATAL_ERROR "LTO is incompatible with sanitizers. Disable one.") endif() include(CheckIPOSupported) check_ipo_supported(RESULT _rj_ipo_ok OUTPUT _rj_ipo_err) if(_rj_ipo_ok) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON) # Force parallel LTO. CMake's default IPO flag is a bare `-flto`, which # makes GCC serialize LTRANS (warns: "using serial compilation of N # LTRANS jobs"). Override per compiler: # GCC : -flto=auto — partition across all host cores. # Clang : -flto=thin — ThinLTO is parallel by design. if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(_rj_lto_flag "-flto=auto") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(_rj_lto_flag "-flto=thin") else() set(_rj_lto_flag "") endif() if(_rj_lto_flag) add_compile_options( $<$:${_rj_lto_flag}> $<$:${_rj_lto_flag}> ) add_link_options( $<$:${_rj_lto_flag}> $<$:${_rj_lto_flag}> ) endif() message( STATUS "LTO enabled for Release and RelWithDebInfo (flag: ${_rj_lto_flag})" ) else() message(WARNING "LTO requested but IPO not supported: ${_rj_ipo_err}") endif() endif() if(_rj_sanitizer_count GREATER 0) if( thread IN_LIST _rj_sanitizer_kinds AND ( address IN_LIST _rj_sanitizer_kinds OR memory IN_LIST _rj_sanitizer_kinds ) ) message( FATAL_ERROR "ThreadSanitizer can not be combined with address or memory sanitizers" ) endif() if(memory IN_LIST _rj_sanitizer_kinds AND _rj_sanitizer_count GREATER 1) message( FATAL_ERROR "MemorySanitizer cannot be combined with other sanitizers" ) endif() list(JOIN _rj_sanitizer_kinds "," _rj_sanitizer_arg) set(RJ_SANITIZER_COMPILE_OPTIONS) set(RJ_SANITIZER_LINK_OPTIONS) set(RJ_SANITIZER_SHARED_LIBRARIES) set(RJ_ASAN_SHARED_LIBRARY "") set(RJ_TSAN_SHARED_LIBRARY "") message(STATUS "Sanitizer enabled: ${_rj_sanitizer_arg}") if(MSVC) # MSVC only supports AddressSanitizer; ubsan/tsan/msan are GCC/Clang-only. if(_rj_sanitizer_arg STREQUAL "address") list(APPEND RJ_SANITIZER_COMPILE_OPTIONS /fsanitize=address) add_compile_options(${RJ_SANITIZER_COMPILE_OPTIONS}) # /INCREMENTAL:NO is required when using MSVC ASAN. add_link_options(/INCREMENTAL:NO) else() message(FATAL_ERROR "Only RJ_ENABLE_ASAN is supported by MSVC.") endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") if( memory IN_LIST _rj_sanitizer_kinds AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) message(FATAL_ERROR "MemorySanitizer requires Clang.") endif() if(RJ_SANITIZER_RUNTIME STREQUAL "SHARED") if(memory IN_LIST _rj_sanitizer_kinds) message( FATAL_ERROR "MemorySanitizer has no supported shared runtime; use " "RJ_SANITIZER_RUNTIME=AUTO or STATIC." ) endif() set(RJ_SANITIZER_USE_SHARED ON) elseif( RJ_SANITIZER_RUNTIME STREQUAL "AUTO" AND NOT memory IN_LIST _rj_sanitizer_kinds ) set(RJ_SANITIZER_USE_SHARED ON) endif() if(RJ_SANITIZER_USE_SHARED) message(STATUS "Sanitizer runtime linkage: shared") else() message(STATUS "Sanitizer runtime linkage: static") endif() list(APPEND RJ_SANITIZER_COMPILE_OPTIONS "-fno-sanitize-recover=all") list( APPEND RJ_SANITIZER_COMPILE_OPTIONS -fsanitize=${_rj_sanitizer_arg} ) list(APPEND RJ_SANITIZER_LINK_OPTIONS -fsanitize=${_rj_sanitizer_arg}) if( address IN_LIST _rj_sanitizer_kinds OR undefined IN_LIST _rj_sanitizer_kinds OR memory IN_LIST _rj_sanitizer_kinds ) list(APPEND RJ_SANITIZER_COMPILE_OPTIONS -fno-omit-frame-pointer) endif() if(address IN_LIST _rj_sanitizer_kinds) # GCC 13+ emits false-positive -Wmaybe-uninitialized in std_function.h # when ASAN is enabled. Suppress to avoid -Werror failures. if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") add_compile_options(-Wno-maybe-uninitialized) endif() endif() if(RJ_SANITIZER_USE_SHARED) rj_find_sanitizer_shared_libraries( RJ_SANITIZER_SHARED_LIBRARIES RJ_ASAN_SHARED_LIBRARY RJ_TSAN_SHARED_LIBRARY COMPILER ${CMAKE_CXX_COMPILER} COMPILER_ARG1 "${CMAKE_CXX_COMPILER_ARG1}" COMPILER_ID "${CMAKE_CXX_COMPILER_ID}" SYSTEM_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}" SANITIZERS ${_rj_sanitizer_kinds} ) foreach( _rj_sanitizer_shared_library IN LISTS RJ_SANITIZER_SHARED_LIBRARIES ) message( STATUS "Sanitizer shared runtime: ${_rj_sanitizer_shared_library}" ) endforeach() endif() rj_sanitizer_runtime_link_options( _rj_sanitizer_runtime_link_options COMPILER_ID "${CMAKE_CXX_COMPILER_ID}" SHARED "${RJ_SANITIZER_USE_SHARED}" SHARED_LIBRARIES ${RJ_SANITIZER_SHARED_LIBRARIES} SANITIZERS ${_rj_sanitizer_kinds} ) list( APPEND RJ_SANITIZER_LINK_OPTIONS ${_rj_sanitizer_runtime_link_options} ) add_compile_options(${RJ_SANITIZER_COMPILE_OPTIONS}) add_link_options(${RJ_SANITIZER_LINK_OPTIONS}) unset(_rj_sanitizer_shared_library) unset(_rj_sanitizer_runtime_link_options) else() message( FATAL_ERROR "Sanitizers are not supported for compiler '${CMAKE_CXX_COMPILER_ID}'." ) endif() unset(_rj_sanitizer_arg) endif() unset(_rj_sanitizer_count) unset(_rj_sanitizer_kinds) if(RJ_CLANG_TIDY) find_program(CLANG_TIDY_EXE NAMES clang-tidy) if(CLANG_TIDY_EXE) message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE}") else() message(WARNING "clang-tidy not found, RJ_CLANG_TIDY ignored") endif() endif() # Third-party dependencies (fetched into third_party/). # Third-party dependencies (fetched into third_party/). # Third-party dependencies (fetched into third_party/ by default). # Override with -DFETCHCONTENT_BASE_DIR=/path for container builds. if(NOT FETCHCONTENT_BASE_DIR) set(FETCHCONTENT_BASE_DIR ${PROJECT_SOURCE_DIR}/third_party) endif() include(FetchContent) # Google Test FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG v1.15.2 ) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) # FlatBuffers - serialization for config, checkpoint, and wire format. FetchContent_Declare( flatbuffers GIT_REPOSITORY https://github.com/google/flatbuffers.git GIT_TAG v24.3.25 ) set(FLATBUFFERS_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(FLATBUFFERS_INSTALL OFF CACHE BOOL "" FORCE) set(FLATBUFFERS_BUILD_FLATLIB ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest flatbuffers) include(rj_flatbuffers) # Set include paths before adding subdirectories so all targets can find them. set(ROCJITSU_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/lib/rocjitsu/include) set(ROCJITSU_SRC_DIR ${PROJECT_SOURCE_DIR}/lib/rocjitsu/src) # Libraries add_subdirectory(lib/util) add_subdirectory(lib/simdojo) add_subdirectory(lib/rocjitsu) add_subdirectory(lib/rocjitsu/src/rocjitsu/vm/plugins) # Main shared library - assembles all object libraries. add_library(rocjitsu_shared SHARED) set_target_properties(rocjitsu_shared PROPERTIES OUTPUT_NAME rocjitsu) target_link_libraries( rocjitsu_shared PRIVATE rocjitsu_analysis rocjitsu_code rocjitsu_isa rocjitsu_isa_registry simdojo rocjitsu_kmd rocjitsu_vm rocjitsu_vm_amdgpu # Host-side plugin loader. The logging/race plugins are no longer # linked in statically; they are separate librocjitsu_plugin_.so # modules discovered and dlopen()ed at runtime. rocjitsu_plugin_loader rocjitsu_vm_risc_v rocjitsu_config rocjitsu_dbt_config util flatbuffers Threads::Threads ) target_include_directories( rocjitsu_shared PRIVATE ${ROCJITSU_INCLUDE_DIR} ${ROCJITSU_SRC_DIR} ${GENERATED_DIR} ) target_include_directories(rocjitsu_shared SYSTEM PRIVATE ${HSA_INCLUDE_DIR}) # Linux-only: KMD interposer (LD_PRELOAD shim) and its dependencies. if(CMAKE_SYSTEM_NAME STREQUAL "Linux") target_sources( rocjitsu_shared PRIVATE ${ROCJITSU_SRC_DIR}/rocjitsu/kmd/linux/interposer.cpp ) target_include_directories(rocjitsu_shared PRIVATE ${DRM_INCLUDE_DIR}) target_compile_definitions(rocjitsu_shared PRIVATE _GNU_SOURCE) target_link_libraries(rocjitsu_shared PRIVATE dl) endif() if(CMAKE_SYSTEM_NAME STREQUAL "Linux") target_link_options(rocjitsu_shared PRIVATE "LINKER:--exclude-libs,ALL") endif() add_dependencies(rocjitsu_shared flatbuffers_schemas) # Developer and test workflow tools. add_subdirectory(tools) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_subdirectory(tools/rocjitsu) endif() # Tests and scaling tools. if(BUILD_TESTING) add_subdirectory(tests) endif() # --------------------------------------------------------------------------- # Install rules. # --------------------------------------------------------------------------- # Public headers: include/rocjitsu/ install( DIRECTORY lib/rocjitsu/include/rocjitsu DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h" ) # Libraries: lib/ install( TARGETS rocjitsu_shared rocjitsu_hooks LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") install( TARGETS hsa_hotswap_rocjitsu LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if(CMAKE_SYSTEM_NAME STREQUAL "Linux") install(TARGETS rocjitsu_bin RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() # Config files and schemas: share/rocjitsu/ install( DIRECTORY configs/ DESTINATION ${CMAKE_INSTALL_DATADIR}/rocjitsu/configs ) install( DIRECTORY schemas/ DESTINATION ${CMAKE_INSTALL_DATADIR}/rocjitsu/schemas FILES_MATCHING PATTERN "*.fbs" )