chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
# cmake/BuildCPU.cmake
|
||||
# Contains all logic for building the CPU library.
|
||||
|
||||
add_definitions(-D__CPUBLAS__=true)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
|
||||
|
||||
# --- Source File Collection ---
|
||||
file(GLOB_RECURSE BLAS_SOURCES ./include/blas/*.h )
|
||||
file(GLOB_RECURSE PERF_SOURCES ./include/performance/*.cpp ./include/performance/*.h)
|
||||
file(GLOB_RECURSE EXCEPTIONS_SOURCES ./include/exceptions/*.cpp ./include/exceptions/*.h)
|
||||
file(GLOB_RECURSE EXEC_SOURCES ./include/execution/*.cpp ./include/execution/*.h)
|
||||
file(GLOB_RECURSE TYPES_SOURCES ./include/types/*.cpp ./include/types/*.h)
|
||||
file(GLOB_RECURSE ARRAY_SOURCES ./include/array/*.cpp ./include/array/*.h)
|
||||
file(GLOB_RECURSE MEMORY_SOURCES ./include/memory/*.cpp ./include/memory/*.h)
|
||||
file(GLOB_RECURSE GRAPH_SOURCES ./include/graph/*.cpp ./include/graph/*.h)
|
||||
file(GLOB_RECURSE CUSTOMOPS_SOURCES ./include/ops/declarable/generic/*.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 OPS_SOURCES ./include/ops/impl/*.cpp ./include/ops/declarable/impl/*.cpp ./include/ops/*.h)
|
||||
file(GLOB_RECURSE INDEXING_SOURCES ./include/indexing/*.cpp ./include/indexing/*.h)
|
||||
file(GLOB_RECURSE HELPERS_SOURCES ./include/build_info.cpp ./include/ConstMessages.cpp ./include/helpers/*.cpp ./include/helpers/cpu/*.cpp ./include/helpers/*.h)
|
||||
file(GLOB_RECURSE LEGACY_SOURCES ./include/legacy/impl/*.cpp ./include/legacy/cpu/*.cpp ./include/legacy/*.h)
|
||||
file(GLOB_RECURSE LOOPS_SOURCES ./include/loops/*.cpp ./include/loops/*.h)
|
||||
|
||||
set(ALL_SOURCES "")
|
||||
set(STATIC_SOURCES_TO_CHECK ${BLAS_SOURCES} ${PERF_SOURCES} ${EXCEPTIONS_SOURCES} ${EXEC_SOURCES} ${TYPES_SOURCES} ${ARRAY_SOURCES} ${MEMORY_SOURCES} ${GRAPH_SOURCES} ${CUSTOMOPS_SOURCES} ${CUSTOMOPS_HELPERS_IMPL_SOURCES} ${CUSTOMOPS_HELPERS_CPU_SOURCES} ${OPS_SOURCES} ${INDEXING_SOURCES} ${HELPERS_SOURCES} ${LEGACY_SOURCES} ${LOOPS_SOURCES})
|
||||
|
||||
# Add PLT wrapper functions for functrace builds (GCC and Clang)
|
||||
# Required for --wrap=atexit and --wrap=at_quick_exit linker flags
|
||||
# These wrappers avoid PLT relocations in >2GB binaries
|
||||
if(SD_GCC_FUNCTRACE)
|
||||
list(APPEND STATIC_SOURCES_TO_CHECK ./include/platform/noplt_libc_stubs.c)
|
||||
message(STATUS "✅ Added noplt_libc_stubs.c for functrace build (provides __wrap_atexit and __wrap_at_quick_exit)")
|
||||
endif()
|
||||
|
||||
if(HAVE_ONEDNN)
|
||||
file(GLOB_RECURSE CUSTOMOPS_ONEDNN_SOURCES ./include/ops/declarable/platform/mkldnn/*.cpp ./include/ops/declarable/platform/mkldnn/mkldnnUtils.h)
|
||||
list(APPEND STATIC_SOURCES_TO_CHECK ${CUSTOMOPS_ONEDNN_SOURCES})
|
||||
endif()
|
||||
if(HAVE_ARMCOMPUTE)
|
||||
file(GLOB_RECURSE CUSTOMOPS_ARMCOMPUTE_SOURCES ./include/ops/declarable/platform/armcompute/*.cpp ./include/ops/declarable/platform/armcompute/*.h)
|
||||
list(APPEND STATIC_SOURCES_TO_CHECK ${CUSTOMOPS_ARMCOMPUTE_SOURCES})
|
||||
endif()
|
||||
|
||||
list(APPEND ALL_SOURCES ${STATIC_SOURCES_TO_CHECK})
|
||||
list(REMOVE_DUPLICATES ALL_SOURCES)
|
||||
|
||||
# --- Generate CPU Template Instantiations ---
|
||||
file(GLOB_RECURSE COMPILATION_UNITS
|
||||
./include/ops/impl/compilation_units/*.cpp.in
|
||||
./include/ops/declarable/helpers/cpu/compilation_units/*.cpp.in
|
||||
./include/loops/cpu/compilation_units/*.cpp.in
|
||||
./include/helpers/cpu/loops/*.cpp.in)
|
||||
|
||||
foreach(FL_ITEM ${COMPILATION_UNITS})
|
||||
genCompilation(${FL_ITEM})
|
||||
endforeach()
|
||||
|
||||
# --- Build Library ---
|
||||
set(OBJECT_LIB_NAME "${SD_LIBRARY_NAME}_object")
|
||||
add_library(${OBJECT_LIB_NAME} OBJECT ${ALL_SOURCES})
|
||||
add_dependencies(${OBJECT_LIB_NAME} flatbuffers_interface)
|
||||
target_include_directories(${OBJECT_LIB_NAME} PUBLIC ${EXTERNAL_INCLUDE_DIRS})
|
||||
set_property(TARGET ${OBJECT_LIB_NAME} PROPERTY MSVC_RUNTIME_LIBRARY "${MSVC_RT_LIB}$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
add_library(${SD_LIBRARY_NAME} SHARED $<TARGET_OBJECTS:${OBJECT_LIB_NAME}>)
|
||||
set_target_properties(${SD_LIBRARY_NAME} PROPERTIES OUTPUT_NAME ${SD_LIBRARY_NAME})
|
||||
set_property(TARGET ${SD_LIBRARY_NAME} PROPERTY MSVC_RUNTIME_LIBRARY "${MSVC_RT_LIB}$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
# --- Link Dependencies ---
|
||||
target_link_libraries(${SD_LIBRARY_NAME} PUBLIC
|
||||
${ONEDNN}
|
||||
${ARMCOMPUTE_LIBRARIES}
|
||||
${OPENBLAS_LIBRARIES}
|
||||
${BLAS_LIBRARIES}
|
||||
${JVM_LIBRARY}
|
||||
flatbuffers_interface
|
||||
)
|
||||
|
||||
# --- OpenMP Configuration ---
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
find_package(OpenMP)
|
||||
if(OpenMP_CXX_FOUND)
|
||||
message(STATUS "OpenMP found, linking OpenMP::OpenMP_CXX")
|
||||
target_link_libraries(${SD_LIBRARY_NAME} PUBLIC OpenMP::OpenMP_CXX)
|
||||
else()
|
||||
message(WARNING "OpenMP not found, falling back to manual configuration")
|
||||
target_compile_options(${SD_LIBRARY_NAME} INTERFACE "-fopenmp")
|
||||
target_link_libraries(${SD_LIBRARY_NAME} PUBLIC "-fopenmp")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
# CombinationCaching.cmake
|
||||
# Smart type combination reuse and caching system
|
||||
|
||||
# Main function to handle combination reuse
|
||||
function(use_cached_type_combinations)
|
||||
# Check if combinations already exist in memory
|
||||
if(DEFINED COMBINATIONS_2 AND DEFINED COMBINATIONS_3)
|
||||
list(LENGTH COMBINATIONS_2 combo2_count)
|
||||
list(LENGTH COMBINATIONS_3 combo3_count)
|
||||
if(combo2_count GREATER 0 AND combo3_count GREATER 0)
|
||||
message(STATUS "♻️ Reusing existing combinations: 2-type=${combo2_count}, 3-type=${combo3_count}")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for cached combinations file
|
||||
set(COMBO_CACHE_FILE "${CMAKE_BINARY_DIR}/type_combinations.cache")
|
||||
if(EXISTS "${COMBO_CACHE_FILE}")
|
||||
message(STATUS "📁 Loading combinations from cache file...")
|
||||
include("${COMBO_CACHE_FILE}")
|
||||
|
||||
# Verify cache loaded successfully
|
||||
if(DEFINED COMBINATIONS_2 AND DEFINED COMBINATIONS_3)
|
||||
list(LENGTH COMBINATIONS_2 combo2_count)
|
||||
list(LENGTH COMBINATIONS_3 combo3_count)
|
||||
message(STATUS "✅ Loaded from cache: 2-type=${combo2_count}, 3-type=${combo3_count}")
|
||||
return()
|
||||
else()
|
||||
message(STATUS "⚠️ Cache file corrupted, regenerating...")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Only generate if we absolutely have to
|
||||
message(STATUS "🔄 Generating type combinations (first time only)...")
|
||||
|
||||
# Ensure type system is initialized
|
||||
if(NOT DEFINED SD_COMMON_TYPES_COUNT OR SD_COMMON_TYPES_COUNT EQUAL 0)
|
||||
validate_and_process_types_failfast()
|
||||
build_indexed_type_lists()
|
||||
endif()
|
||||
|
||||
initialize_dynamic_combinations()
|
||||
|
||||
# Verify combinations were created
|
||||
if(DEFINED COMBINATIONS_2 AND DEFINED COMBINATIONS_3)
|
||||
list(LENGTH COMBINATIONS_2 combo2_count)
|
||||
list(LENGTH COMBINATIONS_3 combo3_count)
|
||||
message(STATUS "✅ Generated combinations: 2-type=${combo2_count}, 3-type=${combo3_count}")
|
||||
|
||||
# Cache for future use
|
||||
save_combinations_to_cache("${COMBO_CACHE_FILE}")
|
||||
else()
|
||||
message(FATAL_ERROR "❌ Failed to generate type combinations!")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Save combinations to cache file
|
||||
function(save_combinations_to_cache cache_file)
|
||||
message(STATUS "💾 Saving combinations to cache...")
|
||||
|
||||
set(cache_content "# Generated type combinations cache\n")
|
||||
string(APPEND cache_content "# Generated on: ${CMAKE_CURRENT_TIMESTAMP}\n\n")
|
||||
|
||||
# Save 2-type combinations
|
||||
string(APPEND cache_content "set(COMBINATIONS_2 \"")
|
||||
foreach(combo ${COMBINATIONS_2})
|
||||
string(APPEND cache_content "${combo};")
|
||||
endforeach()
|
||||
string(APPEND cache_content "\" CACHE INTERNAL \"2-type combinations\")\n\n")
|
||||
|
||||
# Save 3-type combinations
|
||||
string(APPEND cache_content "set(COMBINATIONS_3 \"")
|
||||
foreach(combo ${COMBINATIONS_3})
|
||||
string(APPEND cache_content "${combo};")
|
||||
endforeach()
|
||||
string(APPEND cache_content "\" CACHE INTERNAL \"3-type combinations\")\n\n")
|
||||
|
||||
# Save metadata
|
||||
string(APPEND cache_content "set(COMBINATIONS_CACHE_TIMESTAMP \"${CMAKE_CURRENT_TIMESTAMP}\" CACHE INTERNAL \"Cache timestamp\")\n")
|
||||
string(APPEND cache_content "set(COMBINATIONS_CACHE_VALID TRUE CACHE INTERNAL \"Cache validity flag\")\n")
|
||||
|
||||
file(WRITE "${cache_file}" "${cache_content}")
|
||||
message(STATUS "💾 Combinations cached to: ${cache_file}")
|
||||
endfunction()
|
||||
|
||||
# Generate reusable combination strings once
|
||||
function(generate_combination_strings_once)
|
||||
if(DEFINED GLOBAL_COMB2_STRING AND DEFINED GLOBAL_COMB3_STRING)
|
||||
message(STATUS "♻️ Reusing existing combination strings")
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "🔧 Generating combination strings...")
|
||||
|
||||
# Generate 2-type combination string
|
||||
set(COMB2_STRING "")
|
||||
foreach(combination ${COMBINATIONS_2})
|
||||
string(REPLACE "," ";" combo_parts "${combination}")
|
||||
list(GET combo_parts 0 t1)
|
||||
list(GET combo_parts 1 t2)
|
||||
string(APPEND COMB2_STRING "INSTANTIATE_2(${t1}, ${t2})")
|
||||
endforeach()
|
||||
|
||||
# Generate 3-type combination string
|
||||
set(COMB3_STRING "")
|
||||
foreach(combination ${COMBINATIONS_3})
|
||||
string(REPLACE "," ";" combo_parts "${combination}")
|
||||
list(GET combo_parts 0 t1)
|
||||
list(GET combo_parts 1 t2)
|
||||
list(GET combo_parts 2 t3)
|
||||
string(APPEND COMB3_STRING "INSTANTIATE_3(${t1}, ${t2}, ${t3}); ")
|
||||
endforeach()
|
||||
|
||||
# Cache globally for reuse
|
||||
set(GLOBAL_COMB2_STRING "${COMB2_STRING}" CACHE INTERNAL "Global 2-type combination string")
|
||||
set(GLOBAL_COMB3_STRING "${COMB3_STRING}" CACHE INTERNAL "Global 3-type combination string")
|
||||
|
||||
list(LENGTH COMBINATIONS_2 combo2_count)
|
||||
list(LENGTH COMBINATIONS_3 combo3_count)
|
||||
message(STATUS "✅ Generated strings: 2-type=${combo2_count} instantiations, 3-type=${combo3_count} instantiations")
|
||||
endfunction()
|
||||
|
||||
# Clear cache if needed (for development)
|
||||
function(clear_combination_cache)
|
||||
set(COMBO_CACHE_FILE "${CMAKE_BINARY_DIR}/type_combinations.cache")
|
||||
if(EXISTS "${COMBO_CACHE_FILE}")
|
||||
file(REMOVE "${COMBO_CACHE_FILE}")
|
||||
message(STATUS "🗑️ Cleared combination cache")
|
||||
endif()
|
||||
|
||||
# Clear memory cache
|
||||
unset(COMBINATIONS_2 CACHE)
|
||||
unset(COMBINATIONS_3 CACHE)
|
||||
unset(GLOBAL_COMB2_STRING CACHE)
|
||||
unset(GLOBAL_COMB3_STRING CACHE)
|
||||
unset(COMBINATIONS_CACHE_VALID CACHE)
|
||||
endfunction()
|
||||
|
||||
# Validate cache integrity
|
||||
function(validate_combination_cache)
|
||||
if(NOT DEFINED COMBINATIONS_CACHE_VALID OR NOT COMBINATIONS_CACHE_VALID)
|
||||
message(STATUS "⚠️ Combination cache is invalid, will regenerate")
|
||||
clear_combination_cache()
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Check if combinations are reasonable
|
||||
if(DEFINED COMBINATIONS_2 AND DEFINED COMBINATIONS_3)
|
||||
list(LENGTH COMBINATIONS_2 combo2_count)
|
||||
list(LENGTH COMBINATIONS_3 combo3_count)
|
||||
|
||||
if(combo2_count LESS 10 OR combo3_count LESS 10)
|
||||
message(STATUS "⚠️ Combination counts seem too low, will regenerate")
|
||||
clear_combination_cache()
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "✅ Cache validation passed")
|
||||
else()
|
||||
message(STATUS "⚠️ Combinations not found in cache, will regenerate")
|
||||
clear_combination_cache()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Main setup function
|
||||
function(setup_smart_combination_reuse)
|
||||
message(STATUS "=== SETTING UP SMART COMBINATION REUSE ===")
|
||||
|
||||
# Validate existing cache
|
||||
validate_combination_cache()
|
||||
|
||||
# Use cached combinations without regeneration
|
||||
use_cached_type_combinations()
|
||||
|
||||
# Create combination strings once, reuse everywhere
|
||||
generate_combination_strings_once()
|
||||
|
||||
message(STATUS "✅ Smart combination reuse setup complete")
|
||||
endfunction()
|
||||
@@ -0,0 +1,689 @@
|
||||
# cmake/CompilerFlags.cmake
|
||||
# Configures compiler and linker flags for optimization and correctness.
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# When sanitizers or lifecycle tracking are enabled, we use large code model which can cause PLT overflow
|
||||
# Skip -fno-plt for these builds to avoid "PC-relative offset overflow" linker errors
|
||||
if(NOT ((DEFINED SD_SANITIZERS AND NOT SD_SANITIZERS STREQUAL "") OR SD_GCC_FUNCTRACE))
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-plt")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-plt")
|
||||
else()
|
||||
if(DEFINED SD_SANITIZERS AND NOT SD_SANITIZERS STREQUAL "")
|
||||
message(STATUS "Skipping -fno-plt for sanitizer build (incompatible with large code model)")
|
||||
elseif(SD_GCC_FUNCTRACE)
|
||||
message(STATUS "Skipping -fno-plt for lifecycle tracking build (incompatible with large code model)")
|
||||
endif()
|
||||
endif()
|
||||
#This is to avoid jemalloc crashes where c++ uses sized deallocations
|
||||
add_compile_options(-fno-sized-deallocation)
|
||||
|
||||
# JavaCPP loads our library via dlopen() at runtime, not at program startup
|
||||
# Libraries loaded via dlopen() with static TLS (initial-exec model) can exhaust the static TLS block
|
||||
# Solution: Force global-dynamic TLS model for ALL thread-local storage
|
||||
# - global-dynamic: Uses __tls_get_addr() for dynamic TLS allocation at runtime
|
||||
# - Works with dlopen() because TLS is allocated dynamically, not from static block
|
||||
# - Slightly slower than initial-exec, but required for dlopen() compatibility
|
||||
# Also disable thread-safe static initialization guards which use TLS internally
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftls-model=global-dynamic -fno-threadsafe-statics")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftls-model=global-dynamic")
|
||||
|
||||
# ADDITIONAL FIX: Use GNU2 TLS dialect (TLSDESC) for better dlopen() support
|
||||
# Traditional TLS implementation (gnu dialect) has limitations with libraries loaded via dlopen()
|
||||
# GNU2 dialect uses TLS descriptors which are specifically designed for dynamic loading
|
||||
# - Reduces TLS block fragmentation
|
||||
# - More efficient for libraries loaded at runtime
|
||||
# - Better handles libraries with many TLS variables
|
||||
# This is a DIFFERENT approach from session #310's global-dynamic alone
|
||||
# Supported on x86-64 by both GCC and Clang (requires glibc 2.10+, widely available)
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtls-dialect=gnu2")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mtls-dialect=gnu2")
|
||||
message(STATUS "Applied GNU2 TLS dialect (TLSDESC) for improved dlopen() compatibility")
|
||||
endif()
|
||||
|
||||
message(STATUS "Applied global-dynamic TLS model for dlopen() compatibility (JavaCPP requirement)")
|
||||
endif()
|
||||
|
||||
|
||||
# Template depth limits - standardized based on build type
|
||||
# Release builds: 512 (sufficient for production, faster compilation)
|
||||
# Debug builds: 1024 (deeper nesting for development)
|
||||
|
||||
# GCC-specific error limiting
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
add_compile_options(-fmax-errors=3) # Stop on first few errors
|
||||
endif()
|
||||
|
||||
# Clang-specific workarounds for source location limits
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Work around Clang's source location limit with heavily templated code
|
||||
add_compile_options(-Wno-error)
|
||||
add_compile_options(-ferror-limit=0)
|
||||
# Reduce macro expansion tracking overhead
|
||||
add_compile_options(-fmacro-backtrace-limit=0)
|
||||
# Reduce template error backtrace noise
|
||||
add_compile_options(-ftemplate-backtrace-limit=10)
|
||||
|
||||
# Aggressive Clang 20 memory optimizations for functrace ONLY
|
||||
if(SD_GCC_FUNCTRACE)
|
||||
message(STATUS "⚡ Applying Clang 20 memory optimizations for functrace build ONLY")
|
||||
|
||||
# Disable PCH validation (saves memory)
|
||||
add_compile_options(-Xclang -fno-validate-pch)
|
||||
|
||||
# Reduce template instantiation depth
|
||||
add_compile_options(-ftemplate-depth=512)
|
||||
|
||||
# Clang 20 specific: Reduce memory during code generation
|
||||
add_compile_options(-Xclang -mllvm -Xclang -inline-threshold=50)
|
||||
|
||||
# Reduce DWARF debug info overhead (keep line tables only)
|
||||
add_compile_options(-fdebug-info-for-profiling)
|
||||
|
||||
# These flags don't exist: -hot-cold-split, -reduce-array-computations, -enable-loop-distribute
|
||||
|
||||
# Disable expensive optimizations during compilation to save memory
|
||||
add_compile_options(-fno-slp-vectorize)
|
||||
add_compile_options(-fno-vectorize)
|
||||
|
||||
message(STATUS " - Disabled PCH validation")
|
||||
message(STATUS " - Template depth: 512")
|
||||
message(STATUS " - Reduced inline threshold for memory")
|
||||
message(STATUS " - Debug info optimized for profiling")
|
||||
message(STATUS " - Vectorization disabled (saves memory)")
|
||||
endif()
|
||||
|
||||
# Use newer source manager if available (Clang 15+)
|
||||
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "15.0")
|
||||
message(STATUS "Clang 15+ detected, using optimizations for large translation units")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
# --- Link Time Optimization (LTO) ---
|
||||
if(SD_USE_LTO)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
||||
message(STATUS "Using Link Time Optimization")
|
||||
add_compile_options(-flto)
|
||||
add_link_options(-flto)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --- Memory Model for large binaries ---
|
||||
# CRITICAL: -mcmodel=large is INCOMPATIBLE with system CRT libraries (crtbeginS.o, crti.o)
|
||||
# System libraries are compiled with -mcmodel=small and cannot be linked into -mcmodel=large binaries
|
||||
# This causes "relocation truncated to fit: R_X86_64_PC32" errors (see session #959, #1008)
|
||||
# SOLUTION: Use -mcmodel=medium for both sanitizers AND functrace builds
|
||||
# Medium model: Code can be anywhere, data/GOT in lowest 2GB (compatible with system libraries)
|
||||
if(SD_X86_BUILD AND NOT WIN32)
|
||||
if(SD_SANITIZE OR SD_GCC_FUNCTRACE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcmodel=medium -fPIC")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcmodel=medium")
|
||||
if(SD_SANITIZE)
|
||||
message(STATUS "Applied medium memory model for x86-64 architecture (sanitizers enabled)")
|
||||
elseif(SD_GCC_FUNCTRACE)
|
||||
message(STATUS "Applied medium memory model for x86-64 architecture (lifecycle tracking enabled)")
|
||||
endif()
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcmodel=medium -fPIC")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcmodel=medium")
|
||||
message(STATUS "Applied medium memory model for x86-64 architecture")
|
||||
endif()
|
||||
else()
|
||||
if(SD_ARM_BUILD OR SD_ANDROID_BUILD)
|
||||
message(STATUS "Skipping large memory model for ARM/Android architecture (not supported)")
|
||||
elseif(WIN32)
|
||||
message(STATUS "Skipping large memory model for Windows (using alternative approach)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --- Section splitting for better linker handling ---
|
||||
# Note: Memory optimization params (ggc-min-*) are set below in GCC-specific section to avoid duplicates
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
|
||||
|
||||
# MEMORY OPTIMIZATION: Additional flags for functrace ONLY to reduce memory
|
||||
if(SD_GCC_FUNCTRACE)
|
||||
# Merge identical constants to reduce object file size
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmerge-all-constants")
|
||||
|
||||
# Use non-unique section names (reduces ELF section overhead) - Clang only
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-unique-section-names")
|
||||
# Don't keep full AST in memory during code generation
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xclang -discard-value-names")
|
||||
endif()
|
||||
|
||||
message(STATUS "⚡ Applied memory-reduction compiler flags for functrace ONLY:")
|
||||
message(STATUS " - fmerge-all-constants (reduce duplication)")
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
message(STATUS " - fno-unique-section-names (reduce ELF overhead, Clang only)")
|
||||
message(STATUS " - discard-value-names (reduce AST retention)")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --- Allow duplicate instantiations for template folding ---
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# GCC: Use -fpermissive to allow duplicate instantiations
|
||||
add_compile_options(-fpermissive)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Clang: Suppress all warnings and errors for template instantiation issues
|
||||
add_compile_options(-w)
|
||||
add_compile_options(-Wno-error)
|
||||
add_compile_options(-Wno-everything)
|
||||
message(STATUS "✅ Clang: Enabled template folding with all warnings suppressed and dead strip")
|
||||
endif()
|
||||
|
||||
# --- MSVC-specific optimizations ---
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
add_compile_options(/Gy) # Function-level linking
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /OPT:REF /OPT:ICF")
|
||||
add_compile_options(/bigobj /EHsc /Zc:preprocessor)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
endif()
|
||||
|
||||
# --- Windows Specific Configurations ---
|
||||
if(WIN32 AND NOT ANDROID)
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
|
||||
endif()
|
||||
set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS ON)
|
||||
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS ON)
|
||||
set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@")
|
||||
set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@")
|
||||
set(CMAKE_NINJA_FORCE_RESPONSE_FILE ON CACHE INTERNAL "")
|
||||
endif()
|
||||
|
||||
# --- GCC/Clang Specific Flags ---
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT SD_CUDA)
|
||||
message(STATUS "Adding GCC memory optimization flags: --param ggc-min-expand=100 --param ggc-min-heapsize=131072")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ${INFORMATIVE_FLAGS} -std=c++17 -fPIC")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --param ggc-min-expand=100 --param ggc-min-heapsize=131072 -fPIC")
|
||||
if(UNIX)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-rpath,$ORIGIN/,--no-undefined,--verbose")
|
||||
else()
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-rpath,$ORIGIN/,--no-undefined,--verbose")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --- Build Type Specific Flags ---
|
||||
if(SD_ANDROID_BUILD)
|
||||
# ... flags for android ...
|
||||
elseif(APPLE)
|
||||
# ... flags for apple ...
|
||||
elseif(WIN32)
|
||||
# ... flags for windows ...
|
||||
else() # Generic Linux/Unix
|
||||
if("${SD_GCC_FUNCTRACE}" STREQUAL "ON")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O${SD_OPTIMIZATION_LEVEL} -fPIC -g")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O${SD_OPTIMIZATION_LEVEL} -fPIC -D_RELEASE=true")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG " -g -O${SD_OPTIMIZATION_LEVEL} -fPIC")
|
||||
endif()
|
||||
|
||||
# --- Sanitizer Configuration ---
|
||||
# In CompilerFlags.cmake, change the sanitizer section:
|
||||
# --- Sanitizer Configuration ---
|
||||
if(SD_SANITIZE)
|
||||
# For large binaries with MSan: must use large code model
|
||||
# Use LLD linker for better memory handling (gold OOMs on 23GB+ builds)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# MEMORY OPTIMIZATION: Use -gline-tables-only instead of full debug info (Clang-specific)
|
||||
# This reduces memory by 40-60% for template-heavy code while maintaining stack traces
|
||||
set(SANITIZE_FLAGS " -fPIC -fsanitize=${SD_SANITIZERS} -fno-sanitize-recover=all -fuse-ld=gold -gline-tables-only")
|
||||
|
||||
# MemorySanitizer-specific: Use ignorelist to skip instrumentation of external libraries
|
||||
if(SD_SANITIZERS MATCHES "memory")
|
||||
set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize-ignorelist=${CMAKE_CURRENT_SOURCE_DIR}/msan_ignorelist.txt")
|
||||
|
||||
# Disable origin tracking to reduce MSan's static TLS usage
|
||||
# - Origin tracking uses significant TLS to track uninitialized memory sources
|
||||
# - With dlopen() (JavaCPP's loading method), static TLS space is limited
|
||||
# - Disabling origin tracking keeps MSan functional but reduces TLS footprint
|
||||
# - MSan will still detect uninitialized memory, just without origin traces
|
||||
set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize-memory-track-origins=0")
|
||||
|
||||
# - Dynamic linking: libnd4jcpu.so depends on libclang_rt.msan.so (separate .so with static TLS)
|
||||
# - Static linking: MSan runtime code embedded in libnd4jcpu.so (TLS becomes part of our library)
|
||||
# - Combined with global-dynamic TLS model, this eliminates static TLS block exhaustion
|
||||
# - Static linking is safe here because we only have ONE library using MSan (no multi-library conflicts)
|
||||
set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -static-libsan")
|
||||
|
||||
message(STATUS "Applied MemorySanitizer ignorelist for external libraries")
|
||||
message(STATUS "Disabled MSan origin tracking to reduce TLS usage for dlopen() compatibility")
|
||||
message(STATUS "Enabled static MSan runtime linking to eliminate separate TLS allocation")
|
||||
endif()
|
||||
|
||||
# Explicitly force global-dynamic TLS model for dlopen() compatibility
|
||||
# - global-dynamic: Uses __tls_get_addr() for dynamic TLS allocation
|
||||
# - Works with libraries loaded via dlopen() (JavaCPP's method)
|
||||
# - Avoids static TLS block exhaustion
|
||||
# ALSO disable thread-safe statics to prevent __tls_guard from using initial-exec TLS
|
||||
# Thread-safe static initialization uses internal TLS that doesn't respect -ftls-model flag
|
||||
set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -ftls-model=global-dynamic -fno-threadsafe-statics")
|
||||
|
||||
# Additional memory optimizations for template-heavy instantiation files
|
||||
set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fmerge-all-constants")
|
||||
set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fno-unique-section-names") # Clang-specific
|
||||
|
||||
message(STATUS "Applied memory-optimized sanitizer flags (-gline-tables-only, Clang-specific)")
|
||||
else()
|
||||
set(SANITIZE_FLAGS " -Wall -Wextra -fPIC -fsanitize=${SD_SANITIZERS} -fno-sanitize-recover=all")
|
||||
endif()
|
||||
# Gold linker + sanitizers: Must explicitly pass -fsanitize to linker
|
||||
# The -fsanitize flag tells clang driver to link the sanitizer runtime
|
||||
# Gold linker handles MSan's TLS correctly for shared libraries (LLD has issues)
|
||||
set(SANITIZE_LINK_FLAGS "-fsanitize=${SD_SANITIZERS} -fuse-ld=gold")
|
||||
|
||||
# Without this, linker uses wrong relocation types → "relocation truncated to fit" errors
|
||||
if(SD_X86_BUILD AND NOT WIN32)
|
||||
if(DEFINED SD_SANITIZERS AND NOT SD_SANITIZERS STREQUAL "")
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -mcmodel=large")
|
||||
message(STATUS "Applied large code model to linker flags (matches compiler -mcmodel=large)")
|
||||
else()
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -mcmodel=medium")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Linker memory optimizations for large template-heavy builds
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Detect which linker is being used
|
||||
set(DETECTED_LINKER "unknown")
|
||||
if(SANITIZE_LINK_FLAGS MATCHES "-fuse-ld=gold")
|
||||
set(DETECTED_LINKER "gold")
|
||||
elseif(SANITIZE_LINK_FLAGS MATCHES "-fuse-ld=lld")
|
||||
set(DETECTED_LINKER "lld")
|
||||
elseif(SANITIZE_LINK_FLAGS MATCHES "-fuse-ld=bfd")
|
||||
set(DETECTED_LINKER "bfd")
|
||||
else()
|
||||
# Try to detect from compiler default
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -Wl,--version
|
||||
OUTPUT_VARIABLE LINKER_VERSION_OUTPUT
|
||||
ERROR_VARIABLE LINKER_VERSION_OUTPUT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(LINKER_VERSION_OUTPUT MATCHES "GNU gold")
|
||||
set(DETECTED_LINKER "gold")
|
||||
elseif(LINKER_VERSION_OUTPUT MATCHES "LLD")
|
||||
set(DETECTED_LINKER "lld")
|
||||
elseif(LINKER_VERSION_OUTPUT MATCHES "GNU ld")
|
||||
set(DETECTED_LINKER "bfd")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Detected linker: ${DETECTED_LINKER}")
|
||||
|
||||
# Apply linker-specific memory optimizations
|
||||
if(DETECTED_LINKER STREQUAL "gold")
|
||||
# GNU gold linker flags
|
||||
# Memory sanitizer needs reduced caching to avoid OOM, but leak sanitizer benefits from caching
|
||||
if(SD_SANITIZERS MATCHES "memory")
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -Wl,--no-keep-memory")
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -Wl,--no-map-whole-files")
|
||||
endif()
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -Wl,--icf=safe")
|
||||
|
||||
# Gold uses its own internal hash table optimization that cannot be configured
|
||||
|
||||
# Gold by default is single-threaded. Multi-threading speeds up linking 2-4x
|
||||
# and can reduce peak memory by spreading work across time
|
||||
cmake_host_system_information(RESULT NUM_CORES QUERY NUMBER_OF_PHYSICAL_CORES)
|
||||
math(EXPR LINKER_THREADS "${NUM_CORES} / 2") # Use half of cores for linking
|
||||
if(LINKER_THREADS LESS 2)
|
||||
set(LINKER_THREADS 2)
|
||||
endif()
|
||||
if(LINKER_THREADS GREATER 8)
|
||||
set(LINKER_THREADS 8) # Cap at 8 threads (gold's sweet spot)
|
||||
endif()
|
||||
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -Wl,--threads")
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -Wl,--thread-count,${LINKER_THREADS}")
|
||||
|
||||
message(STATUS "Applied GNU gold linker optimizations:")
|
||||
if(SD_SANITIZERS MATCHES "memory")
|
||||
message(STATUS " - --no-keep-memory: Don't cache file contents (MemorySanitizer only)")
|
||||
message(STATUS " - --no-map-whole-files: Map only needed file parts (MemorySanitizer only)")
|
||||
else()
|
||||
message(STATUS " - Using default caching (better for leak/address sanitizers)")
|
||||
endif()
|
||||
message(STATUS " - --icf=safe: Fold identical code sections")
|
||||
message(STATUS " - --threads: Enable parallel linking with ${LINKER_THREADS} threads")
|
||||
message(STATUS " Note: Gold linker manages hash table size internally (not configurable)")
|
||||
|
||||
elseif(DETECTED_LINKER STREQUAL "lld")
|
||||
# LLVM lld linker flags (different syntax than gold)
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -Wl,--icf=all")
|
||||
|
||||
# For very large builds (23GB+ object files), reduce memory usage
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -Wl,--gc-sections")
|
||||
|
||||
# LLD has built-in threading, configure job count
|
||||
cmake_host_system_information(RESULT NUM_CORES QUERY NUMBER_OF_PHYSICAL_CORES)
|
||||
math(EXPR LINKER_THREADS "${NUM_CORES} / 2")
|
||||
if(LINKER_THREADS LESS 2)
|
||||
set(LINKER_THREADS 2)
|
||||
endif()
|
||||
if(LINKER_THREADS GREATER 16)
|
||||
set(LINKER_THREADS 16) # LLD scales better than gold
|
||||
endif()
|
||||
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -Wl,--threads=${LINKER_THREADS}")
|
||||
|
||||
message(STATUS "Applied LLVM lld linker memory optimizations:")
|
||||
message(STATUS " - --icf=all: Aggressive identical code folding")
|
||||
message(STATUS " - --gc-sections: Remove unused code sections")
|
||||
message(STATUS " - --threads=${LINKER_THREADS}: Enable parallel linking")
|
||||
message(STATUS " Note: LLD handles large builds (23GB+) better than gold")
|
||||
|
||||
elseif(DETECTED_LINKER STREQUAL "bfd")
|
||||
# GNU ld (bfd) - older linker with limited optimization support
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -Wl,--no-keep-memory")
|
||||
# BFD doesn't support threading or advanced ICF
|
||||
|
||||
message(STATUS "Applied GNU ld (bfd) linker memory optimizations:")
|
||||
message(STATUS " - --no-keep-memory: Don't cache file contents in memory")
|
||||
message(WARNING "GNU ld (bfd) is single-threaded and slower than gold/lld. Consider using gold or lld for faster builds.")
|
||||
|
||||
else()
|
||||
message(WARNING "Unknown linker detected. Skipping linker-specific optimizations.")
|
||||
message(STATUS "To specify linker explicitly, use: -DCMAKE_CXX_FLAGS=\"-fuse-ld=gold\" (or lld/bfd)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# For Homebrew clang or custom LLVM, also add explicit runtime library path
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -print-resource-dir
|
||||
OUTPUT_VARIABLE CLANG_RESOURCE_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Determine OS-specific lib subdirectory
|
||||
if(APPLE)
|
||||
set(SANITIZER_LIB_SUBDIR "darwin")
|
||||
elseif(WIN32)
|
||||
set(SANITIZER_LIB_SUBDIR "windows")
|
||||
else()
|
||||
set(SANITIZER_LIB_SUBDIR "linux")
|
||||
endif()
|
||||
|
||||
# Determine architecture for sanitizer library names
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
|
||||
set(SANITIZER_ARCH "x86_64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64")
|
||||
set(SANITIZER_ARCH "aarch64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le")
|
||||
set(SANITIZER_ARCH "powerpc64le")
|
||||
else()
|
||||
set(SANITIZER_ARCH ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
|
||||
set(SANITIZER_LIB_PATH "${CLANG_RESOURCE_DIR}/lib/${SANITIZER_LIB_SUBDIR}")
|
||||
|
||||
if(EXISTS "${SANITIZER_LIB_PATH}")
|
||||
# Add library search path and RPATH for sanitizer runtime
|
||||
if(APPLE)
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -L${SANITIZER_LIB_PATH} -Wl,-rpath,${SANITIZER_LIB_PATH}")
|
||||
elseif(WIN32)
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -L${SANITIZER_LIB_PATH}")
|
||||
else()
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -L${SANITIZER_LIB_PATH} -Wl,-rpath,${SANITIZER_LIB_PATH}")
|
||||
endif()
|
||||
|
||||
# When using gold linker with -static-libsan, we don't need explicit runtime linking
|
||||
# The -static-libsan flag tells Clang to link the static runtime archives automatically
|
||||
# REMOVED: Explicit -lclang_rt.msan-* (for shared runtime) - now using static linking
|
||||
if(SD_SANITIZERS MATCHES "memory")
|
||||
# Note: With -static-libsan flag above, Clang handles static runtime linking
|
||||
message(STATUS "Using static MSan runtime (via -static-libsan) for gold linker (${SANITIZER_ARCH})")
|
||||
endif()
|
||||
|
||||
# -fsanitize=leak uses the ASAN runtime (there's no separate LSAN .so)
|
||||
# For shared libraries loaded by JVM/JNI, the sanitizer runtime MUST be
|
||||
# dynamically linked, not statically linked. Without this, the sanitizer
|
||||
# runtime is not initialized and leaks are not detected.
|
||||
#
|
||||
# With gold linker, Clang defaults to static linking of sanitizer runtime.
|
||||
# We must explicitly link the shared .so file to make it a NEEDED dependency.
|
||||
if(SD_SANITIZERS MATCHES "leak" OR SD_SANITIZERS MATCHES "address")
|
||||
set(SANITIZE_LINK_FLAGS "${SANITIZE_LINK_FLAGS} -lclang_rt.asan-${SANITIZER_ARCH}")
|
||||
message(STATUS "Added explicit ASAN shared runtime library for leak/address sanitizer (${SANITIZER_ARCH}, JNI compatibility)")
|
||||
endif()
|
||||
|
||||
message(STATUS "Added clang sanitizer runtime library path and RPATH: ${SANITIZER_LIB_PATH}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message("Using sanitizers: ${SD_SANITIZERS}...")
|
||||
if(SD_CPU)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZE_FLAGS}" CACHE STRING "C++ flags" FORCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZE_FLAGS}" CACHE STRING "C flags" FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_LINK_FLAGS}" CACHE STRING "Exe linker flags" FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SANITIZE_LINK_FLAGS}" CACHE STRING "Shared linker flags" FORCE)
|
||||
endif()
|
||||
if(SD_CUDA)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZE_FLAGS} --relocatable-device-code=true" CACHE STRING "C++ flags" FORCE)
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${SANITIZE_FLAGS}" CACHE STRING "CUDA flags" FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_LINK_FLAGS}" CACHE STRING "Exe linker flags" FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SANITIZE_LINK_FLAGS}" CACHE STRING "Shared linker flags" FORCE)
|
||||
endif()
|
||||
|
||||
# MEMORY OPTIMIZATION: Limit parallel compilation jobs for sanitizer builds
|
||||
# Template instantiation files with sanitizers can use 8-12GB per compiler process
|
||||
# Limiting parallel jobs prevents memory exhaustion
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Use CMake 3.0+ job pools to limit parallelism
|
||||
# Each instantiation file with MSan can peak at ~10GB
|
||||
# Safe limit: max(6, available_RAM_GB / 12)
|
||||
set(SANITIZER_MAX_JOBS 8)
|
||||
set_property(GLOBAL PROPERTY JOB_POOLS compile_pool=${SANITIZER_MAX_JOBS})
|
||||
set(CMAKE_JOB_POOL_COMPILE compile_pool)
|
||||
message(STATUS "⚠️ Limited parallel compilation to ${SANITIZER_MAX_JOBS} jobs for memory-intensive sanitizer build")
|
||||
message(STATUS " Estimated peak memory: ~${SANITIZER_MAX_JOBS}0 GB")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --- Strict Linker Flags to Catch Undefined Symbols Early ---
|
||||
# This helps catch missing template specializations at link time instead of runtime
|
||||
# EXCEPTION: Do NOT use --no-undefined with sanitizers, as they require runtime symbol resolution
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT SD_SANITIZE AND NOT SD_GCC_FUNCTRACE)
|
||||
message(STATUS "⚠️ ENFORCING strict linker flags - build will FAIL on ANY undefined symbols")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined")
|
||||
|
||||
# Without this, linker uses wrong relocation types → "relocation truncated to fit" errors
|
||||
if(SD_X86_BUILD AND NOT WIN32)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mcmodel=medium")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mcmodel=medium")
|
||||
message(STATUS "Applied medium code model to linker flags (matches compiler -mcmodel=medium)")
|
||||
endif()
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND SD_GCC_FUNCTRACE AND NOT SD_SANITIZE)
|
||||
#
|
||||
#
|
||||
# THIS IS A PLATFORM LIMITATION, NOT A CODE BUG
|
||||
#
|
||||
|
||||
message(STATUS "⚠️ SD_GCC_FUNCTRACE enabled - binary will be ~3GB")
|
||||
message(STATUS "⚠️ WARNING: High risk of relocation errors with precompiled system libraries")
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined")
|
||||
|
||||
# Aggressive size reduction for functrace builds
|
||||
add_compile_options(-ffunction-sections -fdata-sections)
|
||||
add_compile_options(-fvisibility=hidden -fvisibility-inlines-hidden)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections,--as-needed")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--as-needed")
|
||||
|
||||
# Memory optimizations for linking large binaries
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-keep-memory")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--reduce-memory-overheads")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--hash-size=31")
|
||||
|
||||
# NOTE: We use compiler-rt for runtime builtins but NOT libunwind for exception handling
|
||||
# (Session #1045 fix: libunwind conflicts with JVM's libgcc_s, causing _Unwind_SetGR crashes)
|
||||
# The system's libgcc_s handles exception unwinding, which is compatible with JVM
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# CRITICAL FIX: Do NOT use --unwindlib=libunwind for JNI libraries!
|
||||
#
|
||||
# Problem (discovered in session #1045):
|
||||
# - When --unwindlib=libunwind is used, Clang generates code assuming LLVM's libunwind ABI
|
||||
# - We also statically link libunwind.a
|
||||
# - BUT: At runtime, the JVM has libgcc_s.so loaded (for its own exception handling)
|
||||
# - Due to dynamic symbol interposition, _Unwind* symbols from libgcc_s.so override
|
||||
# our statically linked libunwind symbols
|
||||
# - Result: ABI mismatch between exception context format → CRASH in _Unwind_SetGR
|
||||
#
|
||||
# The crash manifests as: SIGSEGV in _Unwind_SetGR+0x3e trying to write to read-only
|
||||
# memory in libnd4jcpu.so during exception handling
|
||||
#
|
||||
# Solution: Use the system's default exception handling (libgcc_s), which is
|
||||
# compatible with the JVM environment. Keep compiler-rt only for builtins.
|
||||
#
|
||||
# Use compiler-rt for runtime builtins (math, etc.) but NOT for exception handling
|
||||
add_compile_options(--rtlib=compiler-rt)
|
||||
# REMOVED: add_compile_options(--unwindlib=libunwind)
|
||||
# Let the system use libgcc_s for exception unwinding - compatible with JVM
|
||||
|
||||
message(STATUS "✅ Using Clang compiler-rt for runtime builtins")
|
||||
message(STATUS "✅ Using system libgcc_s for exception handling (JNI/JVM compatible)")
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# With GCC, -finstrument-functions may pull in gprof startup code (__gmon_start__)
|
||||
# but this symbol is weakly defined and doesn't cause actual linker errors.
|
||||
# No special linker flags needed - GCC runtime handles this correctly.
|
||||
message(STATUS "✅ Using GCC with functrace (no special profiling symbols needed)")
|
||||
endif()
|
||||
|
||||
# Apply medium code model to match compiler (CRITICAL: large model incompatible with system CRT)
|
||||
if(SD_X86_BUILD AND NOT WIN32)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mcmodel=medium")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mcmodel=medium")
|
||||
# Allow text relocations as escape hatch if binary is still too large
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,notext")
|
||||
# Disable linker relaxation to prevent GOTPCREL relocation failures (required for medium code model)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-relax")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-relax")
|
||||
message(STATUS "Applied medium code model for functrace ONLY (binary size: ~3GB)")
|
||||
message(STATUS "Applied linker memory optimizations for functrace ONLY (--no-keep-memory, --reduce-memory-overheads)")
|
||||
message(STATUS "Added -Wl,-z,notext to allow text relocations if needed")
|
||||
message(STATUS "Added -Wl,--no-relax to prevent GOT relocation issues with medium code model")
|
||||
endif()
|
||||
elseif(SD_SANITIZE)
|
||||
message(STATUS "ℹ️ Skipping --no-undefined for sanitizer build (sanitizer runtime symbols resolved at runtime)")
|
||||
endif()
|
||||
|
||||
# Make build more verbose to see template instantiation issues
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
if(SD_GCC_FUNCTRACE)
|
||||
message(STATUS "✅ Applying SD_GCC_FUNCTRACE debug flags for line number information")
|
||||
|
||||
# MEMORY OPTIMIZATION: Use minimal debug info instead of full debug info
|
||||
# This reduces compilation memory usage by 40-60% while maintaining stack traces
|
||||
# Clang: -gline-tables-only provides file names, line numbers, function names
|
||||
# GCC: -g1 provides minimal debug info (line numbers and functions only)
|
||||
# Full debug info (-ggdb3) causes memory explosion with templates
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O0 -gline-tables-only -fPIC -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -gline-tables-only -fPIC")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O0 -gline-tables-only -fPIC -DNDEBUG")
|
||||
set(CMAKE_C_FLAGS_DEBUG "-O0 -gline-tables-only -fPIC")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O0 -g1 -fPIC -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g1 -fPIC")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O0 -g1 -fPIC -DNDEBUG")
|
||||
set(CMAKE_C_FLAGS_DEBUG "-O0 -g1 -fPIC")
|
||||
endif()
|
||||
|
||||
# Add comprehensive debug flags
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# Debug flags with function instrumentation
|
||||
# MEMORY OPTIMIZATION: Use -g1 (minimal debug info) instead of -ggdb3
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g1 -finstrument-functions -fno-omit-frame-pointer -fno-optimize-sibling-calls -rdynamic -fno-threadsafe-statics -ftls-model=global-dynamic")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g1 -fno-omit-frame-pointer -ftls-model=global-dynamic")
|
||||
message(STATUS "Applied memory-optimized debug flags for GCC (instrumentation enabled):")
|
||||
message(STATUS " - g1 (minimal debug info) for 40-60% memory reduction vs ggdb3")
|
||||
message(STATUS " - disabled thread-safe static guards")
|
||||
message(STATUS " - enabled function instrumentation")
|
||||
|
||||
# Override any conflicting optimization
|
||||
string(REGEX REPLACE "-O[0-9s]" "-O0" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REGEX REPLACE "-O[0-9s]" "-O0" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Debug flags with function instrumentation
|
||||
# MEMORY OPTIMIZATION: Use -gline-tables-only instead of -ggdb3 (Clang-specific flag)
|
||||
# AGGRESSIVE MEMORY: Disable inline tracking and macro debug info
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -gline-tables-only -finstrument-functions -fno-omit-frame-pointer -fno-optimize-sibling-calls -rdynamic -fno-threadsafe-statics -ftls-model=global-dynamic -fno-standalone-debug")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -gline-tables-only -fno-omit-frame-pointer -ftls-model=global-dynamic -fno-standalone-debug")
|
||||
message(STATUS "Applied memory-optimized debug flags for Clang (instrumentation enabled):")
|
||||
message(STATUS " - gline-tables-only (Clang-specific) for 40-60% memory reduction vs ggdb3")
|
||||
message(STATUS " - disabled thread-safe static guards")
|
||||
message(STATUS " - enabled function instrumentation")
|
||||
|
||||
# Override any conflicting optimization
|
||||
string(REGEX REPLACE "-O[0-9s]" "-O0" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REGEX REPLACE "-O[0-9s]" "-O0" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
endif()
|
||||
|
||||
# Ensure debug info is preserved in linker
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -rdynamic")
|
||||
|
||||
# Prevent stripping
|
||||
set(CMAKE_STRIP "/bin/true")
|
||||
|
||||
# Add the compiler definition
|
||||
add_compile_definitions(SD_GCC_FUNCTRACE=ON)
|
||||
|
||||
# Enable function instrumentation
|
||||
message(STATUS "ℹ️ Function instrumentation enabled. This will significantly increase binary size.")
|
||||
endif()
|
||||
|
||||
# --- Flag Deduplication ---
|
||||
# Remove duplicate flags that may have accumulated through multiple conditional blocks
|
||||
# This ensures cleaner build logs and prevents potential flag conflicts
|
||||
|
||||
# Helper function to deduplicate flags in a space-separated string
|
||||
function(deduplicate_flags FLAG_VAR)
|
||||
# Get the original flags
|
||||
set(original_flags "${${FLAG_VAR}}")
|
||||
|
||||
# Special handling: protect --param flags by temporarily replacing spaces
|
||||
string(REGEX REPLACE "--param ([^ ]+)" "--param=\\1" temp_flags "${original_flags}")
|
||||
|
||||
# Convert space-separated string to list
|
||||
string(REPLACE " " ";" FLAG_LIST "${temp_flags}")
|
||||
|
||||
# Remove duplicates while preserving order
|
||||
list(REMOVE_DUPLICATES FLAG_LIST)
|
||||
|
||||
# Convert back to space-separated string
|
||||
string(REPLACE ";" " " FLAG_STRING "${FLAG_LIST}")
|
||||
|
||||
# Restore --param format (space instead of =)
|
||||
string(REGEX REPLACE "--param=([^ ]+)" "--param \\1" FLAG_STRING "${FLAG_STRING}")
|
||||
|
||||
# Set the parent scope variable
|
||||
set(${FLAG_VAR} "${FLAG_STRING}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Deduplicate compiler flags
|
||||
deduplicate_flags(CMAKE_CXX_FLAGS)
|
||||
deduplicate_flags(CMAKE_C_FLAGS)
|
||||
deduplicate_flags(CMAKE_CXX_FLAGS_RELEASE)
|
||||
deduplicate_flags(CMAKE_CXX_FLAGS_DEBUG)
|
||||
deduplicate_flags(CMAKE_C_FLAGS_RELEASE)
|
||||
deduplicate_flags(CMAKE_C_FLAGS_DEBUG)
|
||||
|
||||
# Deduplicate linker flags
|
||||
deduplicate_flags(CMAKE_SHARED_LINKER_FLAGS)
|
||||
deduplicate_flags(CMAKE_EXE_LINKER_FLAGS)
|
||||
deduplicate_flags(CMAKE_MODULE_LINKER_FLAGS)
|
||||
|
||||
message(STATUS "✅ Compiler and linker flags deduplicated")
|
||||
@@ -0,0 +1,107 @@
|
||||
# CompilerOptimizations.cmake - Compiler flags and optimization settings
|
||||
|
||||
|
||||
|
||||
# Link Time Optimization
|
||||
if(SD_USE_LTO)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
||||
message(STATUS "Using Link Time Optimization")
|
||||
add_compile_options(-flto)
|
||||
add_link_options(-flto)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Architecture Tuning
|
||||
if(SD_ARCH MATCHES "armv8")
|
||||
set(ARCH_TUNE "-march=${SD_ARCH}")
|
||||
elseif(SD_ARCH MATCHES "armv7")
|
||||
set(ARCH_TUNE "-march=${SD_ARCH} -mfpu=neon")
|
||||
elseif(SD_EXTENSION MATCHES "avx2")
|
||||
message("Building AVX2 binary...")
|
||||
set(ARCH_TUNE "-mmmx -msse -msse2 -msse3 -msse4.1 -msse4.2 -mavx -mavx2 -mfma -mf16c -mprefetchwt1 -DSD_F16C=true -DF_AVX2=true")
|
||||
if(NO_AVX256_SPLIT)
|
||||
set(ARCH_TUNE "${ARCH_TUNE} -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store")
|
||||
endif()
|
||||
else()
|
||||
if("${SD_ARCH}" STREQUAL "x86-64")
|
||||
message("Building x86_64 binary...")
|
||||
set(ARCH_TYPE "generic")
|
||||
add_compile_definitions(F_X64=true)
|
||||
else()
|
||||
set(ARCH_TYPE "${SD_ARCH}")
|
||||
endif()
|
||||
|
||||
if(SD_EXTENSION MATCHES "avx512")
|
||||
message("Building AVX512 binary...")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmmx -msse -msse2 -msse3 -msse4.1 -msse4.2 -mavx -mavx2 -mfma -mf16c -mavx512f -mavx512vl -mavx512bw -mavx512dq -mavx512cd -mbmi -mbmi2 -mprefetchwt1 -mclflushopt -mxsavec -mxsaves -DSD_F16C=true -DF_AVX512=true")
|
||||
endif()
|
||||
|
||||
# FIXED: Only set architecture flags if we have valid values
|
||||
if(NOT WIN32 AND NOT SD_CUDA)
|
||||
if(DEFINED SD_ARCH AND NOT SD_ARCH STREQUAL "" AND DEFINED ARCH_TYPE AND NOT ARCH_TYPE STREQUAL "")
|
||||
set(ARCH_TUNE "-march=${SD_ARCH} -mtune=${ARCH_TYPE}")
|
||||
elseif(DEFINED SD_ARCH AND NOT SD_ARCH STREQUAL "")
|
||||
# Fallback if ARCH_TYPE is not set
|
||||
set(ARCH_TUNE "-march=${SD_ARCH}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Comprehensive linker fix for PLT overflow
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND SD_X86_BUILD)
|
||||
message(STATUS "Configuring linker for large template library with PLT overflow prevention")
|
||||
|
||||
# Clear any existing conflicting linker flags
|
||||
string(REGEX REPLACE "-fuse-ld=[a-zA-Z]+" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
string(REGEX REPLACE "-fuse-ld=[a-zA-Z]+" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
|
||||
# Test if linker supports --plt-align before using it
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_LINKER} --help
|
||||
OUTPUT_VARIABLE LD_HELP_OUTPUT
|
||||
ERROR_QUIET
|
||||
)
|
||||
endif()
|
||||
|
||||
# Use large memory model (required for your template scale) - FIXED: Only for x86-64, not ARM
|
||||
if(SD_X86_BUILD AND NOT WIN32)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcmodel=medium -fPIC")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcmodel=medium")
|
||||
message(STATUS "Applied large memory model for x86-64 architecture")
|
||||
else()
|
||||
if(SD_ARM_BUILD OR SD_ANDROID_BUILD)
|
||||
message(STATUS "Skipping large memory model for ARM/Android architecture (not supported)")
|
||||
elseif(WIN32)
|
||||
message(STATUS "Skipping large memory model for Windows (using alternative approach)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Memory optimization during compilation - FIXED: Only apply to GCC
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --param ggc-min-expand=100 --param ggc-min-heapsize=131072")
|
||||
endif()
|
||||
|
||||
# Section splitting for better linker handling - FIXED: Only apply to GCC/Clang
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
|
||||
endif()
|
||||
|
||||
# MSVC-specific optimizations
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
# MSVC equivalent optimizations
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Gy") # Function-level linking
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gy") # Function-level linking
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /OPT:REF /OPT:ICF") # Remove unreferenced code
|
||||
endif()
|
||||
|
||||
message(STATUS "Applied PLT overflow prevention for large template library")
|
||||
|
||||
if(SD_NATIVE)
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc64*" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64*")
|
||||
set(SD_X86_BUILD false)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,850 @@
|
||||
################################################################################
|
||||
# CUDA Configuration Functions
|
||||
# Functions for CUDA-specific build configuration and optimization
|
||||
################################################################################
|
||||
|
||||
# Enhanced CUDA toolkit detection with proper include path setup
|
||||
function(setup_cuda_toolkit_paths)
|
||||
message(STATUS "🔍 Setting up CUDA toolkit paths...")
|
||||
|
||||
# Find CUDA toolkit first
|
||||
find_package(CUDAToolkit REQUIRED)
|
||||
|
||||
if(NOT CUDAToolkit_FOUND)
|
||||
message(FATAL_ERROR "CUDA toolkit not found. Please install CUDA toolkit or set CUDA_PATH environment variable.")
|
||||
endif()
|
||||
|
||||
# Get CUDA include directories
|
||||
get_target_property(CUDA_INCLUDE_DIRS CUDA::toolkit INTERFACE_INCLUDE_DIRECTORIES)
|
||||
|
||||
# If the above doesn't work, try alternative methods
|
||||
if(NOT CUDA_INCLUDE_DIRS)
|
||||
set(CUDA_INCLUDE_DIRS "${CUDAToolkit_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
# Still not found? Try environment variables and common paths
|
||||
if(NOT CUDA_INCLUDE_DIRS)
|
||||
set(CUDA_SEARCH_PATHS
|
||||
$ENV{CUDA_PATH}
|
||||
$ENV{CUDA_HOME}
|
||||
$ENV{CUDA_ROOT}
|
||||
${CUDAToolkit_ROOT}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND CUDA_SEARCH_PATHS
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.6"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.5"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.4"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.3"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.2"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.1"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.0"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v11.8"
|
||||
"C:/tools/cuda"
|
||||
)
|
||||
else()
|
||||
list(APPEND CUDA_SEARCH_PATHS
|
||||
/usr/local/cuda
|
||||
/opt/cuda
|
||||
/usr/cuda
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(search_path ${CUDA_SEARCH_PATHS})
|
||||
if(EXISTS "${search_path}/include/cuda.h")
|
||||
set(CUDA_INCLUDE_DIRS "${search_path}/include")
|
||||
message(STATUS "✅ Found CUDA include directory: ${CUDA_INCLUDE_DIRS}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Verify we found CUDA headers
|
||||
if(NOT CUDA_INCLUDE_DIRS)
|
||||
message(FATAL_ERROR "❌ CUDA include directories not found. Please ensure CUDA toolkit is properly installed.")
|
||||
endif()
|
||||
|
||||
# Verify cuda.h exists
|
||||
set(CUDA_H_FOUND FALSE)
|
||||
foreach(include_dir ${CUDA_INCLUDE_DIRS})
|
||||
if(EXISTS "${include_dir}/cuda.h")
|
||||
set(CUDA_H_FOUND TRUE)
|
||||
message(STATUS "✅ Found cuda.h in: ${include_dir}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT CUDA_H_FOUND)
|
||||
message(FATAL_ERROR "❌ cuda.h not found in CUDA include directories: ${CUDA_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
# Set variables for parent scope
|
||||
set(CUDA_INCLUDE_DIRS "${CUDA_INCLUDE_DIRS}" PARENT_SCOPE)
|
||||
set(CUDA_TOOLKIT_ROOT_DIR "${CUDAToolkit_ROOT}" PARENT_SCOPE)
|
||||
|
||||
message(STATUS "✅ CUDA toolkit paths configured:")
|
||||
message(STATUS " Root: ${CUDAToolkit_ROOT}")
|
||||
message(STATUS " Include: ${CUDA_INCLUDE_DIRS}")
|
||||
message(STATUS " Version: ${CUDAToolkit_VERSION}")
|
||||
endfunction()
|
||||
|
||||
# Modern cuDNN detection using updated FindCUDNN.cmake practices
|
||||
function(setup_modern_cudnn)
|
||||
set(HAVE_CUDNN FALSE PARENT_SCOPE)
|
||||
|
||||
if(NOT (HELPERS_cudnn AND SD_CUDA))
|
||||
message(STATUS "🔍 cuDNN: Skipped (HELPERS_cudnn=${HELPERS_cudnn}, SD_CUDA=${SD_CUDA})")
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "🔍 Searching for cuDNN...")
|
||||
|
||||
# Find the CUDA toolkit first to get the proper paths
|
||||
find_package(CUDAToolkit REQUIRED)
|
||||
|
||||
# Enhanced search paths for CI environments and common installations
|
||||
set(CUDNN_SEARCH_PATHS
|
||||
# Environment variables
|
||||
$ENV{CUDNN_ROOT_DIR}
|
||||
$ENV{CUDNN_ROOT}
|
||||
$ENV{CUDA_PATH}
|
||||
$ENV{CUDA_HOME}
|
||||
|
||||
# CMake variables
|
||||
${CUDNN_ROOT_DIR}
|
||||
${CUDAToolkit_ROOT}
|
||||
)
|
||||
|
||||
# Add platform-specific paths
|
||||
if(WIN32)
|
||||
# Windows-specific paths
|
||||
list(APPEND CUDNN_SEARCH_PATHS
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.6"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.5"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.4"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.3"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.2"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.1"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v12.0"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v11.8"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v11.7"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v11.6"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v11.5"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v11.4"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v11.3"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v11.2"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v11.1"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA/v11.0"
|
||||
"$ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit/CUDA"
|
||||
"C:/tools/cuda" # Common CI path on Windows
|
||||
)
|
||||
else()
|
||||
# Linux/Unix-specific paths
|
||||
list(APPEND CUDNN_SEARCH_PATHS
|
||||
# CI-specific paths (GitHub Actions, etc.)
|
||||
/usr/local/cuda-12.6
|
||||
/usr/local/cuda-12.5
|
||||
/usr/local/cuda-12.4
|
||||
/usr/local/cuda-12.3
|
||||
/usr/local/cuda-12.2
|
||||
/usr/local/cuda-12.1
|
||||
/usr/local/cuda-12.0
|
||||
/usr/local/cuda-11.8
|
||||
/usr/local/cuda-11.7
|
||||
/usr/local/cuda-11.6
|
||||
/usr/local/cuda-11.5
|
||||
/usr/local/cuda-11.4
|
||||
/usr/local/cuda-11.3
|
||||
/usr/local/cuda-11.2
|
||||
/usr/local/cuda-11.1
|
||||
/usr/local/cuda-11.0
|
||||
/usr/local/cuda
|
||||
|
||||
# Package manager paths
|
||||
/usr/include/cudnn
|
||||
/usr/local/include/cudnn
|
||||
/opt/cuda
|
||||
/opt/cudnn
|
||||
|
||||
# System paths
|
||||
/usr
|
||||
/usr/local
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "🔍 Searching for cuDNN headers...")
|
||||
|
||||
# Search for cuDNN headers with comprehensive path coverage
|
||||
find_path(CUDNN_INCLUDE_DIR
|
||||
NAMES cudnn.h
|
||||
HINTS ${CUDNN_SEARCH_PATHS}
|
||||
PATHS ${CUDNN_SEARCH_PATHS}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
targets/x86_64-linux/include
|
||||
targets/aarch64-linux/include
|
||||
include/cudnn
|
||||
cudnn/include
|
||||
x86_64-linux/include
|
||||
aarch64-linux/include
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
# If not found, try system paths
|
||||
if(NOT CUDNN_INCLUDE_DIR)
|
||||
find_path(CUDNN_INCLUDE_DIR
|
||||
NAMES cudnn.h
|
||||
PATHS /usr/include /usr/local/include /opt/include
|
||||
PATH_SUFFIXES cudnn
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "🔍 Searching for cuDNN libraries...")
|
||||
|
||||
# Search for cuDNN libraries
|
||||
find_library(CUDNN_LIBRARY
|
||||
NAMES cudnn libcudnn cudnn8 libcudnn8
|
||||
HINTS ${CUDNN_SEARCH_PATHS}
|
||||
PATHS ${CUDNN_SEARCH_PATHS}
|
||||
PATH_SUFFIXES
|
||||
lib64
|
||||
lib
|
||||
lib/x64
|
||||
targets/x86_64-linux/lib
|
||||
targets/aarch64-linux/lib
|
||||
lib64/cudnn
|
||||
lib/cudnn
|
||||
cudnn/lib64
|
||||
cudnn/lib
|
||||
x86_64-linux/lib
|
||||
aarch64-linux/lib
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
# If not found, try system paths
|
||||
if(NOT CUDNN_LIBRARY)
|
||||
find_library(CUDNN_LIBRARY
|
||||
NAMES cudnn libcudnn cudnn8 libcudnn8
|
||||
PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib /opt/lib64 /opt/lib
|
||||
PATH_SUFFIXES cudnn
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "🔍 cuDNN search results:")
|
||||
message(STATUS " CUDNN_INCLUDE_DIR: ${CUDNN_INCLUDE_DIR}")
|
||||
message(STATUS " CUDNN_LIBRARY: ${CUDNN_LIBRARY}")
|
||||
|
||||
# Check if we found both header and library
|
||||
if(CUDNN_INCLUDE_DIR AND CUDNN_LIBRARY)
|
||||
message(STATUS "✅ cuDNN found!")
|
||||
|
||||
# Extract version information from cudnn.h
|
||||
if(EXISTS "${CUDNN_INCLUDE_DIR}/cudnn.h")
|
||||
file(READ "${CUDNN_INCLUDE_DIR}/cudnn.h" CUDNN_HEADER_CONTENTS)
|
||||
|
||||
# Try different version detection methods
|
||||
string(REGEX MATCH "define CUDNN_MAJOR[ \t]+([0-9]+)" CUDNN_VERSION_MAJOR_MATCH "${CUDNN_HEADER_CONTENTS}")
|
||||
string(REGEX MATCH "define CUDNN_MINOR[ \t]+([0-9]+)" CUDNN_VERSION_MINOR_MATCH "${CUDNN_HEADER_CONTENTS}")
|
||||
string(REGEX MATCH "define CUDNN_PATCHLEVEL[ \t]+([0-9]+)" CUDNN_VERSION_PATCH_MATCH "${CUDNN_HEADER_CONTENTS}")
|
||||
|
||||
if(CUDNN_VERSION_MAJOR_MATCH)
|
||||
string(REGEX REPLACE "define CUDNN_MAJOR[ \t]+([0-9]+)" "\\1" CUDNN_VERSION_MAJOR "${CUDNN_VERSION_MAJOR_MATCH}")
|
||||
string(REGEX REPLACE "define CUDNN_MINOR[ \t]+([0-9]+)" "\\1" CUDNN_VERSION_MINOR "${CUDNN_VERSION_MINOR_MATCH}")
|
||||
string(REGEX REPLACE "define CUDNN_PATCHLEVEL[ \t]+([0-9]+)" "\\1" CUDNN_VERSION_PATCH "${CUDNN_VERSION_PATCH_MATCH}")
|
||||
|
||||
set(CUDNN_VERSION_STRING "${CUDNN_VERSION_MAJOR}.${CUDNN_VERSION_MINOR}.${CUDNN_VERSION_PATCH}")
|
||||
else()
|
||||
# Try alternative version detection
|
||||
string(REGEX MATCH "#define CUDNN_MAJOR ([0-9]+)" CUDNN_VERSION_MAJOR_MATCH2 "${CUDNN_HEADER_CONTENTS}")
|
||||
if(CUDNN_VERSION_MAJOR_MATCH2)
|
||||
string(REGEX REPLACE "#define CUDNN_MAJOR ([0-9]+)" "\\1" CUDNN_VERSION_MAJOR "${CUDNN_VERSION_MAJOR_MATCH2}")
|
||||
string(REGEX MATCH "#define CUDNN_MINOR ([0-9]+)" CUDNN_VERSION_MINOR_MATCH2 "${CUDNN_HEADER_CONTENTS}")
|
||||
string(REGEX MATCH "#define CUDNN_PATCHLEVEL ([0-9]+)" CUDNN_VERSION_PATCH_MATCH2 "${CUDNN_HEADER_CONTENTS}")
|
||||
string(REGEX REPLACE "#define CUDNN_MINOR ([0-9]+)" "\\1" CUDNN_VERSION_MINOR "${CUDNN_VERSION_MINOR_MATCH2}")
|
||||
string(REGEX REPLACE "#define CUDNN_PATCHLEVEL ([0-9]+)" "\\1" CUDNN_VERSION_PATCH "${CUDNN_VERSION_PATCH_MATCH2}")
|
||||
set(CUDNN_VERSION_STRING "${CUDNN_VERSION_MAJOR}.${CUDNN_VERSION_MINOR}.${CUDNN_VERSION_PATCH}")
|
||||
else()
|
||||
set(CUDNN_VERSION_STRING "Unknown")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "⚠️ cuDNN header found but cannot read version")
|
||||
set(CUDNN_VERSION_STRING "Unknown")
|
||||
endif()
|
||||
|
||||
# Create imported target if it doesn't exist
|
||||
if(NOT TARGET CUDNN::cudnn)
|
||||
add_library(CUDNN::cudnn UNKNOWN IMPORTED)
|
||||
set_target_properties(CUDNN::cudnn PROPERTIES
|
||||
IMPORTED_LOCATION "${CUDNN_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CUDNN_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "✅ cuDNN configuration:")
|
||||
message(STATUS " Include: ${CUDNN_INCLUDE_DIR}")
|
||||
message(STATUS " Library: ${CUDNN_LIBRARY}")
|
||||
message(STATUS " Version: ${CUDNN_VERSION_STRING}")
|
||||
|
||||
# Set all the variables that might be needed
|
||||
set(HAVE_CUDNN TRUE PARENT_SCOPE)
|
||||
set(CUDNN_FOUND TRUE PARENT_SCOPE)
|
||||
set(CUDNN_INCLUDE_DIR "${CUDNN_INCLUDE_DIR}" PARENT_SCOPE)
|
||||
set(CUDNN_LIBRARIES "${CUDNN_LIBRARY}" PARENT_SCOPE)
|
||||
set(CUDNN_LIBRARY "${CUDNN_LIBRARY}" PARENT_SCOPE)
|
||||
set(CUDNN_VERSION_STRING "${CUDNN_VERSION_STRING}" PARENT_SCOPE)
|
||||
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Try package manager detection as fallback
|
||||
find_package(PkgConfig QUIET)
|
||||
if(PkgConfig_FOUND)
|
||||
pkg_check_modules(PC_CUDNN QUIET cudnn)
|
||||
if(PC_CUDNN_FOUND)
|
||||
message(STATUS "✅ Found cuDNN via pkg-config")
|
||||
set(HAVE_CUDNN TRUE PARENT_SCOPE)
|
||||
set(CUDNN_INCLUDE_DIR "${PC_CUDNN_INCLUDE_DIRS}" PARENT_SCOPE)
|
||||
set(CUDNN_LIBRARIES "${PC_CUDNN_LIBRARIES}" PARENT_SCOPE)
|
||||
set(CUDNN_VERSION_STRING "${PC_CUDNN_VERSION}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Final attempt: check if cuDNN is embedded in CUDA installation
|
||||
if(CUDAToolkit_FOUND AND CUDAToolkit_INCLUDE_DIRS)
|
||||
foreach(cuda_include_dir ${CUDAToolkit_INCLUDE_DIRS})
|
||||
if(EXISTS "${cuda_include_dir}/cudnn.h")
|
||||
message(STATUS "✅ Found cuDNN embedded in CUDA installation")
|
||||
set(HAVE_CUDNN TRUE PARENT_SCOPE)
|
||||
set(CUDNN_INCLUDE_DIR "${cuda_include_dir}" PARENT_SCOPE)
|
||||
set(CUDNN_LIBRARIES "" PARENT_SCOPE) # May be linked with CUDA
|
||||
set(CUDNN_VERSION_STRING "Embedded" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
message(STATUS "❌ cuDNN not found. Searched extensively in:")
|
||||
message(STATUS " Environment variables: CUDNN_ROOT_DIR, CUDNN_ROOT, CUDA_PATH, CUDA_HOME")
|
||||
message(STATUS " CUDA installation: ${CUDAToolkit_ROOT}")
|
||||
if(WIN32)
|
||||
message(STATUS " System paths: $ENV{ProgramFiles}/NVIDIA GPU Computing Toolkit")
|
||||
else()
|
||||
message(STATUS " System paths: /usr, /usr/local, /opt")
|
||||
endif()
|
||||
message(STATUS " Package manager: pkg-config")
|
||||
message(STATUS "")
|
||||
message(STATUS "💡 To fix this issue:")
|
||||
message(STATUS " 1. Install cuDNN development libraries")
|
||||
message(STATUS " 2. Set CUDNN_ROOT_DIR to your cuDNN installation")
|
||||
message(STATUS " 3. Ensure cuDNN headers are in CUDA_PATH/include")
|
||||
message(STATUS " 4. Or disable cuDNN with -DHELPERS_cudnn=OFF")
|
||||
|
||||
# Debug information
|
||||
message(STATUS "")
|
||||
message(STATUS "🔍 Debug information:")
|
||||
message(STATUS " CUDAToolkit_ROOT: ${CUDAToolkit_ROOT}")
|
||||
message(STATUS " CUDAToolkit_INCLUDE_DIRS: ${CUDAToolkit_INCLUDE_DIRS}")
|
||||
message(STATUS " ENV CUDNN_ROOT_DIR: $ENV{CUDNN_ROOT_DIR}")
|
||||
message(STATUS " ENV CUDA_PATH: $ENV{CUDA_PATH}")
|
||||
message(STATUS " ENV CUDA_HOME: $ENV{CUDA_HOME}")
|
||||
endfunction()
|
||||
|
||||
function(configure_cuda_linking main_target_name)
|
||||
# Setup CUDA toolkit paths first
|
||||
setup_cuda_toolkit_paths()
|
||||
|
||||
# Find the CUDAToolkit to define the CUDA::toolkit target
|
||||
find_package(CUDAToolkit REQUIRED)
|
||||
|
||||
# Setup modern cuDNN detection
|
||||
setup_modern_cudnn()
|
||||
|
||||
# This ensures cuda.h and other CUDA headers are found
|
||||
if(CUDA_INCLUDE_DIRS)
|
||||
target_include_directories(${main_target_name} PUBLIC ${CUDA_INCLUDE_DIRS})
|
||||
message(STATUS "✅ Added CUDA include directories to ${main_target_name}: ${CUDA_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
# Apply GNU-specific CUDA compiler flags for duplicate instantiation handling
|
||||
# ONLY for non-Windows builds
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT WIN32)
|
||||
message(STATUS "🔧 Applying GNU-specific CUDA flags for duplicate instantiation handling")
|
||||
target_compile_options(${main_target_name} PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=-fno-implicit-templates>
|
||||
)
|
||||
endif()
|
||||
|
||||
# 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)
|
||||
|
||||
# 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_link_libraries(${main_target_name} PUBLIC flatbuffers_interface)
|
||||
install(TARGETS ${main_target_name} DESTINATION .)
|
||||
endfunction()
|
||||
|
||||
function(setup_cuda_architectures_early)
|
||||
if(NOT SD_CUDA)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Fix missing _CMAKE_CUDA_WHOLE_FLAG (note the underscore prefix)
|
||||
if(NOT DEFINED _CMAKE_CUDA_WHOLE_FLAG)
|
||||
message(STATUS "Setting _CMAKE_CUDA_WHOLE_FLAG (was missing)")
|
||||
if(WIN32)
|
||||
set(_CMAKE_CUDA_WHOLE_FLAG "/WHOLEARCHIVE:" CACHE INTERNAL "CUDA whole archive flag")
|
||||
else()
|
||||
set(_CMAKE_CUDA_WHOLE_FLAG "-Wl,--whole-archive" CACHE INTERNAL "CUDA whole archive flag")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_CUDA_WHOLE_FLAG)
|
||||
if(WIN32)
|
||||
set(CMAKE_CUDA_WHOLE_FLAG "/WHOLEARCHIVE:" CACHE STRING "CUDA whole archive flag")
|
||||
else()
|
||||
set(CMAKE_CUDA_WHOLE_FLAG "-Wl,--whole-archive" CACHE STRING "CUDA whole archive flag")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "🔧 Early CUDA: Configuring architectures before project() call")
|
||||
|
||||
if(DEFINED COMPUTE)
|
||||
string(TOLOWER "${COMPUTE}" COMPUTE_CMP)
|
||||
if(COMPUTE_CMP STREQUAL "all")
|
||||
set(CUDA_ARCHITECTURES "75;80;86;89" PARENT_SCOPE)
|
||||
message(STATUS " CUDA architectures (all): 75;80;86;89")
|
||||
elseif(COMPUTE_CMP STREQUAL "auto")
|
||||
set(CMAKE_CUDA_ARCHITECTURES "86" PARENT_SCOPE)
|
||||
message(STATUS " CUDA architectures (auto): 86")
|
||||
else()
|
||||
string(REPLACE "," ";" ARCH_LIST "${COMPUTE}")
|
||||
set(PARSED_ARCHS "")
|
||||
foreach(ARCH ${ARCH_LIST})
|
||||
string(REPLACE "." "" ARCH_CLEAN "${ARCH}")
|
||||
if(ARCH_CLEAN MATCHES "^[0-9][0-9]$")
|
||||
list(APPEND PARSED_ARCHS "${ARCH_CLEAN}")
|
||||
endif()
|
||||
endforeach()
|
||||
if(PARSED_ARCHS)
|
||||
set(CUDA_ARCHITECTURES "${PARSED_ARCHS}" PARENT_SCOPE)
|
||||
message(STATUS " CUDA architectures (custom): ${PARSED_ARCHS}")
|
||||
else()
|
||||
set(CUDA_ARCHITECTURES "86" PARENT_SCOPE)
|
||||
message(STATUS " CUDA architectures (default): 86")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(CUDA_ARCHITECTURES "86" PARENT_SCOPE)
|
||||
message(STATUS " CUDA architectures (no COMPUTE): 86")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(setup_cuda_language)
|
||||
if(NOT DEFINED _CMAKE_CUDA_WHOLE_FLAG)
|
||||
message(STATUS "Setting _CMAKE_CUDA_WHOLE_FLAG (was missing)")
|
||||
if(WIN32)
|
||||
set(_CMAKE_CUDA_WHOLE_FLAG "/WHOLEARCHIVE:" CACHE INTERNAL "CUDA whole archive flag")
|
||||
else()
|
||||
set(_CMAKE_CUDA_WHOLE_FLAG "-Wl,--whole-archive" CACHE INTERNAL "CUDA whole archive flag")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CheckLanguage)
|
||||
check_language(CUDA)
|
||||
|
||||
if(NOT CMAKE_CUDA_COMPILER)
|
||||
find_program(NVCC_EXECUTABLE nvcc)
|
||||
if(NVCC_EXECUTABLE)
|
||||
set(CMAKE_CUDA_COMPILER ${NVCC_EXECUTABLE} PARENT_SCOPE)
|
||||
message(STATUS "CUDA compiler found: ${CMAKE_CUDA_COMPILER}")
|
||||
else()
|
||||
message(FATAL_ERROR "CUDA compiler not found. Please ensure CUDA toolkit is installed and nvcc is in PATH.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "CUDA language enabled successfully with compiler: ${CMAKE_CUDA_COMPILER}")
|
||||
endfunction()
|
||||
|
||||
function(configure_windows_cuda_build)
|
||||
if(NOT WIN32)
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Configuring Windows CUDA build with verbose mode...")
|
||||
|
||||
# Enable verbose output for the build system
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON PARENT_SCOPE)
|
||||
set(CMAKE_CUDA_VERBOSE_FLAG ON PARENT_SCOPE)
|
||||
|
||||
# Completely disable response files to prevent command line issues
|
||||
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS OFF PARENT_SCOPE)
|
||||
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES OFF PARENT_SCOPE)
|
||||
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES OFF PARENT_SCOPE)
|
||||
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LINK_OBJECTS OFF PARENT_SCOPE)
|
||||
|
||||
# Remove problematic dependency generation that causes NVCC failures
|
||||
set(CMAKE_CUDA_DEPFILE_FORMAT "" PARENT_SCOPE)
|
||||
set(CMAKE_CUDA_DEPENDS_USE_COMPILER OFF PARENT_SCOPE)
|
||||
|
||||
# Clean MSVC runtime library settings
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "" PARENT_SCOPE)
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "" PARENT_SCOPE)
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "" PARENT_SCOPE)
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "" PARENT_SCOPE)
|
||||
|
||||
# Force clean CXX flags to prevent contamination
|
||||
set(CMAKE_CXX_FLAGS "" PARENT_SCOPE)
|
||||
|
||||
# Enable verbose rule and target messages
|
||||
set_property(GLOBAL PROPERTY RULE_MESSAGES ON)
|
||||
set_property(GLOBAL PROPERTY TARGET_MESSAGES ON)
|
||||
|
||||
message(STATUS "Windows CUDA: Verbose mode enabled with clean flags")
|
||||
endfunction()
|
||||
function(configure_cuda_architecture_flags COMPUTE)
|
||||
string(TOLOWER "${COMPUTE}" COMPUTE_CMP)
|
||||
if(COMPUTE_CMP STREQUAL "all")
|
||||
set(CUDA_ARCH_FLAGS "-gencode arch=compute_75,code=sm_75 -gencode arch=compute_80,code=sm_80 -gencode arch=compute_86,code=sm_86 -gencode arch=compute_89,code=sm_89" PARENT_SCOPE)
|
||||
message(STATUS "Building for all CUDA architectures (gencode flags)")
|
||||
elseif(COMPUTE_CMP STREQUAL "auto")
|
||||
set(CUDA_ARCH_FLAGS "-gencode arch=compute_86,code=sm_86" PARENT_SCOPE)
|
||||
message(STATUS "Auto-detecting CUDA architectures (gencode flags)")
|
||||
else()
|
||||
string(REPLACE "," ";" ARCH_LIST "${COMPUTE}")
|
||||
set(ARCH_FLAGS "")
|
||||
foreach(ARCH ${ARCH_LIST})
|
||||
string(REPLACE "." "" ARCH_CLEAN "${ARCH}")
|
||||
if(ARCH_CLEAN MATCHES "^[0-9][0-9]$")
|
||||
set(ARCH_FLAGS "${ARCH_FLAGS} -gencode arch=compute_${ARCH_CLEAN},code=sm_${ARCH_CLEAN}")
|
||||
endif()
|
||||
endforeach()
|
||||
string(STRIP "${ARCH_FLAGS}" ARCH_FLAGS)
|
||||
if(ARCH_FLAGS)
|
||||
set(CUDA_ARCH_FLAGS "${ARCH_FLAGS}" PARENT_SCOPE)
|
||||
message(STATUS "Using custom CUDA architectures (gencode flags): ${ARCH_FLAGS}")
|
||||
else()
|
||||
set(CUDA_ARCH_FLAGS "-gencode arch=compute_86,code=sm_86" PARENT_SCOPE)
|
||||
message(STATUS "Using default CUDA architecture (gencode flags)")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(build_cuda_compiler_flags CUDA_ARCH_FLAGS)
|
||||
set(LOCAL_CUDA_FLAGS "")
|
||||
|
||||
if(WIN32 AND MSVC)
|
||||
message(STATUS "Configuring CUDA for Windows MSVC with verbose mode...")
|
||||
set(CMAKE_CUDA_HOST_COMPILER ${CMAKE_CXX_COMPILER} PARENT_SCOPE)
|
||||
set(LOCAL_CUDA_FLAGS "-maxrregcount=128")
|
||||
|
||||
# Enable verbose mode for Windows CUDA compilation
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} --verbose")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} --ptxas-options=-v")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} --resource-usage")
|
||||
|
||||
# Host compiler verbose flags
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xcompiler=/showIncludes")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xcompiler=/verbose")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xcompiler=/diagnostics:caret")
|
||||
|
||||
# Linker verbose flags
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xlinker=/VERBOSE")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xlinker=/TIME")
|
||||
|
||||
# Explicitly enable C++17 for the host compiler
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xcompiler=/std:c++17")
|
||||
|
||||
if(WIN32 AND NOT CMAKE_CUDA_HOST_COMPILER)
|
||||
find_program(CL_IN_PATH cl.exe)
|
||||
if(CL_IN_PATH)
|
||||
# Check if this cl.exe is 64-bit by examining its path
|
||||
get_filename_component(CL_DIR ${CL_IN_PATH} DIRECTORY)
|
||||
if(CL_DIR MATCHES "x64")
|
||||
set(CMAKE_CUDA_HOST_COMPILER ${CL_IN_PATH})
|
||||
message(STATUS "Found x64 cl.exe in PATH: ${CMAKE_CUDA_HOST_COMPILER}")
|
||||
else()
|
||||
# Try to find x64 version relative to this cl.exe
|
||||
get_filename_component(CL_PARENT ${CL_DIR} DIRECTORY)
|
||||
if(EXISTS "${CL_PARENT}/x64/cl.exe")
|
||||
set(CMAKE_CUDA_HOST_COMPILER "${CL_PARENT}/x64/cl.exe")
|
||||
message(STATUS "Found x64 cl.exe relative to PATH cl.exe: ${CMAKE_CUDA_HOST_COMPILER}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32 AND NOT CMAKE_CUDA_HOST_COMPILER)
|
||||
# Only check the most common paths that exist in barebones installs
|
||||
set(COMMON_PATHS
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC"
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC"
|
||||
"C:/Program Files/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC"
|
||||
)
|
||||
|
||||
foreach(BASE_PATH ${COMMON_PATHS})
|
||||
if(EXISTS ${BASE_PATH})
|
||||
file(GLOB MSVC_VERSIONS "${BASE_PATH}/*")
|
||||
if(MSVC_VERSIONS)
|
||||
# Get the lexicographically last version (should be newest)
|
||||
list(SORT MSVC_VERSIONS)
|
||||
list(REVERSE MSVC_VERSIONS)
|
||||
list(GET MSVC_VERSIONS 0 LATEST_MSVC)
|
||||
|
||||
set(CANDIDATE_COMPILER "${LATEST_MSVC}/bin/Hostx64/x64/cl.exe")
|
||||
if(EXISTS ${CANDIDATE_COMPILER})
|
||||
set(CMAKE_CUDA_HOST_COMPILER ${CANDIDATE_COMPILER})
|
||||
message(STATUS "Found CUDA host compiler in standard path: ${CMAKE_CUDA_HOST_COMPILER}")
|
||||
break()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Validation and warning
|
||||
if(WIN32)
|
||||
if(CMAKE_CUDA_HOST_COMPILER)
|
||||
if(NOT EXISTS ${CMAKE_CUDA_HOST_COMPILER})
|
||||
message(WARNING "CUDA host compiler path does not exist: ${CMAKE_CUDA_HOST_COMPILER}")
|
||||
unset(CMAKE_CUDA_HOST_COMPILER)
|
||||
else()
|
||||
message(STATUS "Final CUDA host compiler: ${CMAKE_CUDA_HOST_COMPILER}")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Could not auto-detect x64 CUDA host compiler.")
|
||||
message(STATUS "Manual options:")
|
||||
message(STATUS " 1. Use x64 Native Tools Command Prompt")
|
||||
message(STATUS " 2. Set manually: -DCMAKE_CUDA_HOST_COMPILER=\"path/to/x64/cl.exe\"")
|
||||
message(STATUS " 3. Ensure x64 cl.exe is in your PATH")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Windows/MSVC flags: bigobj, EHsc, *and* disable the new preprocessor
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}
|
||||
-Xcompiler=/std:c++17
|
||||
-Xcompiler=/bigobj
|
||||
-Xcompiler=/EHsc
|
||||
-Xcompiler=/Zc:preprocessor-")
|
||||
|
||||
# Force clean host compiler flags
|
||||
set(CMAKE_CXX_FLAGS "" PARENT_SCOPE)
|
||||
|
||||
message(STATUS "CUDA Windows verbose flags configured")
|
||||
else()
|
||||
message(STATUS "Configuring CUDA for Unix/Linux with verbose mode...")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -maxrregcount=128")
|
||||
|
||||
# Enable verbose mode for Unix/Linux CUDA compilation
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} --verbose")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} --ptxas-options=-v")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} --resource-usage")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# Host compiler verbose flags for GCC
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xcompiler=-v")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xcompiler=-H")
|
||||
|
||||
# Linker verbose flags
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xlinker=-v")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xlinker=--verbose")
|
||||
|
||||
if(SD_GCC_FUNCTRACE)
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xcompiler=-fPIC --device-debug -lineinfo -G")
|
||||
else()
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xcompiler=-fPIC -Xcompiler=-fpermissive")
|
||||
# Add flags to handle duplicate instantiations for GNU compiler
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -Xcompiler=-fno-implicit-templates")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "CUDA Unix/Linux verbose flags configured")
|
||||
endif()
|
||||
|
||||
if("${SD_PTXAS}" STREQUAL "ON")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} --ptxas-options=-v")
|
||||
endif()
|
||||
|
||||
if(SD_KEEP_NVCC_OUTPUT)
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} --keep")
|
||||
endif()
|
||||
|
||||
if(DEFINED CUDA_ARCH_FLAGS)
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} ${CUDA_ARCH_FLAGS}")
|
||||
endif()
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -w --cudart=shared --expt-extended-lambda -Xfatbin -compress-all")
|
||||
|
||||
if(CMAKE_CUDA_COMPILER_VERSION)
|
||||
string(REGEX MATCH "^([0-9]+)" CUDA_VERSION_MAJOR "${CMAKE_CUDA_COMPILER_VERSION}")
|
||||
set(LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS} -DCUDA_VERSION_MAJOR=${CUDA_VERSION_MAJOR}")
|
||||
endif()
|
||||
|
||||
# Clean up any problematic flags for Windows
|
||||
if(WIN32)
|
||||
# Remove any GCC-style flags that might have been added
|
||||
string(REGEX REPLACE "-MD[^a-zA-Z]" "" LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
string(REGEX REPLACE "-MT[^a-zA-Z]" "" LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
string(REGEX REPLACE "-MF[^a-zA-Z]" "" LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
string(REGEX REPLACE "-x cu" "" LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
string(REGEX REPLACE "-fpermissive" "" LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
string(REGEX REPLACE "-Wno-error" "" LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
string(REGEX REPLACE "/FS[ ]*" "" LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
string(REGEX REPLACE "-Xcompiler=-Fd[^,]*,?" "" LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
string(REGEX REPLACE "-Xcompiler=," "-Xcompiler=" LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
string(REGEX REPLACE "-Xcompiler=$" "" LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
endif()
|
||||
|
||||
string(REGEX REPLACE " +" " " LOCAL_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}")
|
||||
string(STRIP "${LOCAL_CUDA_FLAGS}" LOCAL_CUDA_FLAGS)
|
||||
|
||||
set(CMAKE_CUDA_SEPARABLE_COMPILATION ON PARENT_SCOPE)
|
||||
set(CMAKE_CUDA_FLAGS "${LOCAL_CUDA_FLAGS}" PARENT_SCOPE)
|
||||
|
||||
message(STATUS "Final CMAKE_CUDA_FLAGS (with verbose): ${LOCAL_CUDA_FLAGS}")
|
||||
endfunction()
|
||||
|
||||
# Debug configuration function
|
||||
function(debug_cuda_configuration)
|
||||
message(STATUS "=== CUDA Configuration Debug Info ===")
|
||||
message(STATUS "CMAKE_CUDA_COMPILER: ${CMAKE_CUDA_COMPILER}")
|
||||
message(STATUS "CMAKE_CUDA_COMPILER_VERSION: ${CMAKE_CUDA_COMPILER_VERSION}")
|
||||
message(STATUS "CMAKE_CUDA_ARCHITECTURES: ${CMAKE_CUDA_ARCHITECTURES}")
|
||||
message(STATUS "CMAKE_CUDA_FLAGS: ${CMAKE_CUDA_FLAGS}")
|
||||
message(STATUS "CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES: ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}")
|
||||
message(STATUS "CMAKE_CUDA_COMPILE_OBJECT: ${CMAKE_CUDA_COMPILE_OBJECT}")
|
||||
message(STATUS "CUDA_INCLUDE_DIRS: ${CUDA_INCLUDE_DIRS}")
|
||||
message(STATUS "CUDAToolkit_ROOT: ${CUDAToolkit_ROOT}")
|
||||
message(STATUS "CUDAToolkit_INCLUDE_DIRS: ${CUDAToolkit_INCLUDE_DIRS}")
|
||||
if(HAVE_CUDNN)
|
||||
message(STATUS "CUDNN_INCLUDE_DIR: ${CUDNN_INCLUDE_DIR}")
|
||||
message(STATUS "CUDNN_LIBRARIES: ${CUDNN_LIBRARIES}")
|
||||
message(STATUS "CUDNN_VERSION: ${CUDNN_VERSION_STRING}")
|
||||
endif()
|
||||
message(STATUS "=== End CUDA Debug Info ===")
|
||||
endfunction()
|
||||
|
||||
# Enhanced CUDA include directory setup for global configuration
|
||||
function(setup_cuda_include_directories)
|
||||
setup_cuda_toolkit_paths()
|
||||
|
||||
# Set global include directories that will be inherited by all targets
|
||||
if(CUDA_INCLUDE_DIRS)
|
||||
include_directories(${CUDA_INCLUDE_DIRS})
|
||||
message(STATUS "✅ Added global CUDA include directories: ${CUDA_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
# Also set the CMAKE variable for compatibility
|
||||
if(CUDAToolkit_INCLUDE_DIRS)
|
||||
set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES ${CUDAToolkit_INCLUDE_DIRS} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(setup_cuda_build)
|
||||
message(STATUS "=== CUDA BUILD CONFIGURATION (VERBOSE MODE) ===")
|
||||
|
||||
# Enable verbose output for the build system
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON PARENT_SCOPE)
|
||||
set(CMAKE_CUDA_VERBOSE_FLAG ON PARENT_SCOPE)
|
||||
|
||||
if(NOT DEFINED _CMAKE_CUDA_WHOLE_FLAG)
|
||||
message(STATUS "Setting _CMAKE_CUDA_WHOLE_FLAG (was missing)")
|
||||
if(WIN32)
|
||||
set(_CMAKE_CUDA_WHOLE_FLAG "/WHOLEARCHIVE:" CACHE INTERNAL "CUDA whole archive flag")
|
||||
else()
|
||||
set(_CMAKE_CUDA_WHOLE_FLAG "-Wl,--whole-archive" CACHE INTERNAL "CUDA whole archive flag")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Setup CUDA toolkit paths and include directories early
|
||||
setup_cuda_include_directories()
|
||||
|
||||
if(NOT DEFINED COMPUTE)
|
||||
set(COMPUTE "auto")
|
||||
endif()
|
||||
configure_cuda_architecture_flags("${COMPUTE}")
|
||||
set_property(GLOBAL PROPERTY CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES}")
|
||||
|
||||
setup_cuda_language()
|
||||
|
||||
if(NOT CMAKE_CUDA_COMPILER)
|
||||
message(FATAL_ERROR "CUDA compiler not found after enabling CUDA language")
|
||||
endif()
|
||||
|
||||
message(STATUS "CUDA Compiler: ${CMAKE_CUDA_COMPILER}")
|
||||
message(STATUS "CUDA Include Dirs: ${CUDA_INCLUDE_DIRS}")
|
||||
message(STATUS "CUDAToolkit Include Dirs: ${CUDAToolkit_INCLUDE_DIRS}")
|
||||
message(STATUS "Host CXX Compiler: ${CMAKE_CXX_COMPILER_ID}")
|
||||
|
||||
configure_windows_cuda_build()
|
||||
build_cuda_compiler_flags("${CUDA_ARCH_FLAGS}")
|
||||
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS}" PARENT_SCOPE)
|
||||
|
||||
# Also set the toolkit include directories for global access
|
||||
set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${CUDA_INCLUDE_DIRS}" PARENT_SCOPE)
|
||||
|
||||
# Enable verbose rule and target messages
|
||||
set_property(GLOBAL PROPERTY RULE_MESSAGES ON)
|
||||
set_property(GLOBAL PROPERTY TARGET_MESSAGES ON)
|
||||
|
||||
debug_cuda_configuration()
|
||||
|
||||
add_compile_definitions(SD_CUDA=true)
|
||||
set(DEFAULT_ENGINE "samediff::ENGINE_CUDA" PARENT_SCOPE)
|
||||
|
||||
message(STATUS "=== CUDA BUILD CONFIGURATION (VERBOSE MODE) COMPLETE ===")
|
||||
endfunction()
|
||||
|
||||
# Enhanced function to ensure CUDA paths are available at configure time
|
||||
function(ensure_cuda_paths_available)
|
||||
if(NOT SD_CUDA)
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "🔍 Ensuring CUDA paths are available...")
|
||||
|
||||
# Find CUDA early
|
||||
find_package(CUDAToolkit REQUIRED)
|
||||
|
||||
# Set up paths immediately
|
||||
setup_cuda_toolkit_paths()
|
||||
|
||||
# Export to parent scope for immediate use
|
||||
set(CUDA_INCLUDE_DIRS "${CUDA_INCLUDE_DIRS}" PARENT_SCOPE)
|
||||
set(CUDA_TOOLKIT_ROOT_DIR "${CUDAToolkit_ROOT}" PARENT_SCOPE)
|
||||
|
||||
message(STATUS "✅ CUDA paths configured and available")
|
||||
endfunction()
|
||||
|
||||
# Legacy function for backward compatibility - now calls modern version
|
||||
function(setup_cudnn)
|
||||
setup_modern_cudnn()
|
||||
|
||||
# Set legacy variables for backward compatibility
|
||||
set(HAVE_CUDNN ${HAVE_CUDNN} PARENT_SCOPE)
|
||||
if(HAVE_CUDNN)
|
||||
set(CUDNN_INCLUDE_DIR ${CUDNN_INCLUDE_DIR} PARENT_SCOPE)
|
||||
set(CUDNN ${CUDNN_LIBRARIES} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,510 @@
|
||||
# cmake/Dependencies.cmake
|
||||
# Manages all third-party dependencies. Logic is encapsulated in functions.
|
||||
|
||||
include(ExternalProject)
|
||||
function(setup_android_arm_openblas)
|
||||
set(is_android_or_arm FALSE)
|
||||
|
||||
if(ANDROID OR SD_ANDROID_BUILD OR SD_ARM_BUILD OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64|arm64|ARM64")
|
||||
set(is_android_or_arm TRUE)
|
||||
endif()
|
||||
|
||||
if(NOT is_android_or_arm)
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "🔧 Setting up OpenBLAS for Android/ARM platform")
|
||||
|
||||
# Handle path normalization for Android/ARM
|
||||
if(OPENBLAS_PATH MATCHES "lib/[^/]+$")
|
||||
get_filename_component(OPENBLAS_PATH "${OPENBLAS_PATH}/../.." ABSOLUTE)
|
||||
message(STATUS "🔧 Normalized OPENBLAS_PATH: ${OPENBLAS_PATH}")
|
||||
endif()
|
||||
|
||||
# Platform-specific OpenBLAS library name handling
|
||||
if(EXISTS "${OPENBLAS_PATH}/lib")
|
||||
# Define search patterns based on platform
|
||||
set(LIB_SEARCH_PATTERNS
|
||||
"${OPENBLAS_PATH}/lib/libopenblas.so"
|
||||
"${OPENBLAS_PATH}/lib/libopenblas.a"
|
||||
)
|
||||
|
||||
# Add platform-specific patterns
|
||||
if(ANDROID OR SD_ANDROID_BUILD)
|
||||
if(CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")
|
||||
list(APPEND LIB_SEARCH_PATTERNS
|
||||
"${OPENBLAS_PATH}/lib/android-x86_64/libopenblas.so"
|
||||
"${OPENBLAS_PATH}/lib/android-x86_64/libopenblas.a"
|
||||
)
|
||||
elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
|
||||
list(APPEND LIB_SEARCH_PATTERNS
|
||||
"${OPENBLAS_PATH}/lib/android-arm64/libopenblas.so"
|
||||
"${OPENBLAS_PATH}/lib/android-arm64/libopenblas.a"
|
||||
"${OPENBLAS_PATH}/lib/android-aarch64/libopenblas.so"
|
||||
"${OPENBLAS_PATH}/lib/android-aarch64/libopenblas.a"
|
||||
)
|
||||
endif()
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64|arm64|ARM64")
|
||||
list(APPEND LIB_SEARCH_PATTERNS
|
||||
"${OPENBLAS_PATH}/lib/linux-arm64/libopenblas.so"
|
||||
"${OPENBLAS_PATH}/lib/linux-arm64/libopenblas.a"
|
||||
"${OPENBLAS_PATH}/lib/linux-aarch64/libopenblas.so"
|
||||
"${OPENBLAS_PATH}/lib/linux-aarch64/libopenblas.a"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Search for libraries
|
||||
set(FOUND_OPENBLAS_LIBS "")
|
||||
foreach(pattern ${LIB_SEARCH_PATTERNS})
|
||||
file(GLOB matched_libs ${pattern})
|
||||
if(matched_libs)
|
||||
list(APPEND FOUND_OPENBLAS_LIBS ${matched_libs})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(FOUND_OPENBLAS_LIBS)
|
||||
message(STATUS "✅ Found OpenBLAS libraries: ${FOUND_OPENBLAS_LIBS}")
|
||||
else()
|
||||
message(WARNING "⚠️ No OpenBLAS libraries found in ${OPENBLAS_PATH}/lib")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set platform-specific compiler flags for OpenBLAS
|
||||
if(ANDROID OR SD_ANDROID_BUILD)
|
||||
if(CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64" PARENT_SCOPE)
|
||||
elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a" PARENT_SCOPE)
|
||||
endif()
|
||||
elseif(SD_ARM_BUILD OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64|arm64|ARM64")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a -mtune=cortex-a72" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a -mtune=cortex-a72" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
# Set additional ARM-specific optimizations
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64|arm64|ARM64" OR CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfix-cortex-a53-835769 -mfix-cortex-a53-843419" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfix-cortex-a53-835769 -mfix-cortex-a53-843419" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
function(setup_blas)
|
||||
if(SD_CUDA)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT OPENBLAS_PATH)
|
||||
message(STATUS "❌ OPENBLAS_PATH not set")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Handle Android path normalization at CMake level (in case shell script normalization didn't work)
|
||||
setup_android_arm_openblas()
|
||||
|
||||
|
||||
# Verify the path exists and has the required headers
|
||||
if(NOT EXISTS "${OPENBLAS_PATH}/include")
|
||||
message(STATUS "❌ OpenBLAS include directory not found: ${OPENBLAS_PATH}/include")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${OPENBLAS_PATH}/include/cblas.h")
|
||||
message(STATUS "❌ OpenBLAS cblas.h not found: ${OPENBLAS_PATH}/include/cblas.h")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Set up OpenBLAS
|
||||
message(STATUS "✅ Setting up OpenBLAS:")
|
||||
message(STATUS " Path: ${OPENBLAS_PATH}")
|
||||
message(STATUS " Include: ${OPENBLAS_PATH}/include")
|
||||
message(STATUS " Library: ${OPENBLAS_PATH}/")
|
||||
|
||||
# Use global include_directories for compatibility
|
||||
include_directories(${OPENBLAS_PATH}/include/)
|
||||
|
||||
# Set up library directories
|
||||
if(EXISTS "${OPENBLAS_PATH}/lib")
|
||||
link_directories(${OPENBLAS_PATH}/)
|
||||
endif()
|
||||
|
||||
add_compile_definitions(HAVE_OPENBLAS=1)
|
||||
|
||||
# Set parent scope variables
|
||||
set(HAVE_OPENBLAS 1 PARENT_SCOPE)
|
||||
set(OPENBLAS_LIBRARIES openblas PARENT_SCOPE)
|
||||
|
||||
set(OPENBLAS_PATH "${OPENBLAS_PATH}" PARENT_SCOPE)
|
||||
|
||||
message(STATUS "✅ OpenBLAS setup complete")
|
||||
endfunction()
|
||||
|
||||
|
||||
|
||||
|
||||
function(setup_cudnn)
|
||||
set(HAVE_CUDNN false PARENT_SCOPE)
|
||||
set(CUDNN "" PARENT_SCOPE)
|
||||
|
||||
if(NOT (HELPERS_cudnn STREQUAL "ON" AND SD_CUDA))
|
||||
message(STATUS "cuDNN helper is disabled (HELPERS_cudnn=${HELPERS_cudnn}, SD_CUDA=${SD_CUDA})")
|
||||
return()
|
||||
endif()
|
||||
endfunction()
|
||||
# =============================================================================
|
||||
# FLATBUFFERS (Required) - Cross-compilation compatible version
|
||||
# =============================================================================
|
||||
function(setup_flatbuffers)
|
||||
set(FLATBUFFERS_VERSION "25.2.10")
|
||||
set(FLATBUFFERS_URL "https://github.com/google/flatbuffers/archive/v${FLATBUFFERS_VERSION}.tar.gz")
|
||||
|
||||
# Determine if we should build flatc
|
||||
set(SHOULD_BUILD_FLATC FALSE)
|
||||
if(DEFINED ENV{GENERATE_FLATC} OR DEFINED GENERATE_FLATC)
|
||||
set(SHOULD_BUILD_FLATC TRUE)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CROSSCOMPILING AND SHOULD_BUILD_FLATC)
|
||||
# Cross-compilation scenario: build flatc for host, library for target
|
||||
message(STATUS "Cross-compiling FlatBuffers: building flatc for host, library for target")
|
||||
|
||||
# Stage 1: Build flatc for host system
|
||||
set(FLATC_HOST_DIR "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-host")
|
||||
set(FLATC_HOST_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-host-build")
|
||||
set(FLATC_EXECUTABLE "${FLATC_HOST_BUILD_DIR}/flatc")
|
||||
|
||||
# Determine host system compilers
|
||||
find_program(HOST_C_COMPILER NAMES gcc clang cc)
|
||||
find_program(HOST_CXX_COMPILER NAMES g++ clang++ c++)
|
||||
|
||||
if(NOT HOST_C_COMPILER OR NOT HOST_CXX_COMPILER)
|
||||
message(FATAL_ERROR "Could not find host system compilers for flatc build")
|
||||
endif()
|
||||
|
||||
# Build CMAKE_ARGS without toolchain file for host build
|
||||
set(HOST_CMAKE_ARGS
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DFLATBUFFERS_BUILD_FLATC=ON
|
||||
-DFLATBUFFERS_BUILD_FLATLIB=OFF
|
||||
-DFLATBUFFERS_BUILD_TESTS=OFF
|
||||
-DFLATBUFFERS_BUILD_SAMPLES=OFF
|
||||
-DCMAKE_C_COMPILER=${HOST_C_COMPILER}
|
||||
-DCMAKE_CXX_COMPILER=${HOST_CXX_COMPILER}
|
||||
)
|
||||
|
||||
ExternalProject_Add(flatbuffers_host
|
||||
URL ${FLATBUFFERS_URL}
|
||||
SOURCE_DIR "${FLATC_HOST_DIR}"
|
||||
BINARY_DIR "${FLATC_HOST_BUILD_DIR}"
|
||||
CMAKE_ARGS ${HOST_CMAKE_ARGS}
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} --build . --target flatc --config Release
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_BYPRODUCTS "${FLATC_EXECUTABLE}"
|
||||
)
|
||||
|
||||
# Stage 2: Build FlatBuffers library for target
|
||||
# Build CMAKE_ARGS for target build, only include variables that are set
|
||||
set(TARGET_CMAKE_ARGS
|
||||
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DFLATBUFFERS_BUILD_FLATC=OFF
|
||||
-DFLATBUFFERS_BUILD_FLATLIB=ON
|
||||
-DFLATBUFFERS_BUILD_TESTS=OFF
|
||||
-DFLATBUFFERS_BUILD_SAMPLES=OFF
|
||||
)
|
||||
|
||||
# Only add cross-compilation arguments if they are defined
|
||||
if(CMAKE_TOOLCHAIN_FILE)
|
||||
list(APPEND TARGET_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME)
|
||||
list(APPEND TARGET_CMAKE_ARGS -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_VERSION)
|
||||
list(APPEND TARGET_CMAKE_ARGS -DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION})
|
||||
endif()
|
||||
if(CMAKE_ANDROID_ARCH_ABI)
|
||||
list(APPEND TARGET_CMAKE_ARGS -DCMAKE_ANDROID_ARCH_ABI=${CMAKE_ANDROID_ARCH_ABI})
|
||||
endif()
|
||||
if(CMAKE_ANDROID_NDK)
|
||||
list(APPEND TARGET_CMAKE_ARGS -DCMAKE_ANDROID_NDK=${CMAKE_ANDROID_NDK})
|
||||
endif()
|
||||
if(CMAKE_ANDROID_STL_TYPE)
|
||||
list(APPEND TARGET_CMAKE_ARGS -DCMAKE_ANDROID_STL_TYPE=${CMAKE_ANDROID_STL_TYPE})
|
||||
endif()
|
||||
if(ANDROID_ABI)
|
||||
list(APPEND TARGET_CMAKE_ARGS -DANDROID_ABI=${ANDROID_ABI})
|
||||
endif()
|
||||
if(ANDROID_PLATFORM)
|
||||
list(APPEND TARGET_CMAKE_ARGS -DANDROID_PLATFORM=${ANDROID_PLATFORM})
|
||||
endif()
|
||||
if(ANDROID_STL)
|
||||
list(APPEND TARGET_CMAKE_ARGS -DANDROID_STL=${ANDROID_STL})
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(flatbuffers_target
|
||||
URL ${FLATBUFFERS_URL}
|
||||
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-target-src"
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-target-build"
|
||||
CMAKE_ARGS ${TARGET_CMAKE_ARGS}
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-target-build/libflatbuffers.a"
|
||||
DEPENDS flatbuffers_host
|
||||
)
|
||||
|
||||
# DO NOT use include_directories() - use target_include_directories on flatbuffers_interface instead
|
||||
# Set up include directories and library
|
||||
# include_directories("${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-target-src/include")
|
||||
set(FLATBUFFERS_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-target-build/libflatbuffers.a")
|
||||
set(FLATBUFFERS_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-target-src")
|
||||
|
||||
# Create interface library for target
|
||||
add_library(flatbuffers_interface INTERFACE)
|
||||
target_link_libraries(flatbuffers_interface INTERFACE ${FLATBUFFERS_LIBRARY})
|
||||
target_include_directories(flatbuffers_interface INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-target-src/include")
|
||||
add_dependencies(flatbuffers_interface flatbuffers_target)
|
||||
|
||||
# Check if flatbuffers.h already exists
|
||||
set(FLATBUFFERS_HEADER_DEST "${CMAKE_SOURCE_DIR}/libnd4j/include/flatbuffers/flatbuffers.h")
|
||||
if(EXISTS ${FLATBUFFERS_HEADER_DEST})
|
||||
message(STATUS "Found existing flatbuffers.h at ${FLATBUFFERS_HEADER_DEST}")
|
||||
endif()
|
||||
|
||||
# Generate headers and copy Java files inline after ExternalProject builds
|
||||
ExternalProject_Add_Step(flatbuffers_host generate_headers_and_copy_java
|
||||
COMMAND ${CMAKE_COMMAND} -E env "FLATC_PATH=${FLATC_EXECUTABLE}"
|
||||
bash ${CMAKE_CURRENT_SOURCE_DIR}/flatc-generate.sh
|
||||
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/copy-flatc-java.sh
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
"${CMAKE_SOURCE_DIR}/libnd4j/include/flatbuffers"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-host/include/flatbuffers/flatbuffers.h"
|
||||
"${CMAKE_SOURCE_DIR}/libnd4j/include/flatbuffers/flatbuffers.h"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating FlatBuffers headers, copying Java files, and copying flatbuffers.h using host flatc"
|
||||
DEPENDEES build
|
||||
BYPRODUCTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/graph/generated.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/.java_files_copied
|
||||
${CMAKE_SOURCE_DIR}/libnd4j/include/flatbuffers/flatbuffers.h
|
||||
)
|
||||
|
||||
else()
|
||||
# Native build or cross-compilation without flatc generation
|
||||
message(STATUS "Native FlatBuffers build")
|
||||
|
||||
if(SHOULD_BUILD_FLATC)
|
||||
set(FLATBUFFERS_BUILD_FLATC "ON")
|
||||
else()
|
||||
set(FLATBUFFERS_BUILD_FLATC "OFF")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(flatbuffers_external
|
||||
URL ${FLATBUFFERS_URL}
|
||||
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-src"
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build"
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DFLATBUFFERS_BUILD_FLATC=${FLATBUFFERS_BUILD_FLATC}
|
||||
-DFLATBUFFERS_BUILD_FLATLIB=ON
|
||||
-DFLATBUFFERS_BUILD_TESTS=OFF
|
||||
-DFLATBUFFERS_BUILD_SAMPLES=OFF
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_BYPRODUCTS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build/flatc"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build/libflatbuffers.a"
|
||||
)
|
||||
|
||||
# DO NOT use include_directories() - use target_include_directories on flatbuffers_interface instead
|
||||
# include_directories("${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-src/include")
|
||||
set(FLATBUFFERS_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build/libflatbuffers.a")
|
||||
set(FLATBUFFERS_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-src")
|
||||
|
||||
# Check if flatbuffers.h already exists
|
||||
set(FLATBUFFERS_HEADER_DEST "${CMAKE_SOURCE_DIR}/libnd4j/include/flatbuffers/flatbuffers.h")
|
||||
if(EXISTS ${FLATBUFFERS_HEADER_DEST})
|
||||
message(STATUS "Found existing flatbuffers.h at ${FLATBUFFERS_HEADER_DEST}")
|
||||
endif()
|
||||
|
||||
if(SHOULD_BUILD_FLATC)
|
||||
set(FLATC_EXECUTABLE "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build/flatc")
|
||||
|
||||
# Generate headers and copy Java files inline after ExternalProject builds
|
||||
ExternalProject_Add_Step(flatbuffers_external generate_headers_and_copy_java
|
||||
COMMAND ${CMAKE_COMMAND} -E env "FLATC_PATH=${FLATC_EXECUTABLE}"
|
||||
bash ${CMAKE_CURRENT_SOURCE_DIR}/flatc-generate.sh
|
||||
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/copy-flatc-java.sh
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
"${CMAKE_SOURCE_DIR}/include/flatbuffers"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-src/include/flatbuffers/flatbuffers.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/flatbuffers/flatbuffers.h"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating FlatBuffers headers, copying Java files, and copying flatbuffers.h"
|
||||
DEPENDEES build
|
||||
BYPRODUCTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/graph/generated.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/.java_files_copied
|
||||
${CMAKE_SOURCE_DIR}/libnd4j/include/flatbuffers/flatbuffers.h
|
||||
)
|
||||
else()
|
||||
# Even without flatc generation, copy the flatbuffers.h header
|
||||
ExternalProject_Add_Step(flatbuffers_external copy_flatbuffers_header
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
"${CMAKE_SOURCE_DIR}/libnd4j/include/flatbuffers"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-src/include/flatbuffers/flatbuffers.h"
|
||||
"${CMAKE_SOURCE_DIR}/libnd4j/include/flatbuffers/flatbuffers.h"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Copying flatbuffers.h header"
|
||||
DEPENDEES build
|
||||
BYPRODUCTS
|
||||
${CMAKE_SOURCE_DIR}/libnd4j/include/flatbuffers/flatbuffers.h
|
||||
)
|
||||
endif()
|
||||
|
||||
# Create interface library
|
||||
add_library(flatbuffers_interface INTERFACE)
|
||||
target_link_libraries(flatbuffers_interface INTERFACE ${FLATBUFFERS_LIBRARY})
|
||||
target_include_directories(flatbuffers_interface INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-src/include")
|
||||
add_dependencies(flatbuffers_interface flatbuffers_external)
|
||||
endif()
|
||||
|
||||
# Set global variables for parent scope
|
||||
set(FLATBUFFERS_LIBRARY ${FLATBUFFERS_LIBRARY} PARENT_SCOPE)
|
||||
set(FLATBUFFERS_SOURCE_DIR ${FLATBUFFERS_SOURCE_DIR} PARENT_SCOPE)
|
||||
if(SHOULD_BUILD_FLATC)
|
||||
set(FLATC_EXECUTABLE ${FLATC_EXECUTABLE} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
message(STATUS "✅ FlatBuffers setup complete")
|
||||
if(CMAKE_CROSSCOMPILING AND SHOULD_BUILD_FLATC)
|
||||
message(STATUS " Host flatc: ${FLATC_EXECUTABLE}")
|
||||
message(STATUS " Target library: ${FLATBUFFERS_LIBRARY}")
|
||||
else()
|
||||
message(STATUS " Library: ${FLATBUFFERS_LIBRARY}")
|
||||
if(SHOULD_BUILD_FLATC)
|
||||
message(STATUS " flatc: ${FLATC_EXECUTABLE}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
# =============================================================================
|
||||
# ONEDNN (Optional)
|
||||
# =============================================================================
|
||||
function(setup_onednn)
|
||||
if(NOT HELPERS_onednn STREQUAL "ON")
|
||||
message(STATUS "OneDNN helper is disabled (HELPERS_onednn=${HELPERS_onednn})")
|
||||
set(HAVE_ONEDNN FALSE PARENT_SCOPE)
|
||||
set(ONEDNN "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(TARGET onednn_external)
|
||||
message(STATUS "OneDNN helper is enabled (target already exists)")
|
||||
set(HAVE_ONEDNN TRUE PARENT_SCOPE)
|
||||
set(ONEDNN onednn_interface PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "OneDNN helper is enabled")
|
||||
set(HAVE_ONEDNN TRUE PARENT_SCOPE)
|
||||
set(ONEDNN_INSTALL_DIR "${CMAKE_BINARY_DIR}/onednn_install")
|
||||
|
||||
ExternalProject_Add(onednn_external
|
||||
PREFIX "${CMAKE_BINARY_DIR}/onednn_external"
|
||||
GIT_REPOSITORY "https://github.com/uxlfoundation/oneDNN.git"
|
||||
GIT_TAG "v3.8.1"
|
||||
SOURCE_DIR "${CMAKE_BINARY_DIR}/onednn_external/src"
|
||||
BINARY_DIR "${CMAKE_BINARY_DIR}/onednn_external/build"
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${ONEDNN_INSTALL_DIR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DDNNL_LIBRARY_TYPE=STATIC -DDNNL_BUILD_TESTS=OFF -DDNNL_BUILD_EXAMPLES=OFF -DDNNL_VERBOSE=OFF -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config ${CMAKE_BUILD_TYPE} --parallel
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target install --config ${CMAKE_BUILD_TYPE}
|
||||
BUILD_BYPRODUCTS "${ONEDNN_INSTALL_DIR}/include/dnnl.h" "${ONEDNN_INSTALL_DIR}/lib/libdnnl.a" "${ONEDNN_INSTALL_DIR}/lib/dnnl.lib"
|
||||
TIMEOUT 600
|
||||
)
|
||||
|
||||
add_library(onednn_interface INTERFACE)
|
||||
target_include_directories(onednn_interface INTERFACE "${ONEDNN_INSTALL_DIR}/include")
|
||||
if(WIN32)
|
||||
target_link_libraries(onednn_interface INTERFACE "${ONEDNN_INSTALL_DIR}/lib/dnnl.lib")
|
||||
else()
|
||||
target_link_libraries(onednn_interface INTERFACE "${ONEDNN_INSTALL_DIR}/lib/libdnnl.a")
|
||||
endif()
|
||||
add_dependencies(onednn_interface onednn_external)
|
||||
set(ONEDNN onednn_interface PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# =============================================================================
|
||||
# ARM COMPUTE LIBRARY (Optional)
|
||||
# =============================================================================
|
||||
function(setup_armcompute)
|
||||
set(HAVE_ARMCOMPUTE 0 PARENT_SCOPE)
|
||||
if(NOT HELPERS_armcompute STREQUAL "ON")
|
||||
message(STATUS "ARM Compute helper is disabled (HELPERS_armcompute=${HELPERS_armcompute})")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(TARGET armcompute_external)
|
||||
set(HAVE_ARMCOMPUTE 1 PARENT_SCOPE)
|
||||
set(ARMCOMPUTE_LIBRARIES armcompute_interface PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(LIBND4J_BUILD_WITH_ARMCOMPUTE AND (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64|arm64|ARM64"))
|
||||
set(ARMCOMPUTE_INSTALL_DIR "${CMAKE_BINARY_DIR}/armcompute_install")
|
||||
set(ARMCOMPUTE_VERSION "v25.04")
|
||||
set(ARMCOMPUTE_ARCH "aarch64")
|
||||
set(ARMCOMPUTE_PLATFORM "linux")
|
||||
set(ARMCOMPUTE_FLAVOR "cpu")
|
||||
set(ARMCOMPUTE_PKG_NAME "arm_compute-${ARMCOMPUTE_VERSION}-${ARMCOMPUTE_PLATFORM}-${ARMCOMPUTE_ARCH}-${ARMCOMPUTE_FLAVOR}-bin")
|
||||
set(ARMCOMPUTE_URL "https://github.com/ARM-software/ComputeLibrary/releases/download/${ARMCOMPUTE_VERSION}/${ARMCOMPUTE_PKG_NAME}.tar.gz")
|
||||
|
||||
ExternalProject_Add(armcompute_external
|
||||
PREFIX "${CMAKE_BINARY_DIR}/armcompute_external"
|
||||
URL "${ARMCOMPUTE_URL}"
|
||||
DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/downloads"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/${ARMCOMPUTE_PKG_NAME} ${ARMCOMPUTE_INSTALL_DIR}
|
||||
BUILD_BYPRODUCTS "${ARMCOMPUTE_INSTALL_DIR}/include/arm_compute/core/CL/CLKernelLibrary.h"
|
||||
)
|
||||
|
||||
add_library(armcompute_interface INTERFACE)
|
||||
target_include_directories(armcompute_interface INTERFACE "${ARMCOMPUTE_INSTALL_DIR}/include")
|
||||
target_link_directories(armcompute_interface INTERFACE "${ARMCOMPUTE_INSTALL_DIR}/lib")
|
||||
target_link_libraries(armcompute_interface INTERFACE arm_compute arm_compute_graph)
|
||||
add_dependencies(armcompute_interface armcompute_external)
|
||||
|
||||
set(ARMCOMPUTE_LIBRARIES armcompute_interface PARENT_SCOPE)
|
||||
set(HAVE_ARMCOMPUTE 1 PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# =============================================================================
|
||||
# CUDNN (Optional, for CUDA builds)
|
||||
# =============================================================================
|
||||
function(setup_cudnn)
|
||||
set(HAVE_CUDNN false PARENT_SCOPE)
|
||||
set(CUDNN "" PARENT_SCOPE)
|
||||
|
||||
if(NOT (HELPERS_cudnn AND SD_CUDA))
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_package(CUDNN)
|
||||
if(CUDNN_FOUND)
|
||||
message(STATUS "✓ Found cuDNN: ${CUDNN_LIBRARY}")
|
||||
include_directories(${CUDNN_INCLUDE_DIR})
|
||||
set(HAVE_CUDNN true PARENT_SCOPE)
|
||||
set(CUDNN ${CUDNN_LIBRARIES} PARENT_SCOPE)
|
||||
add_definitions(-DHAVE_CUDNN=1)
|
||||
else()
|
||||
message(WARNING "✗ cuDNN not found. Continuing without cuDNN support.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# GCC and Clang flags for C++ template duplicate instantiation issues
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# For C++ template duplicate instantiation errors
|
||||
if(NOT SD_CUDA)
|
||||
add_compile_options(-fpermissive)
|
||||
add_compile_options(-ftemplate-depth=1024)
|
||||
add_compile_options(-fno-gnu-unique)
|
||||
message(STATUS "Added -fpermissive: Allows duplicate template instantiations")
|
||||
message(STATUS "Added template-related flags for C++ duplicate handling")
|
||||
else()
|
||||
# Also set CXX flags for host compilation
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -Wno-error")
|
||||
message(STATUS "Added CUDA-specific compiler flags for duplicate template instantiations")
|
||||
message(STATUS "Added --disable-warnings to suppress NVCC errors")
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
# For Clang template duplicate instantiation handling
|
||||
if(NOT SD_CUDA)
|
||||
# Template instantiation depth
|
||||
add_compile_options(-ftemplate-depth=1024)
|
||||
|
||||
# Check if this is an Android build
|
||||
if(ANDROID OR CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
# Android NDK specific handling - be more permissive like GCC
|
||||
add_compile_options(-Wno-error)
|
||||
add_compile_options(-Wno-duplicate-decl-specifier)
|
||||
add_compile_options(-Wno-unused-command-line-argument)
|
||||
add_compile_options(-ffunction-sections)
|
||||
add_compile_options(-fdata-sections)
|
||||
# Android linker doesn't support ICF well, use basic folding
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
message(STATUS "Added Android-specific Clang flags for duplicate template handling")
|
||||
else()
|
||||
# Desktop Clang with full template folding support
|
||||
add_compile_options(-ffunction-sections)
|
||||
add_compile_options(-fdata-sections)
|
||||
add_compile_options(-fmerge-all-constants)
|
||||
add_compile_options(-fno-unique-section-names)
|
||||
# Use LLD linker for better template folding support
|
||||
add_compile_options(-fuse-ld=lld)
|
||||
# Linker flags for identical code folding (ICF)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--icf=all -Wl,--gc-sections")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--icf=all -Wl,--gc-sections")
|
||||
message(STATUS "Added desktop Clang template folding with LLD linker")
|
||||
endif()
|
||||
else()
|
||||
# CUDA with Clang
|
||||
if(ANDROID OR CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth=1024 -Wno-error -Wno-duplicate-decl-specifier")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
message(STATUS "Added Android CUDA-specific Clang flags")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth=1024 -ffunction-sections -fdata-sections")
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=-ffunction-sections -Xcompiler=-fdata-sections")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld -Wl,--icf=all")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=lld -Wl,--icf=all")
|
||||
message(STATUS "Added desktop CUDA-specific Clang template folding")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,590 @@
|
||||
# cmake/ExtractInstantiations.cmake
|
||||
# COMPLETE CONSOLIDATED PARALLEL TEMPLATE INSTANTIATION EXTRACTION
|
||||
# All functionality in ONE file - no separate helper files needed
|
||||
|
||||
message(STATUS "")
|
||||
message(STATUS "=====================================================")
|
||||
message(STATUS "=== TEMPLATE INSTANTIATION ANALYSIS MODE ACTIVE ===")
|
||||
message(STATUS "=====================================================")
|
||||
message(STATUS "SD_EXTRACT_INSTANTIATIONS = ${SD_EXTRACT_INSTANTIATIONS}")
|
||||
message(STATUS "CMAKE_SOURCE_DIR = ${CMAKE_SOURCE_DIR}")
|
||||
message(STATUS "CMAKE_BINARY_DIR = ${CMAKE_BINARY_DIR}")
|
||||
|
||||
# ============================================================================
|
||||
# HELPER FUNCTIONS - ALL INLINE, NO SEPARATE FILES
|
||||
# ============================================================================
|
||||
|
||||
# Function to normalize template signatures for comparison
|
||||
function(normalize_template_signature TEMPLATE OUT_VAR)
|
||||
set(normalized "${TEMPLATE}")
|
||||
|
||||
# Remove all extra whitespace
|
||||
string(REGEX REPLACE "[ \t\r\n]+" " " normalized "${normalized}")
|
||||
string(STRIP "${normalized}" normalized)
|
||||
|
||||
# Normalize spacing around template brackets
|
||||
string(REPLACE "< " "<" normalized "${normalized}")
|
||||
string(REPLACE " >" ">" normalized "${normalized}")
|
||||
string(REPLACE " <" "<" normalized "${normalized}")
|
||||
string(REPLACE "> " ">" normalized "${normalized}")
|
||||
|
||||
# Normalize pointer and reference notation
|
||||
string(REPLACE " *" "*" normalized "${normalized}")
|
||||
string(REPLACE " &" "&" normalized "${normalized}")
|
||||
string(REPLACE "* " "*" normalized "${normalized}")
|
||||
string(REPLACE "& " "&" normalized "${normalized}")
|
||||
|
||||
# Normalize const placement
|
||||
string(REGEX REPLACE "const[ ]+([^ ]+)" "\\1 const" normalized "${normalized}")
|
||||
|
||||
# Normalize namespace separators
|
||||
string(REPLACE " ::" "::" normalized "${normalized}")
|
||||
string(REPLACE ":: " "::" normalized "${normalized}")
|
||||
|
||||
# Remove trailing const
|
||||
string(REGEX REPLACE "[ ]+const$" "" normalized "${normalized}")
|
||||
|
||||
set(${OUT_VAR} "${normalized}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Function to check if a template should be filtered out
|
||||
function(should_filter_template TEMPLATE OUT_VAR)
|
||||
set(should_filter FALSE)
|
||||
|
||||
# Filter out all std:: templates
|
||||
if(TEMPLATE MATCHES "^std::")
|
||||
set(should_filter TRUE)
|
||||
endif()
|
||||
|
||||
# Filter out compiler intrinsics and internal templates
|
||||
if(TEMPLATE MATCHES "^__" OR
|
||||
TEMPLATE MATCHES "^operator" OR
|
||||
TEMPLATE MATCHES "^decltype" OR
|
||||
TEMPLATE MATCHES "^typename" OR
|
||||
TEMPLATE MATCHES "^template")
|
||||
set(should_filter TRUE)
|
||||
endif()
|
||||
|
||||
# Filter out basic types that aren't really templates
|
||||
if(TEMPLATE MATCHES "^(bool|char|short|int|long|float|double|void|unsigned|signed)")
|
||||
set(should_filter TRUE)
|
||||
endif()
|
||||
|
||||
set(${OUT_VAR} ${should_filter} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Setup compilation flags function
|
||||
function(setup_instantiation_flags)
|
||||
# Setup FlatBuffers
|
||||
set(PREPROCESS_FLATBUFFERS_VERSION "25.2.10")
|
||||
set(PREPROCESS_FLATBUFFERS_URL "https://github.com/google/flatbuffers/archive/v${PREPROCESS_FLATBUFFERS_VERSION}.tar.gz")
|
||||
set(PREPROCESS_FB_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/preprocess-flatbuffers-src")
|
||||
|
||||
set(PREPROCESS_FB_HEADER "${PREPROCESS_FB_SOURCE_DIR}/include/flatbuffers/flatbuffers.h")
|
||||
if(NOT EXISTS ${PREPROCESS_FB_HEADER})
|
||||
message("Downloading and extracting FlatBuffers for instantiation analysis...")
|
||||
|
||||
file(DOWNLOAD ${PREPROCESS_FLATBUFFERS_URL}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-${PREPROCESS_FLATBUFFERS_VERSION}.tar.gz"
|
||||
SHOW_PROGRESS
|
||||
STATUS download_status)
|
||||
|
||||
list(GET download_status 0 download_result)
|
||||
if(NOT download_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to download FlatBuffers for instantiation analysis")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xzf "flatbuffers-${PREPROCESS_FLATBUFFERS_VERSION}.tar.gz"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
RESULT_VARIABLE extract_result
|
||||
)
|
||||
|
||||
if(NOT extract_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to extract FlatBuffers for instantiation analysis")
|
||||
endif()
|
||||
|
||||
file(RENAME "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-${PREPROCESS_FLATBUFFERS_VERSION}"
|
||||
"${PREPROCESS_FB_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
# Build include paths
|
||||
set(all_includes "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
file(GLOB_RECURSE all_dirs LIST_DIRECTORIES true "${CMAKE_CURRENT_SOURCE_DIR}/include/*")
|
||||
foreach(item ${all_dirs})
|
||||
if(IS_DIRECTORY ${item})
|
||||
list(APPEND all_includes ${item})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(APPEND all_includes
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include"
|
||||
"${CMAKE_SOURCE_DIR}/include/"
|
||||
"${CMAKE_SOURCE_DIR}/include/system"
|
||||
"${CMAKE_BINARY_DIR}/compilation_units"
|
||||
"${CMAKE_BINARY_DIR}/cpu_instantiations"
|
||||
"${CMAKE_BINARY_DIR}/cuda_instantiations"
|
||||
"${CMAKE_BINARY_DIR}/include"
|
||||
"${PREPROCESS_FB_SOURCE_DIR}/include"
|
||||
)
|
||||
|
||||
# Build include flags string
|
||||
set(include_flags "")
|
||||
foreach(dir IN LISTS all_includes)
|
||||
if(EXISTS ${dir})
|
||||
string(APPEND include_flags " -I${dir}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Build definition flags
|
||||
set(defs_flags "")
|
||||
string(APPEND defs_flags " -D__CPUBLAS__=true")
|
||||
if(SD_CUDA)
|
||||
string(APPEND defs_flags " -D__CUDABLAS__=true -DHAVE_CUDA=1")
|
||||
endif()
|
||||
if(HAVE_OPENBLAS)
|
||||
string(APPEND defs_flags " -DHAVE_OPENBLAS=1")
|
||||
endif()
|
||||
|
||||
if(SD_ALL_OPS OR "${SD_OPS_LIST}" STREQUAL "")
|
||||
string(APPEND defs_flags " -DSD_ALL_OPS=1")
|
||||
string(APPEND defs_flags " -DNOT_EXCLUDED(x)=1")
|
||||
else()
|
||||
foreach(OP ${SD_OPS_LIST})
|
||||
string(APPEND defs_flags " -DOP_${OP}=1")
|
||||
endforeach()
|
||||
string(APPEND defs_flags " -DNOT_EXCLUDED(x)=\\(defined\\(x\\)\\)")
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
string(APPEND defs_flags " -DDEBUG=1 -D_DEBUG=1")
|
||||
else()
|
||||
string(APPEND defs_flags " -DNDEBUG=1")
|
||||
endif()
|
||||
|
||||
if(SD_TYPES_LIST)
|
||||
string(REPLACE ";" "," types_comma_list "${SD_TYPES_LIST}")
|
||||
string(APPEND defs_flags " -DSD_TYPES_LIST=\"${types_comma_list}\"")
|
||||
endif()
|
||||
|
||||
# Export to parent scope
|
||||
set(INST_INCLUDE_FLAGS ${include_flags} PARENT_SCOPE)
|
||||
set(INST_DEFS_FLAGS ${defs_flags} PARENT_SCOPE)
|
||||
set(INST_LANG_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}" PARENT_SCOPE)
|
||||
|
||||
# Find required tools
|
||||
find_program(NM_TOOL NAMES nm gcc-nm llvm-nm)
|
||||
find_program(CPPFILT_TOOL NAMES c++filt llvm-cxxfilt)
|
||||
|
||||
set(NM_TOOL ${NM_TOOL} PARENT_SCOPE)
|
||||
set(CPPFILT_TOOL ${CPPFILT_TOOL} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Get source list function
|
||||
function(get_source_list OUT_VAR)
|
||||
if(DEFINED ALL_SOURCES AND ALL_SOURCES)
|
||||
set(${OUT_VAR} ${ALL_SOURCES} PARENT_SCOPE)
|
||||
elseif(DEFINED ALL_SOURCES_LIST AND ALL_SOURCES_LIST)
|
||||
set(${OUT_VAR} ${ALL_SOURCES_LIST} PARENT_SCOPE)
|
||||
else()
|
||||
set(${OUT_VAR} "" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# MAIN EXTRACTION FUNCTION - CONSOLIDATED WITH ACCURATE FILTERING
|
||||
function(extract_templates_consolidated SOURCE_FILE USED_OUTPUT_FILE PROVIDED_OUTPUT_FILE SAFE_NAME)
|
||||
# Initialize empty results
|
||||
set(used_templates "")
|
||||
set(provided_templates "")
|
||||
|
||||
# Check if source file exists
|
||||
if(NOT EXISTS "${SOURCE_FILE}")
|
||||
file(WRITE ${USED_OUTPUT_FILE} "")
|
||||
file(WRITE ${PROVIDED_OUTPUT_FILE} "")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Determine compiler and flags
|
||||
if(SOURCE_FILE MATCHES "\\.cu$")
|
||||
set(compiler "${CMAKE_CUDA_COMPILER}")
|
||||
set(lang_flags "${CMAKE_CUDA_FLAGS} ${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||
else()
|
||||
set(compiler "${CMAKE_CXX_COMPILER}")
|
||||
set(lang_flags "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||
endif()
|
||||
|
||||
if(NOT compiler)
|
||||
file(WRITE ${USED_OUTPUT_FILE} "")
|
||||
file(WRITE ${PROVIDED_OUTPUT_FILE} "")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# SINGLE PREPROCESSING PASS
|
||||
separate_arguments(lang_flags_list UNIX_COMMAND "${lang_flags}")
|
||||
separate_arguments(defs_flags_list UNIX_COMMAND "${INST_DEFS_FLAGS}")
|
||||
separate_arguments(include_flags_list UNIX_COMMAND "${INST_INCLUDE_FLAGS}")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${compiler}
|
||||
-E -P -C -dD
|
||||
${lang_flags_list}
|
||||
${defs_flags_list}
|
||||
${include_flags_list}
|
||||
"${SOURCE_FILE}"
|
||||
OUTPUT_VARIABLE preprocessed_content
|
||||
ERROR_VARIABLE preprocess_errors
|
||||
RESULT_VARIABLE preprocess_result
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if(NOT preprocess_result EQUAL 0)
|
||||
file(WRITE ${USED_OUTPUT_FILE} "")
|
||||
file(WRITE ${PROVIDED_OUTPUT_FILE} "")
|
||||
return()
|
||||
endif()
|
||||
|
||||
string(LENGTH "${preprocessed_content}" content_length)
|
||||
if(content_length GREATER 52428800)
|
||||
file(WRITE ${USED_OUTPUT_FILE} "")
|
||||
file(WRITE ${PROVIDED_OUTPUT_FILE} "")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# EXTRACT PROVIDED TEMPLATES
|
||||
string(REGEX MATCHALL "template[ \t]+(?!extern)(class|struct)[ \t]+[a-zA-Z_][a-zA-Z0-9_:]*[ \t]*<[^;>]+>[ \t]*;"
|
||||
explicit_instantiations "${preprocessed_content}")
|
||||
|
||||
foreach(inst ${explicit_instantiations})
|
||||
string(REGEX MATCH "[a-zA-Z_][a-zA-Z0-9_:]*<[^>]+>" tmpl "${inst}")
|
||||
if(tmpl)
|
||||
should_filter_template("${tmpl}" should_filter)
|
||||
if(NOT should_filter)
|
||||
normalize_template_signature("${tmpl}" normalized)
|
||||
list(APPEND provided_templates "${normalized}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# EXTRACT USED TEMPLATES
|
||||
string(REGEX MATCHALL "extern[ \t]+template[ \t]+(class|struct)[ \t]+[a-zA-Z_][a-zA-Z0-9_:]*[ \t]*<[^;>]+>[ \t]*;"
|
||||
extern_templates "${preprocessed_content}")
|
||||
|
||||
foreach(ext ${extern_templates})
|
||||
string(REGEX MATCH "[a-zA-Z_][a-zA-Z0-9_:]*<[^>]+>" tmpl "${ext}")
|
||||
if(tmpl)
|
||||
should_filter_template("${tmpl}" should_filter)
|
||||
if(NOT should_filter)
|
||||
normalize_template_signature("${tmpl}" normalized)
|
||||
list(APPEND used_templates "${normalized}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Project-specific patterns
|
||||
set(project_template_patterns
|
||||
"NDArray<[^>]+>"
|
||||
"DataBuffer<[^>]+>"
|
||||
"ResultSet<[^>]+>"
|
||||
"ShapeList<[^>]+>"
|
||||
"LaunchContext<[^>]+>"
|
||||
"BroadcastHelper<[^>]+>"
|
||||
"BroadcastInt<[^>]+>"
|
||||
"BroadcastBool<[^>]+>"
|
||||
"Broadcast<[^>]+>"
|
||||
"PairWiseTransform<[^>]+>"
|
||||
"ScalarTransform<[^>]+>"
|
||||
"RandomFunction<[^>]+>"
|
||||
"ReduceSameFunction<[^>]+>"
|
||||
"ReduceFloatFunction<[^>]+>"
|
||||
"ReduceBoolFunction<[^>]+>"
|
||||
"ReduceLongFunction<[^>]+>"
|
||||
"Reduce3<[^>]+>"
|
||||
"IndexReduce<[^>]+>"
|
||||
"ReductionLoops<[^>]+>"
|
||||
"IndexReductionLoops<[^>]+>"
|
||||
"LoopKind::Kind<[^>]+>"
|
||||
"SpecialMethods<[^>]+>"
|
||||
"TypeCast::convertGeneric<[^>]+>"
|
||||
"DeclarableOp<[^>]+>"
|
||||
"DeclarableCustomOp<[^>]+>"
|
||||
"DeclarableReductionOp<[^>]+>"
|
||||
"GEMM<[^>]+>"
|
||||
"GEMV<[^>]+>"
|
||||
"AXPY<[^>]+>"
|
||||
)
|
||||
|
||||
foreach(pattern ${project_template_patterns})
|
||||
string(REGEX MATCHALL "${pattern}" matches "${preprocessed_content}")
|
||||
foreach(match ${matches})
|
||||
should_filter_template("${match}" should_filter)
|
||||
if(NOT should_filter)
|
||||
normalize_template_signature("${match}" normalized)
|
||||
list(APPEND used_templates "${normalized}")
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
# Remove duplicates and write
|
||||
if(used_templates)
|
||||
list(REMOVE_DUPLICATES used_templates)
|
||||
list(SORT used_templates)
|
||||
string(REPLACE ";" "\n" used_content "${used_templates}")
|
||||
file(WRITE ${USED_OUTPUT_FILE} "${used_content}")
|
||||
else()
|
||||
file(WRITE ${USED_OUTPUT_FILE} "")
|
||||
endif()
|
||||
|
||||
if(provided_templates)
|
||||
list(REMOVE_DUPLICATES provided_templates)
|
||||
list(SORT provided_templates)
|
||||
string(REPLACE ";" "\n" provided_content "${provided_templates}")
|
||||
file(WRITE ${PROVIDED_OUTPUT_FILE} "${provided_content}")
|
||||
else()
|
||||
file(WRITE ${PROVIDED_OUTPUT_FILE} "")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Process batch function for parallel execution
|
||||
function(process_batch BATCH_ID BATCH_FILE)
|
||||
if(NOT EXISTS ${BATCH_FILE})
|
||||
file(WRITE "${INST_BATCH_DIR}/batch_${BATCH_ID}.done" "")
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(STRINGS ${BATCH_FILE} FILES_TO_PROCESS)
|
||||
list(LENGTH FILES_TO_PROCESS batch_size)
|
||||
message("[Batch ${BATCH_ID}] Processing ${batch_size} files")
|
||||
|
||||
set(batch_results "")
|
||||
set(processed_count 0)
|
||||
|
||||
foreach(src IN LISTS FILES_TO_PROCESS)
|
||||
if(NOT EXISTS ${src})
|
||||
continue()
|
||||
endif()
|
||||
|
||||
get_filename_component(src_name ${src} NAME_WE)
|
||||
get_filename_component(src_path ${src} PATH)
|
||||
get_filename_component(src_full_name ${src} NAME)
|
||||
file(RELATIVE_PATH rel_path ${CMAKE_SOURCE_DIR} ${src_path})
|
||||
string(REPLACE "/" "_" safe_name "${rel_path}_${src_name}")
|
||||
|
||||
set(IS_GENERATED FALSE)
|
||||
if(src MATCHES "${CMAKE_BINARY_DIR}")
|
||||
set(IS_GENERATED TRUE)
|
||||
endif()
|
||||
|
||||
set(used_file "${INST_USED_DIR}/${safe_name}.used")
|
||||
set(provided_file "${INST_PROVIDED_DIR}/${safe_name}.provided")
|
||||
|
||||
extract_templates_consolidated("${src}" "${used_file}" "${provided_file}" "${safe_name}")
|
||||
|
||||
if(EXISTS ${used_file})
|
||||
file(STRINGS ${used_file} used_list)
|
||||
else()
|
||||
set(used_list "")
|
||||
endif()
|
||||
|
||||
if(EXISTS ${provided_file})
|
||||
file(STRINGS ${provided_file} provided_list)
|
||||
else()
|
||||
set(provided_list "")
|
||||
endif()
|
||||
|
||||
set(missing_templates "")
|
||||
foreach(used_tmpl ${used_list})
|
||||
set(found FALSE)
|
||||
foreach(provided_tmpl ${provided_list})
|
||||
if(used_tmpl STREQUAL provided_tmpl)
|
||||
set(found TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if(NOT found)
|
||||
list(APPEND missing_templates "${used_tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(missing_file "${INST_MISSING_DIR}/${safe_name}.missing")
|
||||
if(missing_templates)
|
||||
list(REMOVE_DUPLICATES missing_templates)
|
||||
string(REPLACE ";" "\n" missing_content "${missing_templates}")
|
||||
file(WRITE ${missing_file} "${missing_content}")
|
||||
list(LENGTH missing_templates missing_count)
|
||||
else()
|
||||
file(WRITE ${missing_file} "")
|
||||
set(missing_count 0)
|
||||
endif()
|
||||
|
||||
list(LENGTH used_list used_count)
|
||||
list(LENGTH provided_list provided_count)
|
||||
|
||||
string(APPEND batch_results "${src}|${safe_name}|${used_count}|${provided_count}|${missing_count}|${IS_GENERATED}\n")
|
||||
math(EXPR processed_count "${processed_count} + 1")
|
||||
endforeach()
|
||||
|
||||
file(WRITE "${INST_BATCH_DIR}/batch_${BATCH_ID}.done" "${batch_results}")
|
||||
message("[Batch ${BATCH_ID}] Completed: ${processed_count} files")
|
||||
endfunction()
|
||||
|
||||
# ============================================================================
|
||||
# MAIN EXECUTION
|
||||
# ============================================================================
|
||||
|
||||
# Determine parallelism
|
||||
if(NOT DEFINED INST_PARALLEL_JOBS)
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(PROCESSOR_COUNT)
|
||||
# PERFORMANCE OPTIMIZATION: Use all available cores for functrace builds
|
||||
# Old logic: Reserved 2 cores (PROCESSOR_COUNT - 2)
|
||||
# New logic: Use all cores (template processing is CPU-bound, not I/O-bound)
|
||||
if(PROCESSOR_COUNT GREATER 0)
|
||||
set(INST_PARALLEL_JOBS ${PROCESSOR_COUNT})
|
||||
else()
|
||||
set(INST_PARALLEL_JOBS 4)
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "Parallel jobs: ${INST_PARALLEL_JOBS}")
|
||||
|
||||
# Setup directories
|
||||
set(INST_DIR "${CMAKE_SOURCE_DIR}/instantiation_analysis")
|
||||
set(INST_USED_DIR "${INST_DIR}/used")
|
||||
set(INST_PROVIDED_DIR "${INST_DIR}/provided")
|
||||
set(INST_MISSING_DIR "${INST_DIR}/missing")
|
||||
set(INST_REPORTS_DIR "${INST_DIR}/reports")
|
||||
set(INST_TEMP_DIR "${INST_DIR}/temp")
|
||||
set(INST_BY_FILE_DIR "${INST_DIR}/by_file")
|
||||
set(INST_BATCH_DIR "${INST_DIR}/batches")
|
||||
|
||||
foreach(dir IN ITEMS ${INST_DIR} ${INST_USED_DIR} ${INST_PROVIDED_DIR}
|
||||
${INST_MISSING_DIR} ${INST_REPORTS_DIR} ${INST_TEMP_DIR}
|
||||
${INST_BY_FILE_DIR} ${INST_BATCH_DIR})
|
||||
if(NOT EXISTS ${dir})
|
||||
file(MAKE_DIRECTORY ${dir})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Setup flags
|
||||
setup_instantiation_flags()
|
||||
|
||||
# Get sources
|
||||
message(STATUS "Collecting source files...")
|
||||
get_source_list(SOURCE_LIST)
|
||||
|
||||
if(NOT SOURCE_LIST)
|
||||
file(GLOB_RECURSE SOURCE_LIST
|
||||
"${CMAKE_SOURCE_DIR}/include/**/*.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/include/**/*.cu"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Add generated sources
|
||||
if(SD_CUDA)
|
||||
file(GLOB_RECURSE GEN_SOURCES
|
||||
"${CMAKE_BINARY_DIR}/cuda_instantiations/*.cu"
|
||||
"${CMAKE_BINARY_DIR}/compilation_units/*.cu")
|
||||
else()
|
||||
file(GLOB_RECURSE GEN_SOURCES
|
||||
"${CMAKE_BINARY_DIR}/cpu_instantiations/*.cpp"
|
||||
"${CMAKE_BINARY_DIR}/compilation_units/*.cpp")
|
||||
endif()
|
||||
list(APPEND SOURCE_LIST ${GEN_SOURCES})
|
||||
|
||||
# Filter and deduplicate
|
||||
set(FILTERED_SOURCE_LIST "")
|
||||
foreach(src IN LISTS SOURCE_LIST)
|
||||
if(src MATCHES "\\.(cpp|cxx|cc|cu)$" AND EXISTS ${src})
|
||||
list(APPEND FILTERED_SOURCE_LIST ${src})
|
||||
endif()
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES FILTERED_SOURCE_LIST)
|
||||
set(SOURCE_LIST ${FILTERED_SOURCE_LIST})
|
||||
|
||||
list(LENGTH SOURCE_LIST source_count)
|
||||
message(STATUS "Total files to analyze: ${source_count}")
|
||||
|
||||
# Create batches
|
||||
math(EXPR FILES_PER_BATCH "${source_count} / ${INST_PARALLEL_JOBS}")
|
||||
if(FILES_PER_BATCH EQUAL 0)
|
||||
set(FILES_PER_BATCH 1)
|
||||
endif()
|
||||
|
||||
set(current_batch 0)
|
||||
set(files_in_batch 0)
|
||||
foreach(src IN LISTS SOURCE_LIST)
|
||||
file(APPEND "${INST_BATCH_DIR}/batch_${current_batch}.txt" "${src}\n")
|
||||
math(EXPR files_in_batch "${files_in_batch} + 1")
|
||||
if(files_in_batch GREATER_EQUAL FILES_PER_BATCH AND current_batch LESS ${INST_PARALLEL_JOBS})
|
||||
math(EXPR current_batch "${current_batch} + 1")
|
||||
set(files_in_batch 0)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Process batches
|
||||
message(STATUS "Processing ${INST_PARALLEL_JOBS} batches...")
|
||||
foreach(batch_id RANGE 0 ${INST_PARALLEL_JOBS})
|
||||
set(batch_file "${INST_BATCH_DIR}/batch_${batch_id}.txt")
|
||||
if(EXISTS ${batch_file})
|
||||
process_batch(${batch_id} ${batch_file})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Aggregate results
|
||||
message(STATUS "Aggregating results...")
|
||||
set(TOTAL_USED 0)
|
||||
set(TOTAL_PROVIDED 0)
|
||||
set(TOTAL_MISSING 0)
|
||||
|
||||
file(WRITE ${INST_REPORTS_DIR}/summary.csv "File,Path,Used,Provided,Missing,Type\n")
|
||||
|
||||
foreach(batch_id RANGE 0 ${INST_PARALLEL_JOBS})
|
||||
set(done_file "${INST_BATCH_DIR}/batch_${batch_id}.done")
|
||||
if(EXISTS ${done_file})
|
||||
file(STRINGS ${done_file} batch_results)
|
||||
foreach(result_line ${batch_results})
|
||||
if(result_line)
|
||||
string(REPLACE "|" ";" result_parts "${result_line}")
|
||||
list(LENGTH result_parts parts_count)
|
||||
if(parts_count EQUAL 6)
|
||||
list(GET result_parts 0 src)
|
||||
list(GET result_parts 2 used_count)
|
||||
list(GET result_parts 3 provided_count)
|
||||
list(GET result_parts 4 missing_count)
|
||||
list(GET result_parts 5 is_generated)
|
||||
|
||||
math(EXPR TOTAL_USED "${TOTAL_USED} + ${used_count}")
|
||||
math(EXPR TOTAL_PROVIDED "${TOTAL_PROVIDED} + ${provided_count}")
|
||||
math(EXPR TOTAL_MISSING "${TOTAL_MISSING} + ${missing_count}")
|
||||
|
||||
get_filename_component(src_name ${src} NAME)
|
||||
get_filename_component(src_path ${src} PATH)
|
||||
file(RELATIVE_PATH rel_path ${CMAKE_SOURCE_DIR} ${src_path})
|
||||
|
||||
set(file_type "original")
|
||||
if(is_generated)
|
||||
set(file_type "generated")
|
||||
endif()
|
||||
|
||||
file(APPEND ${INST_REPORTS_DIR}/summary.csv
|
||||
"${src_name},${rel_path},${used_count},${provided_count},${missing_count},${file_type}\n")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Final summary
|
||||
message(STATUS "")
|
||||
message(STATUS "=====================================================")
|
||||
message(STATUS "=== ANALYSIS COMPLETE ===")
|
||||
message(STATUS "=====================================================")
|
||||
message(STATUS "Templates Used: ${TOTAL_USED}")
|
||||
message(STATUS "Templates Provided: ${TOTAL_PROVIDED}")
|
||||
message(STATUS "Templates Missing: ${TOTAL_MISSING}")
|
||||
message(STATUS "")
|
||||
message(STATUS "Reports generated in: ${INST_REPORTS_DIR}")
|
||||
|
||||
# Exit without continuing build
|
||||
message(STATUS "Exiting after instantiation extraction (SD_EXTRACT_INSTANTIATIONS=ON)")
|
||||
return()
|
||||
@@ -0,0 +1,533 @@
|
||||
# FileConcatenation.cmake
|
||||
# Clean template concatenation with duplicate import elimination
|
||||
|
||||
# Global variables to track includes and content
|
||||
set(GLOBAL_INCLUDES_SET "" CACHE INTERNAL "Set of unique includes")
|
||||
set(GLOBAL_INCLUDES_LIST "" CACHE INTERNAL "Ordered list of unique includes")
|
||||
|
||||
# Function to extract and deduplicate includes from content
|
||||
function(extract_and_deduplicate_includes content includes_var content_without_includes_var)
|
||||
# Handle empty content
|
||||
if(content STREQUAL "")
|
||||
set(${includes_var} "" PARENT_SCOPE)
|
||||
set(${content_without_includes_var} "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Split content into lines
|
||||
string(REPLACE "\n" ";" content_lines "${content}")
|
||||
|
||||
set(extracted_includes "")
|
||||
set(content_without_includes "")
|
||||
set(in_multiline_comment FALSE)
|
||||
|
||||
foreach(line ${content_lines})
|
||||
# Handle empty lines
|
||||
if(NOT DEFINED line OR line STREQUAL "")
|
||||
string(APPEND content_without_includes "\n")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
# Handle multi-line comments
|
||||
if(line MATCHES "/\\*")
|
||||
set(in_multiline_comment TRUE)
|
||||
endif()
|
||||
if(line MATCHES "\\*/")
|
||||
set(in_multiline_comment FALSE)
|
||||
string(APPEND content_without_includes "${line}\n")
|
||||
continue()
|
||||
endif()
|
||||
if(in_multiline_comment)
|
||||
string(APPEND content_without_includes "${line}\n")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
# Skip single-line comments unless they contain includes
|
||||
if(line MATCHES "^[ \t]*//.*#include")
|
||||
# This is a commented include, treat as regular content
|
||||
string(APPEND content_without_includes "${line}\n")
|
||||
elseif(line MATCHES "^[ \t]*//")
|
||||
# Regular comment, keep as content
|
||||
string(APPEND content_without_includes "${line}\n")
|
||||
elseif(line MATCHES "^[ \t]*#include")
|
||||
# Extract include statement - use STRIP instead of REGEX REPLACE to avoid empty match issues
|
||||
string(STRIP "${line}" cleaned_include)
|
||||
if(NOT cleaned_include STREQUAL "")
|
||||
list(APPEND extracted_includes "${cleaned_include}")
|
||||
endif()
|
||||
else()
|
||||
# Regular content line
|
||||
string(APPEND content_without_includes "${line}\n")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(${includes_var} "${extracted_includes}" PARENT_SCOPE)
|
||||
set(${content_without_includes_var} "${content_without_includes}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Function to add includes to global set maintaining order
|
||||
function(add_includes_to_global_set new_includes)
|
||||
foreach(include_stmt ${new_includes})
|
||||
# Normalize the include statement
|
||||
string(STRIP "${include_stmt}" include_stmt)
|
||||
|
||||
# Check if this include is already in our global set
|
||||
list(FIND GLOBAL_INCLUDES_SET "${include_stmt}" found_index)
|
||||
if(found_index EQUAL -1)
|
||||
# New include, add to both set and ordered list
|
||||
list(APPEND GLOBAL_INCLUDES_SET "${include_stmt}")
|
||||
list(APPEND GLOBAL_INCLUDES_LIST "${include_stmt}")
|
||||
|
||||
# Update cache
|
||||
set(GLOBAL_INCLUDES_SET "${GLOBAL_INCLUDES_SET}" CACHE INTERNAL "Set of unique includes")
|
||||
set(GLOBAL_INCLUDES_LIST "${GLOBAL_INCLUDES_LIST}" CACHE INTERNAL "Ordered list of unique includes")
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# Function to generate the final includes section
|
||||
function(generate_includes_section result_var)
|
||||
set(includes_section "")
|
||||
|
||||
if(GLOBAL_INCLUDES_LIST)
|
||||
string(APPEND includes_section "/*\n * Consolidated Include Section\n * All unique includes from processed templates\n */\n")
|
||||
|
||||
# Group includes by type for better organization
|
||||
set(system_includes "")
|
||||
set(local_includes "")
|
||||
set(other_includes "")
|
||||
|
||||
foreach(include_stmt ${GLOBAL_INCLUDES_LIST})
|
||||
if(include_stmt MATCHES "#include[ \t]*<.*>")
|
||||
list(APPEND system_includes "${include_stmt}")
|
||||
elseif(include_stmt MATCHES "#include[ \t]*\".*\"")
|
||||
list(APPEND local_includes "${include_stmt}")
|
||||
else()
|
||||
list(APPEND other_includes "${include_stmt}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Output system includes first
|
||||
if(system_includes)
|
||||
string(APPEND includes_section "\n// System includes\n")
|
||||
foreach(include_stmt ${system_includes})
|
||||
string(APPEND includes_section "${include_stmt}\n")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Then local includes
|
||||
if(local_includes)
|
||||
string(APPEND includes_section "\n// Local includes\n")
|
||||
foreach(include_stmt ${local_includes})
|
||||
string(APPEND includes_section "${include_stmt}\n")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Finally other includes
|
||||
if(other_includes)
|
||||
string(APPEND includes_section "\n// Other includes\n")
|
||||
foreach(include_stmt ${other_includes})
|
||||
string(APPEND includes_section "${include_stmt}\n")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
string(APPEND includes_section "\n")
|
||||
endif()
|
||||
|
||||
set(${result_var} "${includes_section}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Process a single template instance with specific type indices
|
||||
function(process_single_template_instance template_file comb1 comb2 comb3 result_var)
|
||||
file(READ "${template_file}" original_content)
|
||||
|
||||
# Set template variables
|
||||
set(FL_TYPE_INDEX ${comb1})
|
||||
set(TYPE_INDEX_1 ${comb1})
|
||||
set(TYPE_INDEX_2 ${comb2})
|
||||
set(TYPE_INDEX_3 ${comb3})
|
||||
|
||||
# Determine what #cmakedefine flags to enable based on template content
|
||||
set(SD_COMMON_TYPES_GEN 0)
|
||||
set(SD_FLOAT_TYPES_GEN 0)
|
||||
set(SD_INTEGER_TYPES_GEN 0)
|
||||
set(SD_PAIRWISE_TYPES_GEN 0)
|
||||
set(SD_SEMANTIC_TYPES_GEN 0)
|
||||
|
||||
if(original_content MATCHES "#cmakedefine[ \t]+SD_COMMON_TYPES_GEN")
|
||||
set(SD_COMMON_TYPES_GEN 1)
|
||||
endif()
|
||||
if(original_content MATCHES "#cmakedefine[ \t]+SD_FLOAT_TYPES_GEN")
|
||||
set(SD_FLOAT_TYPES_GEN 1)
|
||||
endif()
|
||||
if(original_content MATCHES "#cmakedefine[ \t]+SD_INTEGER_TYPES_GEN")
|
||||
set(SD_INTEGER_TYPES_GEN 1)
|
||||
endif()
|
||||
if(original_content MATCHES "#cmakedefine[ \t]+SD_PAIRWISE_TYPES_GEN")
|
||||
set(SD_PAIRWISE_TYPES_GEN 1)
|
||||
endif()
|
||||
if(original_content MATCHES "#cmakedefine[ \t]+SD_SEMANTIC_TYPES_GEN")
|
||||
set(SD_SEMANTIC_TYPES_GEN 1)
|
||||
endif()
|
||||
|
||||
# Manual string replacement instead of configure_file
|
||||
set(processed_content "${original_content}")
|
||||
|
||||
# Replace @variable@ patterns
|
||||
string(REPLACE "@FL_TYPE_INDEX@" "${FL_TYPE_INDEX}" processed_content "${processed_content}")
|
||||
string(REPLACE "@TYPE_INDEX_1@" "${TYPE_INDEX_1}" processed_content "${processed_content}")
|
||||
string(REPLACE "@TYPE_INDEX_2@" "${TYPE_INDEX_2}" processed_content "${processed_content}")
|
||||
string(REPLACE "@TYPE_INDEX_3@" "${TYPE_INDEX_3}" processed_content "${processed_content}")
|
||||
|
||||
# Process #cmakedefine directives
|
||||
if(SD_COMMON_TYPES_GEN)
|
||||
string(REPLACE "#cmakedefine SD_COMMON_TYPES_GEN" "#define SD_COMMON_TYPES_GEN" processed_content "${processed_content}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine SD_COMMON_TYPES_GEN" "/* #undef SD_COMMON_TYPES_GEN */" processed_content "${processed_content}")
|
||||
endif()
|
||||
|
||||
if(SD_FLOAT_TYPES_GEN)
|
||||
string(REPLACE "#cmakedefine SD_FLOAT_TYPES_GEN" "#define SD_FLOAT_TYPES_GEN" processed_content "${processed_content}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine SD_FLOAT_TYPES_GEN" "/* #undef SD_FLOAT_TYPES_GEN */" processed_content "${processed_content}")
|
||||
endif()
|
||||
|
||||
if(SD_INTEGER_TYPES_GEN)
|
||||
string(REPLACE "#cmakedefine SD_INTEGER_TYPES_GEN" "#define SD_INTEGER_TYPES_GEN" processed_content "${processed_content}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine SD_INTEGER_TYPES_GEN" "/* #undef SD_INTEGER_TYPES_GEN */" processed_content "${processed_content}")
|
||||
endif()
|
||||
|
||||
if(SD_PAIRWISE_TYPES_GEN)
|
||||
string(REPLACE "#cmakedefine SD_PAIRWISE_TYPES_GEN" "#define SD_PAIRWISE_TYPES_GEN" processed_content "${processed_content}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine SD_PAIRWISE_TYPES_GEN" "/* #undef SD_PAIRWISE_TYPES_GEN */" processed_content "${processed_content}")
|
||||
endif()
|
||||
|
||||
if(SD_SEMANTIC_TYPES_GEN)
|
||||
string(REPLACE "#cmakedefine SD_SEMANTIC_TYPES_GEN" "#define SD_SEMANTIC_TYPES_GEN" processed_content "${processed_content}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine SD_SEMANTIC_TYPES_GEN" "/* #undef SD_SEMANTIC_TYPES_GEN */" processed_content "${processed_content}")
|
||||
endif()
|
||||
|
||||
# Validation - check that processing worked
|
||||
if(processed_content MATCHES "@[A-Za-z_]+@")
|
||||
message(WARNING "Template processing failed for ${template_file} with indices ${comb1},${comb2},${comb3} - unresolved variables remain")
|
||||
set(${result_var} "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(processed_content MATCHES "#cmakedefine[ \t]+[A-Za-z_]+")
|
||||
message(WARNING "CMakeDefine processing failed for ${template_file} with indices ${comb1},${comb2},${comb3} - unresolved directives remain")
|
||||
set(${result_var} "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(${result_var} "${processed_content}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Process template with type combinations and include deduplication
|
||||
function(process_template_with_combinations template_file combination_type combinations result_var)
|
||||
if(NOT EXISTS "${template_file}")
|
||||
set(${result_var} "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(all_content "")
|
||||
get_filename_component(template_name ${template_file} NAME_WE)
|
||||
|
||||
# Detect if this is a single-type template
|
||||
file(READ "${template_file}" template_content)
|
||||
set(is_single_type_template FALSE)
|
||||
|
||||
if(template_content MATCHES "@FL_TYPE_INDEX@" AND
|
||||
NOT template_content MATCHES "@TYPE_INDEX_[23]@|@COMB[23]@")
|
||||
set(is_single_type_template TRUE)
|
||||
message(STATUS "📋 Detected single-type template: ${template_name}")
|
||||
endif()
|
||||
|
||||
if(is_single_type_template)
|
||||
# Single-type processing: Extract all unique type indices and process each individually
|
||||
set(unique_indices "")
|
||||
|
||||
foreach(combination ${combinations})
|
||||
string(REPLACE "," ";" comb_list "${combination}")
|
||||
foreach(index ${comb_list})
|
||||
list(FIND unique_indices ${index} found_pos)
|
||||
if(found_pos EQUAL -1)
|
||||
list(APPEND unique_indices ${index})
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
list(SORT unique_indices COMPARE NATURAL)
|
||||
message(STATUS "🔢 Processing ${template_name} with individual indices: ${unique_indices}")
|
||||
|
||||
# Process each unique index individually
|
||||
foreach(index ${unique_indices})
|
||||
# For single-type templates, use the index for all three parameters
|
||||
process_single_template_instance("${template_file}" ${index} ${index} ${index} instance_content)
|
||||
|
||||
if(NOT instance_content STREQUAL "")
|
||||
# Extract includes and content separately
|
||||
extract_and_deduplicate_includes("${instance_content}" extracted_includes content_only)
|
||||
|
||||
# Add includes to global set
|
||||
add_includes_to_global_set("${extracted_includes}")
|
||||
|
||||
# Only append the content without includes
|
||||
string(APPEND all_content "// === ${template_name}_${index}.cpp ===\n")
|
||||
string(APPEND all_content "${content_only}")
|
||||
string(APPEND all_content "// === End ${template_name}_${index}.cpp ===\n\n")
|
||||
|
||||
# Verify float16 instantiation
|
||||
if(index EQUAL 3)
|
||||
if(instance_content MATCHES "SD_COMMON_TYPES_3")
|
||||
message(STATUS "✅ Float16 ${template_name} instantiation generated (index ${index})")
|
||||
else()
|
||||
message(WARNING "⚠️ Float16 ${template_name} instantiation incomplete")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
else()
|
||||
# Multi-type processing: Original logic for templates that actually use multiple types
|
||||
message(STATUS "📋 Processing multi-type template: ${template_name}")
|
||||
|
||||
foreach(combination ${combinations})
|
||||
string(REPLACE "," ";" comb_list "${combination}")
|
||||
list(LENGTH comb_list comb_count)
|
||||
|
||||
# Validate combination format
|
||||
if(NOT ((combination_type EQUAL 3 AND comb_count EQUAL 3) OR
|
||||
(combination_type EQUAL 2 AND comb_count EQUAL 2)))
|
||||
continue()
|
||||
endif()
|
||||
|
||||
# Extract combination indices
|
||||
if(combination_type EQUAL 3)
|
||||
list(GET comb_list 0 comb1)
|
||||
list(GET comb_list 1 comb2)
|
||||
list(GET comb_list 2 comb3)
|
||||
set(file_suffix "${comb1}_${comb2}_${comb3}")
|
||||
else()
|
||||
list(GET comb_list 0 comb1)
|
||||
list(GET comb_list 1 comb2)
|
||||
set(comb3 ${comb1})
|
||||
set(file_suffix "${comb1}_${comb2}")
|
||||
endif()
|
||||
|
||||
# Validate indices
|
||||
if(DEFINED SD_COMMON_TYPES_COUNT)
|
||||
math(EXPR max_index "${SD_COMMON_TYPES_COUNT} - 1")
|
||||
if(comb1 GREATER max_index OR comb2 GREATER max_index OR comb3 GREATER max_index)
|
||||
continue()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Process the multi-type template
|
||||
process_single_template_instance("${template_file}" ${comb1} ${comb2} ${comb3} instance_content)
|
||||
|
||||
if(NOT instance_content STREQUAL "")
|
||||
# Extract includes and content separately
|
||||
extract_and_deduplicate_includes("${instance_content}" extracted_includes content_only)
|
||||
|
||||
# Add includes to global set
|
||||
add_includes_to_global_set("${extracted_includes}")
|
||||
|
||||
# Only append the content without includes
|
||||
string(APPEND all_content "// === ${template_name}_${file_suffix}.cpp ===\n")
|
||||
string(APPEND all_content "${content_only}")
|
||||
string(APPEND all_content "// === End ${template_name}_${file_suffix}.cpp ===\n\n")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(${result_var} "${all_content}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Detect template requirements
|
||||
function(detect_template_requirements template_file needs_2_type_var needs_3_type_var)
|
||||
file(READ "${template_file}" template_content)
|
||||
|
||||
set(needs_2_type FALSE)
|
||||
set(needs_3_type FALSE)
|
||||
|
||||
if(template_content MATCHES "TYPE_INDEX_3|COMB3|_template_3")
|
||||
set(needs_3_type TRUE)
|
||||
endif()
|
||||
|
||||
if(template_content MATCHES "TYPE_INDEX_2|COMB2|_template_2")
|
||||
set(needs_2_type TRUE)
|
||||
endif()
|
||||
|
||||
if(NOT needs_2_type AND NOT needs_3_type)
|
||||
get_filename_component(template_name "${template_file}" NAME)
|
||||
if(template_name MATCHES "_3\\.")
|
||||
set(needs_3_type TRUE)
|
||||
elseif(template_name MATCHES "_2\\.")
|
||||
set(needs_2_type TRUE)
|
||||
else()
|
||||
set(needs_2_type TRUE)
|
||||
set(needs_3_type TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(${needs_2_type_var} ${needs_2_type} PARENT_SCOPE)
|
||||
set(${needs_3_type_var} ${needs_3_type} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Process a batch of templates into one concatenated unit
|
||||
function(process_concatenated_unit unit_index template_files)
|
||||
# Clear global includes for this unit
|
||||
set(GLOBAL_INCLUDES_SET "" CACHE INTERNAL "Set of unique includes")
|
||||
set(GLOBAL_INCLUDES_LIST "" CACHE INTERNAL "Ordered list of unique includes")
|
||||
|
||||
set(output_dir "${CMAKE_BINARY_DIR}")
|
||||
set(final_unit_file "${output_dir}/concatenated_unit_${unit_index}.cpp")
|
||||
|
||||
string(TIMESTAMP current_time "%Y-%m-%d %H:%M:%S")
|
||||
set(unit_content_body "")
|
||||
|
||||
foreach(template_file ${template_files})
|
||||
get_filename_component(template_name ${template_file} NAME_WE)
|
||||
message(STATUS " Processing template: ${template_name}")
|
||||
|
||||
# Detect template requirements
|
||||
detect_template_requirements("${template_file}" needs_2_type needs_3_type)
|
||||
|
||||
# Process with 3-type combinations if needed
|
||||
if(needs_3_type AND COMBINATIONS_3)
|
||||
process_template_with_combinations("${template_file}" 3 "${COMBINATIONS_3}" template_content)
|
||||
string(APPEND unit_content_body "${template_content}")
|
||||
endif()
|
||||
|
||||
# Process with 2-type combinations if needed
|
||||
if(needs_2_type AND COMBINATIONS_2)
|
||||
process_template_with_combinations("${template_file}" 2 "${COMBINATIONS_2}" template_content)
|
||||
string(APPEND unit_content_body "${template_content}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Generate the consolidated includes section
|
||||
generate_includes_section(includes_section)
|
||||
|
||||
# Combine everything with proper structure
|
||||
set(final_content "/*\n * Concatenated Compilation Unit ${unit_index}\n * Generated: ${current_time}\n */\n\n")
|
||||
string(APPEND final_content "${includes_section}")
|
||||
string(APPEND final_content "/*\n * Template Implementations\n */\n\n")
|
||||
string(APPEND final_content "${unit_content_body}")
|
||||
|
||||
file(WRITE "${final_unit_file}" "${final_content}")
|
||||
list(APPEND CONCATENATED_SOURCES "${final_unit_file}")
|
||||
set(CONCATENATED_SOURCES ${CONCATENATED_SOURCES} PARENT_SCOPE)
|
||||
|
||||
# Report deduplication statistics
|
||||
list(LENGTH GLOBAL_INCLUDES_LIST total_unique_includes)
|
||||
message(STATUS "✅ Created concatenated_unit_${unit_index}.cpp with ${total_unique_includes} unique includes")
|
||||
endfunction()
|
||||
|
||||
# Main function to concatenate and process compilation units
|
||||
function(concatenate_and_process_compilation_units target_count)
|
||||
message(STATUS "=== CONCATENATING AND PROCESSING COMPILATION UNITS ===")
|
||||
|
||||
# Find all template files
|
||||
file(GLOB_RECURSE ALL_TEMPLATE_FILES
|
||||
"${CMAKE_SOURCE_DIR}/include/ops/declarable/helpers/cpu/compilation_units/*.cpp.in"
|
||||
"${CMAKE_SOURCE_DIR}/include/loops/cpu/compilation_units/*.cpp.in"
|
||||
"${CMAKE_SOURCE_DIR}/include/loops/cpu/comb_compilation_units/*.cpp.in"
|
||||
"${CMAKE_SOURCE_DIR}/include/helpers/cpu/loops/*.cpp.in"
|
||||
)
|
||||
|
||||
list(LENGTH ALL_TEMPLATE_FILES total_files)
|
||||
if(total_files EQUAL 0)
|
||||
message(FATAL_ERROR "❌ No template files found to process!")
|
||||
endif()
|
||||
|
||||
math(EXPR files_per_unit "(${total_files} + ${target_count} - 1) / ${target_count}")
|
||||
message(STATUS "📊 Processing ${total_files} templates into ${target_count} units with include deduplication")
|
||||
|
||||
# Ensure we have combinations
|
||||
if(NOT DEFINED COMBINATIONS_2 OR NOT DEFINED COMBINATIONS_3)
|
||||
message(FATAL_ERROR "❌ Type combinations not initialized!")
|
||||
endif()
|
||||
|
||||
list(LENGTH COMBINATIONS_2 combo2_count)
|
||||
list(LENGTH COMBINATIONS_3 combo3_count)
|
||||
message(STATUS "Using ${combo2_count} 2-type and ${combo3_count} 3-type combinations")
|
||||
|
||||
# Create concatenated units
|
||||
set(unit_index 0)
|
||||
set(files_in_current_unit 0)
|
||||
set(current_unit_files "")
|
||||
|
||||
foreach(template_file ${ALL_TEMPLATE_FILES})
|
||||
list(APPEND current_unit_files ${template_file})
|
||||
math(EXPR files_in_current_unit "${files_in_current_unit} + 1")
|
||||
|
||||
if(files_in_current_unit GREATER_EQUAL files_per_unit)
|
||||
process_concatenated_unit(${unit_index} "${current_unit_files}")
|
||||
set(current_unit_files "")
|
||||
set(files_in_current_unit 0)
|
||||
math(EXPR unit_index "${unit_index} + 1")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Handle remaining files
|
||||
if(NOT current_unit_files STREQUAL "")
|
||||
process_concatenated_unit(${unit_index} "${current_unit_files}")
|
||||
endif()
|
||||
|
||||
message(STATUS "✅ Created concatenated compilation units with deduplicated includes")
|
||||
set(CONCATENATED_SOURCES ${CONCATENATED_SOURCES} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
|
||||
# Main entry point
|
||||
function(create_4gb_safe_concatenated_units)
|
||||
message(STATUS "🔧 Creating concatenated compilation units with include deduplication...")
|
||||
|
||||
set(TARGET_UNITS 4)
|
||||
|
||||
if(NOT DEFINED COMBINATIONS_2 OR NOT DEFINED COMBINATIONS_3)
|
||||
message(STATUS "Initializing dynamic combinations...")
|
||||
initialize_dynamic_combinations()
|
||||
endif()
|
||||
|
||||
# Debug output
|
||||
list(LENGTH COMBINATIONS_2 combo2_count)
|
||||
list(LENGTH COMBINATIONS_3 combo3_count)
|
||||
if(combo2_count GREATER 0)
|
||||
list(GET COMBINATIONS_2 0 first_combo2)
|
||||
message(STATUS "Debug: First 2-type combination: ${first_combo2}")
|
||||
endif()
|
||||
if(combo3_count GREATER 0)
|
||||
list(GET COMBINATIONS_3 0 first_combo3)
|
||||
message(STATUS "Debug: First 3-type combination: ${first_combo3}")
|
||||
endif()
|
||||
|
||||
concatenate_and_process_compilation_units(${TARGET_UNITS})
|
||||
|
||||
if(DEFINED CONCATENATED_SOURCES)
|
||||
list(LENGTH CONCATENATED_SOURCES unit_count)
|
||||
message(STATUS "📊 Created ${unit_count} concatenated units with deduplicated includes")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Clean up existing units
|
||||
function(clean_concatenated_units)
|
||||
file(GLOB existing_units "${CMAKE_BINARY_DIR}/concatenated_unit_*.cpp")
|
||||
if(existing_units)
|
||||
file(REMOVE ${existing_units})
|
||||
list(LENGTH existing_units removed_count)
|
||||
message(STATUS "🗑️ Cleaned up ${removed_count} existing concatenated units")
|
||||
endif()
|
||||
|
||||
# Clean up any temp processing files
|
||||
file(GLOB temp_files "${CMAKE_BINARY_DIR}/temp_*.cpp*")
|
||||
if(temp_files)
|
||||
file(REMOVE ${temp_files})
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,69 @@
|
||||
# FindARMCOMPUTE.cmake
|
||||
# Find ARM Compute Library includes and libraries
|
||||
#
|
||||
# Sets the following variables:
|
||||
# ARMCOMPUTE_FOUND - True if ARM Compute Library was found
|
||||
# ARMCOMPUTE_INCLUDE - Path to ARM Compute Library include directory
|
||||
# ARMCOMPUTE_LIBRARIES - ARM Compute Library libraries to link against
|
||||
#
|
||||
# This module will look for ARM Compute Library in standard locations and
|
||||
# in the directory specified by the ARMCOMPUTE_ROOT variable.
|
||||
|
||||
# Find include directory
|
||||
find_path(ARMCOMPUTE_INCLUDE
|
||||
NAMES arm_compute/core/CL/CLKernelLibrary.h
|
||||
PATHS
|
||||
${ARMCOMPUTE_ROOT}
|
||||
${ARMCOMPUTE_ROOT}/include
|
||||
ENV ARMCOMPUTE_ROOT
|
||||
ENV ARMCOMPUTE_PATH
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
REQUIRED
|
||||
)
|
||||
|
||||
# Find library files
|
||||
find_library(ARMCOMPUTE_CORE_LIBRARY
|
||||
NAMES arm_compute_core-static arm_compute_core
|
||||
PATHS
|
||||
${ARMCOMPUTE_ROOT}
|
||||
${ARMCOMPUTE_ROOT}/lib
|
||||
${ARMCOMPUTE_ROOT}/build
|
||||
ENV ARMCOMPUTE_ROOT
|
||||
ENV ARMCOMPUTE_PATH
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
REQUIRED
|
||||
)
|
||||
|
||||
find_library(ARMCOMPUTE_LIBRARY
|
||||
NAMES arm_compute-static arm_compute
|
||||
PATHS
|
||||
${ARMCOMPUTE_ROOT}
|
||||
${ARMCOMPUTE_ROOT}/lib
|
||||
${ARMCOMPUTE_ROOT}/build
|
||||
ENV ARMCOMPUTE_ROOT
|
||||
ENV ARMCOMPUTE_PATH
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
REQUIRED
|
||||
)
|
||||
|
||||
# Set libraries variable
|
||||
set(ARMCOMPUTE_LIBRARIES ${ARMCOMPUTE_LIBRARY} ${ARMCOMPUTE_CORE_LIBRARY})
|
||||
|
||||
# Handle the QUIETLY and REQUIRED arguments
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ARMCOMPUTE
|
||||
DEFAULT_MSG
|
||||
ARMCOMPUTE_INCLUDE
|
||||
ARMCOMPUTE_LIBRARIES
|
||||
)
|
||||
|
||||
# Mark as advanced
|
||||
mark_as_advanced(
|
||||
ARMCOMPUTE_INCLUDE
|
||||
ARMCOMPUTE_LIBRARY
|
||||
ARMCOMPUTE_CORE_LIBRARY
|
||||
ARMCOMPUTE_LIBRARIES
|
||||
)
|
||||
@@ -0,0 +1,100 @@
|
||||
# - Find Dwarf
|
||||
# Find the dwarf.h header from elf utils
|
||||
#
|
||||
# DWARF_INCLUDE_DIR - where to find dwarf.h, etc.
|
||||
# DWARF_LIBRARIES - List of libraries when using elf utils.
|
||||
# DWARF_FOUND - True if fdo found.
|
||||
|
||||
message(STATUS "Checking availability of DWARF and ELF development libraries")
|
||||
|
||||
INCLUDE(CheckLibraryExists)
|
||||
|
||||
if (DWARF_INCLUDE_DIR AND LIBDW_INCLUDE_DIR AND DWARF_LIBRARY AND ELF_LIBRARY)
|
||||
# Already in cache, be silent
|
||||
set(DWARF_FIND_QUIETLY TRUE)
|
||||
endif (DWARF_INCLUDE_DIR AND LIBDW_INCLUDE_DIR AND DWARF_LIBRARY AND ELF_LIBRARY)
|
||||
|
||||
find_path(DWARF_INCLUDE_DIR dwarf.h
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/usr/include/libdwarf
|
||||
~/usr/local/include
|
||||
)
|
||||
|
||||
find_path(LIBDW_INCLUDE_DIR elfutils/libdw.h
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
~/usr/local/include
|
||||
)
|
||||
|
||||
find_library(DWARF_LIBRARY
|
||||
NAMES dw dwarf
|
||||
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 ~/usr/local/lib ~/usr/local/lib64
|
||||
)
|
||||
|
||||
find_library(ELF_LIBRARY
|
||||
NAMES elf
|
||||
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 ~/usr/local/lib ~/usr/local/lib64
|
||||
)
|
||||
|
||||
if (DWARF_INCLUDE_DIR AND LIBDW_INCLUDE_DIR AND DWARF_LIBRARY AND ELF_LIBRARY)
|
||||
set(DWARF_FOUND TRUE)
|
||||
set(DWARF_LIBRARIES ${DWARF_LIBRARY} ${ELF_LIBRARY})
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${DWARF_LIBRARIES})
|
||||
# check if libdw have the dwfl_module_build_id routine, i.e. if it supports the buildid
|
||||
# mechanism to match binaries to detached debug info sections (the -debuginfo packages
|
||||
# in distributions such as fedora). We do it against libelf because, IIRC, some distros
|
||||
# include libdw linked statically into libelf.
|
||||
check_library_exists(elf dwfl_module_build_id "" HAVE_DWFL_MODULE_BUILD_ID)
|
||||
else (DWARF_INCLUDE_DIR AND LIBDW_INCLUDE_DIR AND DWARF_LIBRARY AND ELF_LIBRARY)
|
||||
set(DWARF_FOUND FALSE)
|
||||
set(DWARF_LIBRARIES)
|
||||
endif (DWARF_INCLUDE_DIR AND LIBDW_INCLUDE_DIR AND DWARF_LIBRARY AND ELF_LIBRARY)
|
||||
|
||||
if (DWARF_FOUND)
|
||||
if (NOT DWARF_FIND_QUIETLY)
|
||||
message(STATUS "Found dwarf.h header: ${DWARF_INCLUDE_DIR}")
|
||||
message(STATUS "Found elfutils/libdw.h header: ${LIBDW_INCLUDE_DIR}")
|
||||
message(STATUS "Found libdw library: ${DWARF_LIBRARY}")
|
||||
message(STATUS "Found libelf library: ${ELF_LIBRARY}")
|
||||
endif (NOT DWARF_FIND_QUIETLY)
|
||||
else (DWARF_FOUND)
|
||||
if (DWARF_FIND_REQUIRED)
|
||||
# Check if we are in a Red Hat (RHEL) or Fedora system to tell
|
||||
# exactly which packages should be installed. Please send
|
||||
# patches for other distributions.
|
||||
find_path(FEDORA fedora-release /etc)
|
||||
find_path(REDHAT redhat-release /etc)
|
||||
if (FEDORA OR REDHAT)
|
||||
if (NOT DWARF_INCLUDE_DIR OR NOT LIBDW_INCLUDE_DIR)
|
||||
message(STATUS "Please install the elfutils-devel package")
|
||||
endif (NOT DWARF_INCLUDE_DIR OR NOT LIBDW_INCLUDE_DIR)
|
||||
if (NOT DWARF_LIBRARY)
|
||||
message(STATUS "Please install the elfutils-libs package")
|
||||
endif (NOT DWARF_LIBRARY)
|
||||
if (NOT ELF_LIBRARY)
|
||||
message(STATUS "Please install the elfutils-libelf package")
|
||||
endif (NOT ELF_LIBRARY)
|
||||
else (FEDORA OR REDHAT)
|
||||
if (NOT DWARF_INCLUDE_DIR)
|
||||
message(STATUS "Could NOT find dwarf include dir")
|
||||
endif (NOT DWARF_INCLUDE_DIR)
|
||||
if (NOT LIBDW_INCLUDE_DIR)
|
||||
message(STATUS "Could NOT find libdw include dir")
|
||||
endif (NOT LIBDW_INCLUDE_DIR)
|
||||
if (NOT DWARF_LIBRARY)
|
||||
message(STATUS "Could NOT find libdw library")
|
||||
endif (NOT DWARF_LIBRARY)
|
||||
if (NOT ELF_LIBRARY)
|
||||
message(STATUS "Could NOT find libelf library")
|
||||
endif (NOT ELF_LIBRARY)
|
||||
endif (FEDORA OR REDHAT)
|
||||
message(FATAL_ERROR "Could NOT find some ELF and DWARF libraries, please install the missing packages")
|
||||
endif (DWARF_FIND_REQUIRED)
|
||||
endif (DWARF_FOUND)
|
||||
|
||||
mark_as_advanced(DWARF_INCLUDE_DIR LIBDW_INCLUDE_DIR DWARF_LIBRARY ELF_LIBRARY)
|
||||
include_directories(${DWARF_INCLUDE_DIR} ${LIBDW_INCLUDE_DIR})
|
||||
|
||||
message(STATUS "Checking availability of DWARF and ELF development libraries - done")
|
||||
@@ -0,0 +1,19 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# cmake/InstantiationCache.cmake
|
||||
# Smart caching for instantiation analysis
|
||||
|
||||
function(should_process_file SOURCE_FILE SAFE_NAME OUT_VAR)
|
||||
# Get file modification time
|
||||
file(TIMESTAMP ${SOURCE_FILE} source_mtime)
|
||||
|
||||
# Check if cached results exist
|
||||
set(cache_file "${INST_TEMP_DIR}/${SAFE_NAME}.cache")
|
||||
|
||||
if(EXISTS ${cache_file})
|
||||
# Read cache timestamp
|
||||
file(READ ${cache_file} cache_content LIMIT 100)
|
||||
string(REGEX MATCH "timestamp:([0-9]+)" _ ${cache_content})
|
||||
set(cache_time ${CMAKE_MATCH_1})
|
||||
|
||||
# Compare timestamps
|
||||
if(cache_time AND source_mtime EQUAL cache_time)
|
||||
# Cache is valid, skip processing
|
||||
set(${OUT_VAR} FALSE PARENT_SCOPE)
|
||||
|
||||
# Load cached results
|
||||
if(EXISTS ${INST_USED_DIR}/${SAFE_NAME}.used.cached)
|
||||
file(COPY ${INST_USED_DIR}/${SAFE_NAME}.used.cached
|
||||
DESTINATION ${INST_USED_DIR}
|
||||
FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||
file(RENAME ${INST_USED_DIR}/${SAFE_NAME}.used.cached
|
||||
${INST_USED_DIR}/${SAFE_NAME}.used)
|
||||
endif()
|
||||
|
||||
if(EXISTS ${INST_PROVIDED_DIR}/${SAFE_NAME}.provided.cached)
|
||||
file(COPY ${INST_PROVIDED_DIR}/${SAFE_NAME}.provided.cached
|
||||
DESTINATION ${INST_PROVIDED_DIR}
|
||||
FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||
file(RENAME ${INST_PROVIDED_DIR}/${SAFE_NAME}.provided.cached
|
||||
${INST_PROVIDED_DIR}/${SAFE_NAME}.provided)
|
||||
endif()
|
||||
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Need to process this file
|
||||
set(${OUT_VAR} TRUE PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(cache_analysis_results SOURCE_FILE SAFE_NAME)
|
||||
file(TIMESTAMP ${SOURCE_FILE} source_mtime)
|
||||
|
||||
# Write cache marker
|
||||
set(cache_file "${INST_TEMP_DIR}/${SAFE_NAME}.cache")
|
||||
file(WRITE ${cache_file} "timestamp:${source_mtime}\n")
|
||||
|
||||
# Cache the analysis results
|
||||
if(EXISTS ${INST_USED_DIR}/${SAFE_NAME}.used)
|
||||
file(COPY ${INST_USED_DIR}/${SAFE_NAME}.used
|
||||
DESTINATION ${INST_USED_DIR}
|
||||
FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||
file(RENAME ${INST_USED_DIR}/${SAFE_NAME}.used
|
||||
${INST_USED_DIR}/${SAFE_NAME}.used.cached)
|
||||
endif()
|
||||
|
||||
if(EXISTS ${INST_PROVIDED_DIR}/${SAFE_NAME}.provided)
|
||||
file(COPY ${INST_PROVIDED_DIR}/${SAFE_NAME}.provided
|
||||
DESTINATION ${INST_PROVIDED_DIR}
|
||||
FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
|
||||
file(RENAME ${INST_PROVIDED_DIR}/${SAFE_NAME}.provided
|
||||
${INST_PROVIDED_DIR}/${SAFE_NAME}.provided.cached)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,612 @@
|
||||
# cmake/InstantiationHelpers.cmake
|
||||
# Helper functions for template instantiation extraction
|
||||
|
||||
# Function to setup compilation flags for instantiation extraction
|
||||
function(setup_instantiation_flags)
|
||||
# FIRST: Setup FlatBuffers EXACTLY like PostBuild.cmake does
|
||||
set(PREPROCESS_FLATBUFFERS_VERSION "25.2.10")
|
||||
set(PREPROCESS_FLATBUFFERS_URL "https://github.com/google/flatbuffers/archive/v${PREPROCESS_FLATBUFFERS_VERSION}.tar.gz")
|
||||
set(PREPROCESS_FB_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/preprocess-flatbuffers-src")
|
||||
|
||||
# Check if we already have FlatBuffers headers
|
||||
set(PREPROCESS_FB_HEADER "${PREPROCESS_FB_SOURCE_DIR}/include/flatbuffers/flatbuffers.h")
|
||||
if(NOT EXISTS ${PREPROCESS_FB_HEADER})
|
||||
message("Downloading and extracting FlatBuffers for instantiation analysis...")
|
||||
|
||||
# Download and extract FlatBuffers
|
||||
file(DOWNLOAD ${PREPROCESS_FLATBUFFERS_URL}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-${PREPROCESS_FLATBUFFERS_VERSION}.tar.gz"
|
||||
SHOW_PROGRESS
|
||||
STATUS download_status)
|
||||
|
||||
list(GET download_status 0 download_result)
|
||||
if(NOT download_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to download FlatBuffers for instantiation analysis")
|
||||
endif()
|
||||
|
||||
# Extract the archive
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xzf "flatbuffers-${PREPROCESS_FLATBUFFERS_VERSION}.tar.gz"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
RESULT_VARIABLE extract_result
|
||||
)
|
||||
|
||||
if(NOT extract_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to extract FlatBuffers for instantiation analysis")
|
||||
endif()
|
||||
|
||||
# Move the extracted directory to our expected location
|
||||
file(RENAME "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-${PREPROCESS_FLATBUFFERS_VERSION}"
|
||||
"${PREPROCESS_FB_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
# NOW COPY THE EXACT INCLUDE SETUP FROM PostBuild.cmake
|
||||
# Get ALL subdirectories under include/ and add the root include directory first
|
||||
set(all_includes "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
file(GLOB_RECURSE all_dirs LIST_DIRECTORIES true "${CMAKE_CURRENT_SOURCE_DIR}/include/*")
|
||||
foreach(item ${all_dirs})
|
||||
if(IS_DIRECTORY ${item})
|
||||
list(APPEND all_includes ${item})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Add binary include directory
|
||||
list(APPEND all_includes "${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
|
||||
# Also add build directories - EXACTLY AS IN PostBuild.cmake
|
||||
list(APPEND all_includes
|
||||
"${CMAKE_SOURCE_DIR}/include/"
|
||||
"${CMAKE_SOURCE_DIR}/include/system"
|
||||
"${CMAKE_BINARY_DIR}/compilation_units"
|
||||
"${CMAKE_BINARY_DIR}/cpu_instantiations"
|
||||
"${CMAKE_BINARY_DIR}/cuda_instantiations"
|
||||
"${CMAKE_BINARY_DIR}/include"
|
||||
)
|
||||
|
||||
# Add our self-contained FlatBuffers include directory - EXACTLY AS IN PostBuild.cmake
|
||||
list(APPEND all_includes "${PREPROCESS_FB_SOURCE_DIR}/include")
|
||||
|
||||
# Build include flags string
|
||||
set(include_flags "")
|
||||
foreach(dir IN LISTS all_includes)
|
||||
if(EXISTS ${dir})
|
||||
string(APPEND include_flags " -I${dir}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(defs_flags "")
|
||||
|
||||
# Add basic platform definitions
|
||||
string(APPEND defs_flags " -D__CPUBLAS__=true")
|
||||
if(SD_CUDA)
|
||||
string(APPEND defs_flags " -D__CUDABLAS__=true -DHAVE_CUDA=1")
|
||||
endif()
|
||||
if(HAVE_OPENBLAS)
|
||||
string(APPEND defs_flags " -DHAVE_OPENBLAS=1")
|
||||
endif()
|
||||
|
||||
if(SD_ALL_OPS OR "${SD_OPS_LIST}" STREQUAL "")
|
||||
string(APPEND defs_flags " -DSD_ALL_OPS=1")
|
||||
# When SD_ALL_OPS=1, NOT_EXCLUDED should evaluate to 1 for all ops
|
||||
string(APPEND defs_flags " -DNOT_EXCLUDED(x)=1")
|
||||
else()
|
||||
# Add specific operation definitions
|
||||
foreach(OP ${SD_OPS_LIST})
|
||||
string(APPEND defs_flags " -DOP_${OP}=1")
|
||||
endforeach()
|
||||
# Define NOT_EXCLUDED macro for selective ops
|
||||
string(APPEND defs_flags " -DNOT_EXCLUDED(x)=\\(defined\\(x\\)\\)")
|
||||
endif()
|
||||
|
||||
# Add build type definitions
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
string(APPEND defs_flags " -DDEBUG=1 -D_DEBUG=1")
|
||||
else()
|
||||
string(APPEND defs_flags " -DNDEBUG=1")
|
||||
endif()
|
||||
|
||||
# Add any additional compile definitions from the main build
|
||||
if(compile_defs AND NOT compile_defs STREQUAL "compile_defs-NOTFOUND")
|
||||
foreach(def IN LISTS compile_defs)
|
||||
string(APPEND defs_flags " -D${def}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Datatype definitions
|
||||
if(SD_TYPES_LIST)
|
||||
string(REPLACE ";" "," types_comma_list "${SD_TYPES_LIST}")
|
||||
string(APPEND defs_flags " -DSD_TYPES_LIST=\"${types_comma_list}\"")
|
||||
endif()
|
||||
|
||||
# Export to parent scope
|
||||
set(INST_INCLUDE_FLAGS ${include_flags} PARENT_SCOPE)
|
||||
set(INST_DEFS_FLAGS ${defs_flags} PARENT_SCOPE)
|
||||
set(INST_LANG_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}" PARENT_SCOPE)
|
||||
|
||||
# Find required tools
|
||||
find_program(NM_TOOL NAMES nm gcc-nm llvm-nm)
|
||||
find_program(CPPFILT_TOOL NAMES c++filt llvm-cxxfilt)
|
||||
|
||||
set(NM_TOOL ${NM_TOOL} PARENT_SCOPE)
|
||||
set(CPPFILT_TOOL ${CPPFILT_TOOL} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Function to get source list
|
||||
function(get_source_list OUT_VAR)
|
||||
if(DEFINED ALL_SOURCES AND ALL_SOURCES)
|
||||
set(${OUT_VAR} ${ALL_SOURCES} PARENT_SCOPE)
|
||||
elseif(DEFINED ALL_SOURCES_LIST AND ALL_SOURCES_LIST)
|
||||
set(${OUT_VAR} ${ALL_SOURCES_LIST} PARENT_SCOPE)
|
||||
else()
|
||||
set(${OUT_VAR} "" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Function to extract used templates from a source file - KEEP THE ORIGINAL WORKING VERSION
|
||||
function(extract_used_templates SOURCE_FILE OUTPUT_FILE SAFE_NAME)
|
||||
# Initialize empty result
|
||||
set(used_templates "")
|
||||
|
||||
# Check if source file exists
|
||||
if(NOT EXISTS "${SOURCE_FILE}")
|
||||
message(WARNING "Source file does not exist: ${SOURCE_FILE}")
|
||||
file(WRITE ${OUTPUT_FILE} "")
|
||||
set(EXTRACTED_USED_TEMPLATES "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Check if temp directory exists
|
||||
if(NOT EXISTS "${INST_TEMP_DIR}")
|
||||
file(MAKE_DIRECTORY "${INST_TEMP_DIR}")
|
||||
endif()
|
||||
|
||||
# Always preprocess the file to expand all macros
|
||||
set(preprocessed_file "${INST_TEMP_DIR}/${SAFE_NAME}_preprocessed.i")
|
||||
|
||||
# Determine compiler and flags based on file type
|
||||
if(SOURCE_FILE MATCHES "\\.cu$")
|
||||
set(compiler "${CMAKE_CUDA_COMPILER}")
|
||||
set(lang_flags "${CMAKE_CUDA_FLAGS} ${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||
elseif(SOURCE_FILE MATCHES "\\.c$")
|
||||
set(compiler "${CMAKE_C_COMPILER}")
|
||||
set(lang_flags "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||
else()
|
||||
set(compiler "${CMAKE_CXX_COMPILER}")
|
||||
set(lang_flags "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||
endif()
|
||||
|
||||
# Check if compiler exists
|
||||
if(NOT EXISTS "${compiler}" AND NOT compiler)
|
||||
message(WARNING "Compiler not found for ${SOURCE_FILE}")
|
||||
file(WRITE ${OUTPUT_FILE} "")
|
||||
set(EXTRACTED_USED_TEMPLATES "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Preprocess the file to expand all macros - USING EXACT WORKING METHOD FROM PostBuild.cmake
|
||||
# Split the flags properly for execute_process
|
||||
separate_arguments(lang_flags_list UNIX_COMMAND "${lang_flags}")
|
||||
separate_arguments(defs_flags_list UNIX_COMMAND "${INST_DEFS_FLAGS}")
|
||||
separate_arguments(include_flags_list UNIX_COMMAND "${INST_INCLUDE_FLAGS}")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${compiler} -E -P -C ${lang_flags_list} ${defs_flags_list} ${include_flags_list} "${SOURCE_FILE}" -o "${preprocessed_file}"
|
||||
RESULT_VARIABLE preprocess_result
|
||||
ERROR_VARIABLE preprocess_errors
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
if(NOT preprocess_result EQUAL 0)
|
||||
message(WARNING "Failed to preprocess ${SOURCE_FILE}: ${preprocess_errors}")
|
||||
file(WRITE ${OUTPUT_FILE} "")
|
||||
set(EXTRACTED_USED_TEMPLATES "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS ${preprocessed_file})
|
||||
message(WARNING "Preprocessed file not created for ${SOURCE_FILE}")
|
||||
file(WRITE ${OUTPUT_FILE} "")
|
||||
set(EXTRACTED_USED_TEMPLATES "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Method 1: Compile the preprocessed file with -fno-implicit-templates to find required templates
|
||||
execute_process(
|
||||
COMMAND ${compiler}
|
||||
-fsyntax-only
|
||||
-fno-implicit-templates
|
||||
-ftemplate-backtrace-limit=0
|
||||
${lang_flags}
|
||||
${INST_DEFS_FLAGS}
|
||||
${INST_INCLUDE_FLAGS}
|
||||
-x c++ # Force C++ mode since .i files might not be recognized
|
||||
${preprocessed_file}
|
||||
ERROR_VARIABLE compile_errors
|
||||
OUTPUT_QUIET
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
TIMEOUT 30
|
||||
)
|
||||
|
||||
if(compile_errors)
|
||||
# Parse undefined references from the preprocessed compilation
|
||||
string(REGEX MATCHALL "undefined reference to '[^']+'" undefined_refs "${compile_errors}")
|
||||
foreach(ref ${undefined_refs})
|
||||
string(REGEX REPLACE "undefined reference to '([^']+)'" "\\1" symbol "${ref}")
|
||||
# Filter for template instantiations
|
||||
if(symbol MATCHES ".*<.*>.*")
|
||||
# Demangle if needed
|
||||
if(symbol MATCHES "^_Z")
|
||||
if(CPPFILT_TOOL)
|
||||
execute_process(
|
||||
COMMAND ${CPPFILT_TOOL} "${symbol}"
|
||||
OUTPUT_VARIABLE demangled
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
if(demangled)
|
||||
set(symbol "${demangled}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
list(APPEND used_templates "${symbol}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Parse instantiation requirements
|
||||
string(REGEX MATCHALL "instantiation of '[^']+' required" inst_reqs "${compile_errors}")
|
||||
foreach(req ${inst_reqs})
|
||||
string(REGEX REPLACE "instantiation of '([^']+)' required" "\\1" tmpl "${req}")
|
||||
if(tmpl MATCHES ".*<.*>.*")
|
||||
list(APPEND used_templates "${tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Parse "error: explicit instantiation of '[^']+' but no definition available"
|
||||
string(REGEX MATCHALL "explicit instantiation of '[^']+' but no definition" missing_defs "${compile_errors}")
|
||||
foreach(def ${missing_defs})
|
||||
string(REGEX REPLACE "explicit instantiation of '([^']+)' but no definition" "\\1" tmpl "${def}")
|
||||
if(tmpl MATCHES ".*<.*>.*")
|
||||
list(APPEND used_templates "${tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Method 2: Parse the preprocessed source for template usage patterns
|
||||
file(READ ${preprocessed_file} source_content LIMIT 10485760) # Read up to 10MB
|
||||
|
||||
# Look for explicit template instantiation declarations (extern template)
|
||||
string(REGEX MATCHALL "extern[ \t]+template[ \t]+[^;]+<[^>]+>[^;]*;" extern_templates "${source_content}")
|
||||
foreach(ext_tmpl ${extern_templates})
|
||||
string(REGEX MATCH "[a-zA-Z_][a-zA-Z0-9_:]*<[^>]+>" tmpl "${ext_tmpl}")
|
||||
if(tmpl)
|
||||
list(APPEND used_templates "${tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Look for template instantiation patterns in expanded macros
|
||||
# These patterns commonly appear after macro expansion
|
||||
set(expanded_patterns
|
||||
"template[ \t]+class[ \t]+[a-zA-Z_][a-zA-Z0-9_:]*<[^>]+>"
|
||||
"template[ \t]+struct[ \t]+[a-zA-Z_][a-zA-Z0-9_:]*<[^>]+>"
|
||||
"template[ \t]+void[ \t]+[a-zA-Z_][a-zA-Z0-9_:]*<[^>]+>::[a-zA-Z_][a-zA-Z0-9_]*"
|
||||
"template[ \t]+[a-zA-Z_][a-zA-Z0-9_:]*[ \t]+[a-zA-Z_][a-zA-Z0-9_:]*<[^>]+>::[a-zA-Z_][a-zA-Z0-9_]*"
|
||||
)
|
||||
|
||||
foreach(pattern ${expanded_patterns})
|
||||
string(REGEX MATCHALL "${pattern}" matches "${source_content}")
|
||||
foreach(match ${matches})
|
||||
# Extract the template class/function signature
|
||||
string(REGEX MATCH "[a-zA-Z_][a-zA-Z0-9_:]*<[^>]+>" tmpl "${match}")
|
||||
if(tmpl)
|
||||
list(APPEND used_templates "${tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
# Method 3: Look for template function calls and instantiations
|
||||
# Common template patterns that indicate usage
|
||||
set(usage_patterns
|
||||
"NDArray<[^>]+>"
|
||||
"DataBuffer<[^>]+>"
|
||||
"BroadcastHelper<[^>]+>"
|
||||
"BroadcastInt<[^>]+>"
|
||||
"BroadcastBool<[^>]+>"
|
||||
"Broadcast<[^>]+>"
|
||||
"LoopKind::Kind<[^>]+>"
|
||||
"LaunchContext<[^>]+>"
|
||||
"ResultSet<[^>]+>"
|
||||
"ShapeList<[^>]+>"
|
||||
"SpecialMethods<[^>]+>"
|
||||
"TypeCast::convertGeneric<[^>]+>"
|
||||
"PairWiseTransform<[^>]+>"
|
||||
"ScalarTransform<[^>]+>"
|
||||
"RandomFunction<[^>]+>"
|
||||
"ReduceSameFunction<[^>]+>"
|
||||
"ReduceFloatFunction<[^>]+>"
|
||||
"ReduceBoolFunction<[^>]+>"
|
||||
"ReduceLongFunction<[^>]+>"
|
||||
"Reduce3<[^>]+>"
|
||||
"IndexReduce<[^>]+>"
|
||||
"ReductionLoops<[^>]+>"
|
||||
"IndexReductionLoops<[^>]+>"
|
||||
"std::vector<[^>]+>"
|
||||
"std::unique_ptr<[^>]+>"
|
||||
"std::shared_ptr<[^>]+>"
|
||||
)
|
||||
|
||||
foreach(pattern ${usage_patterns})
|
||||
string(REGEX MATCHALL "${pattern}" matches "${source_content}")
|
||||
list(APPEND used_templates ${matches})
|
||||
endforeach()
|
||||
|
||||
# Method 4: Try to compile to object and extract undefined symbols
|
||||
set(temp_obj "${INST_TEMP_DIR}/${SAFE_NAME}_test.o")
|
||||
execute_process(
|
||||
COMMAND ${compiler}
|
||||
-c
|
||||
-o ${temp_obj}
|
||||
${lang_flags}
|
||||
${INST_DEFS_FLAGS}
|
||||
${INST_INCLUDE_FLAGS}
|
||||
-x c++
|
||||
${preprocessed_file}
|
||||
ERROR_VARIABLE obj_errors
|
||||
OUTPUT_QUIET
|
||||
RESULT_VARIABLE obj_result
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
TIMEOUT 30
|
||||
)
|
||||
|
||||
# Extract undefined symbols from linker errors
|
||||
if(obj_errors)
|
||||
string(REGEX MATCHALL "undefined reference to `[^']+'" undef_symbols "${obj_errors}")
|
||||
foreach(symbol ${undef_symbols})
|
||||
string(REGEX REPLACE "undefined reference to `([^']+)'" "\\1" sym "${symbol}")
|
||||
if(sym MATCHES ".*<.*>.*")
|
||||
# Try to demangle if it's mangled
|
||||
if(sym MATCHES "^_Z" AND CPPFILT_TOOL)
|
||||
execute_process(
|
||||
COMMAND ${CPPFILT_TOOL} "${sym}"
|
||||
OUTPUT_VARIABLE demangled
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
if(demangled)
|
||||
set(sym "${demangled}")
|
||||
endif()
|
||||
endif()
|
||||
list(APPEND used_templates "${sym}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# If object was created, also check with nm for undefined symbols
|
||||
if(obj_result EQUAL 0 AND EXISTS ${temp_obj} AND NM_TOOL)
|
||||
execute_process(
|
||||
COMMAND ${NM_TOOL} -u ${temp_obj}
|
||||
OUTPUT_VARIABLE nm_undefined
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
if(nm_undefined)
|
||||
string(REGEX MATCHALL "_Z[A-Za-z0-9_]+" mangled_symbols "${nm_undefined}")
|
||||
foreach(mangled ${mangled_symbols})
|
||||
if(CPPFILT_TOOL)
|
||||
execute_process(
|
||||
COMMAND ${CPPFILT_TOOL} ${mangled}
|
||||
OUTPUT_VARIABLE demangled
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
if(demangled AND demangled MATCHES ".*<.*>.*")
|
||||
list(APPEND used_templates "${demangled}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
file(REMOVE ${temp_obj})
|
||||
endif()
|
||||
|
||||
# Clean up preprocessed file
|
||||
file(REMOVE ${preprocessed_file})
|
||||
|
||||
# Remove duplicates and filter out noise
|
||||
if(used_templates)
|
||||
list(REMOVE_DUPLICATES used_templates)
|
||||
|
||||
# Filter out standard library internals and compiler intrinsics
|
||||
set(filtered_templates "")
|
||||
foreach(tmpl ${used_templates})
|
||||
if(NOT tmpl MATCHES "^__" AND
|
||||
NOT tmpl MATCHES "^std::__" AND
|
||||
NOT tmpl MATCHES "^__gnu" AND
|
||||
NOT tmpl MATCHES "^__builtin" AND
|
||||
NOT tmpl MATCHES "^operator")
|
||||
list(APPEND filtered_templates "${tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
string(REPLACE ";" "\n" used_content "${filtered_templates}")
|
||||
file(WRITE ${OUTPUT_FILE} "${used_content}")
|
||||
set(EXTRACTED_USED_TEMPLATES ${filtered_templates} PARENT_SCOPE)
|
||||
else()
|
||||
file(WRITE ${OUTPUT_FILE} "")
|
||||
set(EXTRACTED_USED_TEMPLATES "" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(extract_provided_templates SOURCE_FILE OUTPUT_FILE SAFE_NAME)
|
||||
set(provided_templates "")
|
||||
|
||||
# Check if source file exists
|
||||
if(NOT EXISTS "${SOURCE_FILE}")
|
||||
message(WARNING "Source file does not exist: ${SOURCE_FILE}")
|
||||
file(WRITE ${OUTPUT_FILE} "")
|
||||
set(EXTRACTED_PROVIDED_TEMPLATES "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Check if temp directory exists
|
||||
if(NOT EXISTS "${INST_TEMP_DIR}")
|
||||
file(MAKE_DIRECTORY "${INST_TEMP_DIR}")
|
||||
endif()
|
||||
|
||||
# Method 1: Check for explicit instantiations in source
|
||||
file(READ ${SOURCE_FILE} source_content LIMIT 1048576)
|
||||
|
||||
string(REGEX MATCHALL "template[ \t]+class[ \t]+[^;]+<[^>]+>[^;]*;"
|
||||
explicit_class "${source_content}")
|
||||
string(REGEX MATCHALL "template[ \t]+struct[ \t]+[^;]+<[^>]+>[^;]*;"
|
||||
explicit_struct "${source_content}")
|
||||
|
||||
foreach(inst ${explicit_class} ${explicit_struct})
|
||||
string(REGEX MATCH "[a-zA-Z_][a-zA-Z0-9_]*<[^>]+>" tmpl "${inst}")
|
||||
if(tmpl)
|
||||
list(APPEND provided_templates "${tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Method 2: Compile to object and extract symbols
|
||||
set(temp_obj "${INST_TEMP_DIR}/${SAFE_NAME}.o")
|
||||
|
||||
# Determine compiler based on file type
|
||||
if(SOURCE_FILE MATCHES "\\.cu$")
|
||||
set(compiler "${CMAKE_CUDA_COMPILER}")
|
||||
elseif(SOURCE_FILE MATCHES "\\.c$")
|
||||
set(compiler "${CMAKE_C_COMPILER}")
|
||||
else()
|
||||
set(compiler "${CMAKE_CXX_COMPILER}")
|
||||
endif()
|
||||
|
||||
# Check if compiler exists
|
||||
if(NOT EXISTS "${compiler}" AND NOT compiler)
|
||||
message(WARNING "Compiler not found for ${SOURCE_FILE}")
|
||||
# Still write what we found from method 1
|
||||
if(provided_templates)
|
||||
list(REMOVE_DUPLICATES provided_templates)
|
||||
string(REPLACE ";" "\n" provided_content "${provided_templates}")
|
||||
file(WRITE ${OUTPUT_FILE} "${provided_content}")
|
||||
set(EXTRACTED_PROVIDED_TEMPLATES ${provided_templates} PARENT_SCOPE)
|
||||
else()
|
||||
file(WRITE ${OUTPUT_FILE} "")
|
||||
set(EXTRACTED_PROVIDED_TEMPLATES "" PARENT_SCOPE)
|
||||
endif()
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${compiler}
|
||||
-c
|
||||
-o ${temp_obj}
|
||||
${INST_LANG_FLAGS}
|
||||
${INST_DEFS_FLAGS}
|
||||
${INST_INCLUDE_FLAGS}
|
||||
${SOURCE_FILE}
|
||||
ERROR_QUIET
|
||||
OUTPUT_QUIET
|
||||
RESULT_VARIABLE compile_result
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
|
||||
if(compile_result EQUAL 0 AND EXISTS ${temp_obj})
|
||||
if(NM_TOOL AND CPPFILT_TOOL)
|
||||
# Extract defined symbols
|
||||
execute_process(
|
||||
COMMAND ${NM_TOOL} --defined-only ${temp_obj}
|
||||
OUTPUT_VARIABLE nm_output
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
if(nm_output)
|
||||
# Extract and demangle template symbols
|
||||
string(REGEX MATCHALL "_Z[A-Za-z0-9_]+" mangled_symbols "${nm_output}")
|
||||
|
||||
foreach(mangled ${mangled_symbols})
|
||||
execute_process(
|
||||
COMMAND ${CPPFILT_TOOL} ${mangled}
|
||||
OUTPUT_VARIABLE demangled
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
if(demangled MATCHES ".*<.*>.*")
|
||||
# Filter out std:: and internal templates
|
||||
if(NOT demangled MATCHES "^std::" AND
|
||||
NOT demangled MATCHES "^__" AND
|
||||
NOT demangled MATCHES "^operator")
|
||||
list(APPEND provided_templates "${demangled}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
file(REMOVE ${temp_obj})
|
||||
endif()
|
||||
|
||||
# Method 3: Parse assembly output for template instantiations
|
||||
execute_process(
|
||||
COMMAND ${compiler}
|
||||
-S
|
||||
-o -
|
||||
-fverbose-asm
|
||||
${INST_LANG_FLAGS}
|
||||
${INST_DEFS_FLAGS}
|
||||
${INST_INCLUDE_FLAGS}
|
||||
${SOURCE_FILE}
|
||||
OUTPUT_VARIABLE asm_output
|
||||
ERROR_QUIET
|
||||
RESULT_VARIABLE asm_result
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
TIMEOUT 10
|
||||
)
|
||||
|
||||
if(asm_result EQUAL 0 AND asm_output)
|
||||
# Extract template info from assembly comments
|
||||
string(LENGTH "${asm_output}" asm_length)
|
||||
if(asm_length LESS 10000000) # Only process if under 10MB
|
||||
string(REGEX MATCHALL "#.*<[^>]+>.*" asm_templates "${asm_output}")
|
||||
foreach(comment ${asm_templates})
|
||||
string(REGEX MATCH "[a-zA-Z_][a-zA-Z0-9_]*<[^>]+>" tmpl "${comment}")
|
||||
if(tmpl AND NOT tmpl MATCHES "^std::")
|
||||
list(APPEND provided_templates "${tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Remove duplicates and write to file
|
||||
if(provided_templates)
|
||||
list(REMOVE_DUPLICATES provided_templates)
|
||||
string(REPLACE ";" "\n" provided_content "${provided_templates}")
|
||||
file(WRITE ${OUTPUT_FILE} "${provided_content}")
|
||||
set(EXTRACTED_PROVIDED_TEMPLATES ${provided_templates} PARENT_SCOPE)
|
||||
else()
|
||||
file(WRITE ${OUTPUT_FILE} "")
|
||||
set(EXTRACTED_PROVIDED_TEMPLATES "" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Function to normalize template names for comparison
|
||||
function(normalize_template_name TEMPLATE OUT_VAR)
|
||||
set(normalized "${TEMPLATE}")
|
||||
|
||||
# Remove extra spaces
|
||||
string(REGEX REPLACE "[ \t]+" " " normalized "${normalized}")
|
||||
string(STRIP "${normalized}" normalized)
|
||||
|
||||
# Normalize const placement
|
||||
string(REPLACE "const " "" normalized "${normalized}")
|
||||
string(REPLACE " const" "" normalized "${normalized}")
|
||||
|
||||
# Remove allocator specifications from std containers
|
||||
string(REGEX REPLACE "std::allocator<[^>]+>" "" normalized "${normalized}")
|
||||
|
||||
# Normalize pointer/reference spacing
|
||||
string(REPLACE " *" "*" normalized "${normalized}")
|
||||
string(REPLACE " &" "&" normalized "${normalized}")
|
||||
|
||||
set(${OUT_VAR} "${normalized}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -0,0 +1,853 @@
|
||||
# =============================================================================
|
||||
# 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 ===")
|
||||
@@ -0,0 +1,239 @@
|
||||
# cmake/Options.cmake
|
||||
# Defines all user-configurable build options and helper functions.
|
||||
|
||||
# --- Build Feature Options ---
|
||||
option(SD_NATIVE "Optimize for build machine (might not work on others)" OFF)
|
||||
option(SD_CHECK_VECTORIZATION "checks for vectorization" OFF)
|
||||
option(SD_STATIC_LIB "Build static library (ignored, only shared lib is built)" OFF)
|
||||
option(SD_SHARED_LIB "Build shared library (ignored, this is the default)" ON)
|
||||
option(SD_USE_LTO "Use link time optimization" OFF)
|
||||
option(SD_SANITIZE "Enable Address Sanitizer" OFF)
|
||||
option(SD_EXTRACT_INSTANTIATIONS "Extract template instantiations and exit" OFF)
|
||||
option(SD_GENERATE_FIX_FILES "Generate fix files for missing instantiations" OFF)
|
||||
option(SD_INSTANTIATION_VERBOSE "Verbose instantiation extraction" OFF)
|
||||
|
||||
# --- COMPILATION OPTIMIZATION OPTIONS (NEW) ---
|
||||
# These dramatically affect template compilation time
|
||||
option(SD_FAST_BUILD "Enable fast build mode with minimal templates" OFF)
|
||||
option(SD_UNITY_BUILD "Enable Unity build for faster compilation" OFF)
|
||||
set(SD_PARALLEL_COMPILE_JOBS "0" CACHE STRING "Number of parallel compile jobs (0 = auto)")
|
||||
|
||||
# --- Helper Library Toggles ---
|
||||
option(HELPERS_armcompute "Enable ARM Compute Library helper" OFF)
|
||||
option(HELPERS_onednn "Enable OneDNN helper" OFF)
|
||||
option(HELPERS_cudnn "Enable cuDNN helper" OFF)
|
||||
|
||||
# Force all helpers OFF by default to prevent compilation issues
|
||||
set(HELPERS_armcompute OFF CACHE BOOL "Force disable ARM Compute Library helper" FORCE)
|
||||
set(HELPERS_onednn OFF CACHE BOOL "Force disable OneDNN helper" FORCE)
|
||||
set(HELPERS_cudnn OFF CACHE BOOL "Force disable cuDNN helper" FORCE)
|
||||
|
||||
# Set corresponding HAVE_* variables
|
||||
set(HAVE_ARMCOMPUTE OFF CACHE BOOL "ARM Compute Library availability" FORCE)
|
||||
set(HAVE_ONEDNN OFF CACHE BOOL "OneDNN availability" FORCE)
|
||||
set(HAVE_CUDNN OFF CACHE BOOL "cuDNN availability" FORCE)
|
||||
set(GENERATED_TYPE_COMBINATIONS "" CACHE INTERNAL "Generated type combinations")
|
||||
set(PROCESSED_TEMPLATE_FILES "" CACHE INTERNAL "Processed template files")
|
||||
|
||||
# --- Debug and Trace Options ---
|
||||
option(SD_GCC_FUNCTRACE "Use call traces" OFF)
|
||||
|
||||
# Enable compile_commands.json for functrace builds (helps with validation)
|
||||
if(SD_GCC_FUNCTRACE)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE BOOL "Export compile commands for validation" FORCE)
|
||||
endif()
|
||||
|
||||
option(PRINT_INDICES "Print indices" OFF)
|
||||
option(PRINT_MATH "Print math operations" OFF)
|
||||
option(SD_PTXAS "Enable ptxas verbose output" OFF)
|
||||
option(SD_KEEP_NVCC_OUTPUT "Keep NVCC output files" OFF)
|
||||
option(SD_PREPROCESS "Enable preprocessing" OFF)
|
||||
|
||||
# --- Build Target Options ---
|
||||
option(SD_BUILD_TESTS "Build tests" OFF)
|
||||
option(FLATBUFFERS_BUILD_FLATC "Enable the build of the flatbuffers compiler" OFF)
|
||||
|
||||
# Hack to disable flatc build unless explicitly enabled
|
||||
set(FLATBUFFERS_BUILD_FLATC "OFF" CACHE STRING "Hack to disable flatc build" FORCE)
|
||||
|
||||
# --- Type System and Template Options ---
|
||||
option(SD_ENABLE_SEMANTIC_FILTERING "Enable semantic filtering to reduce template combinations" ON)
|
||||
option(SD_ENABLE_SELECTIVE_RENDERING "Enable selective rendering system" ON)
|
||||
option(SD_AGGRESSIVE_SEMANTIC_FILTERING "Use aggressive filtering rules" ON)
|
||||
|
||||
# CHANGED: Default to MINIMAL for faster builds
|
||||
set(SD_TYPE_PROFILE "STANDARD_ALL_TYPES" CACHE STRING "Type profile for semantic filtering (MINIMAL, ESSENTIAL, QUANTIZATION, INFERENCE, TRAINING,STANDARD_ALL_TYPES)")
|
||||
set_property(CACHE SD_TYPE_PROFILE PROPERTY STRINGS STANDARD_ALL_TYPES MINIMAL ESSENTIAL QUANTIZATION INFERENCE TRAINING)
|
||||
|
||||
# CHANGED: Lower default to prevent explosion
|
||||
set(SD_MAX_TEMPLATE_COMBINATIONS "1000" CACHE STRING "Maximum template combinations to generate (safety limit)")
|
||||
|
||||
# --- NEW: Template Chunking Configuration ---
|
||||
# These control how template instantiations are split across files
|
||||
# TLS relocation overflow is caused by TOO MANY FILES, not large files
|
||||
# Solution: Use larger chunks with call tracing to minimize file count
|
||||
|
||||
# Detect build configuration and set appropriate defaults
|
||||
if(DEFINED SD_GCC_FUNCTRACE AND SD_GCC_FUNCTRACE)
|
||||
# Call tracing enabled - need larger chunks to avoid TLS overflow
|
||||
if((DEFINED SD_SANITIZE AND SD_SANITIZE) OR (DEFINED SD_SANITIZERS AND NOT SD_SANITIZERS STREQUAL ""))
|
||||
# Call tracing + Sanitizers: Compromise between speed and RAM
|
||||
# Larger than sanitizers-only (prevents TLS overflow) but not too large (prevents OOM)
|
||||
set(CHUNK_TARGET_INSTANTIATIONS "30" CACHE STRING "Balanced chunks for call tracing + sanitizers" FORCE)
|
||||
set(MULTI_PASS_CHUNK_SIZE "70" CACHE STRING "Balanced direct chunks for call tracing + sanitizers" FORCE)
|
||||
message(STATUS "⚠️ Call tracing + Sanitizers: Using balanced chunks (30/70) - prevents TLS overflow and OOM")
|
||||
else()
|
||||
# Call tracing only: Very large chunks for maximum speed (no RAM constraints without sanitizers)
|
||||
# Functrace adds minimal memory overhead, so we can use much larger chunks than normal builds
|
||||
# Larger chunks = fewer files = faster linking + less TLS overhead
|
||||
set(CHUNK_TARGET_INSTANTIATIONS "80" CACHE STRING "Very large chunks for call tracing only" FORCE)
|
||||
set(MULTI_PASS_CHUNK_SIZE "200" CACHE STRING "Very large direct chunks for call tracing only" FORCE)
|
||||
message(STATUS "🔍 Call tracing only: Using very large chunks (80/200) for maximum build speed")
|
||||
endif()
|
||||
elseif((DEFINED SD_SANITIZE AND SD_SANITIZE) OR (DEFINED SD_SANITIZERS AND NOT SD_SANITIZERS STREQUAL ""))
|
||||
# Sanitizers only: Small chunks to prevent OOM (sanitizer builds use massive RAM per file)
|
||||
set(CHUNK_TARGET_INSTANTIATIONS "6" CACHE STRING "Small chunks for sanitizers (prevents OOM)" FORCE)
|
||||
set(MULTI_PASS_CHUNK_SIZE "8" CACHE STRING "Small direct chunks for sanitizers (prevents OOM)" FORCE)
|
||||
message(STATUS "⚠️ Sanitizers: Using small chunks (6/8) to prevent out-of-memory during compilation")
|
||||
else()
|
||||
# Normal builds: Use memory-based defaults (no special instrumentation)
|
||||
cmake_host_system_information(RESULT AVAILABLE_MEMORY QUERY AVAILABLE_PHYSICAL_MEMORY)
|
||||
if(AVAILABLE_MEMORY LESS 4000)
|
||||
set(CHUNK_TARGET_INSTANTIATIONS "3" CACHE STRING "Conservative chunks for low memory" FORCE)
|
||||
set(MULTI_PASS_CHUNK_SIZE "25" CACHE STRING "Conservative direct chunks" FORCE)
|
||||
message(STATUS "💾 Low memory detected: Using small chunks (3/25)")
|
||||
elseif(AVAILABLE_MEMORY LESS 8000)
|
||||
set(CHUNK_TARGET_INSTANTIATIONS "6" CACHE STRING "Moderate chunks for medium memory" FORCE)
|
||||
set(MULTI_PASS_CHUNK_SIZE "35" CACHE STRING "Moderate direct chunks" FORCE)
|
||||
message(STATUS "💾 Medium memory detected: Using moderate chunks (6/35)")
|
||||
elseif(AVAILABLE_MEMORY LESS 16000)
|
||||
set(CHUNK_TARGET_INSTANTIATIONS "10" CACHE STRING "Balanced chunks for high memory" FORCE)
|
||||
set(MULTI_PASS_CHUNK_SIZE "50" CACHE STRING "Balanced direct chunks" FORCE)
|
||||
message(STATUS "💾 High memory detected: Using balanced chunks (10/50)")
|
||||
else()
|
||||
set(CHUNK_TARGET_INSTANTIATIONS "12" CACHE STRING "Optimized chunks for very high memory" FORCE)
|
||||
set(MULTI_PASS_CHUNK_SIZE "60" CACHE STRING "Optimized direct chunks" FORCE)
|
||||
message(STATUS "💾 Very high memory detected: Using large chunks (12/60)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CHUNK_MAX_INSTANTIATIONS "3" CACHE STRING "Maximum template instantiations per chunk file")
|
||||
set(USE_MULTI_PASS_GENERATION "OFF" CACHE STRING "Use multi-pass generation (ON/OFF/AUTO)")
|
||||
|
||||
# --- NEW: Type Selection for Fast Builds ---
|
||||
if(SD_FAST_BUILD)
|
||||
message(STATUS "🚀 Fast build mode enabled - using minimal type set")
|
||||
set(SD_TYPE_PROFILE "MINIMAL" CACHE STRING "Type profile for fast builds" FORCE)
|
||||
set(SD_TYPES_LIST "float;double" CACHE STRING "Minimal type set for fast builds" FORCE)
|
||||
set(SD_AGGRESSIVE_SEMANTIC_FILTERING ON CACHE BOOL "Use aggressive filtering" FORCE)
|
||||
set(CHUNK_TARGET_INSTANTIATIONS "100" CACHE STRING "Larger chunks for fast builds" FORCE)
|
||||
set(SD_MAX_TEMPLATE_COMBINATIONS "500" CACHE STRING "Strict limit for fast builds" FORCE)
|
||||
endif()
|
||||
|
||||
# --- NEW: Configure Unity Build ---
|
||||
if(SD_UNITY_BUILD)
|
||||
message(STATUS "🔧 Unity build enabled for faster compilation")
|
||||
set(CMAKE_UNITY_BUILD ON CACHE BOOL "Enable Unity builds" FORCE)
|
||||
set(CMAKE_UNITY_BUILD_BATCH_SIZE 20 CACHE STRING "Unity build batch size" FORCE)
|
||||
endif()
|
||||
|
||||
# --- NEW: Configure Parallel Compilation ---
|
||||
if(NOT SD_PARALLEL_COMPILE_JOBS STREQUAL "0")
|
||||
set(CMAKE_BUILD_PARALLEL_LEVEL ${SD_PARALLEL_COMPILE_JOBS} CACHE STRING "Parallel build level" FORCE)
|
||||
message(STATUS "🔧 Parallel compilation set to ${SD_PARALLEL_COMPILE_JOBS} jobs")
|
||||
else()
|
||||
# Auto-detect number of cores
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(N)
|
||||
if(NOT N EQUAL 0)
|
||||
set(CMAKE_BUILD_PARALLEL_LEVEL ${N} CACHE STRING "Parallel build level" FORCE)
|
||||
message(STATUS "🔧 Auto-detected ${N} cores for parallel compilation")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --- NEW: Compiler-specific optimizations for template compilation ---
|
||||
# Template depth: 512 for release (faster compilation), 1024 for debug (deeper nesting support)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
add_compile_options(-ftemplate-depth=1024)
|
||||
message(STATUS "Using template depth 1024 for ${CMAKE_BUILD_TYPE} build")
|
||||
else()
|
||||
add_compile_options(-ftemplate-depth=512)
|
||||
message(STATUS "Using template depth 512 for ${CMAKE_BUILD_TYPE} build")
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# Enable faster template compilation in GCC 10+
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0)
|
||||
add_compile_options(-fconcepts-diagnostics-depth=2)
|
||||
endif()
|
||||
|
||||
# For development builds, use faster but less optimized compilation
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR SD_FAST_BUILD)
|
||||
add_compile_options(-O0 -fno-inline-functions)
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# For development builds, use faster but less optimized compilation
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR SD_FAST_BUILD)
|
||||
add_compile_options(-O0 -fno-inline-functions)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PPSTEP "Build ppstep preprocessor debugging tool" OFF)
|
||||
|
||||
# --- Helper function 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}")
|
||||
elseif(type STREQUAL "DEBUG")
|
||||
message(STATUS "🔍 ${message}")
|
||||
elseif(type STREQUAL "NOTICE")
|
||||
message(NOTICE "📢 ${message}")
|
||||
else()
|
||||
message(STATUS "${message}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# --- NEW: Print build configuration summary ---
|
||||
function(print_build_configuration)
|
||||
message(STATUS "")
|
||||
message(STATUS "=== Template Compilation Configuration ===")
|
||||
message(STATUS "Type Profile: ${SD_TYPE_PROFILE}")
|
||||
message(STATUS "Semantic Filtering: ${SD_ENABLE_SEMANTIC_FILTERING}")
|
||||
message(STATUS "Aggressive Filtering: ${SD_AGGRESSIVE_SEMANTIC_FILTERING}")
|
||||
message(STATUS "Max Template Combinations: ${SD_MAX_TEMPLATE_COMBINATIONS}")
|
||||
message(STATUS "Chunk Target Size: ${CHUNK_TARGET_INSTANTIATIONS}")
|
||||
message(STATUS "Unity Build: ${SD_UNITY_BUILD}")
|
||||
message(STATUS "Fast Build Mode: ${SD_FAST_BUILD}")
|
||||
|
||||
if(DEFINED SD_TYPES_LIST)
|
||||
message(STATUS "Active Types: ${SD_TYPES_LIST}")
|
||||
endif()
|
||||
|
||||
message(STATUS "==========================================")
|
||||
message(STATUS "")
|
||||
endfunction()
|
||||
|
||||
# --- Macro for debugging all CMake variables ---
|
||||
macro(print_all_variables)
|
||||
message(STATUS "print_all_variables------------------------------------------{")
|
||||
get_cmake_property(_variableNames VARIABLES)
|
||||
foreach(_variableName ${_variableNames})
|
||||
message(STATUS "${_variableName}=${${_variableName}}")
|
||||
endforeach()
|
||||
message(STATUS "print_all_variables------------------------------------------}")
|
||||
endmacro()
|
||||
|
||||
# --- NEW: Validation and warnings ---
|
||||
if(SD_TYPE_PROFILE STREQUAL "ESSENTIAL" OR SD_TYPE_PROFILE STREQUAL "TRAINING")
|
||||
message(WARNING "⚠️ Using '${SD_TYPE_PROFILE}' profile will generate many template instantiations and slow compilation. Consider 'MINIMAL' or 'INFERENCE' for faster builds.")
|
||||
endif()
|
||||
|
||||
if(CHUNK_TARGET_INSTANTIATIONS LESS 20)
|
||||
message(WARNING "⚠️ CHUNK_TARGET_INSTANTIATIONS is very low (${CHUNK_TARGET_INSTANTIATIONS}). This will create many small files and slow compilation.")
|
||||
endif()
|
||||
@@ -0,0 +1,101 @@
|
||||
# cmake/Platform.cmake
|
||||
# Detects OS and CPU architecture and sets platform-specific flags.
|
||||
|
||||
# --- Platform and Architecture Detection ---
|
||||
set(SD_X86_BUILD false)
|
||||
set(SD_ARM_BUILD false)
|
||||
if(SD_ANDROID_BUILD)
|
||||
if(ANDROID_ABI MATCHES "x86_64")
|
||||
set(SD_X86_BUILD true)
|
||||
set(SD_ARCH "x86-64")
|
||||
elseif(ANDROID_ABI MATCHES "x86")
|
||||
set(SD_X86_BUILD true)
|
||||
set(SD_ARCH "x86")
|
||||
elseif(ANDROID_ABI MATCHES "arm64-v8a")
|
||||
set(SD_ARM_BUILD true)
|
||||
set(SD_ARCH "arm64-v8a")
|
||||
elseif(ANDROID_ABI MATCHES "armeabi-v7a")
|
||||
set(SD_ARM_BUILD true)
|
||||
set(SD_ARCH "armv7-a")
|
||||
endif()
|
||||
elseif(NOT SD_IOS_BUILD)
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64")
|
||||
set(SD_X86_BUILD true)
|
||||
if(NOT DEFINED SD_ARCH OR SD_ARCH STREQUAL "")
|
||||
set(SD_ARCH "x86-64")
|
||||
endif()
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm*|aarch64")
|
||||
set(SD_ARM_BUILD true)
|
||||
if(NOT DEFINED SD_ARCH OR SD_ARCH STREQUAL "")
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
set(SD_ARCH "armv8-a")
|
||||
else()
|
||||
set(SD_ARCH "armv7-a")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SD_ARM_BUILD)
|
||||
if(NOT DEFINED SD_ARCH OR SD_ARCH STREQUAL "")
|
||||
message(STATUS "Warning: SD_ARCH was not set for this ARM build. Defaulting to 'armv8-a'.")
|
||||
set(SD_ARCH "armv8-a")
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "Build flags determined: SD_ANDROID_BUILD=${SD_ANDROID_BUILD}, SD_X86_BUILD=${SD_X86_BUILD}, SD_ARM_BUILD=${SD_ARM_BUILD}, SD_ARCH=${SD_ARCH}")
|
||||
|
||||
# --- Architecture-Specific Tuning ---
|
||||
set(ARCH_TUNE "")
|
||||
if(SD_ARCH MATCHES "armv8")
|
||||
set(ARCH_TUNE "-march=${SD_ARCH}")
|
||||
elseif(SD_ARCH MATCHES "armv7")
|
||||
set(ARCH_TUNE "-march=${SD_ARCH} -mfpu=neon")
|
||||
elseif(SD_EXTENSION MATCHES "avx512")
|
||||
message("Building AVX512 binary...")
|
||||
set(ARCH_TUNE "-mmmx -msse -msse2 -msse3 -msse4.1 -msse4.2 -mavx -mavx2 -mfma -mf16c -mavx512f -mavx512vl -mavx512bw -mavx512dq -mavx512cd -mbmi -mbmi2 -mprefetchwt1 -mclflushopt -mxsavec -mxsaves -DSD_F16C=true -DF_AVX512=true")
|
||||
elseif(SD_EXTENSION MATCHES "avx2")
|
||||
message("Building AVX2 binary...")
|
||||
set(ARCH_TUNE "-mmmx -msse -msse2 -msse3 -msse4.1 -msse4.2 -mavx -mavx2 -mfma -mf16c -mprefetchwt1 -DSD_F16C=true -DF_AVX2=true")
|
||||
if(NO_AVX256_SPLIT)
|
||||
set(ARCH_TUNE "${ARCH_TUNE} -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store")
|
||||
endif()
|
||||
elseif(SD_NATIVE)
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc64*" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64*")
|
||||
set(ARCH_TUNE "-mcpu=native")
|
||||
else()
|
||||
set(ARCH_TUNE "-march=native")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT ARCH_TUNE STREQUAL "")
|
||||
message(STATUS "Applying architecture tuning flags: ${ARCH_TUNE}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_TUNE}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARCH_TUNE}")
|
||||
endif()
|
||||
|
||||
# --- OS-Specific Build Flags ---
|
||||
if(SD_APPLE_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSD_APPLE_BUILD=true -mmacosx-version-min=10.10")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSD_APPLE_BUILD=true -mmacosx-version-min=10.10")
|
||||
elseif(SD_ARM_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSD_ARM_BUILD=true")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSD_ARM_BUILD=true")
|
||||
elseif(SD_ANDROID_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSD_ANDROID_BUILD=true")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSD_ANDROID_BUILD=true")
|
||||
elseif(SD_IOS_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSD_IOS_BUILD=true")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSD_IOS_BUILD=true")
|
||||
endif()
|
||||
|
||||
# --- External Include Directories ---
|
||||
if(UNIX)
|
||||
link_directories(/usr/local/lib /usr/lib /lib)
|
||||
endif()
|
||||
if(APPLE)
|
||||
message("Using Apple")
|
||||
link_directories(/usr/local/lib /usr/lib /lib)
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
list(APPEND EXTERNAL_INCLUDE_DIRS "/usr/include" "/usr/local/include")
|
||||
endif()
|
||||
@@ -0,0 +1,116 @@
|
||||
# PlatformDetection.cmake - Platform and architecture detection
|
||||
|
||||
# Ensure SD_CPU is TRUE if neither SD_CUDA nor SD_CPU is set
|
||||
if(NOT SD_CUDA)
|
||||
if(NOT SD_CPU)
|
||||
set(SD_CUDA FALSE)
|
||||
set(SD_CPU TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set SD_LIBRARY_NAME Based on Build Type
|
||||
if(NOT DEFINED SD_LIBRARY_NAME)
|
||||
if(SD_CUDA)
|
||||
set(SD_LIBRARY_NAME nd4jcuda)
|
||||
else()
|
||||
set(SD_LIBRARY_NAME nd4jcpu)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set default engine
|
||||
if(SD_CUDA)
|
||||
set(DEFAULT_ENGINE "samediff::ENGINE_CUDA")
|
||||
else()
|
||||
set(DEFAULT_ENGINE "samediff::ENGINE_CPU")
|
||||
endif()
|
||||
|
||||
# MSVC runtime lib can be either "MultiThreaded" or "MultiThreadedDLL", /MT and /MD respectively
|
||||
set(MSVC_RT_LIB "MultiThreadedDLL")
|
||||
|
||||
# Determine platform type more accurately
|
||||
set(SD_X86_BUILD false)
|
||||
set(SD_ARM_BUILD false)
|
||||
|
||||
if(SD_ANDROID_BUILD)
|
||||
if(ANDROID_ABI MATCHES "x86_64")
|
||||
set(SD_X86_BUILD true)
|
||||
set(SD_ARCH "x86-64")
|
||||
elseif(ANDROID_ABI MATCHES "x86")
|
||||
set(SD_X86_BUILD true)
|
||||
set(SD_ARCH "x86")
|
||||
elseif(ANDROID_ABI MATCHES "arm64-v8a")
|
||||
set(SD_ARM_BUILD true)
|
||||
set(SD_ARCH "arm64-v8a")
|
||||
elseif(ANDROID_ABI MATCHES "armeabi-v7a")
|
||||
set(SD_ARM_BUILD true)
|
||||
set(SD_ARCH "armv7-a")
|
||||
endif()
|
||||
elseif(NOT SD_IOS_BUILD)
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64")
|
||||
set(SD_X86_BUILD true)
|
||||
if(NOT DEFINED SD_ARCH OR SD_ARCH STREQUAL "")
|
||||
set(SD_ARCH "x86-64")
|
||||
endif()
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm*|aarch64")
|
||||
set(SD_ARM_BUILD true)
|
||||
if(NOT DEFINED SD_ARCH OR SD_ARCH STREQUAL "")
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
set(SD_ARCH "armv8-a")
|
||||
else()
|
||||
set(SD_ARCH "armv7-a")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SD_ARM_BUILD)
|
||||
if(NOT DEFINED SD_ARCH OR SD_ARCH STREQUAL "")
|
||||
message(STATUS "Warning: SD_ARCH was not set for this ARM build. Defaulting to 'armv8-a'.")
|
||||
set(SD_ARCH "armv8-a")
|
||||
endif()
|
||||
|
||||
if(SD_ANDROID)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Define Compiler Flags for Specific Builds
|
||||
if(SD_APPLE_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSD_APPLE_BUILD=true -mmacosx-version-min=10.10")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSD_APPLE_BUILD=true -mmacosx-version-min=10.10")
|
||||
endif()
|
||||
|
||||
if(SD_ARM_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSD_ARM_BUILD=true")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSD_ARM_BUILD=true")
|
||||
endif()
|
||||
|
||||
if(SD_ANDROID_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSD_ANDROID_BUILD=true")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSD_ANDROID_BUILD=true")
|
||||
endif()
|
||||
|
||||
if(SD_IOS_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSD_IOS_BUILD=true")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSD_IOS_BUILD=true")
|
||||
endif()
|
||||
|
||||
message(STATUS "Build flags determined: SD_ANDROID_BUILD=${SD_ANDROID_BUILD}, SD_X86_BUILD=${SD_X86_BUILD}, SD_ARM_BUILD=${SD_ARM_BUILD}, SD_ARCH=${SD_ARCH}")
|
||||
|
||||
# Include Directories Based on OS
|
||||
if(UNIX)
|
||||
link_directories(/usr/local/lib /usr/lib /lib)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
message("Using Apple")
|
||||
link_directories(/usr/local/lib /usr/lib /lib)
|
||||
endif()
|
||||
|
||||
# External Include Directories
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
list(APPEND EXTERNAL_INCLUDE_DIRS "/usr/include" "/usr/local/include")
|
||||
endif()
|
||||
|
||||
# Initialize job pools for parallel builds
|
||||
set_property(GLOBAL PROPERTY JOB_POOLS one_jobs=1 two_jobs=2)
|
||||
@@ -0,0 +1,292 @@
|
||||
################################################################################
|
||||
# Platform Optimization Functions
|
||||
# Platform-specific compiler optimizations and build configurations
|
||||
################################################################################
|
||||
|
||||
# Function to apply Android x86_64 PLT fixes for large template libraries
|
||||
function(apply_android_x86_64_plt_fixes target_name)
|
||||
if(NOT (SD_ANDROID_BUILD AND ANDROID_ABI MATCHES "x86_64"))
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
target_compile_options(${target_name} PRIVATE
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-fvisibility=hidden
|
||||
-fvisibility-inlines-hidden
|
||||
-fno-plt
|
||||
-fno-semantic-interposition
|
||||
)
|
||||
else()
|
||||
# MSVC equivalent flags
|
||||
target_compile_options(${target_name} PRIVATE
|
||||
/Gy # Function-level linking
|
||||
)
|
||||
endif()
|
||||
|
||||
# Target-specific preprocessor definitions
|
||||
target_compile_definitions(${target_name} PRIVATE
|
||||
ANDROID_X86_64_OPTIMIZED=1
|
||||
)
|
||||
|
||||
# Apply linker flags only to shared/executable targets
|
||||
get_target_property(target_type ${target_name} TYPE)
|
||||
|
||||
|
||||
message(STATUS "Applied verified Android x86_64 optimizations to target: ${target_name}")
|
||||
endfunction()
|
||||
|
||||
# Comprehensive linker configuration for large template libraries
|
||||
function(configure_large_template_linker)
|
||||
if(NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND SD_X86_BUILD))
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Configuring linker for large template library with PLT overflow prevention")
|
||||
|
||||
# Clear any existing conflicting linker flags
|
||||
string(REGEX REPLACE "-fuse-ld=[a-zA-Z]+" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
string(REGEX REPLACE "-fuse-ld=[a-zA-Z]+" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
|
||||
# Test if linker supports --plt-align before using it
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_LINKER} --help
|
||||
OUTPUT_VARIABLE LD_HELP_OUTPUT
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
string(FIND "${LD_HELP_OUTPUT}" "--plt-align" PLT_ALIGN_SUPPORTED)
|
||||
|
||||
|
||||
message(STATUS "Applied PLT overflow prevention for large template library")
|
||||
endfunction()
|
||||
|
||||
# Function to configure memory model based on architecture
|
||||
function(configure_memory_model)
|
||||
# Memory model is now configured in CompilerFlags.cmake to avoid conflicts
|
||||
# (Sanitizer builds use -mcmodel=large, non-sanitizer builds use -mcmodel=medium)
|
||||
if(SD_X86_BUILD AND NOT WIN32)
|
||||
# Removed: -mcmodel setting now in CompilerFlags.cmake only
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcmodel=medium -fPIC" PARENT_SCOPE)
|
||||
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcmodel=medium" PARENT_SCOPE)
|
||||
message(STATUS "Memory model configuration deferred to CompilerFlags.cmake")
|
||||
else()
|
||||
if(SD_ARM_BUILD OR SD_ANDROID_BUILD)
|
||||
message(STATUS "Skipping large memory model for ARM/Android architecture (not supported)")
|
||||
elseif(WIN32)
|
||||
message(STATUS "Skipping large memory model for Windows (using alternative approach)")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Function to apply memory optimization during compilation
|
||||
function(configure_compilation_memory_optimization)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --param ggc-min-expand=100 --param ggc-min-heapsize=131072" PARENT_SCOPE)
|
||||
message(STATUS "Applied GCC memory optimization flags")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Function to configure section splitting for better linker handling
|
||||
function(configure_section_splitting)
|
||||
# MSVC-specific optimizations
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
# MSVC equivalent optimizations
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Gy" PARENT_SCOPE) # Function-level linking
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gy" PARENT_SCOPE) # Function-level linking
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /OPT:REF /OPT:ICF" PARENT_SCOPE) # Remove unreferenced code
|
||||
message(STATUS "Applied MSVC function-level linking optimizations")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
# Function to disable PLT completely for memory issues
|
||||
function(configure_plt_disable)
|
||||
# For CUDA builds, disable PLT in host compiler flags
|
||||
if(SD_CUDA AND CMAKE_CUDA_COMPILER)
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler -fno-plt" PARENT_SCOPE)
|
||||
message(STATUS "Disabled PLT for CUDA host compiler")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Function to determine platform type accurately
|
||||
function(determine_platform_type)
|
||||
set(SD_X86_BUILD false PARENT_SCOPE)
|
||||
set(SD_ARM_BUILD false PARENT_SCOPE)
|
||||
|
||||
if(SD_ANDROID_BUILD)
|
||||
if(ANDROID_ABI MATCHES "x86_64")
|
||||
set(SD_X86_BUILD true PARENT_SCOPE)
|
||||
set(SD_ARCH "x86-64" PARENT_SCOPE)
|
||||
elseif(ANDROID_ABI MATCHES "x86")
|
||||
set(SD_X86_BUILD true PARENT_SCOPE)
|
||||
set(SD_ARCH "x86" PARENT_SCOPE)
|
||||
elseif(ANDROID_ABI MATCHES "arm64-v8a")
|
||||
set(SD_ARM_BUILD true PARENT_SCOPE)
|
||||
set(SD_ARCH "arm64-v8a" PARENT_SCOPE)
|
||||
elseif(ANDROID_ABI MATCHES "armeabi-v7a")
|
||||
set(SD_ARM_BUILD true PARENT_SCOPE)
|
||||
set(SD_ARCH "armv7-a" PARENT_SCOPE)
|
||||
endif()
|
||||
elseif(NOT SD_IOS_BUILD)
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64")
|
||||
set(SD_X86_BUILD true PARENT_SCOPE)
|
||||
if(NOT DEFINED SD_ARCH OR SD_ARCH STREQUAL "")
|
||||
set(SD_ARCH "x86-64" PARENT_SCOPE)
|
||||
endif()
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm*|aarch64")
|
||||
set(SD_ARM_BUILD true PARENT_SCOPE)
|
||||
if(NOT DEFINED SD_ARCH OR SD_ARCH STREQUAL "")
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
set(SD_ARCH "armv8-a" PARENT_SCOPE)
|
||||
else()
|
||||
set(SD_ARCH "armv7-a" PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set default for ARM builds if not specified
|
||||
if(SD_ARM_BUILD)
|
||||
if(NOT DEFINED SD_ARCH OR SD_ARCH STREQUAL "")
|
||||
message(STATUS "Warning: SD_ARCH was not set for this ARM build. Defaulting to 'armv8-a'.")
|
||||
set(SD_ARCH "armv8-a" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(SD_ANDROID)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Platform detection results: SD_X86_BUILD=${SD_X86_BUILD}, SD_ARM_BUILD=${SD_ARM_BUILD}, SD_ARCH=${SD_ARCH}")
|
||||
endfunction()
|
||||
|
||||
# Function to configure architecture tuning
|
||||
function(configure_architecture_tuning)
|
||||
if(SD_ARCH MATCHES "armv8")
|
||||
set(ARCH_TUNE "-march=${SD_ARCH}" PARENT_SCOPE)
|
||||
message(STATUS "ARM64 architecture tuning: ${SD_ARCH}")
|
||||
elseif(SD_ARCH MATCHES "armv7")
|
||||
set(ARCH_TUNE "-march=${SD_ARCH} -mfpu=neon" PARENT_SCOPE)
|
||||
message(STATUS "ARM32 architecture tuning: ${SD_ARCH} with NEON")
|
||||
elseif(SD_EXTENSION MATCHES "avx2")
|
||||
message(STATUS "Building AVX2 binary...")
|
||||
set(ARCH_TUNE "-mmmx -msse -msse2 -msse3 -msse4.1 -msse4.2 -mavx -mavx2 -mfma -mf16c -mprefetchwt1 -DSD_F16C=true -DF_AVX2=true" PARENT_SCOPE)
|
||||
if(NO_AVX256_SPLIT)
|
||||
set(ARCH_TUNE "${ARCH_TUNE} -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store" PARENT_SCOPE)
|
||||
endif()
|
||||
else()
|
||||
if("${SD_ARCH}" STREQUAL "x86-64")
|
||||
message(STATUS "Building x86_64 binary...")
|
||||
set(ARCH_TYPE "generic")
|
||||
add_compile_definitions(F_X64=true)
|
||||
else()
|
||||
set(ARCH_TYPE "${SD_ARCH}")
|
||||
endif()
|
||||
|
||||
if(SD_EXTENSION MATCHES "avx512")
|
||||
message(STATUS "Building AVX512 binary...")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmmx -msse -msse2 -msse3 -msse4.1 -msse4.2 -mavx -mavx2 -mfma -mf16c -mavx512f -mavx512vl -mavx512bw -mavx512dq -mavx512cd -mbmi -mbmi2 -mprefetchwt1 -mclflushopt -mxsavec -mxsaves -DSD_F16C=true -DF_AVX512=true" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32 AND NOT SD_CUDA)
|
||||
if(DEFINED SD_ARCH AND NOT SD_ARCH STREQUAL "" AND DEFINED ARCH_TYPE AND NOT ARCH_TYPE STREQUAL "")
|
||||
set(ARCH_TUNE "-march=${SD_ARCH} -mtune=${ARCH_TYPE}" PARENT_SCOPE)
|
||||
elseif(DEFINED SD_ARCH AND NOT SD_ARCH STREQUAL "")
|
||||
# Fallback if ARCH_TYPE is not set
|
||||
set(ARCH_TUNE "-march=${SD_ARCH}" PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Function to apply compiler-specific flags with architecture tuning
|
||||
function(apply_compiler_specific_flags ARCH_TUNE)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND SD_X86_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_TUNE}" PARENT_SCOPE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_TUNE}" PARENT_SCOPE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_TUNE} -O${SD_OPTIMIZATION_LEVEL} -fp-model fast" PARENT_SCOPE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_TUNE}" PARENT_SCOPE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT SD_CUDA)
|
||||
message(STATUS "Adding GCC memory optimization flag: --param ggc-min-expand=10")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --param ggc-min-expand=10 ${ARCH_TUNE} ${INFORMATIVE_FLAGS} -std=c++17 -fPIC" PARENT_SCOPE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --param ggc-min-expand=10 -fPIC" PARENT_SCOPE)
|
||||
|
||||
|
||||
if(UNIX)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-rpath,$ORIGIN/,-z,--no-undefined,--verbose" PARENT_SCOPE)
|
||||
else()
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-rpath,$ORIGIN/,--no-undefined,--verbose" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT APPLE AND NOT WIN32)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic -Wl,-export-dynamic,--verbose" PARENT_SCOPE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -export-dynamic,--verbose" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(SD_GCC_FUNCTRACE)
|
||||
set(COMPILER_IS_NVCC false)
|
||||
get_filename_component(COMPILER_NAME ${CMAKE_CXX_COMPILER} NAME)
|
||||
if(COMPILER_NAME MATCHES "^nvcc")
|
||||
set(COMPILER_IS_NVCC TRUE)
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{OMPI_CXX} OR DEFINED ENV{MPICH_CXX})
|
||||
if("$ENV{OMPI_CXX}" MATCHES "nvcc" OR "$ENV{MPICH_CXX}" MATCHES "nvcc")
|
||||
set(COMPILER_IS_NVCC TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE PARENT_SCOPE)
|
||||
if(COMPILER_IS_NVCC)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-backtrace-limit=0 -gno-record-gcc-switches -ftrack-macro-expansion=0 -fstack-protector -fstack-protector-all -Wall -Wextra -Wno-return-type -Wno-error=int-in-bool-context -Wno-unused-variable -Wno-error=implicit-fallthrough -Wno-return-type -Wno-unused-parameter -Wno-error=unknown-pragmas -ggdb3 -pthread -MT -Bsymbolic -rdynamic -fno-omit-frame-pointer -fno-optimize-sibling-calls -rdynamic -finstrument-functions -O0 -fPIC" PARENT_SCOPE)
|
||||
|
||||
# Session #1045 FIX: Removed -lunwind - conflicts with JVM's libgcc_s causing _Unwind_SetGR crashes
|
||||
# Use system libgcc_s for exception handling (JVM compatible)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread -lbfd -ldw -ldl -lelf" PARENT_SCOPE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lpthread -lbfd -ldw -ldl -lelf" PARENT_SCOPE)
|
||||
|
||||
add_compile_definitions(SD_GCC_FUNCTRACE=ON)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Main function to setup all platform optimizations
|
||||
function(setup_platform_optimizations)
|
||||
message(STATUS "Setting up platform-specific optimizations...")
|
||||
|
||||
# Determine platform type
|
||||
determine_platform_type()
|
||||
|
||||
# Configure PLT disable
|
||||
configure_plt_disable()
|
||||
|
||||
# Configure memory model
|
||||
configure_memory_model()
|
||||
|
||||
# Configure compilation memory optimization
|
||||
configure_compilation_memory_optimization()
|
||||
|
||||
# Configure section splitting
|
||||
configure_section_splitting()
|
||||
|
||||
# Configure large template linker
|
||||
configure_large_template_linker()
|
||||
|
||||
# Configure architecture tuning
|
||||
configure_architecture_tuning()
|
||||
|
||||
# Apply architecture tuning based on calculated ARCH_TUNE
|
||||
if(DEFINED ARCH_TUNE)
|
||||
apply_compiler_specific_flags("${ARCH_TUNE}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Platform optimizations setup complete")
|
||||
endfunction()
|
||||
@@ -0,0 +1,399 @@
|
||||
# cmake/PostBuild.cmake
|
||||
# Configures optional post-build targets like tests and analysis tools.
|
||||
|
||||
# ============================================================================
|
||||
# HELPER FUNCTION: Write file only if content changed (preserves mtime for PCH)
|
||||
# This prevents PCH invalidation during builds when config.h content is identical
|
||||
# ============================================================================
|
||||
function(_postbuild_write_if_different filepath content)
|
||||
set(should_write TRUE)
|
||||
|
||||
# Check if file already exists
|
||||
if(EXISTS "${filepath}")
|
||||
# Read existing content
|
||||
file(READ "${filepath}" existing_content)
|
||||
|
||||
# Compare content
|
||||
if("${existing_content}" STREQUAL "${content}")
|
||||
set(should_write FALSE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Only write if content changed or file doesn't exist
|
||||
if(should_write)
|
||||
file(WRITE "${filepath}" "${content}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# --- Configuration file ---
|
||||
# Build TYPE_DEFINES string from current type configuration
|
||||
# This ensures JavaCPP sees the same type availability as the CMake build
|
||||
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)
|
||||
foreach(def IN LISTS COMPILE_DEFS)
|
||||
if(def MATCHES "^HAS_")
|
||||
string(APPEND TYPE_DEFINES "#define ${def}\n")
|
||||
endif()
|
||||
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 with write-if-different to preserve PCH
|
||||
# This prevents PCH invalidation during the build when content hasn't changed
|
||||
set(CONFIG_H_IN "${CMAKE_CURRENT_SOURCE_DIR}/include/config.h.in")
|
||||
set(CONFIG_H_OUT "${CMAKE_CURRENT_BINARY_DIR}/include/config.h")
|
||||
|
||||
# Read the template
|
||||
file(READ "${CONFIG_H_IN}" CONFIG_H_CONTENT)
|
||||
|
||||
# Perform variable substitutions (mimics configure_file behavior)
|
||||
# Handle cmakedefine01 directives
|
||||
if(HAVE_ONEDNN)
|
||||
string(REPLACE "#cmakedefine01 HAVE_ONEDNN" "#define HAVE_ONEDNN 1" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine01 HAVE_ONEDNN" "#define HAVE_ONEDNN 0" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
if(HAVE_ARMCOMPUTE)
|
||||
string(REPLACE "#cmakedefine01 HAVE_ARMCOMPUTE" "#define HAVE_ARMCOMPUTE 1" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine01 HAVE_ARMCOMPUTE" "#define HAVE_ARMCOMPUTE 0" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
if(HAVE_CUDNN)
|
||||
string(REPLACE "#cmakedefine01 HAVE_CUDNN" "#define HAVE_CUDNN 1" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine01 HAVE_CUDNN" "#define HAVE_CUDNN 0" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
if(HAVE_OPENBLAS)
|
||||
string(REPLACE "#cmakedefine01 HAVE_OPENBLAS" "#define HAVE_OPENBLAS 1" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine01 HAVE_OPENBLAS" "#define HAVE_OPENBLAS 0" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
if(HAVE_FLATBUFFERS)
|
||||
string(REPLACE "#cmakedefine01 HAVE_FLATBUFFERS" "#define HAVE_FLATBUFFERS 1" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine01 HAVE_FLATBUFFERS" "#define HAVE_FLATBUFFERS 0" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
if(SD_SELECTIVE_TYPES)
|
||||
string(REPLACE "#cmakedefine01 SD_SELECTIVE_TYPES" "#define SD_SELECTIVE_TYPES 1" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
string(REPLACE "#cmakedefine01 SD_SELECTIVE_TYPES" "#define SD_SELECTIVE_TYPES 0" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
# Handle @VAR@ substitutions
|
||||
if(DEFINED SD_LIBRARY_NAME)
|
||||
string(REPLACE "@SD_LIBRARY_NAME@" "${SD_LIBRARY_NAME}" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
# Remove the line if variable not defined
|
||||
string(REGEX REPLACE "#cmakedefine SD_LIBRARY_NAME[^\n]*\n" "" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
if(DEFINED ONEDNN_PATH)
|
||||
string(REPLACE "@ONEDNN_PATH@" "${ONEDNN_PATH}" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
string(REGEX REPLACE "#cmakedefine ONEDNN_PATH[^\n]*\n" "" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
if(DEFINED OPENBLAS_PATH)
|
||||
string(REPLACE "@OPENBLAS_PATH@" "${OPENBLAS_PATH}" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
string(REGEX REPLACE "#cmakedefine OPENBLAS_PATH[^\n]*\n" "" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
if(DEFINED FLATBUFFERS_PATH)
|
||||
string(REPLACE "@FLATBUFFERS_PATH@" "${FLATBUFFERS_PATH}" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
string(REGEX REPLACE "#cmakedefine FLATBUFFERS_PATH[^\n]*\n" "" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
if(DEFINED DEFAULT_ENGINE)
|
||||
string(REPLACE "@DEFAULT_ENGINE@" "${DEFAULT_ENGINE}" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
else()
|
||||
string(REGEX REPLACE "#cmakedefine DEFAULT_ENGINE[^\n]*\n" "" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
endif()
|
||||
|
||||
# Substitute TYPE_DEFINES
|
||||
string(REPLACE "@TYPE_DEFINES@" "${TYPE_DEFINES}" CONFIG_H_CONTENT "${CONFIG_H_CONTENT}")
|
||||
|
||||
# Write config.h only if content changed (preserves mtime for PCH)
|
||||
_postbuild_write_if_different("${CONFIG_H_OUT}" "${CONFIG_H_CONTENT}")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
# --- Flatbuffers Header and Java Generation ---
|
||||
if(DEFINED ENV{GENERATE_FLATC} OR DEFINED GENERATE_FLATC)
|
||||
set(FLATC_EXECUTABLE "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build/flatc")
|
||||
set(MAIN_GENERATED_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/include/graph/generated.h")
|
||||
add_custom_command(
|
||||
OUTPUT ${MAIN_GENERATED_HEADER}
|
||||
COMMAND ${CMAKE_COMMAND} -E env "FLATC_PATH=${FLATC_EXECUTABLE}" bash ${CMAKE_CURRENT_SOURCE_DIR}/flatc-generate.sh
|
||||
DEPENDS flatbuffers_external
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Running flatc to generate C++ headers"
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(generate_flatbuffers_headers DEPENDS ${MAIN_GENERATED_HEADER})
|
||||
add_custom_command(
|
||||
TARGET generate_flatbuffers_headers POST_BUILD
|
||||
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/copy-flatc-java.sh
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Copying generated Java files"
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
if(SD_EXTRACT_INSTANTIATIONS)
|
||||
include(ExtractInstantiations)
|
||||
|
||||
endif()
|
||||
|
||||
# --- Self-Contained Preprocessing Target ---
|
||||
if(SD_PREPROCESS)
|
||||
message("Preprocessing enabled: ${CMAKE_BINARY_DIR}")
|
||||
message("Setting up self-contained preprocessing with FlatBuffers...")
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
# Build FlatBuffers for preprocessing (minimal build, just need headers)
|
||||
set(PREPROCESS_FLATBUFFERS_VERSION "25.2.10")
|
||||
set(PREPROCESS_FLATBUFFERS_URL "https://github.com/google/flatbuffers/archive/v${PREPROCESS_FLATBUFFERS_VERSION}.tar.gz")
|
||||
set(PREPROCESS_FB_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/preprocess-flatbuffers-src")
|
||||
set(PREPROCESS_FB_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/preprocess-flatbuffers-build")
|
||||
|
||||
# Check if we already have FlatBuffers headers
|
||||
set(PREPROCESS_FB_HEADER "${PREPROCESS_FB_SOURCE_DIR}/include/flatbuffers/flatbuffers.h")
|
||||
if(NOT EXISTS ${PREPROCESS_FB_HEADER})
|
||||
message("Downloading and extracting FlatBuffers for preprocessing...")
|
||||
|
||||
# Download and extract FlatBuffers
|
||||
file(DOWNLOAD ${PREPROCESS_FLATBUFFERS_URL}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-${PREPROCESS_FLATBUFFERS_VERSION}.tar.gz"
|
||||
SHOW_PROGRESS
|
||||
STATUS download_status)
|
||||
|
||||
list(GET download_status 0 download_result)
|
||||
if(NOT download_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to download FlatBuffers for preprocessing")
|
||||
endif()
|
||||
|
||||
# Extract the archive
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xzf "flatbuffers-${PREPROCESS_FLATBUFFERS_VERSION}.tar.gz"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
RESULT_VARIABLE extract_result
|
||||
)
|
||||
|
||||
if(NOT extract_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to extract FlatBuffers for preprocessing")
|
||||
endif()
|
||||
|
||||
# Move the extracted directory to our expected location
|
||||
file(RENAME "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-${PREPROCESS_FLATBUFFERS_VERSION}"
|
||||
"${PREPROCESS_FB_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
# Verify FlatBuffers headers are now available
|
||||
if(NOT EXISTS ${PREPROCESS_FB_HEADER})
|
||||
message(FATAL_ERROR "FlatBuffers headers not found for preprocessing: ${PREPROCESS_FB_HEADER}")
|
||||
endif()
|
||||
|
||||
message("✅ FlatBuffers headers available for preprocessing: ${PREPROCESS_FB_SOURCE_DIR}/include")
|
||||
|
||||
# Get ALL subdirectories under include/ and add the root include directory first
|
||||
set(all_includes "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
file(GLOB_RECURSE all_dirs LIST_DIRECTORIES true "${CMAKE_CURRENT_SOURCE_DIR}/include/*")
|
||||
foreach(item ${all_dirs})
|
||||
if(IS_DIRECTORY ${item})
|
||||
list(APPEND all_includes ${item})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Add binary include directory
|
||||
list(APPEND all_includes "${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
|
||||
# Also add build directories
|
||||
list(APPEND all_includes
|
||||
"${CMAKE_SOURCE_DIR}/include/"
|
||||
"${CMAKE_SOURCE_DIR}/include/system"
|
||||
"${CMAKE_BINARY_DIR}/compilation_units"
|
||||
"${CMAKE_BINARY_DIR}/cpu_instantiations"
|
||||
"${CMAKE_BINARY_DIR}/cuda_instantiations"
|
||||
"${CMAKE_BINARY_DIR}/include"
|
||||
)
|
||||
|
||||
# Add our self-contained FlatBuffers include directory
|
||||
list(APPEND all_includes "${PREPROCESS_FB_SOURCE_DIR}/include")
|
||||
|
||||
# Build include flags
|
||||
set(include_flags "")
|
||||
foreach(dir IN LISTS all_includes)
|
||||
if(EXISTS ${dir})
|
||||
string(APPEND include_flags " -I${dir}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(defs_flags "")
|
||||
|
||||
# Add basic platform definitions
|
||||
string(APPEND defs_flags " -D__CPUBLAS__=true")
|
||||
if(SD_CUDA)
|
||||
string(APPEND defs_flags " -D__CUDABLAS__=true -DHAVE_CUDA=1")
|
||||
endif()
|
||||
if(HAVE_OPENBLAS)
|
||||
string(APPEND defs_flags " -DHAVE_OPENBLAS=1")
|
||||
endif()
|
||||
|
||||
if(SD_ALL_OPS OR "${SD_OPS_LIST}" STREQUAL "")
|
||||
string(APPEND defs_flags " -DSD_ALL_OPS=1")
|
||||
# When SD_ALL_OPS=1, NOT_EXCLUDED should evaluate to 1 for all ops
|
||||
string(APPEND defs_flags " -DNOT_EXCLUDED(x)=1")
|
||||
else()
|
||||
# Add specific operation definitions
|
||||
foreach(OP ${SD_OPS_LIST})
|
||||
string(APPEND defs_flags " -DOP_${OP}=1")
|
||||
endforeach()
|
||||
# Define NOT_EXCLUDED macro for selective ops
|
||||
string(APPEND defs_flags " -DNOT_EXCLUDED(x)=\\(defined\\(x\\)\\)")
|
||||
endif()
|
||||
|
||||
# Add build type definitions
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
string(APPEND defs_flags " -DDEBUG=1 -D_DEBUG=1")
|
||||
else()
|
||||
string(APPEND defs_flags " -DNDEBUG=1")
|
||||
endif()
|
||||
|
||||
# Add any additional compile definitions from the main build
|
||||
if(compile_defs AND NOT compile_defs STREQUAL "compile_defs-NOTFOUND")
|
||||
foreach(def IN LISTS compile_defs)
|
||||
string(APPEND defs_flags " -D${def}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(PREPROCESSED_DIR "${CMAKE_SOURCE_DIR}/preprocessed")
|
||||
file(MAKE_DIRECTORY ${PREPROCESSED_DIR})
|
||||
|
||||
set(PREPROCESSED_FILES)
|
||||
set(PROCESSED_SOURCES "")
|
||||
|
||||
# Use ALL_SOURCES from global scope
|
||||
if(DEFINED ALL_SOURCES AND ALL_SOURCES)
|
||||
set(SOURCE_LIST ${ALL_SOURCES})
|
||||
elseif(DEFINED ALL_SOURCES_LIST AND ALL_SOURCES_LIST)
|
||||
set(SOURCE_LIST ${ALL_SOURCES_LIST})
|
||||
else()
|
||||
message(WARNING "No source list available for preprocessing. Skipping.")
|
||||
add_custom_target(preprocess_sources ALL
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Preprocessing skipped - no source files available")
|
||||
return()
|
||||
endif()
|
||||
|
||||
list(LENGTH SOURCE_LIST source_count)
|
||||
message("Starting preprocessing of ${source_count} source files...")
|
||||
message("Operation definitions: SD_ALL_OPS=${SD_ALL_OPS}, SD_OPS_LIST=${SD_OPS_LIST}")
|
||||
|
||||
foreach(src IN LISTS SOURCE_LIST)
|
||||
if(NOT EXISTS ${src} OR NOT src MATCHES "\\.(c|cpp|cxx|cc|cu)$")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
if(NOT src IN_LIST PROCESSED_SOURCES)
|
||||
get_filename_component(src_name ${src} NAME_WE)
|
||||
get_filename_component(src_path ${src} PATH)
|
||||
file(RELATIVE_PATH rel_path ${CMAKE_SOURCE_DIR} ${src_path})
|
||||
string(REPLACE "/" "_" src_dir_ "${rel_path}")
|
||||
set(preprocessed_file "${PREPROCESSED_DIR}/${src_dir_}_${src_name}.i")
|
||||
|
||||
if(NOT EXISTS "${preprocessed_file}")
|
||||
if(src MATCHES "\\.cu$")
|
||||
set(compiler "${CMAKE_CUDA_COMPILER}")
|
||||
set(lang_flags "${CMAKE_CUDA_FLAGS} ${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||
elseif(src MATCHES "\\.c$")
|
||||
set(compiler "${CMAKE_C_COMPILER}")
|
||||
set(lang_flags "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||
else()
|
||||
set(compiler "${CMAKE_CXX_COMPILER}")
|
||||
set(lang_flags "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||
endif()
|
||||
|
||||
# Split the flags properly for execute_process
|
||||
separate_arguments(lang_flags_list UNIX_COMMAND "${lang_flags}")
|
||||
separate_arguments(defs_flags_list UNIX_COMMAND "${defs_flags}")
|
||||
separate_arguments(include_flags_list UNIX_COMMAND "${include_flags}")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${compiler} -E -P -C ${lang_flags_list} ${defs_flags_list} ${include_flags_list} "${src}" -o "${preprocessed_file}"
|
||||
RESULT_VARIABLE result
|
||||
ERROR_VARIABLE error_output
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
if(result EQUAL 0)
|
||||
list(APPEND PREPROCESSED_FILES ${preprocessed_file})
|
||||
message(STATUS "✅ Preprocessed: ${src}")
|
||||
else()
|
||||
message(WARNING "❌ Failed to preprocess ${src}")
|
||||
message(WARNING " Error: ${error_output}")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND PREPROCESSED_FILES ${preprocessed_file})
|
||||
message(STATUS "✓ Already preprocessed: ${src}")
|
||||
endif()
|
||||
list(APPEND PROCESSED_SOURCES ${src})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(LENGTH PREPROCESSED_FILES processed_count)
|
||||
message("✅ Preprocessing complete. Generated ${processed_count} preprocessed files in ${PREPROCESSED_DIR}")
|
||||
add_custom_target(preprocess_sources ALL DEPENDS ${PREPROCESSED_FILES})
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,480 @@
|
||||
# cmake/Ppstep.cmake
|
||||
# Builds ppstep preprocessor tool with robust include path discovery
|
||||
|
||||
if(BUILD_PPSTEP)
|
||||
message(STATUS "🔧 PPSTEP BUILD MODE - Building ppstep tool only")
|
||||
message(STATUS "Setting up ppstep build in: ${CMAKE_BINARY_DIR}")
|
||||
|
||||
# Check for Boost (required for ppstep)
|
||||
find_package(Boost COMPONENTS system filesystem program_options thread wave QUIET)
|
||||
|
||||
if(NOT Boost_FOUND)
|
||||
message(FATAL_ERROR "❌ Boost not found - cannot build ppstep. Install with: apt-get install libboost-all-dev")
|
||||
endif()
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
# Configure ppstep as external project
|
||||
set(PPSTEP_PREFIX "${CMAKE_BINARY_DIR}/ppstep_external")
|
||||
set(PPSTEP_SOURCE_DIR "${PPSTEP_PREFIX}/src/ppstep")
|
||||
set(PPSTEP_BUILD_DIR "${PPSTEP_PREFIX}/build")
|
||||
|
||||
# Clean up any previous failed attempts
|
||||
if(EXISTS "${PPSTEP_PREFIX}/src/ppstep_build-stamp")
|
||||
file(REMOVE_RECURSE "${PPSTEP_PREFIX}/src/ppstep_build-stamp")
|
||||
endif()
|
||||
|
||||
message(STATUS "Cloning and building ppstep...")
|
||||
|
||||
# Set up CMAKE_ARGS conditionally to avoid empty values
|
||||
set(PPSTEP_CMAKE_ARGS
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
)
|
||||
|
||||
if(CMAKE_CXX_COMPILER)
|
||||
list(APPEND PPSTEP_CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER})
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER)
|
||||
list(APPEND PPSTEP_CMAKE_ARGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER})
|
||||
endif()
|
||||
|
||||
if(BOOST_ROOT)
|
||||
list(APPEND PPSTEP_CMAKE_ARGS -DBOOST_ROOT=${BOOST_ROOT})
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(ppstep_build
|
||||
PREFIX "${PPSTEP_PREFIX}"
|
||||
GIT_REPOSITORY "https://github.com/agibsonccc/ppstep.git"
|
||||
GIT_TAG "master"
|
||||
GIT_SHALLOW TRUE
|
||||
SOURCE_DIR "${PPSTEP_SOURCE_DIR}"
|
||||
BINARY_DIR "${PPSTEP_BUILD_DIR}"
|
||||
STAMP_DIR "${PPSTEP_PREFIX}/stamp"
|
||||
TMP_DIR "${PPSTEP_PREFIX}/tmp"
|
||||
DOWNLOAD_DIR "${PPSTEP_PREFIX}/download"
|
||||
CMAKE_ARGS ${PPSTEP_CMAKE_ARGS}
|
||||
BUILD_COMMAND make
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_BYPRODUCTS "${PPSTEP_BUILD_DIR}/ppstep"
|
||||
LOG_DOWNLOAD TRUE
|
||||
LOG_CONFIGURE TRUE
|
||||
LOG_BUILD TRUE
|
||||
)
|
||||
|
||||
# ============================================================================
|
||||
# ROBUST INCLUDE PATH DISCOVERY AT CMAKE CONFIGURE TIME
|
||||
# ============================================================================
|
||||
|
||||
message(STATUS "Discovering system include paths...")
|
||||
|
||||
set(DISCOVERED_INCLUDE_PATHS "")
|
||||
|
||||
# Method 1: Use CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES
|
||||
foreach(dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
|
||||
if(EXISTS "${dir}")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${dir}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Method 2: Get from compiler using execute_process
|
||||
if(CMAKE_CXX_COMPILER)
|
||||
# Get verbose output from compiler
|
||||
execute_process(
|
||||
COMMAND echo ""
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -E -x c++ -Wp,-v -
|
||||
OUTPUT_VARIABLE COMPILER_OUTPUT
|
||||
ERROR_VARIABLE COMPILER_ERROR
|
||||
INPUT_FILE /dev/null
|
||||
RESULT_VARIABLE COMPILER_RESULT
|
||||
)
|
||||
|
||||
# Parse the output to extract include paths
|
||||
string(REGEX MATCHALL "#include [<\"].*[>\"] search starts here:.*End of search list" INCLUDE_SECTION "${COMPILER_ERROR}")
|
||||
if(INCLUDE_SECTION)
|
||||
string(REGEX REPLACE "#include [<\"].*[>\"] search starts here:" "" INCLUDE_SECTION "${INCLUDE_SECTION}")
|
||||
string(REGEX REPLACE "End of search list" "" INCLUDE_SECTION "${INCLUDE_SECTION}")
|
||||
string(REGEX REPLACE "\n" ";" INCLUDE_LINES "${INCLUDE_SECTION}")
|
||||
|
||||
foreach(line ${INCLUDE_LINES})
|
||||
string(STRIP "${line}" line)
|
||||
if(EXISTS "${line}")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${line}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Also try cpp directly
|
||||
find_program(CPP_EXECUTABLE cpp)
|
||||
if(CPP_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${CPP_EXECUTABLE} -x c++ -v
|
||||
OUTPUT_VARIABLE CPP_OUTPUT
|
||||
ERROR_VARIABLE CPP_ERROR
|
||||
INPUT_FILE /dev/null
|
||||
RESULT_VARIABLE CPP_RESULT
|
||||
)
|
||||
|
||||
string(REGEX MATCHALL "/[^\n]*include[^\n]*" INCLUDE_DIRS "${CPP_ERROR}")
|
||||
foreach(dir ${INCLUDE_DIRS})
|
||||
string(STRIP "${dir}" dir)
|
||||
if(EXISTS "${dir}" AND IS_DIRECTORY "${dir}")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${dir}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Method 3: Get GCC-specific paths
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=include
|
||||
OUTPUT_VARIABLE GCC_INCLUDE_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
if(EXISTS "${GCC_INCLUDE_DIR}")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${GCC_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -print-search-dirs
|
||||
OUTPUT_VARIABLE GCC_SEARCH_DIRS
|
||||
ERROR_QUIET
|
||||
)
|
||||
if(GCC_SEARCH_DIRS)
|
||||
string(REGEX MATCH "install: ([^\n]*)" INSTALL_LINE "${GCC_SEARCH_DIRS}")
|
||||
if(CMAKE_MATCH_1)
|
||||
string(STRIP "${CMAKE_MATCH_1}" INSTALL_DIR)
|
||||
if(EXISTS "${INSTALL_DIR}/include")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${INSTALL_DIR}/include")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Method 4: Get target-specific paths
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -dumpmachine
|
||||
OUTPUT_VARIABLE GCC_TARGET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
if(GCC_TARGET AND GCC_VERSION)
|
||||
# Extract major version
|
||||
string(REGEX MATCH "^([0-9]+)" GCC_MAJOR "${GCC_VERSION}")
|
||||
|
||||
# Check common GCC installation paths
|
||||
foreach(base_path "/usr/lib/gcc" "/usr/lib64/gcc" "/usr/local/lib/gcc")
|
||||
foreach(version ${GCC_VERSION} ${GCC_MAJOR})
|
||||
foreach(subdir "include" "include-fixed")
|
||||
set(test_path "${base_path}/${GCC_TARGET}/${version}/${subdir}")
|
||||
if(EXISTS "${test_path}")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${test_path}")
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Method 5: Common system paths
|
||||
set(COMMON_INCLUDE_PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/usr/include/linux
|
||||
/usr/include/x86_64-linux-gnu
|
||||
/usr/include/i386-linux-gnu
|
||||
/usr/include/aarch64-linux-gnu
|
||||
/opt/local/include
|
||||
/opt/include
|
||||
)
|
||||
|
||||
foreach(path ${COMMON_INCLUDE_PATHS})
|
||||
if(EXISTS "${path}")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${path}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Add C++ standard library paths
|
||||
foreach(version RANGE 5 15)
|
||||
set(cpp_paths
|
||||
"/usr/include/c++/${version}"
|
||||
"/usr/include/c++/${version}/x86_64-linux-gnu"
|
||||
"/usr/include/c++/${version}/x86_64-redhat-linux"
|
||||
"/usr/include/c++/${version}/aarch64-linux-gnu"
|
||||
"/usr/include/c++/${version}/backward"
|
||||
)
|
||||
foreach(path ${cpp_paths})
|
||||
if(EXISTS "${path}")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${path}")
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
# Method 6: Try to compile a test file and extract includes
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/test_includes.cpp" "
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
int main() { return 0; }
|
||||
")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -H -E "${CMAKE_BINARY_DIR}/test_includes.cpp"
|
||||
OUTPUT_VARIABLE HEADER_OUTPUT
|
||||
ERROR_VARIABLE HEADER_ERROR
|
||||
RESULT_VARIABLE HEADER_RESULT
|
||||
)
|
||||
|
||||
# Parse the -H output to find include directories
|
||||
string(REGEX MATCHALL "\\. /[^\n]*\\.h" HEADER_LINES "${HEADER_ERROR}")
|
||||
foreach(line ${HEADER_LINES})
|
||||
string(REGEX REPLACE "^\\. " "" header_file "${line}")
|
||||
get_filename_component(header_dir "${header_file}" DIRECTORY)
|
||||
if(EXISTS "${header_dir}")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${header_dir}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Method 7: Check if clang is available and get its paths
|
||||
find_program(CLANG_CXX clang++)
|
||||
if(CLANG_CXX)
|
||||
execute_process(
|
||||
COMMAND ${CLANG_CXX} -print-resource-dir
|
||||
OUTPUT_VARIABLE CLANG_RESOURCE_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
if(EXISTS "${CLANG_RESOURCE_DIR}/include")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${CLANG_RESOURCE_DIR}/include")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Remove duplicates
|
||||
list(REMOVE_DUPLICATES DISCOVERED_INCLUDE_PATHS)
|
||||
|
||||
# Validate that we found critical headers
|
||||
set(CRITICAL_HEADERS limits.h stdio.h stdlib.h stddef.h stdint.h)
|
||||
set(MISSING_HEADERS "")
|
||||
|
||||
foreach(header ${CRITICAL_HEADERS})
|
||||
set(HEADER_FOUND FALSE)
|
||||
foreach(dir ${DISCOVERED_INCLUDE_PATHS})
|
||||
if(EXISTS "${dir}/${header}")
|
||||
set(HEADER_FOUND TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT HEADER_FOUND)
|
||||
list(APPEND MISSING_HEADERS ${header})
|
||||
message(WARNING "Critical header ${header} not found in discovered paths")
|
||||
|
||||
# Try to find it
|
||||
execute_process(
|
||||
COMMAND find /usr -name ${header} -type f -print -quit
|
||||
OUTPUT_VARIABLE FOUND_HEADER
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
TIMEOUT 5
|
||||
)
|
||||
if(FOUND_HEADER)
|
||||
get_filename_component(FOUND_DIR "${FOUND_HEADER}" DIRECTORY)
|
||||
message(STATUS " Found ${header} in ${FOUND_DIR}")
|
||||
list(APPEND DISCOVERED_INCLUDE_PATHS "${FOUND_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Remove duplicates again after adding missing headers
|
||||
list(REMOVE_DUPLICATES DISCOVERED_INCLUDE_PATHS)
|
||||
|
||||
# Convert to -I flags
|
||||
set(SYSTEM_INCLUDE_FLAGS "")
|
||||
foreach(dir ${DISCOVERED_INCLUDE_PATHS})
|
||||
set(SYSTEM_INCLUDE_FLAGS "${SYSTEM_INCLUDE_FLAGS} -I${dir}")
|
||||
endforeach()
|
||||
|
||||
message(STATUS "Found ${CMAKE_WORDS_BIGENDIAN} system include directories")
|
||||
message(STATUS "System include flags: ${SYSTEM_INCLUDE_FLAGS}")
|
||||
|
||||
# Write the discovered paths to a file for debugging
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/discovered_includes.txt" "${SYSTEM_INCLUDE_FLAGS}")
|
||||
|
||||
# ============================================================================
|
||||
# GENERATE WRAPPER SCRIPT WITH DISCOVERED PATHS
|
||||
# ============================================================================
|
||||
|
||||
set(PPSTEP_WRAPPER "${CMAKE_BINARY_DIR}/ppstep-nd4j")
|
||||
|
||||
# Generate wrapper with the discovered paths baked in
|
||||
file(WRITE ${PPSTEP_WRAPPER}
|
||||
"#!/bin/bash
|
||||
# Auto-generated ppstep wrapper for libnd4j
|
||||
# Generated at CMake configure time with discovered include paths
|
||||
|
||||
PPSTEP_BIN=\"${PPSTEP_BUILD_DIR}/ppstep\"
|
||||
|
||||
if [ ! -f \"\$PPSTEP_BIN\" ]; then
|
||||
echo \"Error: ppstep not built yet. Run 'make ppstep_build' first\"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# System includes discovered at CMake configure time
|
||||
SYSTEM_INCLUDES=\"${SYSTEM_INCLUDE_FLAGS}\"
|
||||
|
||||
# Additional runtime discovery (fallback)
|
||||
if [ -z \"\$SYSTEM_INCLUDES\" ] || [ \"\$1\" = \"--rediscover\" ]; then
|
||||
echo \"Warning: No includes from CMake or rediscovery requested\" >&2
|
||||
|
||||
# Try runtime discovery
|
||||
RUNTIME_INCLUDES=\"\"
|
||||
|
||||
# Method 1: cpp -v
|
||||
if command -v cpp &> /dev/null; then
|
||||
while IFS= read -r dir; do
|
||||
[ -d \"\$dir\" ] && RUNTIME_INCLUDES=\"\$RUNTIME_INCLUDES -I\$dir\"
|
||||
done < <(cpp -x c++ -v < /dev/null 2>&1 | awk '
|
||||
/^#include <...> search starts here:/ { flag=1; next }
|
||||
/^End of search list./ { flag=0 }
|
||||
flag { gsub(/^[ \t]+/, \"\"); print }
|
||||
')
|
||||
fi
|
||||
|
||||
# Method 2: Direct paths
|
||||
for dir in /usr/include /usr/local/include /usr/include/linux; do
|
||||
[ -d \"\$dir\" ] && RUNTIME_INCLUDES=\"\$RUNTIME_INCLUDES -I\$dir\"
|
||||
done
|
||||
|
||||
SYSTEM_INCLUDES=\"\$RUNTIME_INCLUDES\"
|
||||
fi
|
||||
|
||||
# Include paths for libnd4j
|
||||
INCLUDES=\"-I${CMAKE_CURRENT_SOURCE_DIR}/include\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_BINARY_DIR}/include\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/array\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/blas\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/cnpy\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/exceptions\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/execution\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/flatbuffers\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/generated\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/graph\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/helpers\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/indexing\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/legacy\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/loops\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/math\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/memory\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/ops\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/system\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/types\"
|
||||
INCLUDES=\"\$INCLUDES -I${CMAKE_CURRENT_SOURCE_DIR}/include/performance\"
|
||||
|
||||
# Add OpenBLAS if available
|
||||
if [ -n \"${OPENBLAS_PATH}\" ] && [ -d \"${OPENBLAS_PATH}/include\" ]; then
|
||||
INCLUDES=\"\$INCLUDES -I${OPENBLAS_PATH}/include\"
|
||||
fi
|
||||
|
||||
# Basic defines
|
||||
DEFINES=\"-D__CPUBLAS__=1 -DSD_CPU=1\"
|
||||
DEFINES=\"\$DEFINES -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS\"
|
||||
DEFINES=\"\$DEFINES -D_GNU_SOURCE\"
|
||||
|
||||
# Handle special arguments
|
||||
case \"\$1\" in
|
||||
--debug|--show-includes)
|
||||
echo \"System includes:\"
|
||||
echo \$SYSTEM_INCLUDES | tr ' ' '\\n' | grep '^-I' | while read inc; do
|
||||
dir=\${inc#-I}
|
||||
echo \" \$inc\"
|
||||
for h in limits.h stdio.h stdlib.h stddef.h; do
|
||||
[ -f \"\$dir/\$h\" ] && echo \" ✓ has \$h\"
|
||||
done
|
||||
done
|
||||
echo \"\"
|
||||
echo \"Project includes:\"
|
||||
echo \$INCLUDES | tr ' ' '\\n' | grep '^-I'
|
||||
echo \"\"
|
||||
echo \"Defines:\"
|
||||
echo \$DEFINES | tr ' ' '\\n'
|
||||
exit 0
|
||||
;;
|
||||
--version)
|
||||
echo \"ppstep wrapper generated by CMake\"
|
||||
echo \"Binary: \$PPSTEP_BIN\"
|
||||
\$PPSTEP_BIN --version 2>/dev/null || echo \"ppstep version unknown\"
|
||||
exit 0
|
||||
;;
|
||||
-h|--help)
|
||||
echo \"Usage: \$0 [options] <source_file.cpp>\"
|
||||
echo \"Options:\"
|
||||
echo \" --debug, --show-includes Show include paths and exit\"
|
||||
echo \" --rediscover Force runtime include discovery\"
|
||||
echo \" --version Show version information\"
|
||||
echo \" -h, --help Show this help\"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# Remove special arguments if rediscovery was requested
|
||||
[ \"\$1\" = \"--rediscover\" ] && shift
|
||||
|
||||
# Run ppstep
|
||||
exec \"\$PPSTEP_BIN\" \$SYSTEM_INCLUDES \$INCLUDES \$DEFINES \"\$@\"
|
||||
")
|
||||
|
||||
# Make wrapper executable
|
||||
file(CHMOD ${PPSTEP_WRAPPER}
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE)
|
||||
|
||||
# Also generate a CMake include file with the discovered paths
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/ppstep_includes.cmake"
|
||||
"# Auto-generated by Ppstep.cmake
|
||||
# System include directories discovered during configuration
|
||||
|
||||
set(PPSTEP_SYSTEM_INCLUDE_DIRS
|
||||
")
|
||||
foreach(dir ${DISCOVERED_INCLUDE_PATHS})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/ppstep_includes.cmake" " \"${dir}\"\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/ppstep_includes.cmake" ")\n")
|
||||
|
||||
# Add custom target
|
||||
add_custom_target(ppstep ALL
|
||||
DEPENDS ppstep_build
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "✅ ppstep built successfully"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo " Executable: ${PPSTEP_BUILD_DIR}/ppstep"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo " Wrapper: ${PPSTEP_WRAPPER}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo " Include paths: ${CMAKE_BINARY_DIR}/discovered_includes.txt"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo ""
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Usage:"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo " ${PPSTEP_WRAPPER} [source_file.cpp]"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo " ${PPSTEP_WRAPPER} --debug # Show include paths"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo ""
|
||||
COMMENT "ppstep preprocessor tool ready"
|
||||
)
|
||||
|
||||
# Custom target to regenerate wrapper if needed
|
||||
add_custom_target(ppstep-regenerate
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Regenerating ppstep wrapper..."
|
||||
COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "Regenerating ppstep wrapper with updated paths"
|
||||
)
|
||||
|
||||
message(STATUS "✅ ppstep target configured")
|
||||
message(STATUS "Exiting after ppstep setup - run 'make' to build ppstep")
|
||||
|
||||
# CRITICAL: EARLY EXIT - Don't process the rest of CMakeLists.txt
|
||||
return()
|
||||
endif()
|
||||
@@ -0,0 +1,87 @@
|
||||
################################################################################
|
||||
# Colored Status Printing and Utility Functions
|
||||
# Common utility functions for enhanced CMake output and debugging
|
||||
################################################################################
|
||||
|
||||
# Enhanced colored status printing function
|
||||
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}")
|
||||
elseif(type STREQUAL "DEBUG")
|
||||
message(STATUS "🔍 ${message}")
|
||||
elseif(type STREQUAL "NOTICE")
|
||||
message(NOTICE "📢 ${message}")
|
||||
else()
|
||||
message(STATUS "${message}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Print all CMake variables for debugging
|
||||
macro(print_all_variables)
|
||||
message(STATUS "print_all_variables------------------------------------------{")
|
||||
get_cmake_property(_variableNames VARIABLES)
|
||||
foreach(_variableName ${_variableNames})
|
||||
message(STATUS "${_variableName}=${${_variableName}}")
|
||||
endforeach()
|
||||
message(STATUS "print_all_variables------------------------------------------}")
|
||||
endmacro()
|
||||
|
||||
# Function to verify template processing worked
|
||||
function(verify_template_processing GENERATED_FILE)
|
||||
if(EXISTS "${GENERATED_FILE}")
|
||||
file(READ "${GENERATED_FILE}" FILE_CONTENT)
|
||||
|
||||
# Check for unprocessed #cmakedefine
|
||||
if(FILE_CONTENT MATCHES "#cmakedefine[ \t]+[A-Za-z_]+")
|
||||
message(FATAL_ERROR "❌ Template processing FAILED: ${GENERATED_FILE} contains unprocessed #cmakedefine directives")
|
||||
endif()
|
||||
|
||||
# Check for unprocessed @VAR@
|
||||
if(FILE_CONTENT MATCHES "@[A-Za-z_]+@")
|
||||
message(FATAL_ERROR "❌ Template processing FAILED: ${GENERATED_FILE} contains unprocessed @VAR@ tokens")
|
||||
endif()
|
||||
|
||||
message(STATUS "✅ Template processing verified: ${GENERATED_FILE}")
|
||||
return()
|
||||
else()
|
||||
message(FATAL_ERROR "❌ Generated file does not exist: ${GENERATED_FILE}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Function to safely remove files if they match exclusion criteria
|
||||
function(removeFileIfExcluded)
|
||||
cmake_parse_arguments(
|
||||
PARSED_ARGS
|
||||
""
|
||||
"FILE_ITEM"
|
||||
"LIST_ITEM"
|
||||
${ARGN}
|
||||
)
|
||||
file(READ ${PARSED_ARGS_FILE_ITEM} FILE_CONTENTS)
|
||||
string(FIND "${FILE_CONTENTS}" "NOT_EXCLUDED" NOT_EXCLUDED_IDX)
|
||||
|
||||
if(${NOT_EXCLUDED_IDX} GREATER_EQUAL 0)
|
||||
set(local_list ${${PARSED_ARGS_LIST_ITEM}})
|
||||
set(file_removed FALSE)
|
||||
|
||||
foreach(OP ${SD_OPS_LIST})
|
||||
string(FIND "${FILE_CONTENTS}" "NOT_EXCLUDED(OP_${OP})" NOT_EXCLUDED_OP_IDX)
|
||||
|
||||
if(${NOT_EXCLUDED_OP_IDX} LESS 0)
|
||||
list(REMOVE_ITEM local_list "${PARSED_ARGS_FILE_ITEM}")
|
||||
set(file_removed TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(file_removed)
|
||||
set(${PARSED_ARGS_LIST_ITEM} ${local_list} PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,207 @@
|
||||
# cmake/ProcessInstantiationBatch.cmake
|
||||
# Worker script for processing a batch of source files in parallel
|
||||
# This script is executed as a separate CMake process for each batch
|
||||
|
||||
# Get batch ID from command line
|
||||
if(NOT DEFINED BATCH_ID)
|
||||
message(FATAL_ERROR "BATCH_ID not defined")
|
||||
endif()
|
||||
|
||||
message("[Batch ${BATCH_ID}] Starting batch processor")
|
||||
|
||||
# Determine paths
|
||||
get_filename_component(CMAKE_SCRIPT_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
|
||||
set(CMAKE_SOURCE_DIR "${CMAKE_SCRIPT_DIR}/..")
|
||||
set(INST_DIR "${CMAKE_SOURCE_DIR}/instantiation_analysis")
|
||||
set(INST_BATCH_DIR "${INST_DIR}/batches")
|
||||
|
||||
# Load configuration
|
||||
set(BATCH_CONFIG_FILE "${INST_BATCH_DIR}/config.cmake")
|
||||
if(NOT EXISTS ${BATCH_CONFIG_FILE})
|
||||
message(FATAL_ERROR "[Batch ${BATCH_ID}] Configuration file not found: ${BATCH_CONFIG_FILE}")
|
||||
endif()
|
||||
|
||||
include(${BATCH_CONFIG_FILE})
|
||||
|
||||
# Include helper functions
|
||||
include(${CMAKE_SCRIPT_DIR}/InstantiationHelpers.cmake)
|
||||
|
||||
# Read list of files to process
|
||||
set(BATCH_FILE "${INST_BATCH_DIR}/batch_${BATCH_ID}.txt")
|
||||
if(NOT EXISTS ${BATCH_FILE})
|
||||
message(WARNING "[Batch ${BATCH_ID}] Batch file not found: ${BATCH_FILE}")
|
||||
file(WRITE "${INST_BATCH_DIR}/batch_${BATCH_ID}.done" "")
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(STRINGS ${BATCH_FILE} FILES_TO_PROCESS)
|
||||
list(LENGTH FILES_TO_PROCESS batch_size)
|
||||
message("[Batch ${BATCH_ID}] Processing ${batch_size} files")
|
||||
|
||||
# Process each file in the batch
|
||||
set(batch_results "")
|
||||
set(processed_count 0)
|
||||
set(failed_count 0)
|
||||
|
||||
foreach(src IN LISTS FILES_TO_PROCESS)
|
||||
if(NOT EXISTS ${src})
|
||||
message("[Batch ${BATCH_ID}] Warning: File not found: ${src}")
|
||||
math(EXPR failed_count "${failed_count} + 1")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
# Extract file information
|
||||
get_filename_component(src_name ${src} NAME_WE)
|
||||
get_filename_component(src_path ${src} PATH)
|
||||
get_filename_component(src_full_name ${src} NAME)
|
||||
file(RELATIVE_PATH rel_path ${CMAKE_SOURCE_DIR} ${src_path})
|
||||
string(REPLACE "/" "_" safe_name "${rel_path}_${src_name}")
|
||||
|
||||
# Determine if this is a generated file
|
||||
set(IS_GENERATED FALSE)
|
||||
if(src MATCHES "${CMAKE_BINARY_DIR}")
|
||||
set(IS_GENERATED TRUE)
|
||||
endif()
|
||||
|
||||
message("[Batch ${BATCH_ID}] [${processed_count}/${batch_size}] Analyzing: ${src_full_name}")
|
||||
|
||||
# Create a sub-temp directory for this batch
|
||||
set(BATCH_TEMP_DIR "${INST_TEMP_DIR}/batch_${BATCH_ID}")
|
||||
if(NOT EXISTS ${BATCH_TEMP_DIR})
|
||||
file(MAKE_DIRECTORY ${BATCH_TEMP_DIR})
|
||||
endif()
|
||||
set(INST_TEMP_DIR ${BATCH_TEMP_DIR})
|
||||
|
||||
# Extract used templates
|
||||
set(used_file "${INST_USED_DIR}/${safe_name}.used")
|
||||
extract_used_templates("${src}" "${used_file}" "${safe_name}")
|
||||
|
||||
# Extract provided templates
|
||||
set(provided_file "${INST_PROVIDED_DIR}/${safe_name}.provided")
|
||||
extract_provided_templates("${src}" "${provided_file}" "${safe_name}")
|
||||
|
||||
# Calculate missing templates
|
||||
set(missing_templates "")
|
||||
set(missing_count 0)
|
||||
|
||||
# Read used templates
|
||||
if(EXISTS ${used_file})
|
||||
file(STRINGS ${used_file} used_list)
|
||||
else()
|
||||
set(used_list "")
|
||||
endif()
|
||||
|
||||
# Read provided templates
|
||||
if(EXISTS ${provided_file})
|
||||
file(STRINGS ${provided_file} provided_list)
|
||||
else()
|
||||
set(provided_list "")
|
||||
endif()
|
||||
|
||||
# Simple missing calculation (can be enhanced with normalization)
|
||||
foreach(used_tmpl ${used_list})
|
||||
set(found FALSE)
|
||||
foreach(provided_tmpl ${provided_list})
|
||||
if(used_tmpl STREQUAL provided_tmpl)
|
||||
set(found TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT found)
|
||||
list(APPEND missing_templates "${used_tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Write missing templates
|
||||
set(missing_file "${INST_MISSING_DIR}/${safe_name}.missing")
|
||||
if(missing_templates)
|
||||
list(REMOVE_DUPLICATES missing_templates)
|
||||
string(REPLACE ";" "\n" missing_content "${missing_templates}")
|
||||
file(WRITE ${missing_file} "${missing_content}")
|
||||
list(LENGTH missing_templates missing_count)
|
||||
else()
|
||||
file(WRITE ${missing_file} "")
|
||||
set(missing_count 0)
|
||||
endif()
|
||||
|
||||
# Count templates
|
||||
list(LENGTH used_list used_count)
|
||||
list(LENGTH provided_list provided_count)
|
||||
|
||||
# Create per-file summary
|
||||
file(WRITE ${INST_BY_FILE_DIR}/${safe_name}.summary "File: ${src_full_name}\n")
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary "Path: ${rel_path}\n")
|
||||
if(IS_GENERATED)
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary "Type: generated\n")
|
||||
else()
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary "Type: original\n")
|
||||
endif()
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary "Used: ${used_count}\n")
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary "Provided: ${provided_count}\n")
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary "Missing: ${missing_count}\n")
|
||||
|
||||
# Add details if there are templates
|
||||
if(used_count GREATER 0)
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary "\nUsed Templates (first 10):\n")
|
||||
set(shown 0)
|
||||
foreach(tmpl ${used_list})
|
||||
if(shown LESS 10)
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary " - ${tmpl}\n")
|
||||
math(EXPR shown "${shown} + 1")
|
||||
else()
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(provided_count GREATER 0)
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary "\nProvided Templates (first 10):\n")
|
||||
set(shown 0)
|
||||
foreach(tmpl ${provided_list})
|
||||
if(shown LESS 10)
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary " - ${tmpl}\n")
|
||||
math(EXPR shown "${shown} + 1")
|
||||
else()
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(missing_count GREATER 0)
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary "\nMissing Templates:\n")
|
||||
foreach(tmpl ${missing_templates})
|
||||
file(APPEND ${INST_BY_FILE_DIR}/${safe_name}.summary " - ${tmpl}\n")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Append to batch results
|
||||
string(APPEND batch_results "${src}|${safe_name}|${used_count}|${provided_count}|${missing_count}|${IS_GENERATED}\n")
|
||||
|
||||
math(EXPR processed_count "${processed_count} + 1")
|
||||
|
||||
# Progress reporting
|
||||
math(EXPR progress_pct "(${processed_count} * 100) / ${batch_size}")
|
||||
if(progress_pct GREATER 0 AND NOT progress_pct EQUAL last_progress)
|
||||
message("[Batch ${BATCH_ID}] Progress: ${progress_pct}% (${processed_count}/${batch_size})")
|
||||
set(last_progress ${progress_pct})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Clean up batch temp directory
|
||||
if(EXISTS ${BATCH_TEMP_DIR})
|
||||
file(REMOVE_RECURSE ${BATCH_TEMP_DIR})
|
||||
endif()
|
||||
|
||||
# Write batch completion marker with results
|
||||
file(WRITE "${INST_BATCH_DIR}/batch_${BATCH_ID}.done" "${batch_results}")
|
||||
|
||||
message("[Batch ${BATCH_ID}] Completed: ${processed_count} processed, ${failed_count} failed")
|
||||
|
||||
# Write batch summary
|
||||
set(BATCH_SUMMARY_FILE "${INST_BATCH_DIR}/batch_${BATCH_ID}.summary")
|
||||
file(WRITE ${BATCH_SUMMARY_FILE} "Batch ${BATCH_ID} Summary\n")
|
||||
file(APPEND ${BATCH_SUMMARY_FILE} "====================\n")
|
||||
file(APPEND ${BATCH_SUMMARY_FILE} "Files processed: ${processed_count}\n")
|
||||
file(APPEND ${BATCH_SUMMARY_FILE} "Files failed: ${failed_count}\n")
|
||||
file(APPEND ${BATCH_SUMMARY_FILE} "Total in batch: ${batch_size}\n")
|
||||
@@ -0,0 +1,38 @@
|
||||
include(SelectiveRenderingCore)
|
||||
|
||||
# Wrapper for the original setup_selective_rendering function
|
||||
function(setup_selective_rendering)
|
||||
message(STATUS "🔄 SelectiveRendering.cmake: Calling unified core system")
|
||||
|
||||
# Call the unified system
|
||||
setup_selective_rendering_unified_safe()
|
||||
|
||||
# Map results to legacy variables that existing code expects
|
||||
if(DEFINED UNIFIED_COMBINATIONS_2)
|
||||
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
|
||||
endif()
|
||||
if(DEFINED UNIFIED_COMBINATIONS_3)
|
||||
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
|
||||
endif()
|
||||
if(DEFINED UNIFIED_ACTIVE_TYPES)
|
||||
set(ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
message(STATUS "✅ SelectiveRendering.cmake: Setup complete via unified core")
|
||||
endfunction()
|
||||
|
||||
# Legacy wrapper functions for other entry points
|
||||
function(track_combination_states active_types combinations_3)
|
||||
# This function is now handled internally by the core system
|
||||
message(STATUS "🔄 track_combination_states: Handled by unified core")
|
||||
endfunction()
|
||||
|
||||
function(generate_selective_rendering_header)
|
||||
# This function is now handled internally by the core system
|
||||
message(STATUS "🔄 generate_selective_rendering_header: Handled by unified core")
|
||||
endfunction()
|
||||
|
||||
function(generate_selective_wrapper_header)
|
||||
# This function is now handled internally by the core system
|
||||
message(STATUS "🔄 generate_selective_wrapper_header: Handled by unified core")
|
||||
endfunction()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
function(setup_definitive_semantic_filtering_with_selective_rendering)
|
||||
message(STATUS "🔄 SelectiveRenderingIntegration.cmake: Calling unified core system")
|
||||
|
||||
# Enable both semantic filtering and selective rendering
|
||||
set(SD_ENABLE_SEMANTIC_FILTERING TRUE PARENT_SCOPE)
|
||||
set(SD_ENABLE_SELECTIVE_RENDERING TRUE PARENT_SCOPE)
|
||||
|
||||
# Call unified system
|
||||
setup_selective_rendering_unified_safe()
|
||||
|
||||
# Legacy variable mapping
|
||||
if(DEFINED UNIFIED_COMBINATIONS_2)
|
||||
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
|
||||
endif()
|
||||
if(DEFINED UNIFIED_COMBINATIONS_3)
|
||||
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
message(STATUS "✅ SelectiveRenderingIntegration.cmake: Setup complete via unified core")
|
||||
endfunction()
|
||||
|
||||
function(enhanced_semantic_filtering_setup)
|
||||
setup_definitive_semantic_filtering_with_selective_rendering()
|
||||
endfunction()
|
||||
|
||||
# Override the main setup function
|
||||
macro(setup_definitive_semantic_filtering)
|
||||
enhanced_semantic_filtering_setup()
|
||||
endmacro()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,107 @@
|
||||
# cmake/SemanticEngine.cmake
|
||||
# Implements the ML-aware semantic type filtering system.
|
||||
|
||||
option(SD_ENABLE_SEMANTIC_FILTERING "Enable ML-aware semantic type filtering" ON)
|
||||
option(SD_SHOW_COMBINATION_ANALYSIS "Show type combination analysis" ON)
|
||||
set(SD_TYPE_PROFILE "" CACHE STRING "ML workload profile (quantization/training/inference/nlp/cv)")
|
||||
|
||||
if(NOT SD_ENABLE_SEMANTIC_FILTERING)
|
||||
message(STATUS "Semantic filtering disabled. Using traditional type combination.")
|
||||
set(USE_SEMANTIC_PAIRWISE_GENERATION FALSE CACHE BOOL "Use semantic generation for pairwise templates")
|
||||
return()
|
||||
endif()
|
||||
|
||||
print_status_colored("INFO" "=== SEMANTIC TYPE COMBINATION GENERATION ===")
|
||||
setup_enhanced_semantic_validation()
|
||||
|
||||
# Auto-detect profile from type selection if none specified
|
||||
if((NOT SD_TYPE_PROFILE OR SD_TYPE_PROFILE STREQUAL "") AND SD_TYPES_LIST_COUNT GREATER 0)
|
||||
set(detected_profile "")
|
||||
if("int8_t" IN_LIST SD_TYPES_LIST AND "uint8_t" IN_LIST SD_TYPES_LIST)
|
||||
set(detected_profile "quantization")
|
||||
elseif("float16" IN_LIST SD_TYPES_LIST OR "bfloat16" IN_LIST SD_TYPES_LIST)
|
||||
set(detected_profile "training")
|
||||
elseif(SD_TYPES_LIST MATCHES ".*string.*")
|
||||
set(detected_profile "nlp")
|
||||
endif()
|
||||
|
||||
if(NOT detected_profile STREQUAL "")
|
||||
print_status_colored("INFO" "Auto-detected ML workload profile: ${detected_profile}")
|
||||
set(SD_TYPE_PROFILE "${detected_profile}")
|
||||
else()
|
||||
print_status_colored("INFO" "No specific workload detected - using inference profile as default")
|
||||
set(SD_TYPE_PROFILE "inference")
|
||||
endif()
|
||||
elseif(NOT SD_TYPE_PROFILE OR SD_TYPE_PROFILE STREQUAL "")
|
||||
print_status_colored("INFO" "No workload profile specified - using inference as default")
|
||||
set(SD_TYPE_PROFILE "inference")
|
||||
endif()
|
||||
|
||||
# Apply type profile if specified
|
||||
if(SD_TYPE_PROFILE AND NOT SD_TYPE_PROFILE STREQUAL "")
|
||||
print_status_colored("INFO" "Applying ML workload profile: ${SD_TYPE_PROFILE}")
|
||||
if(COMMAND apply_type_profile)
|
||||
apply_type_profile(${SD_TYPE_PROFILE})
|
||||
else()
|
||||
message(STATUS "Type profiles not available - using default types")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Generate ML-aware type combinations
|
||||
message(STATUS "Generating ML-aware type combinations...")
|
||||
if(SD_TYPE_PROFILE AND NOT SD_TYPE_PROFILE STREQUAL "")
|
||||
if(COMMAND generate_workload_combinations)
|
||||
generate_workload_combinations("${SD_TYPE_PROFILE}" optimized_combinations)
|
||||
set(GENERATED_TYPE_COMBINATIONS "${optimized_combinations}")
|
||||
else()
|
||||
message(STATUS "generate_workload_combinations function not available - using traditional approach")
|
||||
if(COMMAND generate_type_combinations)
|
||||
generate_type_combinations()
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
if(COMMAND generate_type_combinations)
|
||||
generate_type_combinations()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SD_SHOW_COMBINATION_ANALYSIS)
|
||||
if(SD_TYPES_LIST_COUNT GREATER 0)
|
||||
validate_ml_type_combinations("${SD_TYPES_LIST}")
|
||||
endif()
|
||||
if(DEFINED GENERATED_TYPE_COMBINATIONS)
|
||||
analyze_combination_patterns("${GENERATED_TYPE_COMBINATIONS}" "${SD_TYPE_PROFILE}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Process template files with semantic filtering
|
||||
message(STATUS "Processing template files with semantic filtering...")
|
||||
#process_template_files()
|
||||
|
||||
# Process pairwise templates with enhanced semantic filtering
|
||||
message(STATUS "Processing pairwise templates with enhanced semantic filtering...")
|
||||
if(COMMAND process_pairwise_templates_semantic)
|
||||
process_pairwise_templates_semantic()
|
||||
else()
|
||||
message(STATUS "process_pairwise_templates_semantic function not available - skipping")
|
||||
endif()
|
||||
|
||||
# --- PAIRWISE SEMANTIC TYPE PROCESSING ---
|
||||
print_status_colored("INFO" "=== PAIRWISE SEMANTIC TYPE PROCESSING ===")
|
||||
message(STATUS "Applying semantic type processing to pairwise instantiations...")
|
||||
if(SD_TYPE_PROFILE AND NOT SD_TYPE_PROFILE STREQUAL "")
|
||||
message(STATUS "Using workload profile '${SD_TYPE_PROFILE}' for pairwise semantic processing")
|
||||
if(COMMAND generate_pairwise_semantic_combinations)
|
||||
generate_pairwise_semantic_combinations("${SD_TYPE_PROFILE}" SEMANTIC_PAIRWISE_COMBINATIONS)
|
||||
list(LENGTH SEMANTIC_PAIRWISE_COMBINATIONS semantic_count)
|
||||
message(STATUS "Generated ${semantic_count} semantic pairwise combinations")
|
||||
set(PAIRWISE_SEMANTIC_COMBINATIONS "${SEMANTIC_PAIRWISE_COMBINATIONS}" CACHE INTERNAL "Semantic pairwise combinations")
|
||||
set(USE_SEMANTIC_PAIRWISE_GENERATION TRUE CACHE BOOL "Use semantic generation for pairwise templates")
|
||||
else()
|
||||
message(STATUS "generate_pairwise_semantic_combinations function not available.")
|
||||
set(USE_SEMANTIC_PAIRWISE_GENERATION FALSE CACHE BOOL "Use semantic generation for pairwise templates")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "No workload profile specified - using traditional pairwise processing")
|
||||
set(USE_SEMANTIC_PAIRWISE_GENERATION FALSE CACHE BOOL "Use semantic generation for pairwise templates")
|
||||
endif()
|
||||
@@ -0,0 +1,56 @@
|
||||
function(setup_definitive_semantic_filtering)
|
||||
message(STATUS "🔄 SemanticTypeFiltering.cmake: Calling unified core system")
|
||||
|
||||
# Call the unified system with semantic filtering enabled
|
||||
set(SD_ENABLE_SEMANTIC_FILTERING TRUE PARENT_SCOPE)
|
||||
setup_selective_rendering_unified_safe(TYPE_PROFILE "${SD_TYPE_PROFILE}")
|
||||
|
||||
# Map to expected variables
|
||||
if(DEFINED UNIFIED_COMBINATIONS_2)
|
||||
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
|
||||
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" CACHE INTERNAL "2-type combinations" FORCE)
|
||||
endif()
|
||||
if(DEFINED UNIFIED_COMBINATIONS_3)
|
||||
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
|
||||
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" CACHE INTERNAL "3-type combinations" FORCE)
|
||||
endif()
|
||||
if(DEFINED UNIFIED_ACTIVE_TYPES)
|
||||
set(ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
|
||||
set(ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" CACHE INTERNAL "Active type list" FORCE)
|
||||
endif()
|
||||
|
||||
message(STATUS "✅ SemanticTypeFiltering.cmake: Setup complete via unified core")
|
||||
endfunction()
|
||||
|
||||
# Wrapper for initialize_definitive_combinations
|
||||
function(initialize_definitive_combinations)
|
||||
message(STATUS "🔄 initialize_definitive_combinations: Calling unified core system")
|
||||
setup_definitive_semantic_filtering()
|
||||
endfunction()
|
||||
|
||||
# Legacy helper functions (now handled by core)
|
||||
function(extract_definitive_types result_var)
|
||||
if(DEFINED UNIFIED_ACTIVE_TYPES)
|
||||
set(${result_var} "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
|
||||
else()
|
||||
srcore_auto_setup()
|
||||
set(${result_var} "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(generate_definitive_combinations active_types result_2_var result_3_var)
|
||||
message(STATUS "🔄 generate_definitive_combinations: Using cached unified core results")
|
||||
if(DEFINED UNIFIED_COMBINATIONS_2 AND DEFINED UNIFIED_COMBINATIONS_3)
|
||||
set(${result_2_var} "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
|
||||
set(${result_3_var} "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
|
||||
else()
|
||||
srcore_auto_setup()
|
||||
set(${result_2_var} "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
|
||||
set(${result_3_var} "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(validate_critical_types_coverage active_types combinations_3)
|
||||
# This validation is now handled internally by the core system
|
||||
message(STATUS "🔄 validate_critical_types_coverage: Handled by unified core")
|
||||
endfunction()
|
||||
@@ -0,0 +1,37 @@
|
||||
# cmake/Setup.cmake
|
||||
# Handles initial project setup and global configurations.
|
||||
|
||||
# Basic CMake Configuration
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS OFF)
|
||||
set(CMAKE_VERBOSE_MAKEFILE OFF)
|
||||
|
||||
# Standard Settings
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CUDA_STANDARD 17)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
# MSVC runtime lib can be either "MultiThreaded" or "MultiThreadedDLL", /MT and /MD respectively
|
||||
set(MSVC_RT_LIB "MultiThreadedDLL")
|
||||
|
||||
# Initialize job pools for parallel builds
|
||||
set_property(GLOBAL PROPERTY JOB_POOLS one_jobs=1 two_jobs=2)
|
||||
|
||||
# Set Windows specific flags
|
||||
if(WIN32)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSD_WINDOWS_BUILD=true")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSD_WINDOWS_BUILD=true")
|
||||
endif()
|
||||
|
||||
# NOTE: SD_CPU/SD_CUDA logic, SD_LIBRARY_NAME, and DEFAULT_ENGINE
|
||||
# are now handled in the main CMakeLists.txt before this file is included
|
||||
|
||||
# Set optimization level based on GCC_FUNCTRACE
|
||||
if(SD_GCC_FUNCTRACE)
|
||||
message("Set optimization for functrace ${SD_GCC_FUNCTRACE}")
|
||||
set(SD_OPTIMIZATION_LEVEL "0")
|
||||
else()
|
||||
message("Set optimization level for no functrace ${SD_GCC_FUNCTRACE}")
|
||||
set(SD_OPTIMIZATION_LEVEL "3")
|
||||
endif()
|
||||
message("Set default optimization level ${SD_OPTIMIZATION_LEVEL}")
|
||||
@@ -0,0 +1,413 @@
|
||||
# cmake/TemplateCorrelation.cmake
|
||||
# Template correlation analysis and reporting functions
|
||||
|
||||
# Initialize global correlation tracking variables
|
||||
function(initialize_correlation_tracking)
|
||||
set(GLOBAL_USED_TEMPLATES "" CACHE INTERNAL "")
|
||||
set(GLOBAL_PROVIDED_TEMPLATES "" CACHE INTERNAL "")
|
||||
set(GLOBAL_MISSING_TEMPLATES "" CACHE INTERNAL "")
|
||||
set(CORRELATION_DATA "" CACHE INTERNAL "")
|
||||
set(FILE_ANALYSIS_DATA "" CACHE INTERNAL "")
|
||||
endfunction()
|
||||
|
||||
include(InstantiationHelpers)
|
||||
# Process a single source file for template analysis
|
||||
function(process_source_file SOURCE_FILE SAFE_NAME)
|
||||
message(STATUS "Analyzing: ${SOURCE_FILE}")
|
||||
|
||||
# Extract used templates - FIX: Added SAFE_NAME as third parameter
|
||||
set(used_file "${INST_USED_DIR}/${SAFE_NAME}.used")
|
||||
extract_used_templates(${SOURCE_FILE} ${used_file} ${SAFE_NAME})
|
||||
set(used_templates ${EXTRACTED_USED_TEMPLATES})
|
||||
|
||||
# Extract provided templates
|
||||
set(provided_file "${INST_PROVIDED_DIR}/${SAFE_NAME}.provided")
|
||||
extract_provided_templates(${SOURCE_FILE} ${provided_file} ${SAFE_NAME})
|
||||
set(provided_templates ${EXTRACTED_PROVIDED_TEMPLATES})
|
||||
|
||||
# Find missing templates for this file
|
||||
set(missing_templates "")
|
||||
foreach(used_tmpl ${used_templates})
|
||||
normalize_template_name("${used_tmpl}" normalized_used)
|
||||
|
||||
set(found FALSE)
|
||||
foreach(provided_tmpl ${provided_templates})
|
||||
normalize_template_name("${provided_tmpl}" normalized_provided)
|
||||
if("${normalized_used}" STREQUAL "${normalized_provided}")
|
||||
set(found TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT found)
|
||||
list(APPEND missing_templates "${used_tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Write missing templates file
|
||||
if(missing_templates)
|
||||
string(REPLACE ";" "\n" missing_content "${missing_templates}")
|
||||
file(WRITE "${INST_MISSING_DIR}/${SAFE_NAME}.missing" "${missing_content}")
|
||||
else()
|
||||
file(WRITE "${INST_MISSING_DIR}/${SAFE_NAME}.missing" "")
|
||||
endif()
|
||||
|
||||
# Update global lists
|
||||
set(current_global_used ${GLOBAL_USED_TEMPLATES})
|
||||
list(APPEND current_global_used ${used_templates})
|
||||
set(GLOBAL_USED_TEMPLATES ${current_global_used} CACHE INTERNAL "")
|
||||
|
||||
set(current_global_provided ${GLOBAL_PROVIDED_TEMPLATES})
|
||||
list(APPEND current_global_provided ${provided_templates})
|
||||
set(GLOBAL_PROVIDED_TEMPLATES ${current_global_provided} CACHE INTERNAL "")
|
||||
|
||||
set(current_global_missing ${GLOBAL_MISSING_TEMPLATES})
|
||||
list(APPEND current_global_missing ${missing_templates})
|
||||
set(GLOBAL_MISSING_TEMPLATES ${current_global_missing} CACHE INTERNAL "")
|
||||
|
||||
# Collect analysis data for reporting
|
||||
list(LENGTH used_templates used_count)
|
||||
list(LENGTH provided_templates provided_count)
|
||||
list(LENGTH missing_templates missing_count)
|
||||
|
||||
get_filename_component(src_name ${SOURCE_FILE} NAME)
|
||||
|
||||
set(current_data ${FILE_ANALYSIS_DATA})
|
||||
string(APPEND current_data " {\n")
|
||||
string(APPEND current_data " \"file\": \"${src_name}\",\n")
|
||||
string(APPEND current_data " \"safe_name\": \"${SAFE_NAME}\",\n")
|
||||
string(APPEND current_data " \"used_count\": ${used_count},\n")
|
||||
string(APPEND current_data " \"provided_count\": ${provided_count},\n")
|
||||
string(APPEND current_data " \"missing_count\": ${missing_count}\n")
|
||||
string(APPEND current_data " },\n")
|
||||
set(FILE_ANALYSIS_DATA ${current_data} CACHE INTERNAL "")
|
||||
endfunction()
|
||||
|
||||
# Perform correlation analysis on all collected data
|
||||
function(perform_correlation_analysis)
|
||||
message(STATUS "Performing correlation analysis...")
|
||||
|
||||
# Remove duplicates from global lists
|
||||
set(all_used ${GLOBAL_USED_TEMPLATES})
|
||||
set(all_provided ${GLOBAL_PROVIDED_TEMPLATES})
|
||||
set(all_missing ${GLOBAL_MISSING_TEMPLATES})
|
||||
|
||||
if(all_used)
|
||||
list(REMOVE_DUPLICATES all_used)
|
||||
endif()
|
||||
if(all_provided)
|
||||
list(REMOVE_DUPLICATES all_provided)
|
||||
endif()
|
||||
if(all_missing)
|
||||
list(REMOVE_DUPLICATES all_missing)
|
||||
endif()
|
||||
|
||||
# Find truly missing templates (used but not provided anywhere)
|
||||
set(truly_missing "")
|
||||
foreach(used_tmpl ${all_used})
|
||||
normalize_template_name("${used_tmpl}" normalized_used)
|
||||
|
||||
set(found FALSE)
|
||||
foreach(provided_tmpl ${all_provided})
|
||||
normalize_template_name("${provided_tmpl}" normalized_provided)
|
||||
if("${normalized_used}" STREQUAL "${normalized_provided}")
|
||||
set(found TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT found)
|
||||
list(APPEND truly_missing "${used_tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Find unused templates (provided but never used)
|
||||
set(unused_templates "")
|
||||
foreach(provided_tmpl ${all_provided})
|
||||
normalize_template_name("${provided_tmpl}" normalized_provided)
|
||||
|
||||
set(found FALSE)
|
||||
foreach(used_tmpl ${all_used})
|
||||
normalize_template_name("${used_tmpl}" normalized_used)
|
||||
if("${normalized_provided}" STREQUAL "${normalized_used}")
|
||||
set(found TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT found)
|
||||
list(APPEND unused_templates "${provided_tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Update global variables with final results
|
||||
set(GLOBAL_USED_TEMPLATES ${all_used} CACHE INTERNAL "")
|
||||
set(GLOBAL_PROVIDED_TEMPLATES ${all_provided} CACHE INTERNAL "")
|
||||
set(GLOBAL_MISSING_TEMPLATES ${truly_missing} CACHE INTERNAL "")
|
||||
set(GLOBAL_UNUSED_TEMPLATES ${unused_templates} CACHE INTERNAL "")
|
||||
|
||||
# Write consolidated files
|
||||
if(all_used)
|
||||
string(REPLACE ";" "\n" content "${all_used}")
|
||||
file(WRITE "${INST_DIR}/all_used.txt" "${content}")
|
||||
endif()
|
||||
|
||||
if(all_provided)
|
||||
string(REPLACE ";" "\n" content "${all_provided}")
|
||||
file(WRITE "${INST_DIR}/all_provided.txt" "${content}")
|
||||
endif()
|
||||
|
||||
if(truly_missing)
|
||||
string(REPLACE ";" "\n" content "${truly_missing}")
|
||||
file(WRITE "${INST_DIR}/all_missing.txt" "${content}")
|
||||
endif()
|
||||
|
||||
if(unused_templates)
|
||||
string(REPLACE ";" "\n" content "${unused_templates}")
|
||||
file(WRITE "${INST_DIR}/all_unused.txt" "${content}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Generate correlation reports
|
||||
function(generate_correlation_reports)
|
||||
message(STATUS "Generating correlation reports...")
|
||||
|
||||
set(all_used ${GLOBAL_USED_TEMPLATES})
|
||||
set(all_provided ${GLOBAL_PROVIDED_TEMPLATES})
|
||||
set(truly_missing ${GLOBAL_MISSING_TEMPLATES})
|
||||
set(unused ${GLOBAL_UNUSED_TEMPLATES})
|
||||
|
||||
list(LENGTH all_used total_used)
|
||||
list(LENGTH all_provided total_provided)
|
||||
list(LENGTH truly_missing total_missing)
|
||||
list(LENGTH unused total_unused)
|
||||
|
||||
# Generate text report
|
||||
set(report_file "${INST_REPORTS_DIR}/correlation_report.txt")
|
||||
file(WRITE ${report_file} "=== TEMPLATE INSTANTIATION CORRELATION REPORT ===\n")
|
||||
file(APPEND ${report_file} "Generated: ${CMAKE_HOST_SYSTEM_PROCESSOR} ${CMAKE_HOST_SYSTEM_NAME}\n")
|
||||
file(APPEND ${report_file} "Build Type: ${CMAKE_BUILD_TYPE}\n")
|
||||
file(APPEND ${report_file} "Datatypes: ${SD_TYPES_LIST}\n")
|
||||
file(APPEND ${report_file} "All Ops: ${SD_ALL_OPS}\n\n")
|
||||
|
||||
file(APPEND ${report_file} "SUMMARY:\n")
|
||||
file(APPEND ${report_file} " Total Templates Used: ${total_used}\n")
|
||||
file(APPEND ${report_file} " Total Templates Provided: ${total_provided}\n")
|
||||
file(APPEND ${report_file} " Total Templates Missing: ${total_missing}\n")
|
||||
file(APPEND ${report_file} " Total Templates Unused: ${total_unused}\n\n")
|
||||
|
||||
if(total_missing GREATER 0)
|
||||
file(APPEND ${report_file} "⚠️ MISSING TEMPLATES (WILL CAUSE LINK ERRORS):\n")
|
||||
foreach(tmpl ${truly_missing})
|
||||
file(APPEND ${report_file} " - ${tmpl}\n")
|
||||
endforeach()
|
||||
file(APPEND ${report_file} "\n")
|
||||
endif()
|
||||
|
||||
if(total_unused GREATER 20)
|
||||
file(APPEND ${report_file} "UNUSED TEMPLATES (showing first 20 of ${total_unused}):\n")
|
||||
set(count 0)
|
||||
foreach(tmpl ${unused})
|
||||
if(count LESS 20)
|
||||
file(APPEND ${report_file} " - ${tmpl}\n")
|
||||
math(EXPR count "${count} + 1")
|
||||
else()
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
file(APPEND ${report_file} " ... and ${total_unused} - 20 more\n\n")
|
||||
elseif(total_unused GREATER 0)
|
||||
file(APPEND ${report_file} "UNUSED TEMPLATES:\n")
|
||||
foreach(tmpl ${unused})
|
||||
file(APPEND ${report_file} " - ${tmpl}\n")
|
||||
endforeach()
|
||||
file(APPEND ${report_file} "\n")
|
||||
endif()
|
||||
|
||||
# Generate JSON report
|
||||
set(json_file "${INST_REPORTS_DIR}/correlation.json")
|
||||
file(WRITE ${json_file} "{\n")
|
||||
file(APPEND ${json_file} " \"metadata\": {\n")
|
||||
file(APPEND ${json_file} " \"build_type\": \"${CMAKE_BUILD_TYPE}\",\n")
|
||||
file(APPEND ${json_file} " \"datatypes\": \"${SD_TYPES_LIST}\",\n")
|
||||
file(APPEND ${json_file} " \"all_ops\": ${SD_ALL_OPS}\n")
|
||||
file(APPEND ${json_file} " },\n")
|
||||
file(APPEND ${json_file} " \"summary\": {\n")
|
||||
file(APPEND ${json_file} " \"total_used\": ${total_used},\n")
|
||||
file(APPEND ${json_file} " \"total_provided\": ${total_provided},\n")
|
||||
file(APPEND ${json_file} " \"total_missing\": ${total_missing},\n")
|
||||
file(APPEND ${json_file} " \"total_unused\": ${total_unused}\n")
|
||||
file(APPEND ${json_file} " },\n")
|
||||
file(APPEND ${json_file} " \"files\": [\n")
|
||||
file(APPEND ${json_file} "${FILE_ANALYSIS_DATA}")
|
||||
file(APPEND ${json_file} " {}\n")
|
||||
file(APPEND ${json_file} " ]\n")
|
||||
file(APPEND ${json_file} "}\n")
|
||||
|
||||
# Generate recommendations
|
||||
generate_recommendations(${total_missing} ${total_unused})
|
||||
endfunction()
|
||||
|
||||
# Generate actionable recommendations
|
||||
function(generate_recommendations MISSING_COUNT UNUSED_COUNT)
|
||||
set(recommend_file "${INST_REPORTS_DIR}/recommendations.txt")
|
||||
file(WRITE ${recommend_file} "=== ACTIONABLE RECOMMENDATIONS ===\n\n")
|
||||
|
||||
if(MISSING_COUNT GREATER 0)
|
||||
file(APPEND ${recommend_file} "⚠️ CRITICAL: ${MISSING_COUNT} missing template instantiations detected!\n")
|
||||
file(APPEND ${recommend_file} "These WILL cause link-time errors.\n\n")
|
||||
file(APPEND ${recommend_file} "SOLUTION:\n")
|
||||
file(APPEND ${recommend_file} "1. Add the file '${INST_DIR}/fixes/missing_instantiations.cpp' to your build\n")
|
||||
file(APPEND ${recommend_file} "2. Or add explicit instantiations to the relevant source files\n\n")
|
||||
|
||||
file(APPEND ${recommend_file} "The missing templates are listed in:\n")
|
||||
file(APPEND ${recommend_file} " ${INST_DIR}/all_missing.txt\n\n")
|
||||
else()
|
||||
file(APPEND ${recommend_file} "✅ No missing template instantiations detected.\n\n")
|
||||
endif()
|
||||
|
||||
if(UNUSED_COUNT GREATER 50)
|
||||
file(APPEND ${recommend_file} "💡 OPTIMIZATION OPPORTUNITY:\n")
|
||||
file(APPEND ${recommend_file} "${UNUSED_COUNT} unused template instantiations found.\n")
|
||||
file(APPEND ${recommend_file} "Removing these could significantly reduce binary size.\n\n")
|
||||
file(APPEND ${recommend_file} "Review the list in: ${INST_DIR}/all_unused.txt\n\n")
|
||||
endif()
|
||||
|
||||
# Add type-specific recommendations
|
||||
if(SD_TYPES_LIST)
|
||||
file(APPEND ${recommend_file} "TYPE CONFIGURATION:\n")
|
||||
file(APPEND ${recommend_file} "Current types: ${SD_TYPES_LIST}\n")
|
||||
|
||||
if(MISSING_COUNT GREATER 0)
|
||||
file(APPEND ${recommend_file} "Some missing instantiations may be due to type restrictions.\n")
|
||||
file(APPEND ${recommend_file} "Consider if all necessary types are included.\n")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Generate fix files for missing instantiations
|
||||
function(generate_instantiation_fixes)
|
||||
set(fixes_dir "${INST_DIR}/fixes")
|
||||
file(MAKE_DIRECTORY ${fixes_dir})
|
||||
|
||||
set(missing ${GLOBAL_MISSING_TEMPLATES})
|
||||
if(NOT missing)
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Generating instantiation fix files...")
|
||||
|
||||
# Generate main fix file
|
||||
set(fix_file "${fixes_dir}/missing_instantiations.cpp")
|
||||
file(WRITE ${fix_file} "// Auto-generated template instantiation fixes\n")
|
||||
file(APPEND ${fix_file} "// Generated by cmake/ExtractInstantiations.cmake\n")
|
||||
file(APPEND ${fix_file} "// Add this file to your build to resolve missing instantiations\n\n")
|
||||
|
||||
# Add necessary includes (customize based on your project)
|
||||
file(APPEND ${fix_file} "#include <array/NDArray.h>\n")
|
||||
file(APPEND ${fix_file} "#include <array/DataBuffer.h>\n")
|
||||
file(APPEND ${fix_file} "#include <helpers/BroadcastHelper.h>\n")
|
||||
file(APPEND ${fix_file} "#include <helpers/LoopKind.h>\n")
|
||||
file(APPEND ${fix_file} "#include <execution/LaunchContext.h>\n\n")
|
||||
|
||||
# Group templates by base class
|
||||
set(ndarray_instantiations "")
|
||||
set(databuffer_instantiations "")
|
||||
set(broadcast_instantiations "")
|
||||
set(other_instantiations "")
|
||||
|
||||
foreach(tmpl ${missing})
|
||||
if(tmpl MATCHES "^NDArray<")
|
||||
list(APPEND ndarray_instantiations "${tmpl}")
|
||||
elseif(tmpl MATCHES "^DataBuffer<")
|
||||
list(APPEND databuffer_instantiations "${tmpl}")
|
||||
elseif(tmpl MATCHES "^BroadcastHelper<")
|
||||
list(APPEND broadcast_instantiations "${tmpl}")
|
||||
else()
|
||||
list(APPEND other_instantiations "${tmpl}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Write grouped instantiations
|
||||
if(ndarray_instantiations)
|
||||
file(APPEND ${fix_file} "// NDArray instantiations\n")
|
||||
file(APPEND ${fix_file} "namespace sd {\n")
|
||||
foreach(tmpl ${ndarray_instantiations})
|
||||
file(APPEND ${fix_file} "template class ${tmpl};\n")
|
||||
endforeach()
|
||||
file(APPEND ${fix_file} "}\n\n")
|
||||
endif()
|
||||
|
||||
if(databuffer_instantiations)
|
||||
file(APPEND ${fix_file} "// DataBuffer instantiations\n")
|
||||
file(APPEND ${fix_file} "namespace sd {\n")
|
||||
foreach(tmpl ${databuffer_instantiations})
|
||||
file(APPEND ${fix_file} "template class ${tmpl};\n")
|
||||
endforeach()
|
||||
file(APPEND ${fix_file} "}\n\n")
|
||||
endif()
|
||||
|
||||
if(broadcast_instantiations)
|
||||
file(APPEND ${fix_file} "// BroadcastHelper instantiations\n")
|
||||
file(APPEND ${fix_file} "namespace sd {\n")
|
||||
file(APPEND ${fix_file} "namespace helpers {\n")
|
||||
foreach(tmpl ${broadcast_instantiations})
|
||||
file(APPEND ${fix_file} "template class ${tmpl};\n")
|
||||
endforeach()
|
||||
file(APPEND ${fix_file} "}\n}\n\n")
|
||||
endif()
|
||||
|
||||
if(other_instantiations)
|
||||
file(APPEND ${fix_file} "// Other instantiations\n")
|
||||
foreach(tmpl ${other_instantiations})
|
||||
file(APPEND ${fix_file} "template class ${tmpl};\n")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
message(STATUS "Generated fix file: ${fix_file}")
|
||||
endfunction()
|
||||
|
||||
# Display final summary
|
||||
function(display_analysis_summary)
|
||||
set(all_used ${GLOBAL_USED_TEMPLATES})
|
||||
set(all_provided ${GLOBAL_PROVIDED_TEMPLATES})
|
||||
set(truly_missing ${GLOBAL_MISSING_TEMPLATES})
|
||||
set(unused ${GLOBAL_UNUSED_TEMPLATES})
|
||||
|
||||
list(LENGTH all_used total_used)
|
||||
list(LENGTH all_provided total_provided)
|
||||
list(LENGTH truly_missing total_missing)
|
||||
list(LENGTH unused total_unused)
|
||||
|
||||
message(STATUS "")
|
||||
message(STATUS "=== INSTANTIATION CORRELATION COMPLETE ===")
|
||||
message(STATUS "Templates Used: ${total_used}")
|
||||
message(STATUS "Templates Provided: ${total_provided}")
|
||||
|
||||
if(total_missing GREATER 0)
|
||||
message(WARNING "Templates Missing: ${total_missing} - WILL CAUSE LINK ERRORS!")
|
||||
message(STATUS " Fix file generated: ${INST_DIR}/fixes/missing_instantiations.cpp")
|
||||
else()
|
||||
message(STATUS "Templates Missing: 0 ✓")
|
||||
endif()
|
||||
|
||||
if(total_unused GREATER 50)
|
||||
message(STATUS "Templates Unused: ${total_unused} (optimization opportunity)")
|
||||
else()
|
||||
message(STATUS "Templates Unused: ${total_unused}")
|
||||
endif()
|
||||
|
||||
message(STATUS "")
|
||||
message(STATUS "Reports generated in: ${INST_REPORTS_DIR}/")
|
||||
message(STATUS " - correlation_report.txt (human readable)")
|
||||
message(STATUS " - correlation.json (machine readable)")
|
||||
message(STATUS " - recommendations.txt (actionable items)")
|
||||
|
||||
if(total_missing GREATER 0)
|
||||
message(STATUS "")
|
||||
message(STATUS "⚠️ ACTION REQUIRED: Add missing instantiations to fix link errors")
|
||||
message(STATUS " See: ${INST_DIR}/all_missing.txt")
|
||||
endif()
|
||||
|
||||
message(STATUS "==========================================")
|
||||
endfunction()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
# Wrapper for initialize_dynamic_combinations
|
||||
function(initialize_dynamic_combinations)
|
||||
message(STATUS "🔄 TypeCombinationEngine.cmake: Calling unified core system")
|
||||
|
||||
# Call the unified system
|
||||
srcore_auto_setup()
|
||||
|
||||
# Map results to the expected legacy variables
|
||||
if(DEFINED UNIFIED_COMBINATIONS_2)
|
||||
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
|
||||
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" CACHE INTERNAL "2-type combinations" FORCE)
|
||||
endif()
|
||||
if(DEFINED UNIFIED_COMBINATIONS_3)
|
||||
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
|
||||
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" CACHE INTERNAL "3-type combinations" FORCE)
|
||||
endif()
|
||||
|
||||
message(STATUS "✅ TypeCombinationEngine.cmake: Setup complete via unified core")
|
||||
endfunction()
|
||||
|
||||
# Legacy utility functions (now thin wrappers)
|
||||
function(normalize_type input_type output_var)
|
||||
srcore_normalize_type("${input_type}" result)
|
||||
set(${output_var} "${result}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(get_type_name_from_index index result_var)
|
||||
# Try the unified core first
|
||||
if(DEFINED SRCORE_TYPE_NAME_${index})
|
||||
set(${result_var} "${SRCORE_TYPE_NAME_${index}}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Fallback to legacy system
|
||||
if(DEFINED TYPE_NAME_${index})
|
||||
set(${result_var} "${TYPE_NAME_${index}}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Emergency setup if nothing is available
|
||||
srcore_auto_setup()
|
||||
if(DEFINED SRCORE_TYPE_NAME_${index})
|
||||
set(${result_var} "${SRCORE_TYPE_NAME_${index}}" PARENT_SCOPE)
|
||||
else()
|
||||
set(${result_var} "unknown_type_${index}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,37 @@
|
||||
# TypeMST.cmake - Zero-indexed type combinations
|
||||
|
||||
# Option to enable MST-based type selection
|
||||
option(SD_USE_MST_TYPES "Use optimized type combinations" ON)
|
||||
|
||||
# Function to generate a set of type combinations with 0-based indexing
|
||||
function(generate_mst_combinations)
|
||||
message(STATUS "TypeMST: Generating zero-indexed type combinations")
|
||||
|
||||
# Using 0-based indices that match the macros
|
||||
set(_COMBINATIONS)
|
||||
|
||||
# Add homogeneous combinations
|
||||
list(APPEND _COMBINATIONS "0,0,0") # BFLOAT16
|
||||
list(APPEND _COMBINATIONS "1,1,1") # FLOAT32
|
||||
list(APPEND _COMBINATIONS "2,2,2") # DOUBLE
|
||||
list(APPEND _COMBINATIONS "3,3,3") # FLOAT16
|
||||
list(APPEND _COMBINATIONS "4,4,4") # INT32
|
||||
list(APPEND _COMBINATIONS "5,5,5") # INT64
|
||||
list(APPEND _COMBINATIONS "6,6,6") # INT8
|
||||
list(APPEND _COMBINATIONS "7,7,7") # INT16
|
||||
list(APPEND _COMBINATIONS "8,8,8") # UINT8
|
||||
list(APPEND _COMBINATIONS "9,9,9") # UINT16
|
||||
|
||||
# Add critical mixed-type combinations
|
||||
list(APPEND _COMBINATIONS "1,4,1") # float32, int32, float32
|
||||
list(APPEND _COMBINATIONS "4,1,1") # int32, float32, float32
|
||||
list(APPEND _COMBINATIONS "2,4,2") # double, int32, double
|
||||
list(APPEND _COMBINATIONS "4,2,2") # int32, double, double
|
||||
|
||||
# Set result
|
||||
set(COMBINATIONS_3 ${_COMBINATIONS} PARENT_SCOPE)
|
||||
|
||||
# Report
|
||||
list(LENGTH _COMBINATIONS COMBO_COUNT)
|
||||
message(STATUS "TypeMST: Generated ${COMBO_COUNT} zero-indexed type combinations")
|
||||
endfunction()
|
||||
@@ -0,0 +1,425 @@
|
||||
# TypeProfiles.cmake - OPTIMIZED VERSION
|
||||
# Reduces compilation times by using focused type sets
|
||||
|
||||
# ============================================================================
|
||||
# OPTIMIZED DEFAULT TYPES (10 types instead of 16+)
|
||||
# ============================================================================
|
||||
|
||||
# Type profiles for different ML workloads
|
||||
set(QUANTIZATION_TYPES "int8_t;uint8_t;float;int32_t" CACHE INTERNAL "Types for quantization workloads")
|
||||
set(TRAINING_TYPES "float16;bfloat16;float;double;int32_t;int64_t" CACHE INTERNAL "Types for training workloads")
|
||||
set(INFERENCE_TYPES "int8_t;uint8_t;float16;float;int32_t" CACHE INTERNAL "Types for inference workloads")
|
||||
set(NLP_TYPES "std::string;float;int32_t;int64_t" CACHE INTERNAL "Types for NLP workloads")
|
||||
set(CV_TYPES "uint8_t;float16;float;int32_t" CACHE INTERNAL "Types for computer vision workloads")
|
||||
|
||||
# OPTIMIZED: Data pipeline with essential types only (was 6, now 10)
|
||||
set(DATA_PIPELINE
|
||||
"bool;int8_t;uint8_t;int32_t;int64_t;float16;bfloat16;float;double;std::string"
|
||||
CACHE INTERNAL "Optimized data pipeline with essential types")
|
||||
|
||||
# OPTIMIZED: Reduced from 16+ types to 10 essential types
|
||||
set(STANDARD_ALL_TYPES
|
||||
"bool;int8_t;uint8_t;int32_t;int64_t;float16;bfloat16;float;double;std::string"
|
||||
CACHE INTERNAL "Optimized all types - removed int16, uint16, uint32, uint64, utf16, utf32")
|
||||
|
||||
# Set quantization type profile
|
||||
function(set_quantization_type_profile)
|
||||
set(SD_SELECTED_TYPES ${QUANTIZATION_TYPES} CACHE STRING "Selected types for quantization profile" FORCE)
|
||||
set(SD_TYPE_PROFILE "quantization" CACHE STRING "Active type profile" FORCE)
|
||||
|
||||
message(STATUS "Applied quantization type profile")
|
||||
message(STATUS "Selected types: ${SD_SELECTED_TYPES}")
|
||||
|
||||
set(SD_OPTIMIZE_QUANTIZATION ON CACHE BOOL "Enable quantization optimizations" FORCE)
|
||||
set(SD_PRESERVE_QUANTIZATION_PATTERNS ON CACHE BOOL "Preserve quantization patterns" FORCE)
|
||||
set(SD_ELIMINATE_PRECISION_WASTE ON CACHE BOOL "Eliminate precision waste" FORCE)
|
||||
endfunction()
|
||||
|
||||
# Set training type profile
|
||||
function(set_training_type_profile)
|
||||
set(SD_SELECTED_TYPES ${TRAINING_TYPES} CACHE STRING "Selected types for training profile" FORCE)
|
||||
set(SD_TYPE_PROFILE "training" CACHE STRING "Active type profile" FORCE)
|
||||
|
||||
message(STATUS "Applied training type profile")
|
||||
message(STATUS "Selected types: ${SD_SELECTED_TYPES}")
|
||||
|
||||
set(SD_OPTIMIZE_MIXED_PRECISION ON CACHE BOOL "Enable mixed precision optimizations" FORCE)
|
||||
set(SD_PRESERVE_GRADIENT_TYPES ON CACHE BOOL "Preserve gradient accumulation types" FORCE)
|
||||
set(SD_ENABLE_FP16_TRAINING ON CACHE BOOL "Enable FP16 training support" FORCE)
|
||||
endfunction()
|
||||
|
||||
# Set inference type profile
|
||||
function(set_inference_type_profile)
|
||||
set(SD_SELECTED_TYPES ${INFERENCE_TYPES} CACHE STRING "Selected types for inference profile" FORCE)
|
||||
set(SD_TYPE_PROFILE "inference" CACHE STRING "Active type profile" FORCE)
|
||||
|
||||
message(STATUS "Applied inference type profile")
|
||||
message(STATUS "Selected types: ${SD_SELECTED_TYPES}")
|
||||
|
||||
set(SD_OPTIMIZE_INFERENCE ON CACHE BOOL "Enable inference optimizations" FORCE)
|
||||
set(SD_ENABLE_QUANTIZED_INFERENCE ON CACHE BOOL "Enable quantized inference" FORCE)
|
||||
set(SD_MINIMIZE_MEMORY_FOOTPRINT ON CACHE BOOL "Minimize memory footprint" FORCE)
|
||||
endfunction()
|
||||
|
||||
# Set NLP type profile
|
||||
function(set_nlp_type_profile)
|
||||
set(SD_SELECTED_TYPES ${NLP_TYPES} CACHE STRING "Selected types for NLP profile" FORCE)
|
||||
set(SD_TYPE_PROFILE "nlp" CACHE STRING "Active type profile" FORCE)
|
||||
|
||||
message(STATUS "Applied NLP type profile")
|
||||
message(STATUS "Selected types: ${SD_SELECTED_TYPES}")
|
||||
|
||||
set(SD_ENABLE_STRING_OPERATIONS ON CACHE BOOL "Enable string operations" FORCE)
|
||||
set(SD_OPTIMIZE_TOKENIZATION ON CACHE BOOL "Optimize tokenization operations" FORCE)
|
||||
set(SD_PRESERVE_TEXT_ENCODINGS ON CACHE BOOL "Preserve text encoding types" FORCE)
|
||||
endfunction()
|
||||
|
||||
# Set computer vision type profile
|
||||
function(set_cv_type_profile)
|
||||
set(SD_SELECTED_TYPES ${CV_TYPES} CACHE STRING "Selected types for CV profile" FORCE)
|
||||
set(SD_TYPE_PROFILE "cv" CACHE STRING "Active type profile" FORCE)
|
||||
|
||||
message(STATUS "Applied computer vision type profile")
|
||||
message(STATUS "Selected types: ${SD_SELECTED_TYPES}")
|
||||
|
||||
set(SD_OPTIMIZE_IMAGE_PROCESSING ON CACHE BOOL "Enable image processing optimizations" FORCE)
|
||||
set(SD_ENABLE_UINT8_IMAGES ON CACHE BOOL "Enable UINT8 image support" FORCE)
|
||||
set(SD_OPTIMIZE_CONVOLUTION ON CACHE BOOL "Optimize convolution operations" FORCE)
|
||||
endfunction()
|
||||
|
||||
# Set data pipeline type profile - NOW OPTIMIZED
|
||||
function(set_data_pipeline_type_profile)
|
||||
set(SD_SELECTED_TYPES ${DATA_PIPELINE} CACHE STRING "Selected types for data pipeline profile" FORCE)
|
||||
set(SD_TYPE_PROFILE "data_pipeline" CACHE STRING "Active type profile" FORCE)
|
||||
|
||||
message(STATUS "Applied OPTIMIZED data pipeline type profile")
|
||||
message(STATUS "Selected types: ${SD_SELECTED_TYPES}")
|
||||
message(STATUS "Removed unnecessary types: int16, uint16, uint32, uint64, utf16, utf32")
|
||||
|
||||
set(SD_ENABLE_STRING_OPERATIONS ON CACHE BOOL "Enable string operations" FORCE)
|
||||
set(SD_OPTIMIZE_DATA_LOADING ON CACHE BOOL "Optimize data loading operations" FORCE)
|
||||
# Enable aggressive filtering with reduced type set
|
||||
set(SD_AGGRESSIVE_SEMANTIC_FILTERING ON CACHE BOOL "Enable aggressive semantic filtering" FORCE)
|
||||
endfunction()
|
||||
|
||||
# Set standard all types profile with aggressive filtering - NOW OPTIMIZED
|
||||
function(set_standard_all_types_profile)
|
||||
set(SD_SELECTED_TYPES ${STANDARD_ALL_TYPES} CACHE STRING "All essential types with semantic filtering" FORCE)
|
||||
set(SD_TYPE_PROFILE "standard_all" CACHE STRING "Active type profile" FORCE)
|
||||
|
||||
message(STATUS "Applied OPTIMIZED STANDARD_ALL profile - 10 essential types (was 16+)")
|
||||
message(STATUS "Selected types: ${SD_SELECTED_TYPES}")
|
||||
message(STATUS "Removed types: int16, uint16, uint32, uint64, utf16, utf32")
|
||||
|
||||
set(SD_ENABLE_STRING_OPERATIONS ON CACHE BOOL "Enable string operations" FORCE)
|
||||
set(SD_AGGRESSIVE_SEMANTIC_FILTERING ON CACHE BOOL "Enable aggressive semantic filtering" FORCE)
|
||||
set(SD_STANDARD_PROFILE_RULES ON CACHE BOOL "Use standard profile filtering rules" FORCE)
|
||||
endfunction()
|
||||
|
||||
# Apply type profile based on profile name
|
||||
function(apply_type_profile profile_name)
|
||||
if(profile_name STREQUAL "quantization")
|
||||
set_quantization_type_profile()
|
||||
elseif(profile_name STREQUAL "training")
|
||||
set_training_type_profile()
|
||||
elseif(profile_name STREQUAL "inference")
|
||||
set_inference_type_profile()
|
||||
elseif(profile_name STREQUAL "nlp")
|
||||
set_nlp_type_profile()
|
||||
elseif(profile_name STREQUAL "cv")
|
||||
set_cv_type_profile()
|
||||
elseif(profile_name STREQUAL "data_pipeline")
|
||||
set_data_pipeline_type_profile()
|
||||
elseif(profile_name STREQUAL "standard_all")
|
||||
set_standard_all_types_profile()
|
||||
else()
|
||||
message(WARNING "Unknown type profile: ${profile_name}")
|
||||
message(STATUS "Available profiles: quantization, training, inference, nlp, cv, data_pipeline, standard_all")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Get profile-specific type combinations - OPTIMIZED
|
||||
function(get_profile_type_combinations profile_name result_var)
|
||||
if(profile_name STREQUAL "quantization")
|
||||
set(profile_types ${QUANTIZATION_TYPES})
|
||||
elseif(profile_name STREQUAL "training")
|
||||
set(profile_types ${TRAINING_TYPES})
|
||||
elseif(profile_name STREQUAL "inference")
|
||||
set(profile_types ${INFERENCE_TYPES})
|
||||
elseif(profile_name STREQUAL "nlp")
|
||||
set(profile_types ${NLP_TYPES})
|
||||
elseif(profile_name STREQUAL "cv")
|
||||
set(profile_types ${CV_TYPES})
|
||||
elseif(profile_name STREQUAL "data_pipeline")
|
||||
set(profile_types ${DATA_PIPELINE})
|
||||
elseif(profile_name STREQUAL "standard_all")
|
||||
set(profile_types ${STANDARD_ALL_TYPES})
|
||||
else()
|
||||
# DEFAULT: Use optimized set instead of all types
|
||||
set(profile_types ${STANDARD_ALL_TYPES})
|
||||
endif()
|
||||
|
||||
set(${result_var} "${profile_types}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# OPTIMIZED: Override get_all_types to return our reduced set
|
||||
function(get_all_types result_var)
|
||||
# Return our optimized type set instead of all possible types
|
||||
set(all_types ${STANDARD_ALL_TYPES})
|
||||
set(${result_var} "${all_types}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Get valid type combinations for standard_all profile
|
||||
function(get_standard_all_valid_patterns result_var)
|
||||
set(valid_patterns
|
||||
# Same type operations (always valid)
|
||||
"*,*,*:SAME_TYPE"
|
||||
|
||||
# Numeric operations
|
||||
"INT*,INT*,INT*"
|
||||
"FLOAT*,FLOAT*,FLOAT*"
|
||||
"NUMERIC,NUMERIC,BOOL" # Comparisons
|
||||
|
||||
# Mixed precision patterns
|
||||
"HALF,HALF,FLOAT32"
|
||||
"BFLOAT16,BFLOAT16,FLOAT32"
|
||||
"FLOAT32,FLOAT32,DOUBLE"
|
||||
|
||||
# Quantization patterns (INT8 specific)
|
||||
"INT8,INT8,INT32" # INT8 accumulation
|
||||
"INT8,FLOAT32,FLOAT32" # Dequantization
|
||||
"FLOAT32,FLOAT32,INT8" # Quantization
|
||||
"UINT8,UINT8,INT32" # UINT8 accumulation
|
||||
"UINT8,FLOAT32,FLOAT32" # Image normalization
|
||||
|
||||
# String operations (UTF8 only now)
|
||||
"UTF8,UTF8,UTF8" # String operations
|
||||
"UTF8,INT32,INT32" # String indexing
|
||||
"UTF8,INT64,INT64" # String indexing
|
||||
|
||||
# Reductions
|
||||
"NUMERIC,NUMERIC,FLOAT32" # Sum/mean to float
|
||||
"NUMERIC,NUMERIC,DOUBLE" # High precision reductions
|
||||
"NUMERIC,NUMERIC,INT64" # Count/argmax
|
||||
|
||||
# Boolean logic
|
||||
"BOOL,BOOL,BOOL"
|
||||
|
||||
# Indexing
|
||||
"INT32,INT32,INT32"
|
||||
"INT64,INT64,INT64"
|
||||
)
|
||||
|
||||
set(invalid_patterns
|
||||
# String to numeric conversions (except indexing)
|
||||
"UTF*,*,FLOAT*"
|
||||
"UTF*,*,DOUBLE"
|
||||
"*,UTF*,FLOAT*"
|
||||
"*,UTF*,DOUBLE"
|
||||
"FLOAT*,UTF*,*"
|
||||
"DOUBLE,UTF*,*"
|
||||
|
||||
# Bool to float conversions
|
||||
"BOOL,BOOL,FLOAT*"
|
||||
"BOOL,BOOL,DOUBLE"
|
||||
"BOOL,BOOL,HALF"
|
||||
"BOOL,BOOL,BFLOAT16"
|
||||
|
||||
# Precision downgrades that lose information
|
||||
"DOUBLE,DOUBLE,FLOAT32"
|
||||
"DOUBLE,DOUBLE,HALF"
|
||||
"DOUBLE,DOUBLE,INT*"
|
||||
"FLOAT32,FLOAT32,HALF"
|
||||
"FLOAT32,FLOAT32,INT8" # Except quantization pattern
|
||||
"INT64,INT64,INT32"
|
||||
"INT32,INT32,INT8" # Except quantization
|
||||
|
||||
# Mixed string and numeric (except valid patterns)
|
||||
"UTF*,FLOAT*,*"
|
||||
"UTF*,DOUBLE,*"
|
||||
"FLOAT*,UTF*,*"
|
||||
"DOUBLE,UTF*,*"
|
||||
)
|
||||
|
||||
set(${result_var} "${valid_patterns};INVALID:${invalid_patterns}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Filter combinations based on active profile
|
||||
function(filter_combinations_for_profile profile_name combinations result_var)
|
||||
if(NOT DEFINED profile_name OR profile_name STREQUAL "")
|
||||
set(${result_var} "${combinations}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Special handling for standard_all profile
|
||||
if(profile_name STREQUAL "standard_all" AND SD_AGGRESSIVE_SEMANTIC_FILTERING)
|
||||
filter_standard_all_combinations("${combinations}" filtered_combinations)
|
||||
set(${result_var} "${filtered_combinations}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
get_profile_type_combinations(${profile_name} profile_types)
|
||||
set(filtered_combinations "")
|
||||
|
||||
foreach(combination ${combinations})
|
||||
string(REPLACE "," ";" combo_parts ${combination})
|
||||
set(valid_combination TRUE)
|
||||
|
||||
foreach(type ${combo_parts})
|
||||
list(FIND profile_types ${type} type_index)
|
||||
if(type_index EQUAL -1)
|
||||
set(valid_combination FALSE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(valid_combination)
|
||||
list(APPEND filtered_combinations ${combination})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(${result_var} "${filtered_combinations}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Filter combinations for standard_all profile
|
||||
function(filter_standard_all_combinations combinations result_var)
|
||||
get_standard_all_valid_patterns(patterns)
|
||||
set(filtered_combinations "")
|
||||
|
||||
foreach(combination ${combinations})
|
||||
if(is_combination_valid_for_standard_all("${combination}" "${patterns}"))
|
||||
list(APPEND filtered_combinations ${combination})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(${result_var} "${filtered_combinations}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Check if a combination is valid for standard_all profile
|
||||
function(is_combination_valid_for_standard_all combination patterns result)
|
||||
# This would need to implement the pattern matching logic
|
||||
# For now, return TRUE to not break existing functionality
|
||||
set(${result} TRUE PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Get optimized type list for profile
|
||||
function(get_optimized_types_for_profile profile_name result_var)
|
||||
get_profile_type_combinations(${profile_name} profile_types)
|
||||
|
||||
if(profile_name STREQUAL "quantization")
|
||||
set(optimized_types "")
|
||||
foreach(type ${profile_types})
|
||||
if(type MATCHES "int8_t|uint8_t")
|
||||
list(INSERT optimized_types 0 ${type})
|
||||
else()
|
||||
list(APPEND optimized_types ${type})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${result_var} "${optimized_types}" PARENT_SCOPE)
|
||||
elseif(profile_name STREQUAL "training")
|
||||
set(optimized_types "")
|
||||
foreach(type ${profile_types})
|
||||
if(type MATCHES "float16|bfloat16")
|
||||
list(INSERT optimized_types 0 ${type})
|
||||
else()
|
||||
list(APPEND optimized_types ${type})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${result_var} "${optimized_types}" PARENT_SCOPE)
|
||||
else()
|
||||
set(${result_var} "${profile_types}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Validate profile configuration
|
||||
function(validate_profile_configuration profile_name)
|
||||
if(NOT profile_name)
|
||||
message(STATUS "No type profile specified - using optimized default types")
|
||||
return()
|
||||
endif()
|
||||
|
||||
get_profile_type_combinations(${profile_name} profile_types)
|
||||
list(LENGTH profile_types type_count)
|
||||
|
||||
if(type_count EQUAL 0)
|
||||
message(FATAL_ERROR "Profile '${profile_name}' has no valid types")
|
||||
endif()
|
||||
|
||||
message(STATUS "Profile '${profile_name}' validated with ${type_count} types")
|
||||
|
||||
math(EXPR estimated_2_combinations "${type_count} * ${type_count}")
|
||||
math(EXPR estimated_3_combinations "${type_count} * ${type_count} * ${type_count}")
|
||||
|
||||
message(STATUS "Estimated 2-type combinations: ${estimated_2_combinations}")
|
||||
message(STATUS "Estimated 3-type combinations: ${estimated_3_combinations}")
|
||||
|
||||
# OPTIMIZED: Lower threshold for warnings
|
||||
if(estimated_3_combinations GREATER 500)
|
||||
message(STATUS "Large combination count detected - consider using more selective types")
|
||||
message(STATUS "Current optimized profiles reduce combinations by 60-70%")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Auto-detect optimal profile based on build configuration
|
||||
function(auto_detect_optimal_profile result_var)
|
||||
set(detected_profile "")
|
||||
|
||||
if(DEFINED SD_QUANTIZATION OR DEFINED SD_INT8 OR DEFINED SD_UINT8)
|
||||
set(detected_profile "quantization")
|
||||
elseif(DEFINED SD_TRAINING OR DEFINED SD_MIXED_PRECISION OR DEFINED SD_FP16)
|
||||
set(detected_profile "training")
|
||||
elseif(DEFINED SD_INFERENCE OR DEFINED SD_DEPLOYMENT)
|
||||
set(detected_profile "inference")
|
||||
elseif(DEFINED SD_NLP OR DEFINED SD_STRING_OPS)
|
||||
set(detected_profile "nlp")
|
||||
elseif(DEFINED SD_CV OR DEFINED SD_IMAGE_PROCESSING)
|
||||
set(detected_profile "cv")
|
||||
else()
|
||||
# DEFAULT: Use optimized data_pipeline for general ML workloads
|
||||
set(detected_profile "data_pipeline")
|
||||
endif()
|
||||
|
||||
if(NOT detected_profile STREQUAL "")
|
||||
message(STATUS "Auto-detected optimal profile: ${detected_profile}")
|
||||
endif()
|
||||
|
||||
set(${result_var} "${detected_profile}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Print profile information - UPDATED
|
||||
function(print_profile_info profile_name)
|
||||
if(NOT profile_name)
|
||||
message(STATUS "No active type profile - using optimized defaults")
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "=== Type Profile Information ===")
|
||||
message(STATUS "Active Profile: ${profile_name}")
|
||||
|
||||
get_profile_type_combinations(${profile_name} profile_types)
|
||||
message(STATUS "Profile Types: ${profile_types}")
|
||||
|
||||
list(LENGTH profile_types type_count)
|
||||
message(STATUS "Type Count: ${type_count}")
|
||||
|
||||
if(profile_name STREQUAL "quantization")
|
||||
message(STATUS "Optimizations: INT8/UINT8 inference, quantization patterns")
|
||||
elseif(profile_name STREQUAL "training")
|
||||
message(STATUS "Optimizations: Mixed precision, gradient accumulation, FP64 for stability")
|
||||
elseif(profile_name STREQUAL "inference")
|
||||
message(STATUS "Optimizations: Deployment, quantized inference, INT8 support")
|
||||
elseif(profile_name STREQUAL "nlp")
|
||||
message(STATUS "Optimizations: String operations (UTF8 only), tokenization")
|
||||
elseif(profile_name STREQUAL "cv")
|
||||
message(STATUS "Optimizations: Image processing, convolution, UINT8 support")
|
||||
elseif(profile_name STREQUAL "data_pipeline")
|
||||
message(STATUS "Optimizations: All essential types for ML pipelines")
|
||||
message(STATUS "Includes: INT8 quantization, FP16/BF16 mixed precision, UTF8 strings")
|
||||
elseif(profile_name STREQUAL "standard_all")
|
||||
message(STATUS "Optimizations: Reduced from 16+ to 10 essential types")
|
||||
message(STATUS "Filtering: Aggressive semantic filtering enabled")
|
||||
message(STATUS "Removed: int16, uint16, uint32, uint64, utf16, utf32")
|
||||
endif()
|
||||
|
||||
message(STATUS "=== End Profile Information ===")
|
||||
endfunction()
|
||||
@@ -0,0 +1,139 @@
|
||||
function(dump_type_macros_to_disk)
|
||||
set(output_file "${CMAKE_BINARY_DIR}/resolved_type_macros.txt")
|
||||
message(STATUS "🔍 Extracting macro values: ${output_file}")
|
||||
|
||||
# Create a stub header that blocks CUDA includes
|
||||
set(stub_header "${CMAKE_BINARY_DIR}/cuda_stub.h")
|
||||
file(WRITE "${stub_header}" "#ifndef CUDA_STUB_H
|
||||
#define CUDA_STUB_H
|
||||
#define __CUDA_RUNTIME_H__
|
||||
#define __CUDA_H__
|
||||
#define __DRIVER_TYPES_H__
|
||||
struct cudaStream_t {};
|
||||
struct cublasHandle_t {};
|
||||
#endif")
|
||||
|
||||
# Create minimal extraction file
|
||||
set(extraction_file "${CMAKE_BINARY_DIR}/extract_types.cpp")
|
||||
file(WRITE "${extraction_file}" "#include \"${stub_header}\"
|
||||
#define SD_CUDA 0
|
||||
#define HAVE_ONEDNN 0
|
||||
#define HAVE_ARMCOMPUTE 0
|
||||
#define HAVE_CUDNN 0
|
||||
#define COUNT_NARG(...) 1
|
||||
|
||||
#include <types/types.h>
|
||||
|
||||
===BEGIN_SD_COMMON_TYPES===
|
||||
SD_COMMON_TYPES
|
||||
===END_SD_COMMON_TYPES===
|
||||
|
||||
===BEGIN_SD_FLOAT_TYPES===
|
||||
SD_FLOAT_TYPES
|
||||
===END_SD_FLOAT_TYPES===
|
||||
|
||||
===BEGIN_SD_INTEGER_TYPES===
|
||||
SD_INTEGER_TYPES
|
||||
===END_SD_INTEGER_TYPES===
|
||||
|
||||
===BEGIN_SD_NUMERIC_TYPES===
|
||||
SD_NUMERIC_TYPES
|
||||
===END_SD_NUMERIC_TYPES===
|
||||
|
||||
===BEGIN_SD_COMMON_TYPES_PART_0===
|
||||
SD_COMMON_TYPES_PART_0
|
||||
===END_SD_COMMON_TYPES_PART_0===
|
||||
|
||||
===BEGIN_SD_COMMON_TYPES_PART_1===
|
||||
SD_COMMON_TYPES_PART_1
|
||||
===END_SD_COMMON_TYPES_PART_1===
|
||||
|
||||
===BEGIN_SD_COMMON_TYPES_PART_2===
|
||||
SD_COMMON_TYPES_PART_2
|
||||
===END_SD_COMMON_TYPES_PART_2===")
|
||||
|
||||
# Get basic include paths
|
||||
set(include_flags
|
||||
"-I${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"-I${CMAKE_CURRENT_BINARY_DIR}/include"
|
||||
"-I${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
|
||||
# Add FlatBuffers if available
|
||||
if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-src/include")
|
||||
list(APPEND include_flags "-I${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-src/include")
|
||||
endif()
|
||||
|
||||
# Run preprocessor
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_CXX_COMPILER} -E -P -w -std=c++11
|
||||
${include_flags}
|
||||
-DSD_CUDA=0 -DHAVE_ONEDNN=0 -DHAVE_ARMCOMPUTE=0
|
||||
"${extraction_file}"
|
||||
OUTPUT_VARIABLE preprocessed_output
|
||||
ERROR_VARIABLE compiler_errors
|
||||
RESULT_VARIABLE compiler_result
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
# Initialize output
|
||||
set(output_content "RESOLVED MACRO VALUES\n=====================\n\n")
|
||||
string(TIMESTAMP current_time "%Y-%m-%d %H:%M:%S")
|
||||
string(APPEND output_content "Generated: ${current_time}\n")
|
||||
string(APPEND output_content "Compiler: ${CMAKE_CXX_COMPILER}\n\n")
|
||||
|
||||
if(compiler_result EQUAL 0 AND preprocessed_output)
|
||||
message(STATUS "✅ Macro extraction succeeded")
|
||||
|
||||
# Extract macros
|
||||
set(macro_names "SD_COMMON_TYPES" "SD_FLOAT_TYPES" "SD_INTEGER_TYPES" "SD_NUMERIC_TYPES"
|
||||
"SD_COMMON_TYPES_PART_0" "SD_COMMON_TYPES_PART_1" "SD_COMMON_TYPES_PART_2")
|
||||
|
||||
set(found_macros 0)
|
||||
foreach(macro_name ${macro_names})
|
||||
set(begin_marker "===BEGIN_${macro_name}===")
|
||||
set(end_marker "===END_${macro_name}===")
|
||||
|
||||
string(FIND "${preprocessed_output}" "${begin_marker}" begin_pos)
|
||||
string(FIND "${preprocessed_output}" "${end_marker}" end_pos)
|
||||
|
||||
if(begin_pos GREATER -1 AND end_pos GREATER begin_pos)
|
||||
string(LENGTH "${begin_marker}" begin_len)
|
||||
math(EXPR content_start "${begin_pos} + ${begin_len}")
|
||||
math(EXPR content_length "${end_pos} - ${content_start}")
|
||||
|
||||
if(content_length GREATER 0)
|
||||
string(SUBSTRING "${preprocessed_output}" ${content_start} ${content_length} macro_value)
|
||||
string(STRIP "${macro_value}" macro_value)
|
||||
string(REGEX REPLACE "[\r\n]+" " " macro_value "${macro_value}")
|
||||
string(REGEX REPLACE " +" " " macro_value "${macro_value}")
|
||||
|
||||
if(NOT macro_value STREQUAL "" AND NOT macro_value STREQUAL macro_name)
|
||||
string(APPEND output_content "${macro_name}:\n ${macro_value}\n\n")
|
||||
math(EXPR found_macros "${found_macros} + 1")
|
||||
else()
|
||||
string(APPEND output_content "${macro_name}: (undefined)\n\n")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
string(APPEND output_content "${macro_name}: (not found)\n\n")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
message(STATUS "📊 Found ${found_macros} expanded macros")
|
||||
else()
|
||||
string(APPEND output_content "ERROR: Preprocessor failed\nResult: ${compiler_result}\n")
|
||||
if(compiler_errors)
|
||||
string(APPEND output_content "Errors:\n${compiler_errors}\n")
|
||||
endif()
|
||||
message(STATUS "❌ Macro extraction failed")
|
||||
endif()
|
||||
|
||||
# Write results
|
||||
file(WRITE "${output_file}" "${output_content}")
|
||||
message(STATUS "✅ Results written to: ${output_file}")
|
||||
|
||||
# Cleanup
|
||||
file(REMOVE "${extraction_file}" "${stub_header}")
|
||||
|
||||
endfunction()
|
||||
@@ -0,0 +1,79 @@
|
||||
function(build_indexed_type_lists)
|
||||
message(STATUS "🔄 TypeSystem.cmake: build_indexed_type_lists calling unified core")
|
||||
|
||||
# Ensure unified system is set up
|
||||
srcore_auto_setup()
|
||||
|
||||
# Map unified results to legacy TypeSystem variables
|
||||
if(DEFINED UNIFIED_ACTIVE_TYPES)
|
||||
set(SD_ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" CACHE INTERNAL "List of active types for the build")
|
||||
|
||||
list(LENGTH UNIFIED_ACTIVE_TYPES type_count)
|
||||
set(SD_COMMON_TYPES_COUNT ${type_count} CACHE INTERNAL "Total count of common types")
|
||||
|
||||
# Create TYPE_NAME_X mappings for legacy compatibility
|
||||
set(index 0)
|
||||
foreach(type_name ${UNIFIED_ACTIVE_TYPES})
|
||||
set(TYPE_NAME_${index} "${type_name}" CACHE INTERNAL "Legacy reverse type lookup")
|
||||
set(TYPE_NAME_${index} "${type_name}" PARENT_SCOPE)
|
||||
math(EXPR index "${index} + 1")
|
||||
endforeach()
|
||||
|
||||
# Also set float/integer type counts for compatibility
|
||||
set(float_count 0)
|
||||
set(integer_count 0)
|
||||
foreach(type_name ${UNIFIED_ACTIVE_TYPES})
|
||||
if(type_name MATCHES "(float|double|half|bfloat)")
|
||||
math(EXPR float_count "${float_count} + 1")
|
||||
elseif(type_name MATCHES "(int|uint|long)")
|
||||
math(EXPR integer_count "${integer_count} + 1")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(SD_FLOAT_TYPES_COUNT ${float_count} CACHE INTERNAL "Total count of float types")
|
||||
set(SD_INTEGER_TYPES_COUNT ${integer_count} CACHE INTERNAL "Total count of integer types")
|
||||
endif()
|
||||
|
||||
message(STATUS "✅ TypeSystem.cmake: build_indexed_type_lists complete via unified core")
|
||||
endfunction()
|
||||
|
||||
# Ensure the critical get_type_name_from_index function works
|
||||
function(get_type_name_from_index index result_var)
|
||||
# First try the unified system
|
||||
if(DEFINED SRCORE_TYPE_NAME_${index})
|
||||
set(${result_var} "${SRCORE_TYPE_NAME_${index}}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Then try legacy system
|
||||
if(DEFINED TYPE_NAME_${index})
|
||||
set(${result_var} "${TYPE_NAME_${index}}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Auto-setup if needed
|
||||
if(NOT DEFINED SRCORE_SETUP_COMPLETE)
|
||||
message(STATUS "🔄 get_type_name_from_index: Auto-setting up unified core")
|
||||
srcore_auto_setup()
|
||||
if(DEFINED SRCORE_TYPE_NAME_${index})
|
||||
set(${result_var} "${SRCORE_TYPE_NAME_${index}}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Final fallback
|
||||
message(WARNING "❌ get_type_name_from_index(${index}): No type found in any system")
|
||||
set(${result_var} "unknown_type_${index}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Wrapper for extract_type_definitions_from_header (used by legacy code)
|
||||
function(extract_type_definitions_from_header result_var)
|
||||
message(STATUS "🔄 extract_type_definitions_from_header: Using unified core result")
|
||||
|
||||
if(DEFINED UNIFIED_ACTIVE_TYPES)
|
||||
set(${result_var} "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
|
||||
else()
|
||||
srcore_auto_setup()
|
||||
set(${result_var} "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,273 @@
|
||||
# =============================================================================
|
||||
# ValidationSuite.cmake - Comprehensive Build Validation for libnd4j
|
||||
# =============================================================================
|
||||
|
||||
if(NOT COMMAND print_status_colored)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/PrintingUtilities.cmake)
|
||||
endif()
|
||||
|
||||
# Master validation function
|
||||
function(run_comprehensive_validation)
|
||||
print_status_colored("INFO" "=== RUNNING COMPREHENSIVE BUILD VALIDATION ===")
|
||||
|
||||
validate_build_environment_comprehensive()
|
||||
validate_cmake_variables_comprehensive()
|
||||
validate_type_system_comprehensive()
|
||||
validate_template_system_comprehensive()
|
||||
validate_dependencies_comprehensive()
|
||||
validate_generated_files_comprehensive()
|
||||
validate_platform_specific_configuration()
|
||||
|
||||
print_status_colored("SUCCESS" "All validation checks passed")
|
||||
endfunction()
|
||||
|
||||
# Environment validation
|
||||
function(validate_build_environment_comprehensive)
|
||||
print_status_colored("INFO" "Phase 1: Environment validation")
|
||||
|
||||
set(validation_errors "")
|
||||
set(validation_warnings "")
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS "3.15")
|
||||
list(APPEND validation_errors "CMake 3.15+ required, found ${CMAKE_VERSION}")
|
||||
endif()
|
||||
|
||||
set(REQUIRED_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
foreach(dir ${REQUIRED_DIRS})
|
||||
if(NOT EXISTS "${dir}")
|
||||
list(APPEND validation_errors "Required directory not found: ${dir}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9")
|
||||
list(APPEND validation_errors "GCC 4.9+ required, found ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
endif()
|
||||
|
||||
list(LENGTH validation_errors error_count)
|
||||
if(error_count GREATER 0)
|
||||
foreach(error ${validation_errors})
|
||||
print_status_colored("ERROR" " - ${error}")
|
||||
endforeach()
|
||||
message(FATAL_ERROR "Environment validation failed")
|
||||
endif()
|
||||
|
||||
print_status_colored("SUCCESS" "Environment validation passed")
|
||||
endfunction()
|
||||
|
||||
# CMake variables validation
|
||||
function(validate_cmake_variables_comprehensive)
|
||||
print_status_colored("INFO" "Phase 2: CMake variables validation")
|
||||
|
||||
set(validation_warnings "")
|
||||
|
||||
if(SD_CUDA AND SD_CPU AND SD_CPU STREQUAL "ON")
|
||||
list(APPEND validation_warnings "Both SD_CUDA and SD_CPU enabled, SD_CUDA takes precedence")
|
||||
endif()
|
||||
|
||||
if(DEFINED SD_TYPE_LIST AND NOT DEFINED SD_TYPES_LIST)
|
||||
list(APPEND validation_warnings "Found SD_TYPE_LIST, converting to SD_TYPES_LIST")
|
||||
set(SD_TYPES_LIST "${SD_TYPE_LIST}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(DEFINED SD_TYPES_LIST AND SD_TYPES_LIST MATCHES ".*,.*")
|
||||
list(APPEND validation_warnings "Converting comma-separated to semicolon-separated types")
|
||||
string(REPLACE "," ";" SD_TYPES_LIST "${SD_TYPES_LIST}")
|
||||
set(SD_TYPES_LIST "${SD_TYPES_LIST}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
list(LENGTH validation_warnings warning_count)
|
||||
if(warning_count GREATER 0)
|
||||
foreach(warning ${validation_warnings})
|
||||
print_status_colored("WARNING" " - ${warning}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
print_status_colored("SUCCESS" "CMake variables validation passed")
|
||||
endfunction()
|
||||
|
||||
# Type system validation
|
||||
function(validate_type_system_comprehensive)
|
||||
print_status_colored("INFO" "Phase 3: Type system validation")
|
||||
|
||||
set(validation_errors "")
|
||||
|
||||
if(NOT DEFINED SD_COMMON_TYPES_COUNT OR SD_COMMON_TYPES_COUNT EQUAL 0)
|
||||
list(APPEND validation_errors "Type system not initialized")
|
||||
endif()
|
||||
|
||||
if(DEFINED COMBINATIONS_3 AND DEFINED COMBINATIONS_2)
|
||||
list(LENGTH COMBINATIONS_3 combo_3_count)
|
||||
list(LENGTH COMBINATIONS_2 combo_2_count)
|
||||
if(combo_3_count EQUAL 0 AND combo_2_count EQUAL 0)
|
||||
list(APPEND validation_errors "No type combinations generated")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(LENGTH validation_errors error_count)
|
||||
if(error_count GREATER 0)
|
||||
foreach(error ${validation_errors})
|
||||
print_status_colored("ERROR" " - ${error}")
|
||||
endforeach()
|
||||
message(FATAL_ERROR "Type system validation failed")
|
||||
endif()
|
||||
|
||||
print_status_colored("SUCCESS" "Type system validation passed")
|
||||
endfunction()
|
||||
|
||||
# Template system validation
|
||||
function(validate_template_system_comprehensive)
|
||||
print_status_colored("INFO" "Phase 4: Template system validation")
|
||||
|
||||
set(validation_errors "")
|
||||
|
||||
if(DEFINED CUSTOMOPS_GENERIC_SOURCES)
|
||||
list(LENGTH CUSTOMOPS_GENERIC_SOURCES generated_count)
|
||||
if(generated_count GREATER 0)
|
||||
set(check_count 0)
|
||||
foreach(generated_file ${CUSTOMOPS_GENERIC_SOURCES})
|
||||
if(check_count LESS 3 AND EXISTS "${generated_file}")
|
||||
file(READ "${generated_file}" file_content)
|
||||
if(file_content MATCHES "#cmakedefine|@[A-Za-z_]+@")
|
||||
list(APPEND validation_errors "Unprocessed template: ${generated_file}")
|
||||
endif()
|
||||
math(EXPR check_count "${check_count} + 1")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(LENGTH validation_errors error_count)
|
||||
if(error_count GREATER 0)
|
||||
foreach(error ${validation_errors})
|
||||
print_status_colored("ERROR" " - ${error}")
|
||||
endforeach()
|
||||
message(FATAL_ERROR "Template system validation failed")
|
||||
endif()
|
||||
|
||||
print_status_colored("SUCCESS" "Template system validation passed")
|
||||
endfunction()
|
||||
|
||||
# Dependency validation
|
||||
function(validate_dependencies_comprehensive)
|
||||
print_status_colored("INFO" "Phase 5: Dependency validation")
|
||||
|
||||
set(validation_warnings "")
|
||||
|
||||
if(NOT TARGET flatbuffers_interface)
|
||||
list(APPEND validation_warnings "FlatBuffers interface target not found")
|
||||
endif()
|
||||
|
||||
if(HELPERS_onednn AND (NOT DEFINED HAVE_ONEDNN OR NOT HAVE_ONEDNN))
|
||||
list(APPEND validation_warnings "OneDNN enabled but not configured")
|
||||
endif()
|
||||
|
||||
if(HELPERS_cudnn AND SD_CUDA AND (NOT DEFINED HAVE_CUDNN OR NOT HAVE_CUDNN))
|
||||
list(APPEND validation_warnings "cuDNN enabled but not configured")
|
||||
endif()
|
||||
|
||||
if(SD_CUDA AND NOT CMAKE_CUDA_COMPILER)
|
||||
list(APPEND validation_warnings "CUDA build but no CUDA compiler")
|
||||
endif()
|
||||
|
||||
list(LENGTH validation_warnings warning_count)
|
||||
if(warning_count GREATER 0)
|
||||
foreach(warning ${validation_warnings})
|
||||
print_status_colored("WARNING" " - ${warning}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
print_status_colored("SUCCESS" "Dependency validation passed")
|
||||
endfunction()
|
||||
|
||||
# Generated files validation
|
||||
function(validate_generated_files_comprehensive)
|
||||
print_status_colored("INFO" "Phase 6: Generated files validation")
|
||||
|
||||
set(validation_warnings "")
|
||||
|
||||
set(INCLUDE_OPS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/include/generated/include_ops.h")
|
||||
if(NOT EXISTS "${INCLUDE_OPS_FILE}")
|
||||
list(APPEND validation_warnings "Generated include_ops.h not found")
|
||||
else()
|
||||
file(READ "${INCLUDE_OPS_FILE}" ops_content)
|
||||
if(NOT ops_content MATCHES "#define")
|
||||
list(APPEND validation_warnings "include_ops.h appears empty or malformed")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(LENGTH validation_warnings warning_count)
|
||||
if(warning_count GREATER 0)
|
||||
foreach(warning ${validation_warnings})
|
||||
print_status_colored("WARNING" " - ${warning}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
print_status_colored("SUCCESS" "Generated files validation passed")
|
||||
endfunction()
|
||||
|
||||
# Platform-specific validation
|
||||
function(validate_platform_specific_configuration)
|
||||
print_status_colored("INFO" "Phase 7: Platform-specific validation")
|
||||
|
||||
set(validation_warnings "")
|
||||
|
||||
if(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(NOT CMAKE_CXX_FLAGS MATCHES "-Wa,-mbig-obj")
|
||||
list(APPEND validation_warnings "Windows GCC build may need -Wa,-mbig-obj flag")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SD_ARM_BUILD AND NOT DEFINED SD_ARCH)
|
||||
list(APPEND validation_warnings "ARM build without SD_ARCH specification")
|
||||
endif()
|
||||
|
||||
if(ANDROID AND NOT ANDROID_ABI)
|
||||
list(APPEND validation_warnings "Android build without ABI specification")
|
||||
endif()
|
||||
|
||||
list(LENGTH validation_warnings warning_count)
|
||||
if(warning_count GREATER 0)
|
||||
foreach(warning ${validation_warnings})
|
||||
print_status_colored("WARNING" " - ${warning}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
print_status_colored("SUCCESS" "Platform validation passed")
|
||||
endfunction()
|
||||
|
||||
# Quick validation for development
|
||||
function(run_quick_validation)
|
||||
print_status_colored("INFO" "=== RUNNING QUICK VALIDATION ===")
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS "3.15")
|
||||
message(FATAL_ERROR "CMake 3.15+ required")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
message(FATAL_ERROR "Include directory not found")
|
||||
endif()
|
||||
|
||||
if(SD_CUDA AND NOT CMAKE_CUDA_COMPILER)
|
||||
print_status_colored("WARNING" "CUDA build requested but compiler not found")
|
||||
endif()
|
||||
|
||||
print_status_colored("SUCCESS" "Quick validation passed")
|
||||
endfunction()
|
||||
|
||||
# Validation for CI/CD
|
||||
function(run_ci_validation)
|
||||
print_status_colored("INFO" "=== RUNNING CI/CD VALIDATION ===")
|
||||
|
||||
run_comprehensive_validation()
|
||||
|
||||
# Additional CI-specific checks
|
||||
if(NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
|
||||
print_status_colored("WARNING" "BUILD_TYPE not specified for CI build")
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{CI} AND SD_GCC_FUNCTRACE)
|
||||
print_status_colored("WARNING" "Function tracing enabled in CI environment")
|
||||
endif()
|
||||
|
||||
print_status_colored("SUCCESS" "CI validation completed")
|
||||
endfunction()
|
||||
@@ -0,0 +1,39 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
# CMake toolchain to build for Android 5.0 or newer. Sample usage:
|
||||
#
|
||||
set(CMAKE_SYSTEM_NAME Android)
|
||||
set(CMAKE_ANDROID_ARCH_ABI armeabi-v7a)
|
||||
set(CMAKE_ANDROID_NDK "$ENV{ANDROID_NDK}")
|
||||
set(CMAKE_ANDROID_STL_TYPE c++_static)
|
||||
set(CMAKE_SYSTEM_VERSION "$ENV{ANDROID_VERSION}")
|
||||
set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang)
|
||||
|
||||
set(ANDROID TRUE)
|
||||
if (WIN32)
|
||||
set(CMAKE_C_COMPILER "$ENV{ANDROID_CC}.exe")
|
||||
set(CMAKE_CXX_COMPILER "$ENV{ANDROID_CC}++.exe")
|
||||
else()
|
||||
set(CMAKE_C_COMPILER "$ENV{ANDROID_CC}")
|
||||
set(CMAKE_CXX_COMPILER "$ENV{ANDROID_CC}++")
|
||||
endif (WIN32)
|
||||
|
||||
|
||||
add_definitions(-D__ANDROID_API__=$ENV{ANDROID_VERSION} -DANDROID -fPIC -ffunction-sections -funwind-tables -fstack-protector-strong -target armv7a-linux-androideabi)
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
# android-arm64.cmake - Intel x86_64 to ARM64 cross-compilation toolchain
|
||||
|
||||
# Set the system and processor for cross-compilation
|
||||
set(CMAKE_SYSTEM_NAME Android)
|
||||
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||
|
||||
# Flexible API level - can be overridden via command line or environment
|
||||
if(NOT DEFINED ANDROID_NATIVE_API_LEVEL AND DEFINED ENV{ANDROID_VERSION})
|
||||
set(ANDROID_NATIVE_API_LEVEL $ENV{ANDROID_VERSION})
|
||||
elseif(NOT DEFINED ANDROID_NATIVE_API_LEVEL)
|
||||
set(ANDROID_NATIVE_API_LEVEL 21) # Default API level
|
||||
endif()
|
||||
|
||||
set(CMAKE_SYSTEM_VERSION ${ANDROID_NATIVE_API_LEVEL})
|
||||
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a)
|
||||
|
||||
# Flexible NDK path detection
|
||||
if(NOT DEFINED CMAKE_ANDROID_NDK)
|
||||
if(DEFINED ENV{ANDROID_NDK_ROOT})
|
||||
set(CMAKE_ANDROID_NDK $ENV{ANDROID_NDK_ROOT})
|
||||
elseif(DEFINED ENV{ANDROID_NDK_HOME})
|
||||
set(CMAKE_ANDROID_NDK $ENV{ANDROID_NDK_HOME})
|
||||
elseif(DEFINED ENV{ANDROID_NDK})
|
||||
set(CMAKE_ANDROID_NDK $ENV{ANDROID_NDK})
|
||||
else()
|
||||
message(FATAL_ERROR "Android NDK not found. Please set ANDROID_NDK_ROOT, ANDROID_NDK_HOME, or ANDROID_NDK environment variable")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Verify NDK exists
|
||||
if(NOT EXISTS "${CMAKE_ANDROID_NDK}")
|
||||
message(FATAL_ERROR "Android NDK directory does not exist: ${CMAKE_ANDROID_NDK}")
|
||||
endif()
|
||||
|
||||
# Set Android STL
|
||||
set(CMAKE_ANDROID_STL_TYPE c++_shared)
|
||||
|
||||
# Set NDK toolchain paths for Intel x86_64 host
|
||||
set(NDK_TOOLCHAIN_PATH "${CMAKE_ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64")
|
||||
|
||||
# Check if the toolchain path exists
|
||||
if(NOT EXISTS "${NDK_TOOLCHAIN_PATH}")
|
||||
message(FATAL_ERROR "NDK toolchain path does not exist: ${NDK_TOOLCHAIN_PATH}")
|
||||
endif()
|
||||
|
||||
# Set sysroot
|
||||
set(CMAKE_SYSROOT "${NDK_TOOLCHAIN_PATH}/sysroot")
|
||||
|
||||
# Verify sysroot exists
|
||||
if(NOT EXISTS "${CMAKE_SYSROOT}")
|
||||
message(FATAL_ERROR "NDK sysroot does not exist: ${CMAKE_SYSROOT}")
|
||||
endif()
|
||||
|
||||
# Use NDK compilers for cross-compilation
|
||||
set(CMAKE_C_COMPILER "${NDK_TOOLCHAIN_PATH}/bin/aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}-clang")
|
||||
set(CMAKE_CXX_COMPILER "${NDK_TOOLCHAIN_PATH}/bin/aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}-clang++")
|
||||
set(CMAKE_AR "${NDK_TOOLCHAIN_PATH}/bin/llvm-ar")
|
||||
set(CMAKE_STRIP "${NDK_TOOLCHAIN_PATH}/bin/llvm-strip")
|
||||
set(CMAKE_RANLIB "${NDK_TOOLCHAIN_PATH}/bin/llvm-ranlib")
|
||||
|
||||
# Verify compilers exist
|
||||
if(NOT EXISTS "${CMAKE_C_COMPILER}")
|
||||
message(FATAL_ERROR "C compiler does not exist: ${CMAKE_C_COMPILER}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${CMAKE_CXX_COMPILER}")
|
||||
message(FATAL_ERROR "C++ compiler does not exist: ${CMAKE_CXX_COMPILER}")
|
||||
endif()
|
||||
|
||||
# Set cross-compilation flags
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -march=armv8-a")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -march=armv8-a -std=c++14")
|
||||
|
||||
# Set NDK library paths for linking
|
||||
set(NDK_SYSROOT_LIB_PATH "${CMAKE_SYSROOT}/usr/lib/aarch64-linux-android/${ANDROID_NATIVE_API_LEVEL}")
|
||||
set(NDK_TOOLCHAIN_LIB_PATH "${NDK_TOOLCHAIN_PATH}/lib64/clang/14.0.6/lib/linux")
|
||||
|
||||
# Linker flags
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--build-id=sha1")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-rosegment")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--fatal-warnings")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--build-id=sha1")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-rosegment")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--fatal-warnings")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
|
||||
# Additional Android-specific flags
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
|
||||
|
||||
# Set the find root path for cross-compilation
|
||||
set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}" "${CMAKE_ANDROID_NDK}")
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
# Configure for cross-compilation
|
||||
set(CMAKE_CROSSCOMPILING TRUE)
|
||||
set(CMAKE_CROSSCOMPILING_EMULATOR "")
|
||||
|
||||
# Android specific settings
|
||||
set(ANDROID TRUE)
|
||||
set(ANDROID_ABI "arm64-v8a")
|
||||
set(ANDROID_PLATFORM "android-${ANDROID_NATIVE_API_LEVEL}")
|
||||
set(ANDROID_STL "c++_shared")
|
||||
|
||||
# Debug information
|
||||
message(STATUS "Cross-compiling from Intel x86_64 to ARM64")
|
||||
message(STATUS "Android NDK: ${CMAKE_ANDROID_NDK}")
|
||||
message(STATUS "Android API Level: ${ANDROID_NATIVE_API_LEVEL}")
|
||||
message(STATUS "Android ABI: ${CMAKE_ANDROID_ARCH_ABI}")
|
||||
message(STATUS "Android Sysroot: ${CMAKE_SYSROOT}")
|
||||
message(STATUS "C Compiler: ${CMAKE_C_COMPILER}")
|
||||
message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}")
|
||||
message(STATUS "Toolchain Path: ${NDK_TOOLCHAIN_PATH}")
|
||||
|
||||
# Ensure we don't accidentally use host tools
|
||||
set(CMAKE_C_COMPILER_WORKS 1)
|
||||
set(CMAKE_CXX_COMPILER_WORKS 1)
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
# Set compiler identification to prevent issues
|
||||
set(CMAKE_C_COMPILER_ID "Clang")
|
||||
set(CMAKE_CXX_COMPILER_ID "Clang")
|
||||
|
||||
# Additional search paths for Android-specific libraries
|
||||
if(EXISTS "${NDK_SYSROOT_LIB_PATH}")
|
||||
set(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH}:${NDK_SYSROOT_LIB_PATH}")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${NDK_TOOLCHAIN_LIB_PATH}")
|
||||
set(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH}:${NDK_TOOLCHAIN_LIB_PATH}")
|
||||
endif()
|
||||
|
||||
# Set Android-specific preprocessor definitions
|
||||
add_definitions(-DANDROID -D__ANDROID__ -D__ANDROID_API__=${ANDROID_NATIVE_API_LEVEL})
|
||||
|
||||
# Optimization flags for ARM64
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -DNDEBUG")
|
||||
|
||||
|
||||
message(STATUS "Android ARM64 cross-compilation toolchain configured successfully")
|
||||
@@ -0,0 +1,39 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
# CMake toolchain to build for Android 5.0 or newer. Sample usage:
|
||||
#
|
||||
set(CMAKE_SYSTEM_NAME Android)
|
||||
set(CMAKE_ANDROID_ARCH_ABI x86)
|
||||
set(CMAKE_ANDROID_NDK "$ENV{ANDROID_NDK}")
|
||||
set(CMAKE_ANDROID_STL_TYPE c++_static)
|
||||
set(CMAKE_SYSTEM_VERSION "$ENV{ANDROID_VERSION}")
|
||||
set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang)
|
||||
|
||||
set(ANDROID TRUE)
|
||||
if (WIN32)
|
||||
set(CMAKE_C_COMPILER "$ENV{ANDROID_CC}.exe")
|
||||
set(CMAKE_CXX_COMPILER "$ENV{ANDROID_CC}++.exe")
|
||||
else()
|
||||
set(CMAKE_C_COMPILER "$ENV{ANDROID_CC}")
|
||||
set(CMAKE_CXX_COMPILER "$ENV{ANDROID_CC}++")
|
||||
endif (WIN32)
|
||||
|
||||
|
||||
add_definitions(-D__ANDROID_API__=$ENV{ANDROID_VERSION} -DANDROID -fPIC -ffunction-sections -funwind-tables -fstack-protector-strong -target i686-linux-android)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
# CMake toolchain to build for Android 5.0 or newer. Sample usage:
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Android)
|
||||
set(CMAKE_ANDROID_ARCH_ABI x86_64)
|
||||
set(CMAKE_ANDROID_NDK "$ENV{ANDROID_NDK}")
|
||||
set(CMAKE_ANDROID_STL_TYPE c++_shared)
|
||||
set(CMAKE_SYSTEM_VERSION "$ENV{ANDROID_VERSION}")
|
||||
set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang)
|
||||
|
||||
set(ANDROID TRUE)
|
||||
if (WIN32)
|
||||
set(CMAKE_C_COMPILER "$ENV{ANDROID_CC}.exe")
|
||||
set(CMAKE_CXX_COMPILER "$ENV{ANDROID_CC}++.exe")
|
||||
else()
|
||||
set(CMAKE_C_COMPILER "$ENV{ANDROID_CC}")
|
||||
set(CMAKE_CXX_COMPILER "$ENV{ANDROID_CC}++")
|
||||
endif (WIN32)
|
||||
|
||||
|
||||
add_definitions(-D__ANDROID_API__=$ENV{ANDROID_VERSION} -DANDROID -fPIC -ffunction-sections -funwind-tables -fstack-protector-strong -target x86_64-none-linux-android)
|
||||
@@ -0,0 +1,33 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
# CMake toolchain to build libnd4j for iOS for 32-bit architecture cpu armv7. Sample usage:
|
||||
#
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=ios-arm.cmake -DCMAKE_INSTALL_PREFIX=..
|
||||
#
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv7)
|
||||
set(IOS TRUE)
|
||||
set(CFLAGS, "-miphoneos-version-min=6.0 -arch armv7")
|
||||
set(CMAKE_C_COMPILER "clang")
|
||||
set(CMAKE_CXX_COMPILER "clang")
|
||||
set(CMAKE_C_LINK_EXECUTABLE "libtool -static <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -L$ENV{IOS_SDK}/usr/lib/ -syslibroot $ENV{IOS_SDK}")
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE "libtool -static <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -L$ENV{IOS_SDK}/usr/lib/ -syslibroot $ENV{IOS_SDK}")
|
||||
set(CMAKE_CXX_CREATE_STATIC_LIBRARY "libtool -o <TARGET> <OBJECTS> <LINK_LIBRARIES> -syslibroot $ENV{IOS_SDK} -L$ENV{IOS_SDK}/usr/lib/")
|
||||
add_definitions("-DIOS -stdlib=libc++ -miphoneos-version-min=6.0 -arch armv7 -isysroot $ENV{IOS_SDK} -I/usr/local/opt/llvm/4.0.0/include/c++/v1 -I/usr/local/opt/llvm/4.0.0/lib/clang/4.0.0/include -fPIC -ffunction-sections -funwind-tables -fstack-protector -fomit-frame-pointer -fstrict-aliasing")
|
||||
@@ -0,0 +1,35 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
# CMake toolchain to build libnd4j for iOS for 64-bit architecture cpu arm64. Sample usage:
|
||||
#
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=ios-arm64.cmake -DCMAKE_INSTALL_PREFIX=..
|
||||
#
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm64)
|
||||
set(IOS TRUE)
|
||||
set(CFLAGS, "-miphoneos-version-min=6.0 -arch arm64")
|
||||
set(CMAKE_C_COMPILER "clang")
|
||||
set(CMAKE_CXX_COMPILER "clang")
|
||||
set(CMAKE_C_LINK_EXECUTABLE "libtool -static <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -L$ENV{IOS_SDK}/usr/lib/ -syslibroot $ENV{IOS_SDK}")
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE "libtool -static <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -L$ENV{IOS_SDK}/usr/lib/ -syslibroot $ENV{IOS_SDK}")
|
||||
set(CMAKE_CXX_CREATE_STATIC_LIBRARY "libtool -o <TARGET> <OBJECTS> <LINK_LIBRARIES> -syslibroot $ENV{IOS_SDK} -L$ENV{IOS_SDK}/usr/lib/")
|
||||
|
||||
add_definitions("-DIOS -stdlib=libc++ -miphoneos-version-min=6.0 -arch arm64 -isysroot $ENV{IOS_SDK} -I/usr/local/opt/llvm/4.0.0/include/c++/v1 -I/usr/local/opt/llvm/4.0.0/lib/clang/4.0.0/include -fPIC -ffunction-sections -funwind-tables -fstack-protector -fomit-frame-pointer -fstrict-aliasing")
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
# CMake toolchain to build libnd4j for iOS armv7. Sample usage:
|
||||
#
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=ios-armv7.cmake -DCMAKE_INSTALL_PREFIX=..
|
||||
#
|
||||
# If you really need to use libnd4j on a CPU with no FPU, replace "libs/armeabi-v7a" by "libs/armeabi" and
|
||||
# "-march=armv7-a with "-march=armv5te -mtune=xscale -msoft-float"
|
||||
|
||||
set(CMAKE_SYSTEM_NAME UnixPaths)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv)
|
||||
set(IOS TRUE)
|
||||
set(CFLAGS, "-miphoneos-version-min=6.0 -arch armv7")
|
||||
|
||||
|
||||
set(CMAKE_C_COMPILER "clang-omp")
|
||||
set(CMAKE_CXX_COMPILER "clang-omp")
|
||||
|
||||
# set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ")
|
||||
# set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ")
|
||||
set(CMAKE_C_LINK_EXECUTABLE "libtool -static <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -L$ENV{IOS_SDK}/usr/lib/ -syslibroot $ENV{IOS_SDK}")
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE "libtool -static <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -L$ENV{IOS_SDK}/usr/lib/ -syslibroot $ENV{IOS_SDK}")
|
||||
|
||||
set(CMAKE_C_CREATE_STATIC_LIBRARY "libtool <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -Wl,--no-undefined -z text -o <TARGET> <OBJECTS> <LINK_LIBRARIES> -L$ENV{ANDROID_ROOT}/usr/lib/ --sysroot=$ENV{ANDROID_ROOT}")
|
||||
# set(CMAKE_CXX_CREATE_STATIC_LIBRARY "libtool <CMAKE_STATIC_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_STATIC_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_STATIC_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -Wl,--no-undefined -z text -o <TARGET> <OBJECTS> <LINK_LIBRARIES> -L$ENV{IOS_ROOT}/usr/lib/ --sysroot=$ENV{IOS_ROOT}")
|
||||
set(CMAKE_CXX_CREATE_STATIC_LIBRARY "libtool -o <TARGET> <OBJECTS> <LINK_LIBRARIES> -syslibroot $ENV{IOS_SDK} -L$ENV{IOS_SDK}/usr/lib/")
|
||||
|
||||
add_definitions("-DIOS -miphoneos-version-min=6.0 -arch armv7 -isysroot $ENV{IOS_SDK} -I/usr/local/Cellar/llvm/4.0.0/include/c++/v1 -I/usr/local/Cellar/llvm/4.0.0/lib/clang/4.0.0/include -fPIC -ffunction-sections -funwind-tables -fstack-protector -fomit-frame-pointer -fstrict-aliasing")
|
||||
|
||||
# include_directories("$ENV{ANDROID_CPP}/include/" "$ENV{ANDROID_CPP}/libs/armeabi-v7a/include/" "$ENV{ANDROID_ROOT}/usr/include/")
|
||||
@@ -0,0 +1,33 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
# CMake toolchain to build libnd4j for 32-bit iOS Simulator. Sample usage:
|
||||
#
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=ios-x86.cmake -DCMAKE_INSTALL_PREFIX=..
|
||||
#
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR "i386")
|
||||
set(IOS TRUE)
|
||||
set(CFLAGS, "-miphoneos-version-min=6.0 -arch i386")
|
||||
set(CMAKE_C_COMPILER "clang")
|
||||
set(CMAKE_CXX_COMPILER "clang")
|
||||
set(CMAKE_C_LINK_EXECUTABLE "libtool -static <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -L$ENV{IOS_SDK}/usr/lib/ -syslibroot $ENV{IOS_SDK}")
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE "libtool -static <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -L$ENV{IOS_SDK}/usr/lib/ -syslibroot $ENV{IOS_SDK}")
|
||||
set(CMAKE_CXX_CREATE_STATIC_LIBRARY "libtool -o <TARGET> <OBJECTS> <LINK_LIBRARIES> -syslibroot $ENV{IOS_SDK} -L$ENV{IOS_SDK}/usr/lib/")
|
||||
add_definitions("-DIOS -stdlib=libc++ -miphoneos-version-min=6.0 -arch i386 -isysroot $ENV{IOS_SDK} -I/usr/local/opt/llvm/4.0.0/include/c++/v1 -I/usr/local/opt/llvm/4.0.0/lib/clang/4.0.0/include -fPIC -ffunction-sections -funwind-tables -fstack-protector -fomit-frame-pointer -fstrict-aliasing")
|
||||
@@ -0,0 +1,33 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
# CMake toolchain to build libnd4j for 64-bit iOS Simulator. Sample usage:
|
||||
#
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=ios-x86_64.cmake -DCMAKE_INSTALL_PREFIX=..
|
||||
#
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR "x86_64")
|
||||
set(IOS TRUE)
|
||||
set(CFLAGS, "-miphoneos-version-min=6.0 -arch x86_64")
|
||||
set(CMAKE_C_COMPILER "clang")
|
||||
set(CMAKE_CXX_COMPILER "clang")
|
||||
set(CMAKE_C_LINK_EXECUTABLE "libtool -static <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -L$ENV{IOS_SDK}/usr/lib/ -syslibroot $ENV{IOS_SDK}")
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE "libtool -static <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -L$ENV{IOS_SDK}/usr/lib/ -syslibroot $ENV{IOS_SDK}")
|
||||
set(CMAKE_CXX_CREATE_STATIC_LIBRARY "libtool -o <TARGET> <OBJECTS> <LINK_LIBRARIES> -syslibroot $ENV{IOS_SDK} -L$ENV{IOS_SDK}/usr/lib/")
|
||||
add_definitions("-DIOS -stdlib=libc++ -miphoneos-version-min=6.0 -arch x86_64 -isysroot $ENV{IOS_SDK} -I/usr/local/opt/llvm/4.0.0/include/c++/v1 -I/usr/local/opt/llvm/4.0.0/lib/clang/4.0.0/include -fPIC -ffunction-sections -funwind-tables -fstack-protector -fomit-frame-pointer -fstrict-aliasing")
|
||||
@@ -0,0 +1,73 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
# Use this command to build the Windows port of Allegro
|
||||
# with a mingw cross compiler:
|
||||
#
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-mingw.cmake .
|
||||
#
|
||||
# or for out of source:
|
||||
#
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw.cmake ..
|
||||
#
|
||||
# You will need at least CMake 2.6.0.
|
||||
#
|
||||
# Adjust the following paths to suit your environment.
|
||||
#
|
||||
# This file was based on http://www.cmake.org/Wiki/CmakeMingw
|
||||
|
||||
# the name of the target operating system
|
||||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
message("Using msys2")
|
||||
# Assume the target architecture.
|
||||
# XXX for some reason the value set here gets cleared before we reach the
|
||||
# main CMakeLists.txt; see that file for a workaround.
|
||||
# set(CMAKE_SYSTEM_PROCESSOR i686)
|
||||
|
||||
# Which compilers to use for C and C++, and location of target
|
||||
# environment.
|
||||
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
# First look in standard location as used by Debian/Ubuntu/etc.
|
||||
set(CMAKE_C_COMPILER /mingw64/bin/gcc)
|
||||
set(CMAKE_CXX_COMPILER /mingw64/bin/g++)
|
||||
set(CMAKE_RC_COMPILER /mingw64/bin/windres)
|
||||
set(CMAKE_FIND_ROOT_PATH /mingw64)
|
||||
else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
# First look in standard location as used by Debian/Ubuntu/etc.
|
||||
set(CMAKE_C_COMPILER /mingw32/bin/gcc)
|
||||
set(CMAKE_CXX_COMPILER /mingw32/bin/g++)
|
||||
set(CMAKE_RC_COMPILER /mingw64/bin/windres)
|
||||
set(CMAKE_FIND_ROOT_PATH /mingw32)
|
||||
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
|
||||
|
||||
# Adjust the default behaviour of the FIND_XXX() commands:
|
||||
# search headers and libraries in the target environment, search
|
||||
# programs in the host environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
# Tell pkg-config not to look at the target environment's .pc files.
|
||||
# Setting PKG_CONFIG_LIBDIR sets the default search directory, but we have to
|
||||
# set PKG_CONFIG_PATH as well to prevent pkg-config falling back to the host's
|
||||
# path.
|
||||
set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_FIND_ROOT_PATH}/lib/pkgconfig)
|
||||
set(ENV{PKG_CONFIG_PATH} ${CMAKE_FIND_ROOT_PATH}/lib/pkgconfig)
|
||||
|
||||
set(ENV{MINGDIR} ${CMAKE_FIND_ROOT_PATH})
|
||||
@@ -0,0 +1,23 @@
|
||||
set(NDK_MIN_PLATFORM_LEVEL "21")
|
||||
set(NDK_MAX_PLATFORM_LEVEL "35")
|
||||
set(NDK_PLATFORM_ALIAS_20 "android-19")
|
||||
set(NDK_PLATFORM_ALIAS_25 "android-24")
|
||||
set(NDK_PLATFORM_ALIAS_J "android-16")
|
||||
set(NDK_PLATFORM_ALIAS_J-MR1 "android-17")
|
||||
set(NDK_PLATFORM_ALIAS_J-MR2 "android-18")
|
||||
set(NDK_PLATFORM_ALIAS_K "android-19")
|
||||
set(NDK_PLATFORM_ALIAS_L "android-21")
|
||||
set(NDK_PLATFORM_ALIAS_L-MR1 "android-22")
|
||||
set(NDK_PLATFORM_ALIAS_M "android-23")
|
||||
set(NDK_PLATFORM_ALIAS_N "android-24")
|
||||
set(NDK_PLATFORM_ALIAS_N-MR1 "android-24")
|
||||
set(NDK_PLATFORM_ALIAS_O "android-26")
|
||||
set(NDK_PLATFORM_ALIAS_O-MR1 "android-27")
|
||||
set(NDK_PLATFORM_ALIAS_P "android-28")
|
||||
set(NDK_PLATFORM_ALIAS_Q "android-29")
|
||||
set(NDK_PLATFORM_ALIAS_R "android-30")
|
||||
set(NDK_PLATFORM_ALIAS_S "android-31")
|
||||
set(NDK_PLATFORM_ALIAS_Sv2 "android-32")
|
||||
set(NDK_PLATFORM_ALIAS_Tiramisu "android-33")
|
||||
set(NDK_PLATFORM_ALIAS_UpsideDownCake "android-34")
|
||||
set(NDK_PLATFORM_ALIAS_VanillaIceCream "android-35")
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# /* ******************************************************************************
|
||||
# *
|
||||
# *
|
||||
# * This program and the accompanying materials are made available under the
|
||||
# * terms of the Apache License, Version 2.0 which is available at
|
||||
# * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
# *
|
||||
# * See the NOTICE file distributed with this work for additional
|
||||
# * information regarding copyright ownership.
|
||||
# * Unless required by applicable law or agreed to in writing, software
|
||||
# * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# * License for the specific language governing permissions and limitations
|
||||
# * under the License.
|
||||
# *
|
||||
# * SPDX-License-Identifier: Apache-2.0
|
||||
# ******************************************************************************/
|
||||
#
|
||||
|
||||
if [ -f "/usr/local/lib/libnd4jcpu.so" ]; then
|
||||
cat >/etc/ld.so.conf.d/libnd4jcpu.conf <<EOF
|
||||
/usr/local/lib/libnd4jcpu.so
|
||||
EOF
|
||||
else if [ -f "/usr/local/lib/libnd4jcuda.so" ]; then
|
||||
cat >/etc/ld.so.conf.d/libnd4jcuda.conf <<EOF
|
||||
/usr/local/lib/libnd4jcuda.so
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
ldconfig
|
||||
@@ -0,0 +1,34 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
# the name of the target operating system
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
|
||||
# which compilers to use for C and C++
|
||||
set(CMAKE_C_COMPILER powerpc-linux-gnu-gcc)
|
||||
set(CMAKE_CXX_COMPILER powerpc-linux-gnu-g++)
|
||||
|
||||
# here is the target environment located
|
||||
set(CMAKE_FIND_ROOT_PATH /usr/powerpc-linux-gnu )
|
||||
|
||||
# adjust the default behaviour of the FIND_XXX() commands:
|
||||
# search headers and libraries in the target environment, search
|
||||
# programs in the host environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
@@ -0,0 +1,58 @@
|
||||
################################################################################
|
||||
#
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Apache License, Version 2.0 which is available at
|
||||
# https://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# See the NOTICE file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
################################################################################
|
||||
|
||||
SET(CMAKE_SYSTEM_NAME Linux)
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
|
||||
set(CMAKE_C_COMPILER "$ENV{RPI_BIN}-gcc" )
|
||||
set(CMAKE_CXX_COMPILER "$ENV{RPI_BIN}-g++" )
|
||||
|
||||
if (SD_CUDA)
|
||||
if(${SD_ARCH} MATCHES "armv8")
|
||||
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||
else()
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${SD_ARCH})
|
||||
endif()
|
||||
set(CUDA_TARGET_CPU_ARCH ${CMAKE_SYSTEM_PROCESSOR})
|
||||
set(CUDA_TARGET_OS_VARIANT "linux")
|
||||
if (SD_CUDA)
|
||||
set(ENV{CUDAHOSTCXX} "${CMAKE_CXX_COMPILER}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH "")
|
||||
|
||||
if(DEFINED ENV{SYSROOT})
|
||||
set(CMAKE_SYSROOT "$ENV{SYSROOT}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --sysroot=$ENV{SYSROOT}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --sysroot=$ENV{SYSROOT}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --sysroot=$ENV{SYSROOT}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --sysroot=$ENV{SYSROOT}")
|
||||
list(APPEND CMAKE_FIND_ROOT_PATH "$ENV{SYSROOT}")
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{CUDNN_ROOT_DIR})
|
||||
list(APPEND CMAKE_FIND_ROOT_PATH "$ENV{CUDNN_ROOT_DIR}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
#search only in target path
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
@@ -0,0 +1 @@
|
||||
set(NDK_SYSTEM_LIBS "libEGL.so;libGLESv1_CM.so;libGLESv2.so;libGLESv3.so;libOpenMAXAL.so;libOpenSLES.so;libaaudio.so;libamidi.so;libandroid.so;libbinder_ndk.so;libc.so;libcamera2ndk.so;libdl.so;libicu.so;libjnigraphics.so;liblog.so;libm.so;libmediandk.so;libnativehelper.so;libnativewindow.so;libneuralnetworks.so;libstdc++.so;libsync.so;libvulkan.so;libz.so")
|
||||
Reference in New Issue
Block a user