Heuristic:Haifengl Smile Platform Native Library Selection
| Knowledge Sources | |
|---|---|
| Domains | Infrastructure, Cross_Platform, Native_Libraries |
| Last Updated | 2026-02-08 22:00 GMT |
Overview
Platform-specific rules for selecting BLAS, LAPACK, and ARPACK native library names to avoid `UnsatisfiedLinkError` on different operating systems.
Description
Smile auto-detects the operating system at runtime and selects the appropriate native library name for BLAS and LAPACK. This is necessary because each platform uses different library naming conventions: macOS provides BLAS/LAPACK through the Accelerate framework (library names `blas` and `lapack`), Linux uses OpenBLAS (library name `openblas` for both), and Windows requires `libopenblas` specifically because ARPACK has a hard dependency on that exact library name. Understanding this mapping prevents cryptic `UnsatisfiedLinkError` failures.
Usage
Use this heuristic when deploying Smile on a new platform, debugging native library loading failures, or customizing the BLAS/LAPACK backend. Particularly important when migrating between macOS and Linux, or when using a non-standard BLAS distribution (e.g., Intel MKL or ATLAS).
The Insight (Rule of Thumb)
- Action: Ensure the correct native library is installed for your platform, OR override via system properties.
- Value:
- Linux: Library name = `openblas` (install `libopenblas-dev`)
- macOS: Library name = `blas`/`lapack` (built-in Accelerate)
- Windows: Library name = `libopenblas` (not `openblas`!)
- Trade-off: Using the system default is simplest but limits vendor choice. Override via `-Dsmile.lib.blas=mkl` to use Intel MKL.
- Critical Windows note: Windows BLAS must be named `libopenblas`, not `openblas`, because ARPACK has a dependency on this exact filename.
- macOS SIP workaround: System Integrity Protection may block `DYLD_LIBRARY_PATH`. Copy `libarpack.dylib` directly to the working directory.
Reasoning
The platform detection uses `System.getProperty("os.name")` and normalizes it to lowercase, taking only the first word (e.g., "Mac OS X" becomes "mac", "Windows 10" becomes "windows"). This is a standard Java idiom for cross-platform code.
The Windows library naming constraint (`libopenblas` instead of `openblas`) is a subtle but critical detail: ARPACK's Fortran code links against `libopenblas` at compile time, so the DLL must match exactly. This is documented in a source code comment but easily missed.
Code evidence from `base/src/main/java/smile/linalg/blas/cblas_h.java:58-63`:
static final String OS = System.getProperty("os.name", "linux")
.toLowerCase().split(" ")[0];
static final String LIBRARY_NAME = System.getProperty("smile.lib.blas",
switch (OS) {
case "mac" -> "blas"; // macOS's builtin Accelerate framework
case "windows" -> "libopenblas"; // ARPACK depends on this name
default -> "openblas"; // OpenBLAS
});
The symbol lookup chain provides graceful fallback from `cblas_h.java:64-66`:
static final SymbolLookup SYMBOL_LOOKUP =
SymbolLookup.libraryLookup(System.mapLibraryName(LIBRARY_NAME), LIBRARY_ARENA)
.or(SymbolLookup.loaderLookup())
.or(Linker.nativeLinker().defaultLookup());
OS-specific cache directory from `base/src/main/java/smile/io/CacheFiles.java:41-51`:
String os = System.getProperty("os.name");
if (os.startsWith("Windows")) {
path = System.getenv("LocalAppData") + smile;
} else if (os.startsWith("Mac")) {
path = home + "/Library/Caches" + smile;
} else {
path = home + File.separator + ".cache" + smile;
}