# Copyright © Advanced Micro Devices, Inc., or its affiliates. # SPDX-License-Identifier: MIT cmake_minimum_required(VERSION 3.25.2) # Used by the shared CTest test categorisation helpers # (shared/ctest/TestCategories.cmake) to locate the parser script. if(NOT DEFINED ROCM_LIBRARIES_ROOT) set(ROCM_LIBRARIES_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../..") endif() # hipDNN dependency versions to use file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/default_flatc_version.txt" _HIPDNN_DEFAULT_FLATBUFFERS_VERSION LIMIT_COUNT 1) set(HIPDNN_SPDLOG_VERSION "1.15.3" CACHE STRING "Version of spdlog to use") set(HIPDNN_FLATBUFFERS_VERSION "${_HIPDNN_DEFAULT_FLATBUFFERS_VERSION}" CACHE STRING "Version of flatbuffers to use") set(HIPDNN_NLOHMANN_JSON_VERSION "3.12.0" CACHE STRING "Version of nlohmann_json to use") set(HIPDNN_GTEST_VERSION "1.16.0" CACHE STRING "Version of googletest to use") option(HIPDNN_SKIP_JSON_LIB "Defines whether SDK public headers should not include nlohmann/json.hpp." OFF) # Status message if(HIPDNN_SKIP_JSON_LIB) message(STATUS "hipDNN: JSON serialization disabled in SDK public headers") else() message(STATUS "hipDNN: JSON serialization enabled in SDK public headers (requires nlohmann_json)") endif() set(CMAKE_POSITION_INDEPENDENT_CODE ON) add_compile_definitions(__HIP_PLATFORM_AMD__) if(NOT CMAKE_TOOLCHAIN_FILE) set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClangToolChain.cmake" CACHE FILEPATH "Toolchain file" ) endif() # Each component carries its own version (see /version.json and # cmake/VersionUtils.cmake); the umbrella project is intentionally unversioned. project(hipdnn LANGUAGES CXX) # ---------------------------------------------------------------------------- # TheRock Feature Flags # # See: https://github.com/ROCm/TheRock/blob/main/docs/development/flags.md # # These flags are injected during the project() call above via # CMAKE_PROJECT_TOP_LEVEL_INCLUDES (TheRock's build system), which only # populates the cache during that call. They must therefore be declared AFTER # project(): declared before, option() captures the pre-injection default # (typically OFF) and the injected value is silently ignored, leaving the # feature compiled out despite the flag being set. # ---------------------------------------------------------------------------- option(HIPDNN_ENABLE_SDPA "Enable SDPA (Scaled Dot-Product Attention) support" OFF) if(HIPDNN_ENABLE_SDPA) message(STATUS "hipDNN: SDPA support enabled") add_compile_definitions(HIPDNN_ENABLE_SDPA) else() message(STATUS "hipDNN: SDPA support disabled") endif() # Gates install of the cuDNN-compatibility shim headers and build/run of its # tests. The shim sources always exist in the tree; this option controls only # whether they are installed and tested. option(HIPDNN_ENABLE_CUDNN_COMPATIBILITY "Enable the cuDNN compatibility shim (headers + tests)" OFF ) if(HIPDNN_ENABLE_CUDNN_COMPATIBILITY) message(STATUS "hipDNN: cuDNN compatibility shim enabled") else() message(STATUS "hipDNN: cuDNN compatibility shim disabled") endif() include(${CMAKE_CURRENT_LIST_DIR}/cmake/CheckPreCommit.cmake) if(NOT WIN32) if(CMAKE_GENERATOR STREQUAL "Ninja") message(STATUS "The CMake generator is Ninja.") else() message(WARNING "The CMake generator is not Ninja. Ninja is preferred over Make.") endif() endif() # Only set if not already specified by user if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND ROCM_PATH) set(CMAKE_INSTALL_PREFIX "${ROCM_PATH}" CACHE PATH "Install path prefix" FORCE) message(STATUS "CMAKE_INSTALL_PREFIX set using ROCM_PATH: ${CMAKE_INSTALL_PREFIX}") elseif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND ROCM_CMAKE_PATH) set(CMAKE_INSTALL_PREFIX "${ROCM_CMAKE_PATH}" CACHE PATH "Install path prefix" FORCE) message(STATUS "CMAKE_INSTALL_PREFIX set using ROCM_CMAKE_PATH: ${CMAKE_INSTALL_PREFIX}") else() message(STATUS "CMAKE_INSTALL_PREFIX set to default: ${CMAKE_INSTALL_PREFIX}") endif() include(GNUInstallDirs) set(CMAKE_CXX_STANDARD 17) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) if(WIN32) set(HIPDNN_PLUGIN_ROOTDIR "${CMAKE_INSTALL_BINDIR}" CACHE STRING "Root location for plugins") set(HIPDNN_PLUGIN_FULL_ROOTDIR "${CMAKE_INSTALL_FULL_BINDIR}" CACHE STRING "Root location for plugins" ) else() set(HIPDNN_PLUGIN_ROOTDIR "${CMAKE_INSTALL_LIBDIR}" CACHE STRING "Root location for plugins") set(HIPDNN_PLUGIN_FULL_ROOTDIR "${CMAKE_INSTALL_FULL_LIBDIR}" CACHE STRING "Root location for plugins" ) endif() set(HIPDNN_PLUGIN_ENGINE_SUBDIR "hipdnn_plugins/engines" CACHE STRING "Subdirectory for official hipDNN engine plugins" ) set(HIPDNN_BUILD_PLUGIN_ENGINE_DIR "${CMAKE_BINARY_DIR}/${HIPDNN_PLUGIN_ROOTDIR}/${HIPDNN_PLUGIN_ENGINE_SUBDIR}" CACHE PATH "Build directory for official hipDNN engine plugins" ) set(HIPDNN_FULL_INSTALL_PLUGIN_ENGINE_DIR "${HIPDNN_PLUGIN_FULL_ROOTDIR}/${HIPDNN_PLUGIN_ENGINE_SUBDIR}" CACHE STRING "Full install directory for official hipDNN engine plugins. Uses the CMAKE_INSTALL_PREFIX set at configure time (defaults to /opt/rocm/)." ) set(HIPDNN_RELATIVE_INSTALL_PLUGIN_ENGINE_DIR "${HIPDNN_PLUGIN_ROOTDIR}/${HIPDNN_PLUGIN_ENGINE_SUBDIR}" CACHE STRING "Relative install directory for official hipDNN engine plugins" ) set(HIPDNN_PLUGIN_HEURISTIC_SUBDIR "hipdnn_plugins/heuristics" CACHE STRING "Subdirectory for official hipDNN heuristic plugins" ) set(HIPDNN_BUILD_PLUGIN_HEURISTIC_DIR "${CMAKE_BINARY_DIR}/${HIPDNN_PLUGIN_ROOTDIR}/${HIPDNN_PLUGIN_HEURISTIC_SUBDIR}" CACHE PATH "Build directory for official hipDNN heuristic plugins" ) set(HIPDNN_FULL_INSTALL_PLUGIN_HEURISTIC_DIR "${HIPDNN_PLUGIN_FULL_ROOTDIR}/${HIPDNN_PLUGIN_HEURISTIC_SUBDIR}" CACHE STRING "Full install directory for official hipDNN heuristic plugins. Uses the CMAKE_INSTALL_PREFIX set at configure time (defaults to /opt/rocm/)." ) set(HIPDNN_RELATIVE_INSTALL_PLUGIN_HEURISTIC_DIR "${HIPDNN_PLUGIN_ROOTDIR}/${HIPDNN_PLUGIN_HEURISTIC_SUBDIR}" CACHE STRING "Relative install directory for official hipDNN heuristic plugins" ) set(HIPDNN_TEST_PLUGIN_DIR "${CMAKE_BINARY_DIR}/${HIPDNN_PLUGIN_ROOTDIR}/test_plugins" CACHE INTERNAL "Build directory for test plugins" ) set(HIPDNN_TEST_PLUGIN_INSTALL_DIR "${HIPDNN_PLUGIN_ROOTDIR}/test_plugins" CACHE INTERNAL "Install directory for test plugins" ) # Migrate HIP_DNN_BUILD_BACKEND -> HIPDNN_BUILD_BACKEND if(DEFINED HIP_DNN_BUILD_BACKEND) set(HIPDNN_BUILD_BACKEND ${HIP_DNN_BUILD_BACKEND} CACHE BOOL "Build the backend code" FORCE) unset(HIP_DNN_BUILD_BACKEND CACHE) message(DEPRECATION "HIP_DNN_BUILD_BACKEND has been renamed to HIPDNN_BUILD_BACKEND. Please update your build scripts to use -DHIPDNN_BUILD_BACKEND instead.") endif() option(HIPDNN_BUILD_BACKEND "Build the backend code" ON) # Migrate HIP_DNN_BUILD_FRONTEND -> HIPDNN_BUILD_FRONTEND if(DEFINED HIP_DNN_BUILD_FRONTEND) set(HIPDNN_BUILD_FRONTEND ${HIP_DNN_BUILD_FRONTEND} CACHE BOOL "Build the frontend code" FORCE) unset(HIP_DNN_BUILD_FRONTEND CACHE) message(DEPRECATION "HIP_DNN_BUILD_FRONTEND has been renamed to HIPDNN_BUILD_FRONTEND. Please update your build scripts to use -DHIPDNN_BUILD_FRONTEND instead.") endif() option(HIPDNN_BUILD_FRONTEND "Build the frontend code" ON) # Migrate HIP_DNN_GENERATE_SDK_HEADERS -> HIPDNN_GENERATE_SDK_HEADERS if(DEFINED HIP_DNN_GENERATE_SDK_HEADERS) set(HIPDNN_GENERATE_SDK_HEADERS ${HIP_DNN_GENERATE_SDK_HEADERS} CACHE BOOL "Automatically generates sdk headers from schema during build" FORCE) unset(HIP_DNN_GENERATE_SDK_HEADERS CACHE) message(DEPRECATION "HIP_DNN_GENERATE_SDK_HEADERS has been renamed to HIPDNN_GENERATE_SDK_HEADERS. Please update your build scripts to use -DHIPDNN_GENERATE_SDK_HEADERS instead.") endif() option(HIPDNN_GENERATE_SDK_HEADERS "Automatically generates sdk headers from schema during build" ON) # Migrate HIP_DNN_SKIP_TESTS -> HIPDNN_SKIP_TESTS if(DEFINED HIP_DNN_SKIP_TESTS) set(HIPDNN_SKIP_TESTS ${HIP_DNN_SKIP_TESTS} CACHE BOOL "Skips building all tests" FORCE) unset(HIP_DNN_SKIP_TESTS CACHE) message(DEPRECATION "HIP_DNN_SKIP_TESTS has been renamed to HIPDNN_SKIP_TESTS. Please update your build scripts to use -DHIPDNN_SKIP_TESTS instead.") endif() option(HIPDNN_SKIP_TESTS "Skips building all tests" OFF) option(HIPDNN_ENABLE_COVERAGE "Build with code coverage flags" OFF) option(BUILD_ADDRESS_SANITIZER "Build with Address Sanitizer enabled" OFF) option(BUILD_THREAD_SANITIZER "Build with Thread Sanitizer enabled" OFF) option(ENABLE_CLANG_FORMAT "Enable Clang-Format checks" ON) if(WIN32) option(ENABLE_CLANG_TIDY "Enable Clang-Tidy checks" OFF) else() option(ENABLE_CLANG_TIDY "Enable Clang-Tidy checks" ON) endif() if(ENABLE_CLANG_TIDY) if(WIN32) message(WARNING "Clang-Tidy enabled on Windows - this significantly increases build time.") endif() else() message(WARNING "Clang-Tidy is disabled - some build issues may be missed.") endif() set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE CACHE BOOL "Add paths to linker search and installed rpath" ) include(cmake/Dependencies.cmake) include(cmake/VersionUtils.cmake) include(cmake/CheckToolVersion.cmake) include(cmake/ClangCheck.cmake) include(cmake/ClangTidy.cmake) include(cmake/Sanitizers.cmake) include(cmake/Tests.cmake) include(cmake/TestPluginNames.cmake) include(cmake/Spdlog.cmake) # Add global compile options set(EXTRA_COMPILE_OPTIONS) set(EXTRA_LINK_OPTIONS) if(HIPDNN_ENABLE_COVERAGE) message(VERBOSE "Enabling compile flags for coverage-mapping") list(PREPEND EXTRA_COMPILE_OPTIONS -fprofile-instr-generate -fcoverage-mapping) list(PREPEND EXTRA_LINK_OPTIONS -fprofile-instr-generate -fcoverage-mapping) endif() list( PREPEND HIPDNN_WARNING_COMPILE_OPTIONS -Werror # Treat all warnings as errors -Wall # Enable most common warnings -Wextra # Enable additional warnings not covered by -Wall -Wpedantic # Enforce strict ISO C++ compliance -Wshadow # Warn about variable shadowing -Wnon-virtual-dtor # Warn if a class with virtual functions has a non-virtual destructor -Wold-style-cast # Warn about C-style casts -Wcast-align # Warn about potential performance issues with misaligned casts -Woverloaded-virtual # Warn if a base class function is hidden by a derived class function with # the same name -Wconversion # Warn about implicit type conversions that may alter a value -Wsign-conversion # Warn about implicit conversions between signed and unsigned types -Wnull-dereference # Warn about dereferencing null pointers -Wdouble-promotion # Warn when a float is implicitly promoted to a double -Wformat=2 # Enable stricter format string checks -Winit-self # Warn about variables initialized with itself -Wunreachable-code # Warn about unreachable code $<$:-Wno-error=unused-command-line-argument> # Clang: disable error for unused command line arguments -Wno-error=null-dereference # Downgrade null-dereference to warning (false positives with flatbuffers in backend/data_sdk) -Wswitch-default # Warn if a switch statement does not have a default case ) add_compile_options(${EXTRA_COMPILE_OPTIONS}) add_link_options(${EXTRA_LINK_OPTIONS}) # Disable RTTI in production code and RTTI-free test targets. # Public headers must not use typeid, dynamic_cast, or dynamic_pointer_cast. set(HIPDNN_NO_RTTI_OPTIONS $<$:/GR-> $<$>:-fno-rtti> ) add_subdirectory(data_sdk) add_subdirectory(flatbuffers_sdk) if(HIPDNN_BUILD_BACKEND) add_subdirectory(backend) endif() if(HIPDNN_BUILD_FRONTEND) add_subdirectory(frontend) endif() add_subdirectory(test_sdk) add_subdirectory(plugin_sdk) add_subdirectory(tests) add_subdirectory(tools) # Python bindings are a standalone CMake project that consumes installed hipDNN # artifacts. Configure projects/hipdnn/python/frontend_bindings separately after # installing hipDNN. if(NOT HIPDNN_SKIP_TESTS) # Keep this after all build folders have been added so they have a chance to register their tests # using add_*_test_target() finalize_test_targets("${PROJECT_NAME}") endif() # keep this after all the targets have been added that could use the HIP language compiler. add_clang_tidy_custom_target() # Doxygen documentation target (standalone builds only to avoid target name # collisions with other projects in the superbuild) if(PROJECT_IS_TOP_LEVEL) find_package(Doxygen QUIET) if(DOXYGEN_FOUND) add_custom_target( doxygen COMMAND ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating Doxygen documentation" VERBATIM USES_TERMINAL ) else() add_custom_target( doxygen COMMAND ${CMAKE_COMMAND} -E echo "Error: Doxygen not found. Please install it (e.g. sudo apt-get install doxygen)." COMMAND ${CMAKE_COMMAND} -E false COMMENT "Doxygen not found" VERBATIM USES_TERMINAL ) endif() endif() if(HIPDNN_ENABLE_COVERAGE) findandcheckllvmtools() set(CODE_COVERAGE_IGNORE_REGEX ".*deps.*|.*tests.*|.*data_objects.*|.*HipErrorHandler.*|.*/test_sdk/.*/Mock[^/]*" ) set(CODE_COVERAGE_OBJECTS -object ./${CMAKE_INSTALL_LIBDIR}/libhipdnn_backend.so -object ./${CMAKE_INSTALL_BINDIR}/hipdnn_backend_tests -object ./${CMAKE_INSTALL_BINDIR}/hipdnn_frontend_tests -object ./${CMAKE_INSTALL_BINDIR}/hipdnn_public_backend_tests -object ./${CMAKE_INSTALL_BINDIR}/hipdnn_data_sdk_tests -object ./${CMAKE_INSTALL_BINDIR}/hipdnn_flatbuffers_sdk_tests -object ./${CMAKE_INSTALL_BINDIR}/hipdnn_plugin_sdk_tests -object ./${CMAKE_INSTALL_BINDIR}/hipdnn_test_sdk_tests ) # Helper function to create a code coverage target # ~~~ # Parameters: # TARGET_NAME - Name of the coverage target to create # DEPENDS_TARGET - The target that must be built before generating # coverage (required, use "" for no dependency) # ~~~ function(add_custom_coverage_target TARGET_NAME DEPENDS_TARGET) # Build the DEPENDS clause set(DEPENDS_CLAUSE "") if(NOT "${DEPENDS_TARGET}" STREQUAL "") set(DEPENDS_CLAUSE DEPENDS ${DEPENDS_TARGET}) endif() # cmake-format: off add_custom_target( ${TARGET_NAME} COMMAND find . -name "*.profraw" -print0 | xargs -0 ${LLVM_PROFDATA_BINARY} merge -sparse -o ./coverage-report/hipdnn.profdata COMMAND ${LLVM_COV_BINARY} report ${CODE_COVERAGE_OBJECTS} -instr-profile=./coverage-report/hipdnn.profdata -ignore-filename-regex=${CODE_COVERAGE_IGNORE_REGEX} > ./coverage-report/code_cov_hipdnn.report COMMAND ${LLVM_COV_BINARY} show -Xdemangler=${LLVM_CXXFILT_BINARY} ${CODE_COVERAGE_OBJECTS} -instr-profile=./coverage-report/hipdnn.profdata -ignore-filename-regex=${CODE_COVERAGE_IGNORE_REGEX} --format=html --output-dir=coverage-report COMMAND ${LLVM_COV_BINARY} export ${CODE_COVERAGE_OBJECTS} -instr-profile=./coverage-report/hipdnn.profdata -ignore-filename-regex=${CODE_COVERAGE_IGNORE_REGEX} --format=lcov > ./coverage-report/coverage.info ${DEPENDS_CLAUSE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Generating code coverage report" VERBATIM USES_TERMINAL ) # cmake-format: on endfunction() if(HIPDNN_SKIP_TESTS) message( WARNING "\nThe code coverage targets depend on test targets but test targets don't exist because HIPDNN_SKIP_TESTS is enabled." ) else() add_custom_coverage_target(code_coverage check) # code_coverage depends on 'check' add_custom_coverage_target(unit-coverage unit-check) # unit-coverage depends on 'unit-check' add_custom_coverage_target(integration-coverage integration-check) # ... 'integration-check' # Make alias to target coverage add_custom_target( coverage DEPENDS code_coverage COMMENT "Alias for code_coverage to match mathci" ) endif() # Create a coverage target that does not depend on any other target and will use the coverage # data that already exists on disk from prior / manual target runs performed before this target # is run. add_custom_coverage_target(current-coverage "") endif() if(NOT HIPDNN_SKIP_TESTS) install_hipdnn_ctest_files() endif()