fn main() {
let target = std::env::var("TARGET").unwrap_or_default();
println!("cargo:rustc-check-cfg=cfg(numrs_has_mkl)");
println!("cargo:rustc-check-cfg=cfg(numrs_has_blis)");
println!("cargo:rustc-check-cfg=cfg(numrs_has_blas)");
println!("cargo:rustc-check-cfg=cfg(numrs_has_accelerate)");
println!("cargo:rustc-check-cfg=cfg(numrs_has_avx2)");
println!("cargo:rustc-check-cfg=cfg(numrs_has_fma)");
println!("cargo:rustc-check-cfg=cfg(numrs_prefer_blas_for_matmul)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_matmul_blas)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_matmul_simd)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_matmul_gpu)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_matmul_scalar)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_sum_blas)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_sum_simd)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_sum_gpu)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_sum_scalar)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_elementwise_blas)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_elementwise_simd)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_elementwise_gpu)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_elementwise_scalar)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_conv_gpu)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_conv_simd)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_batchnorm_gpu)");
println!("cargo:rustc-check-cfg=cfg(numrs_kernel_dropout_gpu)");
let compile_all = std::env::var("NUMRS_COMPILE_ALL_KERNELS")
.map(|v| matches!(v.as_str(), "1" | "true" | "TRUE"))
.unwrap_or(false);
if compile_all {
println!("cargo:warning=NumRs: NUMRS_COMPILE_ALL_KERNELS=1 -> compiling all kernel variants for runtime probing");
println!("cargo:rustc-cfg=numrs_kernel_matmul_blas");
println!("cargo:rustc-cfg=numrs_kernel_matmul_simd");
println!("cargo:rustc-cfg=numrs_kernel_matmul_gpu");
println!("cargo:rustc-cfg=numrs_kernel_matmul_scalar");
println!("cargo:rustc-cfg=numrs_kernel_sum_blas");
println!("cargo:rustc-cfg=numrs_kernel_sum_simd");
println!("cargo:rustc-cfg=numrs_kernel_sum_gpu");
println!("cargo:rustc-cfg=numrs_kernel_sum_scalar");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_blas");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_simd");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_gpu");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_scalar");
println!("cargo:rustc-cfg=numrs_kernel_conv_gpu");
println!("cargo:rustc-cfg=numrs_kernel_conv_simd");
println!("cargo:rustc-cfg=numrs_kernel_batchnorm_gpu");
println!("cargo:rustc-cfg=numrs_kernel_dropout_gpu");
}
let mut has_accelerate = false;
let mut has_mkl = false;
let mut has_blis = false;
let is_wasm = target.contains("wasm32");
let blas_disabled = std::env::var("CARGO_FEATURE_DISABLED_BLAS").is_ok();
if blas_disabled {
println!("cargo:warning=NumRs: disabled-blas feature enabled -> no BLAS (pure Rust)");
} else if target.contains("apple-darwin") || target.contains("macos") {
has_accelerate = true;
println!("cargo:warning=NumRs: macOS detected -> using Accelerate framework (static)");
} else if !is_wasm && (target.contains("x86_64") || target.contains("x86")) {
has_mkl = true;
println!("cargo:warning=NumRs: x86_64 detected -> using intel-mkl-src (static, automatic)");
} else if !is_wasm {
has_blis = true;
println!("cargo:warning=NumRs: Non-x86 architecture detected -> using blis-src (static, automatic)");
} else {
println!("cargo:warning=NumRs: wasm32 detected -> no BLAS (pure Rust)");
}
let prefer_mkl_env = std::env::var("NUMRS_USE_MKL")
.map(|v| matches!(v.as_str(), "1" | "true" | "TRUE"))
.unwrap_or(false);
let prefer_blis_env = std::env::var("NUMRS_PREFER_BLIS")
.map(|v| matches!(v.as_str(), "1" | "true" | "TRUE"))
.unwrap_or(false);
if prefer_mkl_env && !has_mkl {
println!("cargo:warning=NumRs: NUMRS_USE_MKL=1 but mkl feature not enabled, ignoring");
}
if prefer_blis_env && !has_blis {
println!("cargo:warning=NumRs: NUMRS_PREFER_BLIS=1 but blis feature not enabled, ignoring");
}
if has_accelerate {
println!("cargo:rustc-cfg=numrs_has_accelerate");
println!("cargo:rustc-env=NUMRS_HAS_ACCELERATE=1");
println!("cargo:rustc-cfg=numrs_kernel_matmul_blas");
println!("cargo:rustc-cfg=numrs_kernel_sum_blas");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_blas");
}
if has_mkl {
println!("cargo:rustc-cfg=numrs_has_mkl");
println!("cargo:rustc-env=NUMRS_HAS_MKL=1");
println!("cargo:rustc-cfg=numrs_kernel_matmul_blas");
println!("cargo:rustc-cfg=numrs_kernel_sum_blas");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_blas");
}
if has_blis {
println!("cargo:rustc-cfg=numrs_has_blis");
println!("cargo:rustc-env=NUMRS_HAS_BLIS=1");
println!("cargo:rustc-cfg=numrs_kernel_matmul_blas");
println!("cargo:rustc-cfg=numrs_kernel_sum_blas");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_blas");
}
let has_blas = !blas_disabled && (has_accelerate || has_mkl || has_blis);
if has_blas {
println!("cargo:rustc-cfg=numrs_has_blas");
}
let host = std::env::var("HOST").unwrap_or_default();
let target = std::env::var("TARGET").unwrap_or_default();
let mut has_avx2 = false;
let mut has_fma = false;
let mut has_wasm_simd = false;
let disable_wasm_simd = std::env::var("NUMRS_DISABLE_WASM_SIMD")
.map(|v| matches!(v.as_str(), "1" | "true" | "TRUE"))
.unwrap_or(false);
if is_wasm && !disable_wasm_simd {
has_wasm_simd = true;
println!("cargo:rustc-cfg=numrs_has_wasm_simd");
println!("cargo:rustc-cfg=numrs_kernel_matmul_simd");
println!("cargo:rustc-cfg=numrs_kernel_sum_simd");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_simd");
println!("cargo:warning=NumRs: WASM SIMD128 enabled");
} else if host == target && (target.contains("x86_64") || target.contains("x86")) {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
has_avx2 = std::is_x86_feature_detected!("avx2");
has_fma = std::is_x86_feature_detected!("fma");
if has_avx2 {
println!("cargo:rustc-cfg=numrs_has_avx2");
}
if has_avx2 {
println!("cargo:rustc-cfg=numrs_kernel_matmul_simd");
println!("cargo:rustc-cfg=numrs_kernel_sum_simd");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_simd");
println!("cargo:rustc-cfg=numrs_kernel_conv_simd");
}
if has_fma {
println!("cargo:rustc-cfg=numrs_has_fma");
}
}
} else {
if let Ok(v) = std::env::var("NUMRS_ASSUME_AVX2") {
has_avx2 = matches!(v.as_str(), "1" | "true" | "TRUE");
}
if let Ok(v) = std::env::var("NUMRS_ASSUME_FMA") {
has_fma = matches!(v.as_str(), "1" | "true" | "TRUE");
}
}
let has_webgpu = cfg!(feature = "webgpu") || std::env::var("CARGO_FEATURE_WEBGPU").is_ok();
let has_webgl = cfg!(feature = "webgl") || std::env::var("CARGO_FEATURE_WEBGL").is_ok();
let has_gpu_env = std::env::var("NUMRS_HAS_GPU")
.map(|v| matches!(v.as_str(), "1" | "true" | "TRUE"))
.unwrap_or(false);
let has_gpu = has_webgpu || has_webgl || has_gpu_env;
if has_gpu {
println!("cargo:rustc-cfg=numrs_kernel_matmul_gpu");
println!("cargo:rustc-cfg=numrs_kernel_sum_gpu");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_gpu");
println!("cargo:rustc-cfg=numrs_kernel_conv_gpu");
println!("cargo:rustc-cfg=numrs_kernel_batchnorm_gpu");
println!("cargo:rustc-cfg=numrs_kernel_dropout_gpu");
}
let alignment_32 = target.contains("64") && !is_wasm;
let sum_method = if has_blas {
"sum_blas"
} else if has_avx2 || has_wasm_simd {
"sum_simd"
} else {
"sum_scalar"
};
let elementwise_method = if has_gpu {
"elementwise_gpu"
} else if has_avx2 || has_wasm_simd {
"elementwise_simd"
} else {
"elementwise_scalar"
};
let matmul_method = if has_accelerate {
"matmul_accel"
} else if has_mkl {
"matmul_mkl"
} else if has_blis {
"matmul_blis"
} else if has_gpu {
"matmul_gpu"
} else if has_avx2 || has_wasm_simd {
"matmul_simd"
} else {
"matmul_scalar"
};
println!("cargo:rustc-cfg=numrs_kernel_matmul_scalar");
println!("cargo:rustc-cfg=numrs_kernel_sum_scalar");
println!("cargo:rustc-cfg=numrs_kernel_elementwise_scalar");
println!("cargo:warning=NumRs: detectadas capacidades -> avx2={}, fma={}, mkl={}, blis={}, accelerate={}, blas_any={}, gpu={}, wasm={}, wasm_simd={}, align32={}", has_avx2, has_fma, has_mkl, has_blis, has_accelerate, has_blas, has_gpu, is_wasm, has_wasm_simd, alignment_32);
println!("cargo:warning=NumRs: selección por defecto de métodos (prioridad):");
println!("cargo:warning= SUMA: {}", sum_method);
println!("cargo:warning= ELEM: {}", elementwise_method);
println!("cargo:warning= MATMUL: {}", matmul_method);
if std::env::var("NUMRS_PREFER_BLAS_FOR_MATMUL")
.map(|v| matches!(v.as_str(), "1" | "true" | "TRUE"))
.unwrap_or(false)
{
println!("cargo:rustc-cfg=numrs_prefer_blas_for_matmul");
println!("cargo:warning=NumRs: opt-in build: prefer BLAS for MatMul enabled (NUMRS_PREFER_BLAS_FOR_MATMUL)");
}
}