Files
2026-07-13 12:47:05 +08:00

853 lines
38 KiB
CMake
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# 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
<system/op_boilerplate.h>
<system/type_boilerplate.h>
)
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 $<TARGET_OBJECTS:${OBJECT_LIB_NAME}>)
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$<$<CONFIG:Debug>: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
<vector>
<memory>
<algorithm>
<functional>
<cstring>
"${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 ===")