diff --git a/CMakeLists.txt b/CMakeLists.txt index fd142c14..457d4bf4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -323,9 +323,6 @@ target_include_directories( mlx PUBLIC $ $) -# Do not add mlx_EXPORTS define for shared library. -set_target_properties(mlx PROPERTIES DEFINE_SYMBOL "") - if(USE_SYSTEM_FMT) find_package(fmt REQUIRED) else() diff --git a/mlx/CMakeLists.txt b/mlx/CMakeLists.txt index 0f122e61..82e72a7e 100644 --- a/mlx/CMakeLists.txt +++ b/mlx/CMakeLists.txt @@ -25,6 +25,21 @@ target_compile_definitions(mlx_version PRIVATE MLX_VERSION="${MLX_VERSION}") target_include_directories(mlx_version PRIVATE ${PROJECT_SOURCE_DIR}) target_link_libraries(mlx PRIVATE $) +# Do not export symbols by default. +set_target_properties( + mlx mlx_version + PROPERTIES VISIBILITY_INLINES_HIDDEN ON + CXX_VISIBILITY_PRESET hidden + CUDA_VISIBILITY_PRESET hidden) + +# Define MLX_EXPORT for shared libraries. +set_target_properties(mlx mlx_version PROPERTIES DEFINE_SYMBOL MLX_EXPORT) +# Define MLX_STATIC for static libraries. +if(NOT BUILD_SHARED_LIBS) + target_compile_definitions(mlx PUBLIC MLX_STATIC) + target_compile_definitions(mlx_version PUBLIC MLX_STATIC) +endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # Supress warnings: note: parameter passing for argument of type # 'std::pair' when C++17 is enabled changed to match C++14 in @@ -33,16 +48,6 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") endif() if(MSVC) - # Windows DLLs have a 65535 symbol export limit. We use explicit exports via - # MLX_API macro (__declspec(dllexport)) on public API functions only. This - # avoids exporting internal template instantiations. - if(BUILD_SHARED_LIBS) - target_compile_definitions(mlx PRIVATE MLX_EXPORT) - target_compile_definitions(mlx_version PRIVATE MLX_EXPORT) - else() - target_compile_definitions(mlx PUBLIC MLX_STATIC) - target_compile_definitions(mlx_version PRIVATE MLX_STATIC) - endif() # Some of CUDA's headers include windows.h, which defines min/max macros. target_compile_definitions(mlx PRIVATE NOMINMAX) # Disable some MSVC warnings to speed up compilation. diff --git a/mlx/api.h b/mlx/api.h index e2a701d0..8aed0910 100644 --- a/mlx/api.h +++ b/mlx/api.h @@ -2,30 +2,28 @@ #pragma once -// MLX_API macro for controlling symbol visibility -// -// On Windows, DLL symbols must be explicitly exported. This header provides -// the MLX_API macro which: -// - Expands to __declspec(dllexport) when building the MLX DLL (MLX_EXPORT -// defined) -// - Expands to __declspec(dllimport) when using the MLX DLL -// - Expands to nothing for static library builds or non-Windows platforms +// MLX_API macro for controlling symbol visibility, must add for public APIs. // // Usage: -// MLX_API array arange(double start, double stop, ...); +// MLX_API void some_function(...); // class MLX_API SomeClass { ... }; -#if defined(_WIN32) || defined(_WIN64) #if defined(MLX_STATIC) + // Static library build - no import/export decorations needed #define MLX_API -#elif defined(MLX_EXPORT) + +#else + +// Shared library build. +#if defined(_WIN32) +#if defined(MLX_EXPORT) #define MLX_API __declspec(dllexport) #else #define MLX_API __declspec(dllimport) -#endif +#endif // defined(MLX_EXPORT) #else -// On non-Windows platforms, symbols are visible by default -// Could use __attribute__((visibility("default"))) if needed -#define MLX_API -#endif +#define MLX_API __attribute__((visibility("default"))) +#endif // defined(_WIN32) + +#endif // defined(MLX_STATIC) diff --git a/mlx/backend/cpu/encoder.h b/mlx/backend/cpu/encoder.h index b8e33ca8..e04179e5 100644 --- a/mlx/backend/cpu/encoder.h +++ b/mlx/backend/cpu/encoder.h @@ -12,7 +12,7 @@ namespace mlx::core::cpu { // Number of dispatches per scheduler task constexpr int DISPATCHES_PER_TASK = 10; -struct CommandEncoder { +struct MLX_API CommandEncoder { CommandEncoder(Stream stream) : stream_(stream) {} CommandEncoder(const CommandEncoder&) = delete; @@ -62,6 +62,6 @@ struct CommandEncoder { int num_ops_{0}; }; -CommandEncoder& get_command_encoder(Stream stream); +MLX_API CommandEncoder& get_command_encoder(Stream stream); } // namespace mlx::core::cpu diff --git a/mlx/backend/metal/device.h b/mlx/backend/metal/device.h index a433b804..bf83b8cf 100644 --- a/mlx/backend/metal/device.h +++ b/mlx/backend/metal/device.h @@ -20,7 +20,7 @@ using MTLFCList = struct DeviceStream; -struct CommandEncoder { +struct MLX_API CommandEncoder { explicit CommandEncoder(DeviceStream& stream); CommandEncoder(const CommandEncoder&) = delete; CommandEncoder& operator=(const CommandEncoder&) = delete; @@ -146,7 +146,7 @@ struct DeviceStream { std::vector temporaries; }; -class Device { +class MLX_API Device { public: Device(); Device(const Device&) = delete; @@ -261,7 +261,7 @@ class Device { int max_mb_per_buffer_; }; -Device& device(mlx::core::Device); +MLX_API Device& device(mlx::core::Device); std::unique_ptr> new_scoped_memory_pool(); diff --git a/mlx/backend/metal/utils.h b/mlx/backend/metal/utils.h index e7784e59..dcee1e2b 100644 --- a/mlx/backend/metal/utils.h +++ b/mlx/backend/metal/utils.h @@ -10,8 +10,8 @@ namespace mlx::core { -std::string type_to_name(const Dtype& t); -std::string type_to_name(const array& a); +MLX_API std::string type_to_name(const Dtype& t); +MLX_API std::string type_to_name(const array& a); // Compute the grid and block dimensions, check backend/common/utils.h for docs. MTL::Size get_block_dims(int dim0, int dim1, int dim2, int pow2 = 10); diff --git a/mlx/dtype.cpp b/mlx/dtype.cpp index 429fa420..380a9362 100644 --- a/mlx/dtype.cpp +++ b/mlx/dtype.cpp @@ -92,6 +92,21 @@ Dtype::Kind kindof(const Dtype& t) { return type_kinds[static_cast(t.val())]; } +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; +template class MLX_API TypeToDtype; + template <> TypeToDtype::operator Dtype() { return bool_; diff --git a/mlx/primitives.h b/mlx/primitives.h index 1e02d96d..4091aafc 100644 --- a/mlx/primitives.h +++ b/mlx/primitives.h @@ -173,7 +173,7 @@ class Abs : public UnaryPrimitive { DEFINE_INPUT_OUTPUT_SHAPE() }; -class Add : public UnaryPrimitive { +class MLX_API Add : public UnaryPrimitive { public: explicit Add(Stream stream) : UnaryPrimitive(stream) {} @@ -624,7 +624,7 @@ class Ceil : public UnaryPrimitive { DEFINE_INPUT_OUTPUT_SHAPE() }; -class Compiled : public Primitive { +class MLX_API Compiled : public Primitive { public: /* * The inputs, outputs and tape are either tracers or constants. @@ -1018,7 +1018,7 @@ class ErfInv : public UnaryPrimitive { DEFINE_INPUT_OUTPUT_SHAPE() }; -class Exp : public UnaryPrimitive { +class MLX_API Exp : public UnaryPrimitive { public: explicit Exp(Stream stream) : UnaryPrimitive(stream) {} @@ -1768,7 +1768,7 @@ class Reshape : public UnaryPrimitive { Shape shape_; }; -class Reduce : public UnaryPrimitive { +class MLX_API Reduce : public UnaryPrimitive { public: enum ReduceType { And, Or, Sum, Prod, Min, Max };