# Copyright (c) 2019-2021 Advanced Micro Devices, Inc. All rights reserved. # Modifications Copyright (c) Microsoft Corporation. Licensed under the MIT License. cmake_minimum_required(VERSION 3.16) if(BUILD_TESTS) option(OPENMP_TESTS_ENABLED "Enable OpenMP for unit tests" OFF) option(ENABLE_MPI_TESTS "Enable MPI-based tests" OFF) #Automatically enabled when MPI-based tests available option(RCCL_HAS_GIN_IB_PROXY "Build the IB Proxy GIN transport-level tests" ON) option(ENABLE_HOST_API_TESTS "Build the host-API tests" ON) message("Building rccl unit tests (Installed in /test/rccl-UnitTests)") if(ENABLE_MPI_TESTS) message("MPI-based tests are enabled") endif() # CPU-only generator unit test: guards the -fgpu-rdc device-function dispatch # codegen in src/device/generate.py. Needs no GPU and no built library. find_package(Python3 COMPONENTS Interpreter REQUIRED) add_test( NAME rccl-generate-device-table COMMAND "${Python3_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/src/device/test_generate_device_table.py" ) if (ENABLE_CODE_COVERAGE) add_compile_options("SHELL:-Xarch_host -fprofile-instr-generate" "SHELL:-Xarch_host -fcoverage-mapping") add_link_options("SHELL:-Xarch_host -fprofile-instr-generate" "SHELL:-Xarch_host -fcoverage-mapping") # Allow ProcessIsolatedTestRunner.cpp to call __llvm_profile_write_file() # explicitly before _exit() so child-process coverage data is flushed. add_compile_definitions(RCCL_TEST_CODE_COVERAGE=1) endif() find_package(hsa-runtime64 PATHS /opt/rocm ) if(${hsa-runtime64_FOUND}) message("hsa-runtime64 found @ ${hsa-runtime64_DIR} ") else() message("find_package did NOT find hsa-runtime64, finding it the OLD Way") message("Looking for header files in ${ROCR_INC_DIR}") message("Looking for library files in ${ROCR_LIB_DIR}") # Search for ROCr header file in user defined locations find_path(ROCR_HDR hsa/hsa.h PATHS ${ROCR_INC_DIR} "/opt/rocm" PATH_SUFFIXES include REQUIRED) include_directories(${ROCR_HDR}) # Search for ROCr library file in user defined locations find_library(ROCR_LIB ${CORE_RUNTIME_TARGET} PATHS ${ROCR_LIB_DIR} "/opt/rocm" PATH_SUFFIXES lib lib64 REQUIRED) endif() if(OPENMP_TESTS_ENABLED) find_package(OpenMP REQUIRED) endif() # MPI configuration if(ENABLE_MPI_TESTS) # Set MPI path: 1) environment variable (always wins), 2) CMake variable, 3) default if(DEFINED ENV{MPI_PATH}) set(MPI_PATH "$ENV{MPI_PATH}" CACHE PATH "Path to MPI installation" FORCE) elseif(NOT DEFINED MPI_PATH) set(MPI_PATH "/opt/ompi" CACHE PATH "Path to MPI installation") endif() # Verify MPI path exists if(NOT EXISTS ${MPI_PATH}) message(WARNING "MPI_PATH does not exist: ${MPI_PATH}") message(WARNING "Please set MPI_PATH to your MPI installation directory") message(FATAL_ERROR "MPI installation not found") endif() message(STATUS "Using MPI installation at: ${MPI_PATH}") # Find required MPI library find_library(MPI_LIBRARY NAMES mpi PATHS ${MPI_PATH}/lib ${MPI_PATH}/lib64 NO_DEFAULT_PATH REQUIRED ) if(NOT MPI_LIBRARY) message(FATAL_ERROR "Could not find MPI library (libmpi.so) in ${MPI_PATH}/lib or ${MPI_PATH}/lib64") endif() # Set up MPI variables set(MPI_CXX_LIBRARIES ${MPI_LIBRARY}) set(MPI_CXX_INCLUDE_DIRS ${MPI_PATH}/include) set(MPI_CXX_LINK_FLAGS "-L${MPI_PATH}/lib -Wl,-rpath,${MPI_PATH}/lib") set(MPIEXEC_EXECUTABLE ${MPI_PATH}/bin/mpirun CACHE FILEPATH "MPI executable") # Add link directories for MPI link_directories(${MPI_PATH}/lib) message(STATUS "MPI library: ${MPI_CXX_LIBRARIES}") message(STATUS "MPI include: ${MPI_CXX_INCLUDE_DIRS}") message(STATUS "MPI executable: ${MPIEXEC_EXECUTABLE}") endif() include_directories(${GTEST_INCLUDE_DIRS} ./common) # Common include directories set(RCCL_COMMON_INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} ${PROJECT_BINARY_DIR}/include # for generated rccl.h header ${PROJECT_BINARY_DIR}/hipify/src/include # for rccl_bfloat16.h ${PROJECT_BINARY_DIR}/hipify/src/include/nccl_device # for rccl_ptr.h ${PROJECT_BINARY_DIR}/hipify/gensrc # for rccl_bfloat16.h ${PROJECT_BINARY_DIR}/hipify/src # for graph/topo.h ${PROJECT_BINARY_DIR}/hipify/src/include/plugin # for recorder tests, nccl_tuner.h ${PROJECT_BINARY_DIR}/hipify/src/transport/net_ib_cast # for net_ib_fault_inject.h, net_ib_cast_inspect.h ${PROJECT_BINARY_DIR}/hipify/src/transport # for net_ib_limits.h ${ROCM_PATH}/include ${ROCM_PATH} ) # Add MPI include directories if MPI tests are enabled if(ENABLE_MPI_TESTS AND MPI_CXX_INCLUDE_DIRS) list(APPEND RCCL_COMMON_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS}) endif() # Common compile definitions set(RCCL_COMMON_COMPILE_DEFS ROCM_PATH="${ROCM_PATH}") if(LL128_ENABLED) list(APPEND RCCL_COMMON_COMPILE_DEFS ENABLE_LL128) endif() if(OPENMP_TESTS_ENABLED) list(APPEND RCCL_COMMON_COMPILE_DEFS ENABLE_OPENMP) endif() if(ENABLE_MPI_TESTS) list(APPEND RCCL_COMMON_COMPILE_DEFS MPI_TESTS_ENABLED) if(RCCL_HAS_GIN_IB_PROXY) list(APPEND RCCL_COMMON_COMPILE_DEFS RCCL_HAS_GIN_IB_PROXY) endif() if(ENABLE_HOST_API_TESTS) list(APPEND RCCL_COMMON_COMPILE_DEFS RCCL_ENABLE_HOST_API_TESTS) endif() endif() list(APPEND RCCL_COMMON_COMPILE_DEFS __HIP_PLATFORM_AMD__) # All test executables link against GTest; tell MPIHelpers.cpp so it can use # GTest's current_test_info() rather than relying on __has_include (which only # proves the header is installed, not that the target actually links the library). list(APPEND RCCL_COMMON_COMPILE_DEFS RCCL_MPIHelpers_HAS_GTEST) # Common link libraries set(RCCL_COMMON_LINK_LIBS ${GTEST_BOTH_LIBRARIES} hip::host hip::device hsa-runtime64::hsa-runtime64 Threads::Threads dl fmt::fmt-header-only ) if(OPENMP_TESTS_ENABLED) list(APPEND RCCL_COMMON_LINK_LIBS "${OpenMP_CXX_FLAGS}") endif() if(ENABLE_MPI_TESTS AND MPI_CXX_LIBRARIES) list(APPEND RCCL_COMMON_LINK_LIBS ${MPI_CXX_LIBRARIES}) endif() # Get the compile definitions from the main rccl target # These helps to keep the test compile definitions in sync with the main rccl target # Also, all the structure layout remains the same across all the targets get_target_property(RCCL_COMPILE_DEFINITIONS rccl COMPILE_DEFINITIONS) if(RCCL_COMPILE_DEFINITIONS) list(APPEND RCCL_COMMON_COMPILE_DEFS ${RCCL_COMPILE_DEFINITIONS}) endif() # Also get interface compile definitions get_target_property(RCCL_INTERFACE_COMPILE_DEFINITIONS rccl INTERFACE_COMPILE_DEFINITIONS) if(RCCL_INTERFACE_COMPILE_DEFINITIONS) list(APPEND RCCL_COMMON_COMPILE_DEFS ${RCCL_INTERFACE_COMPILE_DEFINITIONS}) endif() # Collect testing framework source files set(TEST_SOURCE_FILES AllGatherTests.cpp AllReduceTests.cpp AllToAllTests.cpp AllToAllVTests.cpp AsymmetricVisibilityTests.cpp BroadcastTests.cpp DoneEventOrderingTests.cpp GatherTests.cpp GroupCallTests.cpp NonBlockingTests.cpp RasJsonTests.cpp ReduceScatterTests.cpp ReduceTests.cpp RegisterTests.cpp ScatterTests.cpp P2pChannelScalingTests.cpp VersionGateTests.cpp SendRecvTests.cpp StandaloneTests.cpp DdaIpcTests.cpp TeardownStressTests.cpp _RecorderTests.cpp common/main.cpp common/CallCollectiveForked.cpp common/CollectiveArgs.cpp common/EnvVars.cpp common/PrepDataFuncs.cpp common/PtrUnion.cpp common/ProcessIsolatedTestRunner.cpp common/TestBed.cpp common/TestBedChild.cpp common/StandaloneUtils.cpp proxy_trace/ProxyTraceUnitTests.cpp ../src/misc/proxy_trace/proxy_trace.cc latency_profiler/LatencyProfilerUnitTest.cpp ../src/misc/latency_profiler/CollTraceUtils.cc ) # Due to default hidden symbol visibility, append source file if build type is not Debug. # It requires explicit addition of the following source file(s) # to the unit tests to ensure it is included for the existing rccl-UnitTests execution if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") list(APPEND TEST_SOURCE_FILES ../src/misc/recorder.cc ../src/misc/proxy_trace/proxy_trace.cc ) endif() set(RCCL_TEST_EXECUTABLES rccl-UnitTests) # Create rccl-UnitTests binary add_executable(rccl-UnitTests ${TEST_SOURCE_FILES}) # rccl-UnitTestsFixtures: Tests that only use header-only internal dependencies # (inline, static, constexpr, template functions) and can run in both Release and Debug. if (ROCM_VERSION VERSION_GREATER_EQUAL "60400") list(APPEND RCCL_TEST_EXECUTABLES rccl-UnitTestsFixtures) set(TEST_FIXTURE_SOURCE_FILES BitOpsTests.cpp IommuPassthrough_test.cpp MiscTests.cpp RomeTopoConsensusTests.cpp EnqueueCountTests.cpp DdaCollCommonTests.cpp VersionInfoTests.cpp device/TestOp128.cpp device/GinDeviceTests.cpp device/GinAnvilIpcDevice_test.cpp DeviceApiTests.cpp common/main_fixtures.cpp common/EnvVars.cpp common/ProcessIsolatedTestRunner.cpp common/TestChecks.cpp ../src/misc/kernel_config.cc ) if(ENABLE_ROCSHMEM_GIN) list(APPEND TEST_FIXTURE_SOURCE_FILES gin/GinAnvilIpcTableHost_test.cpp ../src/gin/gin_anvil_ipc_table_host.cc ) endif() if(ENABLE_ROCSHMEM_GIN AND (ENABLE_ROCSHMEM OR GIN_ANVIL_UNIT_TESTS)) list(APPEND TEST_FIXTURE_SOURCE_FILES device/GinAnvilSdmaTemplate_test.cpp ) endif() add_executable(rccl-UnitTestsFixtures ${TEST_FIXTURE_SOURCE_FILES}) target_include_directories(rccl-UnitTestsFixtures PRIVATE ${PROJECT_BINARY_DIR}/hipify/src/device ${PROJECT_BINARY_DIR}/hipify/src/include ${PROJECT_BINARY_DIR}/hipify/src/include/nccl_device ) if(ENABLE_ROCSHMEM_GIN) target_compile_definitions(rccl-UnitTestsFixtures PRIVATE ENABLE_ROCSHMEM_GIN) endif() if(ENABLE_ROCSHMEM_GIN AND (ENABLE_ROCSHMEM OR GIN_ANVIL_UNIT_TESTS)) target_compile_definitions(rccl-UnitTestsFixtures PRIVATE ENABLE_ROCSHMEM) endif() if(ENABLE_ROCSHMEM_GIN OR GIN_ANVIL_UNIT_TESTS) if(ROCSHMEM_INCLUDE_DIR) target_include_directories(rccl-UnitTestsFixtures PRIVATE ${ROCSHMEM_INCLUDE_DIR}) elseif(ROCSHMEM_INSTALL_DIR) target_include_directories(rccl-UnitTestsFixtures PRIVATE "${ROCSHMEM_INSTALL_DIR}/include") endif() if(ROCSHMEM_SOURCE_DIR) target_include_directories(rccl-UnitTestsFixtures PRIVATE "${ROCSHMEM_SOURCE_DIR}/src" "${ROCSHMEM_SOURCE_DIR}/include") endif() if(ROCSHMEM_BUILD_DIR) target_include_directories(rccl-UnitTestsFixtures PRIVATE ${ROCSHMEM_BUILD_DIR}) endif() endif() if(ENABLE_ROCSHMEM_GIN AND ROCM_VERSION VERSION_GREATER_EQUAL "60400") list(APPEND RCCL_TEST_EXECUTABLES rccl-UnitTestsGinAnvilPlugin) add_executable(rccl-UnitTestsGinAnvilPlugin gin/GinAnvilPlugin_test.cpp gin/gin_anvil_plugin_test_stubs.cc ../src/gin/gin_plugin_anvil_sdma.cc ../src/gin/gin_anvil_ipc_table_host.cc common/main_fixtures.cpp common/EnvVars.cpp common/TestChecks.cpp common/ProcessIsolatedTestRunner.cpp ) target_include_directories(rccl-UnitTestsGinAnvilPlugin PRIVATE ${PROJECT_BINARY_DIR}/hipify/src/include ${PROJECT_BINARY_DIR}/hipify/src/include/nccl_device ${CMAKE_CURRENT_SOURCE_DIR}/gin ) if(ROCSHMEM_SOURCE_DIR) target_include_directories(rccl-UnitTestsGinAnvilPlugin PRIVATE ${ROCSHMEM_SOURCE_DIR}/include) else() target_include_directories(rccl-UnitTestsGinAnvilPlugin PRIVATE ${CMAKE_SOURCE_DIR}/../rocshmem/include) endif() target_compile_definitions(rccl-UnitTestsGinAnvilPlugin PRIVATE ENABLE_ROCSHMEM_GIN) endif() endif() # rccl-UnitTestsFixturesDebug: Tests that access internal symbols compiled into # librccl.so which are only visible in Debug builds (hidden visibility in Release). if (ROCM_VERSION VERSION_GREATER_EQUAL "60400" AND CMAKE_BUILD_TYPE MATCHES "Debug") list(APPEND RCCL_TEST_EXECUTABLES rccl-UnitTestsFixturesDebug) set(TEST_FIXTURE_DEBUG_SOURCE_FILES AllocTests.cpp ParamTests.cpp ParameterApiTests.cpp ArgCheckTests.cpp BootstrapBidirTests.cpp DdaAlltoAllThresholdTests.cpp DdaIpcEligibilityTests.cpp DdaFabricEligibilityTests.cpp EnqueueTests.cpp IpcsocketTests.cpp TopoEnvPolicyTests.cpp NetSocketTests.cpp PluginCompatV11_test.cpp ProxyTests.cpp RcclWrapTests.cpp TransportTests.cpp TimeoutTests.cpp mem_manager/MemManagerTests.cpp graph/SearchTests.cpp graph/XmlTests.cpp graph/NetDevsPolicyP2pNetTests.cpp graph/TopoTests.cpp common/main_fixtures.cpp common/EnvVars.cpp common/ProcessIsolatedTestRunner.cpp ) add_executable(rccl-UnitTestsFixturesDebug ${TEST_FIXTURE_DEBUG_SOURCE_FILES}) # SearchTests.cpp #includes the hipify-generated copy of src/graph/search.cc # directly (via #include SEARCH_CC_PATH) so it can exercise search.cc's # internal symbols in the same TU. Pass the absolute path as a source-scoped # define; the hipify step is ordered ahead of the test via the add_dependencies # / link to the rccl target that the common foreach below applies. set_source_files_properties(graph/SearchTests.cpp PROPERTIES COMPILE_DEFINITIONS "SEARCH_CC_PATH=\"${PROJECT_BINARY_DIR}/hipify/src/graph/search.cc\"") # TopoEnvPolicyTests and NetDevsPolicyP2pNetTests load a topology XML fixture # from the source tree (tools/topo_expl/models). Expose the test source dir # so they can build the path. target_compile_definitions(rccl-UnitTestsFixturesDebug PRIVATE RCCL_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") # PluginCompatV11_test.cpp resolves its in-process mock plugin symbols via # dlsym(dlopen(NULL), ...), which only sees the executable's dynamic symbols. target_link_options(rccl-UnitTestsFixturesDebug PRIVATE -Wl,--export-dynamic-symbol=ncclNetPlugin_v11 -Wl,--export-dynamic-symbol=ncclCollNetPlugin_v11) endif() # rccl-UnitTestsAltRsmi: Compiles alt_rsmi.cc directly (not via librccl.so) with # ARSMI_TEST_BUILD, which gives external linkage to thread_local sysfs root variables # so tests can redirect them to a temp directory. No librccl.so symbols needed, # so this target works in both Release and Debug builds. if (ROCM_VERSION VERSION_GREATER_EQUAL "60400") list(APPEND RCCL_TEST_EXECUTABLES rccl-UnitTestsAltRsmi) set(TEST_ALTRSMI_SOURCE_FILES AltRsmiTests.cpp ../src/misc/alt_rsmi.cc common/main_altrsmi.cpp common/ProcessIsolatedTestRunner.cpp ) add_executable(rccl-UnitTestsAltRsmi ${TEST_ALTRSMI_SOURCE_FILES}) # Define ARSMI_TEST_BUILD specifically for rccl-UnitTestsAltRsmi target_compile_definitions(rccl-UnitTestsAltRsmi PRIVATE ARSMI_TEST_BUILD) # amdsmi_wrap.h is compiled directly into this target (via alt_rsmi.cc), so it # needs the amdsmi include path that the rccl library target gets but doesn't # propagate (PRIVATE scope). Without this, __has_include() # returns false in test TUs even when AMDSMI_FABRIC_DIRECT is set. if(DEFINED SMI_INCLUDE_DIR) target_include_directories(rccl-UnitTestsAltRsmi PRIVATE ${SMI_INCLUDE_DIR}) endif() endif() # rccl-UnitTestsAmdSmi: tests for the amdsmi_wrap layer. # # AmdSmiFabricTests.cpp covers the fabric predicates and struct layout pinned in # amdsmi_wrap.h. Those are header-inline, so they need no librccl.so symbols and # run in both Release and Debug. # # AmdSmiWrapTests.cpp drives the amd_smi_* API itself, so it needs symbols that # src/CMakeLists.txt only exports under -fvisibility=default in Debug. Adding it # in Release would fail to link, so it joins the target only where they exist. if (ROCM_VERSION VERSION_GREATER_EQUAL "60400") list(APPEND RCCL_TEST_EXECUTABLES rccl-UnitTestsAmdSmi) # main_altrsmi.cpp is a plain InitGoogleTest/RUN_ALL_TESTS entry point, reused here. set(TEST_AMDSMI_SOURCE_FILES AmdSmiFabricTests.cpp common/main_altrsmi.cpp ) if(CMAKE_BUILD_TYPE MATCHES "Debug") list(APPEND TEST_AMDSMI_SOURCE_FILES AmdSmiWrapTests.cpp common/ProcessIsolatedTestRunner.cpp ) # Loaded only by isolated lifecycle tests, never by the normal test process. add_library(rccl-AmdSmiLifecycleStub SHARED AmdSmiLifecycleStub.cpp) set_target_properties(rccl-AmdSmiLifecycleStub PROPERTIES OUTPUT_NAME "amd_smi" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/amdsmi_lifecycle_stub" ) # Match the versioned name used by amdsmi_wrap when headers are present. # Older ROCm configurations may not define SMI_INCLUDE_DIR, so also check # ROCM_PATH; without either header amdsmi_wrap uses the unversioned name. if(EXISTS "${SMI_INCLUDE_DIR}/amd_smi/amdsmi.h") set(AMDSMI_TEST_HEADER "${SMI_INCLUDE_DIR}/amd_smi/amdsmi.h") elseif(EXISTS "${ROCM_PATH}/include/amd_smi/amdsmi.h") set(AMDSMI_TEST_HEADER "${ROCM_PATH}/include/amd_smi/amdsmi.h") endif() if(AMDSMI_TEST_HEADER) file(STRINGS "${AMDSMI_TEST_HEADER}" AMDSMI_VERSION_MAJOR_LINE REGEX "^#define AMDSMI_LIB_VERSION_MAJOR [0-9]+" LIMIT_COUNT 1 ) string(REGEX REPLACE ".* ([0-9]+)$" "\\1" AMDSMI_TEST_SOVERSION "${AMDSMI_VERSION_MAJOR_LINE}" ) set_target_properties(rccl-AmdSmiLifecycleStub PROPERTIES SOVERSION "${AMDSMI_TEST_SOVERSION}" ) endif() endif() add_executable(rccl-UnitTestsAmdSmi ${TEST_AMDSMI_SOURCE_FILES}) if(CMAKE_BUILD_TYPE MATCHES "Debug") add_dependencies(rccl-UnitTestsAmdSmi rccl-AmdSmiLifecycleStub) target_compile_definitions(rccl-UnitTestsAmdSmi PRIVATE AMDSMI_TEST_STUB_DIR="$" AMDSMI_TEST_STUB_SONAME="$" ) endif() # amdsmi_wrap.h needs both halves of this pairing: the include path so its # __has_include finds amdsmi, and AMDSMI_FABRIC_DIRECT, which is PRIVATE to the # rccl target and so does not reach test TUs. With the headers reachable but the # define absent, the header's fabric compat block compiles on top of the real # declarations and every fabric type collides. if(DEFINED SMI_INCLUDE_DIR) target_include_directories(rccl-UnitTestsAmdSmi PRIVATE ${SMI_INCLUDE_DIR}) endif() if(AMDSMI_FABRIC_API) target_compile_definitions(rccl-UnitTestsAmdSmi PRIVATE AMDSMI_FABRIC_DIRECT) endif() endif() # Create separate MPI test binary if MPI tests are enabled if(ENABLE_MPI_TESTS) set(MPI_TEST_SOURCE_FILES common/main_mpi.cpp common/MPIHelpers.cpp common/MPITestCore.cpp common/MPIEnvironment.cpp common/TestChecks.cpp transport/TransportMPIBase.cpp transport/P2pMPITests.cpp transport/NetMPITests.cpp transport/ShmMPITests.cpp transport/NetIbMPI/GeneralTests.cpp transport/NetIbMPI/NicFusionTests.cpp transport/NetIbMPI/CastTests.cpp transport/NetIbMPI/FaultInjectTests.cpp transport/NetIbMPI/OpsFaultUnitTests.cpp transport/GinMPI/GinMPITests.cpp transport/NetIbMPI/StressTests.cpp transport/GinDeviceMPITests.cpp WarpSpeedMPITests.cpp ImplicitLaunchOrderMPITests.cpp CommMPITests.cpp RegistrationMPITests.cpp HostApiMPITests.cpp mem_manager/SuspendResumeMPITests.cpp RevokeMPITests.cpp ce/CeMPITests.cpp ce/CeInternalMPITests.cpp GrowMPITests.cpp GinNcclTimeoutMPITests.cpp SymmetricKernelMPITests.cpp SymmetricWindowMPITests.cpp CommNetMismatchMPITests.cpp ) add_executable(rccl-UnitTestsMPI ${MPI_TEST_SOURCE_FILES}) list(APPEND RCCL_TEST_EXECUTABLES rccl-UnitTestsMPI) endif() foreach(test_executable IN LISTS RCCL_TEST_EXECUTABLES) target_include_directories(${test_executable} PRIVATE ${RCCL_COMMON_INCLUDE_DIRS}) target_compile_definitions(${test_executable} PRIVATE ${RCCL_COMMON_COMPILE_DEFS}) if(ENABLE_DEVICE_LINKER) # Mirror the rccl library define so device-linker-specific test expectations compile in. target_compile_definitions(${test_executable} PRIVATE RCCL_DEVICE_LINKER) endif() target_link_libraries(${test_executable} PRIVATE ${RCCL_COMMON_LINK_LIBS}) if(BUILD_ADDRESS_SANITIZER) target_compile_options(${test_executable} PRIVATE -fsanitize=address) target_link_options(${test_executable} PRIVATE -fsanitize=address -shared-libasan) if(DEFINED ASAN_RUNTIME_DIR) target_link_options(${test_executable} PRIVATE "LINKER:-rpath,${ASAN_RUNTIME_DIR}") endif() endif() # Add MPI-specific configuration if MPI tests are enabled if(ENABLE_MPI_TESTS) if(MPI_CXX_COMPILE_FLAGS) target_compile_options(${test_executable} PRIVATE ${MPI_CXX_COMPILE_FLAGS}) endif() if(MPI_CXX_LINK_FLAGS) set_target_properties(${test_executable} PROPERTIES LINK_FLAGS "${MPI_CXX_LINK_FLAGS}") endif() endif() if(BUILD_SHARED_LIBS) target_link_libraries(${test_executable} PRIVATE rccl) if(${HOST_OS_ID} STREQUAL "debian") set_property(TARGET ${test_executable} PROPERTY INSTALL_RPATH "${CMAKE_BINARY_DIR}") elseif(DEFINED HOST_OS_FAMILY AND "${HOST_OS_FAMILY}" STREQUAL "debian") set_property(TARGET ${test_executable} PROPERTY INSTALL_RPATH "${CMAKE_BINARY_DIR}") endif() else() add_dependencies(${test_executable} rccl) target_link_libraries(${test_executable} PRIVATE dl rt numa -lrccl -L${CMAKE_BINARY_DIR} -lrocm_smi64 -L${ROCM_PATH}/lib -L${ROCM_PATH}/rocm_smi/lib) endif() # Link the GIN device backend library and device-link its rdc code (-fgpu-rdc # --hip-link --offload-arch=... -rdynamic) so GIN device tests can run. if(ENABLE_ROCSHMEM_GIN AND ROCSHMEM_INSTALL_DIR AND "${test_executable}" STREQUAL "rccl-UnitTestsMPI") set(_ROCSHMEM_OFFLOAD_FLAGS "") foreach(_g IN LISTS GPU_TARGETS) if(_g) list(APPEND _ROCSHMEM_OFFLOAD_FLAGS "--offload-arch=${_g}") endif() endforeach() # Fall back to linking by bare name if the hint lookup misses (avoids injecting -NOTFOUND into the link line). find_library(_ROCSHMEM_DRM NAMES drm HINTS ${ROCM_PATH}/lib/rocm_sysdeps/lib) find_library(_ROCSHMEM_DRM_AMDGPU NAMES drm_amdgpu HINTS ${ROCM_PATH}/lib/rocm_sysdeps/lib) if(NOT _ROCSHMEM_DRM) set(_ROCSHMEM_DRM drm) endif() if(NOT _ROCSHMEM_DRM_AMDGPU) set(_ROCSHMEM_DRM_AMDGPU drm_amdgpu) endif() # Enable the GIN device backend in the test kernels so ncclGinCall has a # dispatch case for the corresponding runtime GIN type. target_compile_definitions(${test_executable} PRIVATE NCCL_GIN_ROCSHMEM_GDA_ENABLE=1) target_compile_options(${test_executable} PRIVATE -fgpu-rdc) target_link_libraries(${test_executable} PRIVATE ${ROCSHMEM_INSTALL_DIR}/lib/librocshmem.a ibverbs hsa-runtime64 hsakmt numa ${_ROCSHMEM_DRM} ${_ROCSHMEM_DRM_AMDGPU}) target_link_options(${test_executable} PRIVATE -fgpu-rdc --hip-link ${_ROCSHMEM_OFFLOAD_FLAGS} -rdynamic) endif() rocm_install(TARGETS ${test_executable} COMPONENT tests) endforeach() # Suite H: shadow rocSHMEM sdma headers with no-op test stubs (higher-priority include path). if(ENABLE_ROCSHMEM_GIN AND (ENABLE_ROCSHMEM OR GIN_ANVIL_UNIT_TESTS)) if(ROCSHMEM_SOURCE_DIR) target_include_directories(rccl-UnitTestsFixtures PRIVATE ${ROCSHMEM_SOURCE_DIR}/src) else() target_include_directories(rccl-UnitTestsFixtures PRIVATE ${CMAKE_SOURCE_DIR}/../rocshmem/src) endif() target_include_directories(rccl-UnitTestsFixtures BEFORE PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/device) endif() # Create install-time test file for distribution set(INSTALL_TEST_FILE "${CMAKE_CURRENT_BINARY_DIR}/install_CTestTestfile.cmake") file(WRITE "${INSTALL_TEST_FILE}" [=[ # This is a test file generated by rccl for install time. # Tests are defined with relative paths to work in the installed location. ]=] ) # Shared ROCm Libraries CTest categories (see shared/ctest/README.md) if(ROCM_SYSTEMS_ROOT AND EXISTS "${ROCM_SYSTEMS_ROOT}/shared/ctest/TestCategories.cmake") # Currently these files only exist in rocm-libraries, without that repo this will fail. # get_filename_component(ROCM_SYSTEMS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../.." ABSOLUTE) include("${ROCM_SYSTEMS_ROOT}/shared/ctest/TestCategories.cmake") enable_testing() set(_rccl_test_categories_yaml "${CMAKE_CURRENT_SOURCE_DIR}/test_categories.yaml") if(EXISTS "${_rccl_test_categories_yaml}") message(STATUS "Applying test categories for rccl-UnitTests") apply_test_category_labels( rccl-UnitTests "${_rccl_test_categories_yaml}" "${PROJECT_BINARY_DIR}" "${INSTALL_TEST_FILE}" ) else() message(WARNING "Skipping test categories for rccl-UnitTests: missing ${_rccl_test_categories_yaml}") endif() if(ROCM_VERSION VERSION_GREATER_EQUAL "60400") set(_rccl_test_categories_fixtures_yaml "${CMAKE_CURRENT_SOURCE_DIR}/test_categories_fixtures.yaml") if(EXISTS "${_rccl_test_categories_fixtures_yaml}") message(STATUS "Applying test categories for rccl-UnitTestsFixtures") apply_test_category_labels( rccl-UnitTestsFixtures "${_rccl_test_categories_fixtures_yaml}" "${PROJECT_BINARY_DIR}" "${INSTALL_TEST_FILE}" ) else() message(WARNING "Skipping test categories for rccl-UnitTestsFixtures: missing ${_rccl_test_categories_fixtures_yaml}") endif() # Registered outside the Debug-only block below: this target's fabric predicate # and layout cases need no librccl symbols and so run in Release too. The # AmdSmiWrap* patterns in the yaml match nothing in a Release binary, where # that file is left out for lack of exported amd_smi_* symbols. set(_rccl_test_categories_amdsmi_yaml "${CMAKE_CURRENT_SOURCE_DIR}/test_categories_amdsmi.yaml") if(EXISTS "${_rccl_test_categories_amdsmi_yaml}") message(STATUS "Applying test categories for rccl-UnitTestsAmdSmi") apply_test_category_labels( rccl-UnitTestsAmdSmi "${_rccl_test_categories_amdsmi_yaml}" "${PROJECT_BINARY_DIR}" "${INSTALL_TEST_FILE}" ) else() message(WARNING "Skipping test categories for rccl-UnitTestsAmdSmi: missing ${_rccl_test_categories_amdsmi_yaml}") endif() endif() if(ROCM_VERSION VERSION_GREATER_EQUAL "60400" AND CMAKE_BUILD_TYPE MATCHES "Debug") set(_rccl_test_categories_fixtures_debug_yaml "${CMAKE_CURRENT_SOURCE_DIR}/test_categories_fixtures_debug.yaml") if(EXISTS "${_rccl_test_categories_fixtures_debug_yaml}") message(STATUS "Applying test categories for rccl-UnitTestsFixturesDebug") apply_test_category_labels( rccl-UnitTestsFixturesDebug "${_rccl_test_categories_fixtures_debug_yaml}" "${PROJECT_BINARY_DIR}" "${INSTALL_TEST_FILE}" ) else() message(WARNING "Skipping test categories for rccl-UnitTestsFixturesDebug: missing ${_rccl_test_categories_fixtures_debug_yaml}") endif() set(_rccl_test_categories_altrsmi_yaml "${CMAKE_CURRENT_SOURCE_DIR}/test_categories_altrsmi.yaml") if(EXISTS "${_rccl_test_categories_altrsmi_yaml}") message(STATUS "Applying test categories for rccl-UnitTestsAltRsmi") apply_test_category_labels( rccl-UnitTestsAltRsmi "${_rccl_test_categories_altrsmi_yaml}" "${PROJECT_BINARY_DIR}" "${INSTALL_TEST_FILE}" ) else() message(WARNING "Skipping test categories for rccl-UnitTestsAltRsmi: missing ${_rccl_test_categories_altrsmi_yaml}") endif() endif() if(ENABLE_MPI_TESTS) set(_rccl_test_categories_mpi_yaml "${CMAKE_CURRENT_SOURCE_DIR}/test_categories_mpi.yaml") if(EXISTS "${_rccl_test_categories_mpi_yaml}") message(STATUS "Applying test categories for rccl-UnitTestsMPI") apply_test_category_labels( rccl-UnitTestsMPI "${_rccl_test_categories_mpi_yaml}" "${PROJECT_BINARY_DIR}" ) else() message(WARNING "Skipping test categories for rccl-UnitTestsMPI: missing ${_rccl_test_categories_mpi_yaml}") endif() endif() endif() install( FILES "${INSTALL_TEST_FILE}" DESTINATION "${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME}" COMPONENT tests RENAME "CTestTestfile.cmake" ) endif()