From 310ad8d9db16e838b556c88a2f8aacc7c7083510 Mon Sep 17 00:00:00 2001 From: Cheng Date: Wed, 11 Dec 2024 09:14:44 +0900 Subject: [PATCH] Build OpenBLAS from source code for MSVC (#1674) * Download OpenBLAS binaries when building with MSVC * Download dlfcn-win32 * Link with dlfcn-win32 correctly * Build OpenBLAS from source code * Link with openblas statically * Link with BLAS privately --- CMakeLists.txt | 52 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b6228167..ff3df8aa6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ option(MLX_METAL_DEBUG "Enhance metal debug workflow" OFF) option(MLX_ENABLE_X64_MAC "Enable building for x64 macOS" OFF) option(MLX_BUILD_GGUF "Include support for GGUF format" ON) option(MLX_BUILD_SAFETENSORS "Include support for safetensors format" ON) +option(MLX_BUILD_BLAS_FROM_SOURCE "Build OpenBLAS from source code" OFF) option(MLX_METAL_JIT "Use JIT compilation for Metal kernels" OFF) option(BUILD_SHARED_LIBS "Build mlx as a shared library" OFF) @@ -112,16 +113,52 @@ elseif(MLX_BUILD_METAL) target_link_libraries(mlx PUBLIC ${METAL_LIB} ${FOUNDATION_LIB} ${QUARTZ_LIB}) endif() +if(WIN32) + if(MSVC) + # GGUF does not build with MSVC. + set(MLX_BUILD_GGUF OFF) + # There is no prebuilt OpenBLAS distribution for MSVC. + set(MLX_BUILD_BLAS_FROM_SOURCE ON) + endif() + # Windows implementation of dlfcn.h APIs. + FetchContent_Declare( + dlfcn-win32 + GIT_REPOSITORY https://github.com/dlfcn-win32/dlfcn-win32.git + GIT_TAG v1.4.1 + EXCLUDE_FROM_ALL) + FetchContent_MakeAvailable(dlfcn-win32) + target_include_directories(mlx PRIVATE "${dlfcn-win32_SOURCE_DIR}/src") + target_link_libraries(mlx PRIVATE dl) +endif() + if(MLX_BUILD_CPU) find_library(ACCELERATE_LIBRARY Accelerate) if(ACCELERATE_LIBRARY) message(STATUS "Accelerate found ${ACCELERATE_LIBRARY}") set(MLX_BUILD_ACCELERATE ON) - target_link_libraries(mlx PUBLIC ${ACCELERATE_LIBRARY}) - add_compile_definitions(ACCELERATE_NEW_LAPACK) else() message(STATUS "Accelerate or arm neon not found, using default backend.") set(MLX_BUILD_ACCELERATE OFF) + endif() + + if(MLX_BUILD_ACCELERATE) + target_link_libraries(mlx PUBLIC ${ACCELERATE_LIBRARY}) + add_compile_definitions(ACCELERATE_NEW_LAPACK) + elseif(MLX_BUILD_BLAS_FROM_SOURCE) + # Download and build OpenBLAS from source code. + FetchContent_Declare( + openblas + GIT_REPOSITORY https://github.com/OpenMathLib/OpenBLAS.git + GIT_TAG v0.3.28 + EXCLUDE_FROM_ALL) + set(BUILD_STATIC_LIBS ON) # link statically + set(NOFORTRAN ON) # msvc has no fortran compiler + FetchContent_MakeAvailable(openblas) + target_link_libraries(mlx PRIVATE openblas) + target_include_directories( + mlx PRIVATE "${openblas_SOURCE_DIR}/lapack-netlib/LAPACKE/include" + "${CMAKE_BINARY_DIR}/generated" "${CMAKE_BINARY_DIR}") + else() if(${CMAKE_HOST_APPLE}) # The blas shipped in macOS SDK is not supported, search homebrew for # openblas instead. @@ -139,7 +176,7 @@ if(MLX_BUILD_CPU) message(STATUS "Lapack lib " ${LAPACK_LIBRARIES}) message(STATUS "Lapack include " ${LAPACK_INCLUDE_DIRS}) target_include_directories(mlx PRIVATE ${LAPACK_INCLUDE_DIRS}) - target_link_libraries(mlx PUBLIC ${LAPACK_LIBRARIES}) + target_link_libraries(mlx PRIVATE ${LAPACK_LIBRARIES}) # List blas after lapack otherwise we may accidentally incldue an old # version of lapack.h from the include dirs of blas. find_package(BLAS REQUIRED) @@ -152,14 +189,7 @@ if(MLX_BUILD_CPU) message(STATUS "Blas lib " ${BLAS_LIBRARIES}) message(STATUS "Blas include " ${BLAS_INCLUDE_DIRS}) target_include_directories(mlx PRIVATE ${BLAS_INCLUDE_DIRS}) - target_link_libraries(mlx PUBLIC ${BLAS_LIBRARIES}) - - if(WIN32) - find_package(dlfcn-win32 REQUIRED) - message(STATUS "dlfcn-win32 lib " ${dlfcn-win32_LIBRARIES}) - message(STATUS "dlfcn-win32 include " ${dlfcn-win32_INCLUDE_DIRS}) - target_link_libraries(mlx PUBLIC ${dlfcn-win32_LIBRARIES}) - endif() + target_link_libraries(mlx PRIVATE ${BLAS_LIBRARIES}) endif() else() set(MLX_BUILD_ACCELERATE OFF)