Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/test-windows/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ runs:
DEVICE: cpu
run: |
echo "::group::CPP tests - CPU"
./build/tests/tests -tce="*gguf*,test random uniform"
./build/tests.exe -tce="*gguf*,test random uniform"
echo "::endgroup::"
49 changes: 31 additions & 18 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ 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_BUILD_PYTHON_STUBS "Build stub files for python bindings" ON)
option(MLX_METAL_JIT "Use JIT compilation for Metal kernels" OFF)
option(MLX_USE_CCACHE "Use CCache for compilation cache when available" ON)
Expand Down Expand Up @@ -219,14 +218,17 @@ 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()
# Generate DLL and EXE in the same dir, otherwise EXE will not be able to run.
# This is only done when MLX is built as the top project.
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
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
GIT_TAG v1.4.2
EXCLUDE_FROM_ALL)
block()
set(BUILD_SHARED_LIBS OFF)
Expand All @@ -250,23 +252,25 @@ if(MLX_BUILD_CPU)
target_link_libraries(mlx PUBLIC ${ACCELERATE_LIBRARY})
add_compile_definitions(MLX_USE_ACCELERATE)
add_compile_definitions(ACCELERATE_NEW_LAPACK)
elseif(MLX_BUILD_BLAS_FROM_SOURCE)
# Download and build OpenBLAS from source code.
elseif(WIN32)
# Download and link prebuilt binaries of OpenBLAS. Note that we can only
# link with the dynamic library, the prebuilt binaries were built with MinGW
# so static-linking would require linking with MinGW's runtime.
FetchContent_Declare(
openblas
GIT_REPOSITORY https://github.com/OpenMathLib/OpenBLAS.git
GIT_TAG v0.3.28
EXCLUDE_FROM_ALL)
block(PROPAGATE openblas_SOURCE_DIR)
set(BUILD_SHARED_LIBS OFF) # link statically
set(BUILD_STATIC_LIBS ON)
set(NOFORTRAN ON) # msvc has no fortran compiler
URL "https://github.com/OpenMathLib/OpenBLAS/releases/download/v0.3.31/OpenBLAS-0.3.31-x64.zip"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw, I've also been playing around with trying to get things building on Windows ARM64, which needed patching of the OpenBLAS cmake files to get all the variables set up properly for LLVM-MinGW.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OpenBLAS provides binaries for Windows ARM64 (the woa64 files), can we just link with that?

)
FetchContent_MakeAvailable(openblas)
endblock()
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}")
target_link_libraries(mlx
PRIVATE "${openblas_SOURCE_DIR}/lib/libopenblas.lib")
target_include_directories(mlx PRIVATE "${openblas_SOURCE_DIR}/include")
# Make sure the DLL file is placed in the same dir with executables.
set(OPENBLAS_DLL_FILE "${openblas_SOURCE_DIR}/bin/libopenblas.dll")
add_custom_command(
TARGET mlx
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${OPENBLAS_DLL_FILE}
${CMAKE_BINARY_DIR})
else()
if(${CMAKE_HOST_APPLE})
# The blas shipped in macOS SDK is not supported, search homebrew for
Expand Down Expand Up @@ -365,6 +369,15 @@ endif()
# ----------------------------- Installation -----------------------------
include(GNUInstallDirs)

if(WIN32)
# Install DLLs to the same dir with extension file (core.pyd) on Windows.
set(CMAKE_INSTALL_BINDIR ".")
if(MLX_BUILD_CPU)
# Install OpenBLAS.
install(FILES ${OPENBLAS_DLL_FILE} TYPE BIN)
endif()
endif()

# Install library
install(
TARGETS mlx
Expand Down
8 changes: 0 additions & 8 deletions benchmarks/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@ function(build_benchmark SRCFILE)
set(target "${src_name}")
add_executable(${target} ${SRCFILE})
target_link_libraries(${target} PRIVATE mlx)
# On Windows, copy the mlx DLL to the executable directory for runtime loading
if(WIN32 AND BUILD_SHARED_LIBS)
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:mlx>
$<TARGET_FILE_DIR:${target}>)
endif()
endfunction(build_benchmark)

build_benchmark(single_ops.cpp)
Expand Down
8 changes: 0 additions & 8 deletions examples/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@ function(build_example SRCFILE)
set(target "${src_name}")
add_executable(${target} ${SRCFILE})
target_link_libraries(${target} PRIVATE mlx)
# On Windows, copy the mlx DLL to the executable directory for runtime loading
if(WIN32 AND BUILD_SHARED_LIBS)
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:mlx>
$<TARGET_FILE_DIR:${target}>)
endif()
endfunction(build_example)

build_example(tutorial.cpp)
Expand Down
8 changes: 1 addition & 7 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def build_extension(self, ext: CMakeExtension) -> None:
"-DMLX_BUILD_TESTS=OFF",
"-DMLX_BUILD_BENCHMARKS=OFF",
"-DMLX_BUILD_EXAMPLES=OFF",
"-DBUILD_SHARED_LIBS=ON",
]
if build_stage == 2 and build_cuda:
# Last arch is always real and virtual for forward-compatibility
Expand Down Expand Up @@ -125,13 +126,6 @@ def build_extension(self, ext: CMakeExtension) -> None:
archs = re.findall(r"-arch (\S+)", os.environ.get("ARCHFLAGS", ""))
if archs:
cmake_args += ["-DCMAKE_OSX_ARCHITECTURES={}".format(";".join(archs))]
if platform.system() == "Windows":
# On Windows DLLs must be put in the same dir with the extension
# while cmake puts mlx.dll into the "bin" sub-dir. Link with mlx
# statically to work around it.
cmake_args += ["-DBUILD_SHARED_LIBS=OFF"]
else:
cmake_args += ["-DBUILD_SHARED_LIBS=ON"]

# Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level
# across all generators.
Expand Down
10 changes: 0 additions & 10 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,5 @@ target_link_libraries(tests PRIVATE mlx doctest)
target_compile_options(tests PRIVATE ${SANITIZER_COMPILE_FLAGS})
target_link_options(tests PRIVATE ${SANITIZER_LINK_FLAGS})

# On Windows, copy the mlx DLL to the test executable directory for runtime
# loading
if(WIN32 AND BUILD_SHARED_LIBS)
add_custom_command(
TARGET tests
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:mlx>
$<TARGET_FILE_DIR:tests>)
endif()

doctest_discover_tests(tests)
add_test(NAME tests COMMAND tests)
Loading