# ============================================================================= # UNIFIED BUILD ORCHESTRATION SCRIPT WITH CUDA TEMPLATE PARITY # # This enhanced version includes support for CUDA template processing # to achieve complete parity between CPU and CUDA template systems. # UPDATED with modern cuDNN integration # # CACHE INVALIDATION: Modified to force CMake reconfiguration after # PCH disabling in session #1002. Resolves Makefile2 having stale # progress count (99 steps) while build.make has correct count (1251 steps). # This inconsistency caused build to stop at 98% missing files 48-64. # ============================================================================= # ============================================================================= # SECTION 1: HELPER FUNCTION DEFINITIONS # All functions are defined first to ensure they are available when called. # ============================================================================= # --- Helper for colored status messages --- function(print_status_colored type message) if(type STREQUAL "ERROR") message(FATAL_ERROR "❌ ${message}") elseif(type STREQUAL "WARNING") message(WARNING "⚠️ ${message}") elseif(type STREQUAL "SUCCESS") message(STATUS "✅ ${message}") elseif(type STREQUAL "INFO") message(STATUS "ℹ️ ${message}") else() message(STATUS "${message}") endif() endfunction() function(libnd4j_setup_target_with_types target_name) message(STATUS "🔧 Setting up libnd4j target with type definitions: ${target_name}") # Ensure target exists if(NOT TARGET ${target_name}) message(FATAL_ERROR "Target ${target_name} does not exist") endif() # Apply type definitions immediately after target creation setup_type_definitions_for_target(${target_name}) # Apply any additional target configuration set_target_properties(${target_name} PROPERTIES POSITION_INDEPENDENT_CODE ON) message(STATUS "✅ Target ${target_name} configured with type definitions") endfunction() function(orchestrate_enhanced_build target_name) message(STATUS "ℹ️ === ORCHESTRATING ENHANCED LIBND4J BUILD WITH TEMPLATE PARITY ===") message(STATUS "ℹ️ === 1. INITIALIZING BUILD CONFIGURATION ===") # Setup target with type definitions libnd4j_setup_target_with_types(${target_name}) message(STATUS "ℹ️ === 2. INITIALIZING DEPENDENCIES & OPERATIONS ===") message(STATUS "Dependencies initialization complete.") message(STATUS "ℹ️ === 3. CONFIGURING ENHANCED SELECTIVE RENDERING ===") message(STATUS "✅ Enhanced CPU selective rendering setup complete") message(STATUS "ℹ️ === 4. FINALIZING BUILD WITH TYPE DEFINITIONS ===") finalize_build_with_type_definitions(${target_name}) message(STATUS "✅ === ENHANCED BUILD ORCHESTRATION COMPLETE ===") message(STATUS "🖥️ Enhanced CPU build orchestration complete - System ready for compilation") endfunction() # Simplified function for immediate use after target creation function(apply_libnd4j_type_definitions target_name) if(TARGET ${target_name}) setup_type_definitions_for_target(${target_name}) message(STATUS "✅ Applied type definitions to ${target_name}") else() message(FATAL_ERROR "❌ Target ${target_name} not found for type definitions") endif() endfunction() function(apply_libnd4j_type_definitions_auto) # Use the SD_LIBRARY_NAME variable set in CMakeLists.txt if(DEFINED SD_LIBRARY_NAME AND TARGET ${SD_LIBRARY_NAME}) set(target_name ${SD_LIBRARY_NAME}) message(STATUS "Using SD_LIBRARY_NAME target: ${target_name}") setup_type_definitions_for_target(${target_name}) return() endif() # Fallback to detecting the target based on build type if(SD_CUDA AND TARGET nd4jcuda) setup_type_definitions_for_target(nd4jcuda) message(STATUS "Applied type definitions to nd4jcuda") elseif(SD_CPU AND TARGET nd4jcpu) setup_type_definitions_for_target(nd4jcpu) message(STATUS "Applied type definitions to nd4jcpu") elseif(TARGET nd4jcpu) setup_type_definitions_for_target(nd4jcpu) message(STATUS "Applied type definitions to nd4jcpu (fallback)") elseif(TARGET nd4jcuda) setup_type_definitions_for_target(nd4jcuda) message(STATUS "Applied type definitions to nd4jcuda (fallback)") else() message(WARNING "❌ No nd4j targets found for type definitions") get_property(all_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY BUILDSYSTEM_TARGETS) message(STATUS "Available targets: ${all_targets}") endif() endfunction() # Function to apply to specific target by name function(apply_libnd4j_type_definitions target_name) if(TARGET ${target_name}) setup_type_definitions_for_target(${target_name}) message(STATUS "✅ Applied type definitions to ${target_name}") else() message(FATAL_ERROR "❌ Target ${target_name} not found for type definitions") endif() endfunction() # Function to apply to all libnd4j targets function(apply_libnd4j_type_definitions_all) set(possible_targets "nd4jcpu;nd4jcuda;nd4j;libnd4j") set(applied_count 0) foreach(target ${possible_targets}) if(TARGET ${target}) setup_type_definitions_for_target(${target}) message(STATUS "✅ Applied type definitions to ${target}") math(EXPR applied_count "${applied_count} + 1") endif() endforeach() if(applied_count EQUAL 0) message(WARNING "❌ No libnd4j targets found") get_property(all_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY BUILDSYSTEM_TARGETS) message(STATUS "Available targets: ${all_targets}") else() message(STATUS "✅ Applied type definitions to ${applied_count} targets") endif() endfunction() # --- Platform environment setup functions --- function(setup_cpu_environment) message(STATUS "🔧 Setting up CPU environment") add_definitions(-D__CPUBLAS__=true) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") find_package(OpenMP) if(OpenMP_CXX_FOUND) message(STATUS "✅ OpenMP found and will be linked") else() message(STATUS "⚠️ OpenMP not found, will use manual configuration") endif() endif() if(SD_X86_BUILD) message(STATUS "🎯 Enabling x86 optimizations") endif() message(STATUS "✅ CPU environment setup complete") endfunction() # --- Enhanced source collection with CUDA template support --- function(collect_all_sources out_source_list) set(ALL_SOURCES_LIST "") file(GLOB_RECURSE PERF_SOURCES ./include/performance/*.cpp) file(GLOB_RECURSE EXCEPTIONS_SOURCES ./include/exceptions/*.cpp) file(GLOB_RECURSE TYPES_SOURCES ./include/types/*.cpp) file(GLOB_RECURSE GRAPH_SOURCES ./include/graph/*.cpp) file(GLOB_RECURSE CUSTOMOPS_SOURCES ./include/ops/declarable/generic/*.cpp) file(GLOB_RECURSE OPS_SOURCES ./include/ops/impl/*.cpp ./include/ops/declarable/impl/*.cpp) file(GLOB_RECURSE INDEXING_SOURCES ./include/indexing/*.cpp) list(APPEND ALL_SOURCES_LIST ${PERF_SOURCES} ${EXCEPTIONS_SOURCES} ${TYPES_SOURCES} ${GRAPH_SOURCES} ${CUSTOMOPS_SOURCES} ${OPS_SOURCES} ${INDEXING_SOURCES} ) # This call populates CUSTOMOPS_GENERIC_SOURCES with both CPU and CUDA generated files setup_template_processing() if(SD_CUDA) file(GLOB_RECURSE EXEC_SOURCES ./include/execution/impl/*.cpp ./include/execution/cuda/*.cu ./include/execution/*.cu) file(GLOB_RECURSE ARRAY_SOURCES ./include/array/cuda/*.cu ./include/array/impl/*.cpp ./include/array/*.cpp) file(GLOB_RECURSE MEMORY_SOURCES ./include/memory/impl/*.cpp ./include/memory/cuda/*.cu) file(GLOB_RECURSE CUSTOMOPS_HELPERS_SOURCES ./include/ops/declarable/helpers/cuda/*.cu ./include/ops/declarable/helpers/impl/*.cpp) file(GLOB_RECURSE HELPERS_SOURCES ./include/build_info.cpp ./include/ConstMessages.cpp ./include/helpers/*.cpp ./include/helpers/cuda/*.cu) file(GLOB_RECURSE LOOPS_SOURCES ./include/loops/impl/*.cpp) file(GLOB_RECURSE LEGACY_SOURCES ./include/legacy/impl/*.cpp ./include/legacy/*.cu) file(GLOB_RECURSE LOOPS_SOURCES_CUDA ./include/loops/*.cu ./include/loops/cuda/**/*.cu) file(GLOB_RECURSE VALIDATION_SOURCES ./include/array/DataTypeValidation.cpp) file(GLOB CPU_HELPERS_TO_EXCLUDE ./include/legacy/cpu/*.cpp ./include/helpers/cpu/*.cpp ./include/array/cpu/*.cpp) list(APPEND ALL_SOURCES_LIST ${EXEC_SOURCES} ${ARRAY_SOURCES} ${MEMORY_SOURCES} ${CUSTOMOPS_HELPERS_SOURCES} ${HELPERS_SOURCES} ${LOOPS_SOURCES} ${LEGACY_SOURCES} ${LOOPS_SOURCES_CUDA} ${VALIDATION_SOURCES} ) list(REMOVE_ITEM ALL_SOURCES_LIST ${CPU_HELPERS_TO_EXCLUDE}) if(HAVE_CUDNN) file(GLOB_RECURSE CUSTOMOPS_CUDNN_SOURCES ./include/ops/declarable/platform/cudnn/*.cu) list(APPEND ALL_SOURCES_LIST ${CUSTOMOPS_CUDNN_SOURCES}) endif() message(STATUS "🚀 CUDA build: Enhanced template system will generate additional CUDA instantiations") else() file(GLOB_RECURSE EXEC_SOURCES ./include/execution/*.cpp) file(GLOB_RECURSE ARRAY_SOURCES ./include/array/*.cpp) file(GLOB_RECURSE MEMORY_SOURCES ./include/memory/*.cpp) file(GLOB_RECURSE CUSTOMOPS_HELPERS_IMPL_SOURCES ./include/ops/declarable/helpers/impl/*.cpp) file(GLOB_RECURSE CUSTOMOPS_HELPERS_CPU_SOURCES ./include/ops/declarable/helpers/cpu/*.cpp) file(GLOB_RECURSE HELPERS_SOURCES ./include/build_info.cpp ./include/ConstMessages.cpp ./include/helpers/*.cpp ./include/helpers/cpu/*.cpp) file(GLOB_RECURSE LEGACY_SOURCES ./include/legacy/impl/*.cpp ./include/legacy/cpu/*.cpp) file(GLOB_RECURSE LOOPS_SOURCES ./include/loops/*.cpp) list(APPEND ALL_SOURCES_LIST ${EXEC_SOURCES} ${ARRAY_SOURCES} ${MEMORY_SOURCES} ${CUSTOMOPS_HELPERS_IMPL_SOURCES} ${CUSTOMOPS_HELPERS_CPU_SOURCES} ${HELPERS_SOURCES} ${LEGACY_SOURCES} ${LOOPS_SOURCES} ) if(HAVE_ONEDNN) file(GLOB_RECURSE CUSTOMOPS_ONEDNN_SOURCES ./include/ops/declarable/platform/mkldnn/*.cpp) list(APPEND ALL_SOURCES_LIST ${CUSTOMOPS_ONEDNN_SOURCES}) endif() if(HAVE_ARMCOMPUTE) file(GLOB_RECURSE CUSTOMOPS_ARMCOMPUTE_SOURCES ./include/ops/declarable/platform/armcompute/*.cpp) list(APPEND ALL_SOURCES_LIST ${CUSTOMOPS_ARMCOMPUTE_SOURCES}) endif() message(STATUS "🖥️ CPU build: Enhanced template system will generate optimized CPU instantiations") endif() # When SD_GCC_FUNCTRACE is ON, the binary exceeds 2GB and PLT relocations fail # libc_nonshared.a contains precompiled functions (like atexit) that use PLT # We provide our own implementations compiled with -fno-plt to override them if(SD_GCC_FUNCTRACE) list(APPEND ALL_SOURCES_LIST ${CMAKE_CURRENT_SOURCE_DIR}/include/platform/noplt_libc_stubs.c) message(STATUS "✅ Added no-PLT libc stubs for >2GB functrace build compatibility") endif() # ✅ Add the generated template sources (now includes both CPU and CUDA) list(APPEND ALL_SOURCES_LIST ${CUSTOMOPS_GENERIC_SOURCES}) list(REMOVE_DUPLICATES ALL_SOURCES_LIST) set(${out_source_list} ${ALL_SOURCES_LIST} PARENT_SCOPE) # Enhanced logging list(LENGTH CUSTOMOPS_GENERIC_SOURCES template_source_count) if(SD_CUDA) message(STATUS "📊 Total CUDA template-generated sources: ${template_source_count}") else() message(STATUS "📊 Total CPU template-generated sources: ${template_source_count}") endif() endfunction() function(configure_cpu_linking main_target_name) target_link_libraries(${main_target_name} PUBLIC ${ONEDNN} ${ARMCOMPUTE_LIBRARIES} ${OPENBLAS_LIBRARIES} ${BLAS_LIBRARIES} ${JVM_LIBRARY} flatbuffers_interface) # Add debug libraries when SD_GCC_FUNCTRACE is enabled if(SD_GCC_FUNCTRACE) # CRITICAL FIX (Session #1045): Do NOT link libunwind! # - We removed --unwindlib=libunwind from compile flags in CompilerFlags.cmake # - Using system libgcc_s for exception handling (JVM compatible) # - libunwind would conflict with JVM's libgcc_s causing _Unwind_SetGR crashes # Both Clang and GCC now use the same debug libraries (no libunwind) target_link_libraries(${main_target_name} PUBLIC bfd dw dl elf pthread) message(STATUS "✅ Added debug libraries for SD_GCC_FUNCTRACE (using libgcc_s for unwinding, JVM compatible)") endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") find_package(OpenMP) if(OpenMP_CXX_FOUND) target_link_libraries(${main_target_name} PUBLIC OpenMP::OpenMP_CXX) else() target_link_libraries(${main_target_name} PUBLIC "-fopenmp") endif() endif() endfunction() # UPDATED: Modern CUDA linking with improved cuDNN detection function(configure_cuda_linking main_target_name) # Find the CUDAToolkit to define the CUDA::toolkit target find_package(CUDAToolkit REQUIRED) # Setup modern cuDNN detection setup_modern_cudnn() # Modern CMake uses imported targets which handle all necessary dependencies. # Linking against CUDA::toolkit automatically adds include directories, # runtime libraries, and all other required flags. target_link_libraries(${main_target_name} PUBLIC CUDA::toolkit ${JVM_LIBRARY}) # If cuDNN was found, link against its imported target if(HAVE_CUDNN AND TARGET CUDNN::cudnn) message(STATUS "✅ Linking with modern CUDNN::cudnn target") target_link_libraries(${main_target_name} PUBLIC CUDNN::cudnn) target_compile_definitions(${main_target_name} PUBLIC HAVE_CUDNN=1) elseif(HAVE_CUDNN AND CUDNN_LIBRARIES) message(STATUS "✅ Linking with cuDNN libraries: ${CUDNN_LIBRARIES}") target_link_libraries(${main_target_name} PUBLIC ${CUDNN_LIBRARIES}) target_include_directories(${main_target_name} PUBLIC ${CUDNN_INCLUDE_DIR}) target_compile_definitions(${main_target_name} PUBLIC HAVE_CUDNN=1) elseif(HAVE_CUDNN AND CUDNN_INCLUDE_DIR) message(STATUS "✅ Linking with cuDNN include-only (embedded in CUDA)") target_include_directories(${main_target_name} PUBLIC ${CUDNN_INCLUDE_DIR}) target_compile_definitions(${main_target_name} PUBLIC HAVE_CUDNN=1) else() message(STATUS "ℹ️ Building without cuDNN support") target_compile_definitions(${main_target_name} PUBLIC HAVE_CUDNN=0) endif() target_include_directories("${main_target_name}" PUBLIC "${CUDA_INCLUDE_DIRS}") target_link_libraries(${main_target_name} PUBLIC flatbuffers_interface) endfunction() # --- Enhanced library creation function --- function(create_and_link_library) set(OBJECT_LIB_NAME "${SD_LIBRARY_NAME}_object") set(MAIN_LIB_NAME "${SD_LIBRARY_NAME}") if(NOT TARGET ${OBJECT_LIB_NAME}) add_library(${OBJECT_LIB_NAME} OBJECT ${ALL_SOURCES}) add_dependencies(${OBJECT_LIB_NAME} flatbuffers_interface) target_link_libraries(${OBJECT_LIB_NAME} PUBLIC flatbuffers_interface) # picking up incomplete flatbuffers.h from libnd4j/include/flatbuffers/ # The ExternalProject downloads full headers to flatbuffers-src/include get_target_property(FLATBUFFERS_INCLUDES flatbuffers_interface INTERFACE_INCLUDE_DIRECTORIES) if(FLATBUFFERS_INCLUDES) target_include_directories(${OBJECT_LIB_NAME} BEFORE PUBLIC ${FLATBUFFERS_INCLUDES}) endif() if(SD_CUDA) # Find the CUDA Toolkit to make the CUDA::toolkit target available. find_package(CUDAToolkit REQUIRED) # THE FIX: For OBJECT libraries, you must get the include directories from # the modern CUDA::toolkit target and apply them DIRECTLY to the object library # that is being compiled. get_target_property(CUDA_INCLUDE_DIRS CUDA::toolkit INTERFACE_INCLUDE_DIRECTORIES) target_include_directories(${OBJECT_LIB_NAME} PUBLIC ${CUDA_INCLUDE_DIRS}) # UPDATED: Add cuDNN include directories if available if(HAVE_CUDNN AND CUDNN_INCLUDE_DIR) target_include_directories(${OBJECT_LIB_NAME} PUBLIC ${CUDNN_INCLUDE_DIR}) target_compile_definitions(${OBJECT_LIB_NAME} PUBLIC HAVE_CUDNN=1) message(STATUS "🔧 Added cuDNN includes to object library: ${CUDNN_INCLUDE_DIR}") else() target_compile_definitions(${OBJECT_LIB_NAME} PUBLIC HAVE_CUDNN=0) endif() message(STATUS "🚀 CUDA object library configured with enhanced template support") endif() target_include_directories(${OBJECT_LIB_NAME} PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/include/array" "${CMAKE_CURRENT_SOURCE_DIR}/include/execution" "${CMAKE_CURRENT_SOURCE_DIR}/include/exceptions" "${CMAKE_CURRENT_SOURCE_DIR}/include/graph" "${CMAKE_CURRENT_SOURCE_DIR}/include/helpers" "${CMAKE_CURRENT_SOURCE_DIR}/include/loops" "${CMAKE_CURRENT_SOURCE_DIR}/include/memory" "${CMAKE_CURRENT_SOURCE_DIR}/include/ops" "${CMAKE_CURRENT_SOURCE_DIR}/include/types" "${CMAKE_CURRENT_SOURCE_DIR}/include/system" "${CMAKE_CURRENT_SOURCE_DIR}/include/legacy" "${CMAKE_CURRENT_SOURCE_DIR}/include/performance" "${CMAKE_CURRENT_SOURCE_DIR}/include/indexing" "${CMAKE_CURRENT_SOURCE_DIR}/include/generated" "${CMAKE_BINARY_DIR}/compilation_units" "${CMAKE_BINARY_DIR}/cpu_instantiations" ) if(SD_CUDA) target_include_directories(${OBJECT_LIB_NAME} PUBLIC "${CMAKE_BINARY_DIR}/cuda_instantiations" ) else() target_include_directories(${OBJECT_LIB_NAME} PUBLIC "${OPENBLAS_PATH}/include" "${CMAKE_BINARY_DIR}/cpu_instantiations" ) endif () if(SD_CUDA AND DEFINED CMAKE_CUDA_ARCHITECTURES AND CMAKE_CUDA_ARCHITECTURES) set_target_properties(${OBJECT_LIB_NAME} PROPERTIES CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES}") endif() message(STATUS "🔧 Applying type definitions to OBJECT library: ${OBJECT_LIB_NAME}") setup_type_definitions_for_target(${OBJECT_LIB_NAME}) # Enable precompiled headers for large commonly-included headers # This significantly speeds up incremental builds when these headers change # PERMANENTLY DISABLED: Causes cache staleness issues when SD_GCC_FUNCTRACE changes # The CMake cache can hold stale values causing build failures if(FALSE) # Disabled to prevent cache staleness issues message(STATUS "🚀 Enabling precompiled headers for ${OBJECT_LIB_NAME}") target_precompile_headers(${OBJECT_LIB_NAME} PRIVATE ) message(STATUS "✅ Precompiled headers enabled for op_boilerplate.h and type_boilerplate.h") elseif(SD_GCC_FUNCTRACE) message(STATUS "⚠️ Precompiled headers DISABLED (prevents CMake cache staleness issues)") else() message(STATUS "⚠️ Precompiled headers DISABLED (prevents CMake cache staleness issues)") endif() endif() if(NOT TARGET ${MAIN_LIB_NAME}) add_library(${MAIN_LIB_NAME} SHARED $) set_target_properties(${MAIN_LIB_NAME} PROPERTIES OUTPUT_NAME ${MAIN_LIB_NAME}) # Code model configuration is now centralized in CompilerFlags.cmake to avoid conflicts # (CMAKE_SHARED_LINKER_FLAGS is set there with -mcmodel=large for sanitizer builds) # Removed: target_link_options setting to prevent duplicate -mcmodel flags in link command # if(SD_X86_BUILD AND NOT WIN32 AND DEFINED SD_SANITIZERS AND NOT SD_SANITIZERS STREQUAL "") # target_link_options(${MAIN_LIB_NAME} PRIVATE "-mcmodel=large") # message(STATUS "Applied -mcmodel=large to linker for ${MAIN_LIB_NAME}") # endif() message(STATUS "Code model configuration deferred to CompilerFlags.cmake (via CMAKE_SHARED_LINKER_FLAGS)") # No CUDA includes needed here, they are handled by the linking function target_include_directories(${MAIN_LIB_NAME} PUBLIC "${OPENBLAS_PATH}/include" "${CMAKE_CURRENT_SOURCE_DIR}/include/blas" "${CMAKE_CURRENT_BINARY_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/include/array" "${CMAKE_CURRENT_SOURCE_DIR}/include/execution" "${CMAKE_CURRENT_SOURCE_DIR}/include/exceptions" "${CMAKE_CURRENT_SOURCE_DIR}/include/graph" "${CMAKE_CURRENT_SOURCE_DIR}/include/helpers" "${CMAKE_CURRENT_SOURCE_DIR}/include/loops" "${CMAKE_CURRENT_SOURCE_DIR}/include/memory" "${CMAKE_CURRENT_SOURCE_DIR}/include/ops" "${CMAKE_CURRENT_SOURCE_DIR}/include/types" "${CMAKE_CURRENT_SOURCE_DIR}/include/system" "${CMAKE_CURRENT_SOURCE_DIR}/include/legacy" "${CMAKE_CURRENT_SOURCE_DIR}/include/performance" "${CMAKE_CURRENT_SOURCE_DIR}/include/indexing" "${CMAKE_CURRENT_SOURCE_DIR}/include/generated" "${CMAKE_BINARY_DIR}/compilation_units" "${CMAKE_BINARY_DIR}/cpu_instantiations" "${CMAKE_BINARY_DIR}/cuda_instantiations") if(SD_CUDA) target_include_directories(${MAIN_LIB_NAME} PUBLIC "${CMAKE_BINARY_DIR}/cuda_instantiations" ) else() target_include_directories(${MAIN_LIB_NAME} PUBLIC "${OPENBLAS_PATH}/include" "${CMAKE_BINARY_DIR}/cpu_instantiations" ) endif () # 🔧 ALSO apply type definitions to the shared library (for completeness) message(STATUS "🔧 Applying type definitions to SHARED library: ${MAIN_LIB_NAME}") setup_type_definitions_for_target(${MAIN_LIB_NAME}) endif() # Remove the old call since we're now applying to both targets explicitly # apply_libnd4j_type_definitions_auto() if(SD_CUDA) configure_cuda_linking(${MAIN_LIB_NAME}) else() configure_cpu_linking(${MAIN_LIB_NAME}) endif() endfunction() # ============================================================================= # SECTION 2: MAIN BUILD ORCHESTRATION WITH ENHANCED CUDA/CPU TEMPLATE SUPPORT # The main, sequential build process starts here. # ============================================================================= print_status_colored("INFO" "=== ORCHESTRATING ENHANCED LIBND4J BUILD WITH TEMPLATE PARITY ===") # --- Phase 1: Initial Setup --- print_status_colored("INFO" "=== 1. INITIALIZING BUILD CONFIGURATION ===") function(setup_initial_configuration) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) message(FATAL_ERROR "❌ You need at least GCC 4.9") endif() set(CMAKE_CXX_STANDARD 17) set(CMAKE_CUDA_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(MSVC) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") endif() message(STATUS "🔧 Configuring Position Independent Code (PIC)...") set(CMAKE_POSITION_INDEPENDENT_CODE ON) message(STATUS "✅ Position Independent Code configuration complete") endfunction() setup_initial_configuration() include(Dependencies) setup_flatbuffers() # --- Set library name and default engine first --- if(NOT DEFINED SD_LIBRARY_NAME) if(SD_CUDA) set(SD_LIBRARY_NAME nd4jcuda) set(DEFAULT_ENGINE "samediff::ENGINE_CUDA") add_compile_definitions(DEFAULT_ENGINE=samediff::ENGINE_CUDA) print_status_colored("INFO" "🚀 CUDA build mode: Enhanced template system will provide full CPU/CUDA parity") else() set(SD_LIBRARY_NAME nd4jcpu) set(DEFAULT_ENGINE "samediff::ENGINE_CPU") add_compile_definitions(DEFAULT_ENGINE=samediff::ENGINE_CPU) print_status_colored("INFO" "🖥️ CPU build mode: Enhanced template system active") endif() endif() # ============================================================================= # MINIMAL TYPE VALIDATION INTEGRATION - ONLY WHAT'S NEEDED # ============================================================================= print_status_colored("INFO" "=== INTEGRATING TYPE VALIDATION ===") # Call the type validation setup LIBND4J_SETUP_TYPE_VALIDATION() print_status_colored("SUCCESS" "Type validation integration complete") # ============================================================================= if(SD_CUDA) print_status_colored("INFO" "=== CUDA EARLY INITIALIZATION WITH TEMPLATE SUPPORT ===") include(CudaConfiguration) setup_cuda_build() print_status_colored("SUCCESS" "CUDA initialization complete with enhanced template support") endif() # --- Phase 2: Handle Dependencies & Operations --- print_status_colored("INFO" "=== 2. INITIALIZING DEPENDENCIES & OPERATIONS ===") include(DuplicateInstantiationDetection) include(TemplateProcessing) include(CompilerFlags) setup_platform_optimizations() setup_onednn() setup_armcompute() # UPDATED: Modern cuDNN setup if(SD_CUDA) include(CudaConfiguration) setup_modern_cudnn() # Use the modern cuDNN detection message(STATUS "🔧 Modern cuDNN configuration: HAVE_CUDNN=${HAVE_CUDNN}") if(HAVE_CUDNN) message(STATUS "✅ cuDNN found and configured") if(DEFINED CUDNN_VERSION_STRING) message(STATUS " cuDNN version: ${CUDNN_VERSION_STRING}") endif() else() message(STATUS "ℹ️ Building without cuDNN support") endif() else() # For CPU builds, set HAVE_CUDNN to false set(HAVE_CUDNN FALSE) endif() setup_blas() setup_blas() message(STATUS "🔍 DEBUG: After setup_blas() - OPENBLAS_PATH='${OPENBLAS_PATH}', HAVE_OPENBLAS='${HAVE_OPENBLAS}'") message(STATUS "Dependencies initialization complete.") message(STATUS "Dependencies initialization complete.") message(STATUS "🔧 Helper Configuration: ONEDNN=${HAVE_ONEDNN}, ARMCOMPUTE=${HAVE_ARMCOMPUTE}, CUDNN=${HAVE_CUDNN}") # --- Build TYPE_DEFINES string before generating config.h --- # This ensures config.h has all HAS_* macros defined from the start set(TYPE_DEFINES "") # Check if we're in selective types mode if(DEFINED SD_TYPES_LIST AND NOT SD_TYPES_LIST STREQUAL "") # Selective types mode - export only enabled types # The HAS_* macros were already set by apply_type_definitions_to_target # We need to capture them and add to TYPE_DEFINES # Get all HAS_* definitions that were set get_directory_property(COMPILE_DEFS COMPILE_DEFINITIONS) # Sort definitions to ensure deterministic order # This prevents config.h from changing during build-time CMake reconfiguration set(HAS_DEFS_LIST "") foreach(def IN LISTS COMPILE_DEFS) if(def MATCHES "^HAS_") list(APPEND HAS_DEFS_LIST "${def}") endif() endforeach() # Sort alphabetically for consistent output list(SORT HAS_DEFS_LIST) # Build TYPE_DEFINES string with sorted definitions foreach(def IN LISTS HAS_DEFS_LIST) string(APPEND TYPE_DEFINES "#define ${def}\n") endforeach() else() # All types mode - define all HAS_* macros string(APPEND TYPE_DEFINES "#define HAS_BOOL 1\n") string(APPEND TYPE_DEFINES "#define HAS_FLOAT 1\n") string(APPEND TYPE_DEFINES "#define HAS_FLOAT32 1\n") string(APPEND TYPE_DEFINES "#define HAS_DOUBLE 1\n") string(APPEND TYPE_DEFINES "#define HAS_FLOAT64 1\n") string(APPEND TYPE_DEFINES "#define HAS_FLOAT16 1\n") string(APPEND TYPE_DEFINES "#define HAS_HALF 1\n") string(APPEND TYPE_DEFINES "#define HAS_BFLOAT16 1\n") string(APPEND TYPE_DEFINES "#define HAS_BFLOAT 1\n") string(APPEND TYPE_DEFINES "#define HAS_FLOAT8 1\n") string(APPEND TYPE_DEFINES "#define HAS_HALF2 1\n") string(APPEND TYPE_DEFINES "#define HAS_INT8 1\n") string(APPEND TYPE_DEFINES "#define HAS_INT8_T 1\n") string(APPEND TYPE_DEFINES "#define HAS_INT16 1\n") string(APPEND TYPE_DEFINES "#define HAS_INT16_T 1\n") string(APPEND TYPE_DEFINES "#define HAS_INT32 1\n") string(APPEND TYPE_DEFINES "#define HAS_INT32_T 1\n") string(APPEND TYPE_DEFINES "#define HAS_INT 1\n") string(APPEND TYPE_DEFINES "#define HAS_INT64 1\n") string(APPEND TYPE_DEFINES "#define HAS_INT64_T 1\n") string(APPEND TYPE_DEFINES "#define HAS_LONG 1\n") string(APPEND TYPE_DEFINES "#define HAS_UINT8 1\n") string(APPEND TYPE_DEFINES "#define HAS_UINT8_T 1\n") string(APPEND TYPE_DEFINES "#define HAS_UINT16 1\n") string(APPEND TYPE_DEFINES "#define HAS_UINT16_T 1\n") string(APPEND TYPE_DEFINES "#define HAS_UINT32 1\n") string(APPEND TYPE_DEFINES "#define HAS_UINT32_T 1\n") string(APPEND TYPE_DEFINES "#define HAS_UINT64 1\n") string(APPEND TYPE_DEFINES "#define HAS_UINT64_T 1\n") string(APPEND TYPE_DEFINES "#define HAS_UNSIGNEDLONG 1\n") string(APPEND TYPE_DEFINES "#define HAS_UTF8 1\n") string(APPEND TYPE_DEFINES "#define HAS_STD_STRING 1\n") string(APPEND TYPE_DEFINES "#define HAS_UTF16 1\n") string(APPEND TYPE_DEFINES "#define HAS_STD_U16STRING 1\n") string(APPEND TYPE_DEFINES "#define HAS_UTF32 1\n") string(APPEND TYPE_DEFINES "#define HAS_STD_U32STRING 1\n") endif() # --- Generate config.h AFTER setting all variables including TYPE_DEFINES --- configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/include/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/config.h") set(DEFINITIONS_CONTENT "") if(SD_ALL_OPS OR "${SD_OPS_LIST}" STREQUAL "") add_compile_definitions(SD_ALL_OPS=1) string(APPEND DEFINITIONS_CONTENT "#define SD_ALL_OPS 1\n") else() foreach(OP ${SD_OPS_LIST}) add_compile_definitions(OP_${OP}=1) string(APPEND DEFINITIONS_CONTENT "#define OP_${OP} 1\n") endforeach() endif() file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/generated") set(INCLUDE_OPS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/include/generated/include_ops.h") file(WRITE "${INCLUDE_OPS_FILE}" "#ifndef SD_DEFINITIONS_GEN_H_\n#define SD_DEFINITIONS_GEN_H_\n${DEFINITIONS_CONTENT}\n#endif\n") # --- Phase 3: Enhanced Selective Rendering Setup --- print_status_colored("INFO" "=== 3. CONFIGURING ENHANCED SELECTIVE RENDERING ===") include(SelectiveRenderingCore) setup_selective_rendering_unified_safe( TYPE_PROFILE "${SD_TYPE_PROFILE}" OUTPUT_DIR "${CMAKE_BINARY_DIR}/include") if(NOT DEFINED UNIFIED_COMBINATIONS_3 OR NOT UNIFIED_COMBINATIONS_3) message(FATAL_ERROR "❌ CRITICAL: Unified selective rendering setup failed!") endif() list(LENGTH UNIFIED_ACTIVE_TYPES type_count) list(LENGTH UNIFIED_COMBINATIONS_3 combo_3_count) if(SD_CUDA) message(STATUS "✅ Enhanced CUDA selective rendering setup complete: ${type_count} types, ${combo_3_count} combinations.") else() message(STATUS "✅ Enhanced CPU selective rendering setup complete: ${type_count} types, ${combo_3_count} combinations.") endif() if(DEFINED HAS_FLOAT16 AND HAS_FLOAT16) list(FIND UNIFIED_ACTIVE_TYPES "float16" float16_pos) if(float16_pos LESS 0) message(FATAL_ERROR "❌ CRITICAL: float16 missing despite HAS_FLOAT16=TRUE! This will cause build errors.") else() message(STATUS "✅ VERIFIED: float16 present at position ${float16_pos}") endif() endif() # --- Phase 4: Create and Link Final Library with Enhanced Template System --- print_status_colored("INFO" "=== 4. CREATING AND LINKING FINAL LIBRARY WITH ENHANCED TEMPLATES ===") # ✅ DO NOT reset CUSTOMOPS_GENERIC_SOURCES - it's a CACHE variable populated by TemplateProcessing.cmake # Resetting it here causes the cached template files to be lost, resulting in build errors collect_all_sources(ALL_SOURCES) create_and_link_library() message(STATUS "Final library target created and linked with enhanced template support.") # --- Phase 5: Enhanced Final Reports and Summaries --- if(DEFINED SD_GENERATE_TYPE_REPORT AND SD_GENERATE_TYPE_REPORT) print_status_colored("INFO" "=== GENERATING ENHANCED USAGE DOCUMENTATION ===") set(usage_doc "${CMAKE_BINARY_DIR}/enhanced_selective_rendering_usage.md") set(doc_content "# Enhanced Unified Selective Rendering Usage\n\nThis build was configured with the enhanced unified selective rendering system providing full CPU/CUDA parity.\n\n") if(DEFINED SD_TYPE_PROFILE) string(APPEND doc_content "**Type Profile**: ${SD_TYPE_PROFILE}\n\n") endif() if(SD_CUDA) string(APPEND doc_content "**Build Mode**: CUDA with enhanced template system\n") string(APPEND doc_content "**Template Parity**: Full parity achieved between CPU and CUDA template systems\n\n") if(HAVE_CUDNN) string(APPEND doc_content "**cuDNN Support**: Enabled\n") if(DEFINED CUDNN_VERSION_STRING) string(APPEND doc_content "**cuDNN Version**: ${CUDNN_VERSION_STRING}\n") endif() else() string(APPEND doc_content "**cuDNN Support**: Disabled\n") endif() else() string(APPEND doc_content "**Build Mode**: CPU with enhanced template system\n\n") endif() file(WRITE "${usage_doc}" "${doc_content}") message(STATUS "📝 Enhanced usage documentation written to: ${usage_doc}") endif() print_status_colored("SUCCESS" "=== ENHANCED BUILD ORCHESTRATION COMPLETE ===") message(STATUS "") message(STATUS "🎯 ENHANCED BUILD SUMMARY:") message(STATUS " Library: ${SD_LIBRARY_NAME}") message(STATUS " Platform: ${CMAKE_SYSTEM_NAME}") if(SD_CUDA) message(STATUS " CUDA: Enabled with enhanced template parity") message(STATUS " Template System: CUDA templates achieve full CPU parity") message(STATUS " cuDNN: ${HAVE_CUDNN}") if(HAVE_CUDNN AND DEFINED CUDNN_VERSION_STRING) message(STATUS " cuDNN Version: ${CUDNN_VERSION_STRING}") endif() else() message(STATUS " CUDA: Disabled") message(STATUS " Template System: Enhanced CPU templates") endif() if(DEFINED SD_TYPE_PROFILE) message(STATUS " Type Profile: ${SD_TYPE_PROFILE}") endif() if(DEFINED type_count) message(STATUS " Active Types: ${type_count}") endif() if(DEFINED combo_3_count) message(STATUS " Template Combinations: ${combo_3_count}") endif() include(TypeRegistryGenerator) dump_type_macros_to_disk() if(SD_CUDA) message(STATUS "🚀 Enhanced CUDA build orchestration complete - CUDA/CPU template parity achieved") else() message(STATUS "🖥️ Enhanced CPU build orchestration complete - System ready for compilation") endif() message(STATUS "") # === ENHANCED TEMPLATE SYSTEM VERIFICATION === print_status_colored("INFO" "=== VERIFYING ENHANCED TEMPLATE SYSTEM ===") # Verify template generation worked list(LENGTH CUSTOMOPS_GENERIC_SOURCES template_file_count) if(template_file_count GREATER 0) if(SD_CUDA) message(STATUS "✅ CUDA template generation verified: ${template_file_count} files") # Check for CUDA-specific template files set(cuda_template_count 0) foreach(source_file ${CUSTOMOPS_GENERIC_SOURCES}) if(source_file MATCHES "\\.cu$") math(EXPR cuda_template_count "${cuda_template_count} + 1") endif() endforeach() message(STATUS "🔍 CUDA template files: ${cuda_template_count}") if(cuda_template_count GREATER 0) print_status_colored("SUCCESS" "CUDA template parity system operational") else() print_status_colored("WARNING" "No CUDA template files detected - check template processing") endif() else() message(STATUS "✅ CPU template generation verified: ${template_file_count} files") print_status_colored("SUCCESS" "Enhanced CPU template system operational") endif() endif() # Final verification of directory structure if(SD_CUDA) if(EXISTS "${CMAKE_BINARY_DIR}/cuda_instantiations") message(STATUS "✅ CUDA instantiation directory verified") else() message(WARNING "⚠️ CUDA instantiation directory not found") endif() else() if(EXISTS "${CMAKE_BINARY_DIR}/cpu_instantiations") message(STATUS "✅ CPU instantiation directory verified") else() message(WARNING "⚠️ CPU instantiation directory not found") endif() endif() # Set OBJECT_LIB_NAME for PostBuild.cmake (matches pattern from create_and_link_library function) if(NOT DEFINED OBJECT_LIB_NAME AND DEFINED SD_LIBRARY_NAME) set(OBJECT_LIB_NAME "${SD_LIBRARY_NAME}_object") message(STATUS "Set OBJECT_LIB_NAME for PostBuild: ${OBJECT_LIB_NAME}") endif() # Check for instantiation extraction BEFORE PostBuild if(SD_EXTRACT_INSTANTIATIONS) print_status_colored("INFO" "=== TEMPLATE INSTANTIATION EXTRACTION MODE ===") include(ExtractInstantiations) # ExtractInstantiations.cmake will handle everything and exit return() endif() # Precompiled headers PERMANENTLY DISABLED to prevent CMake cache staleness issues # When SD_GCC_FUNCTRACE or other flags change, stale cache can cause build failures if(FALSE) # Disabled to prevent cache staleness issues target_precompile_headers(${SD_LIBRARY_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/system/op_boilerplate.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/system/type_boilerplate.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/system/type_boiler_plate_expansioons.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/array/DataType.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/array/NDArray.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/array/NDArray.hXX" "${CMAKE_CURRENT_SOURCE_DIR}/include/types/types.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/math/platformmath.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/math/templatemath.h" ) message(STATUS "✅ Precompiled headers enabled for main library") else() message(STATUS "⚠️ Precompiled headers DISABLED (prevents CMake cache staleness issues)") endif() include(PostBuild) print_status_colored("SUCCESS" "=== ENHANCED TEMPLATE SYSTEM VERIFICATION COMPLETE ===")