| find_library(FOUNDATION_LIBRARY Foundation REQUIRED) | |
| find_library(METAL_FRAMEWORK Metal REQUIRED) | |
| find_library(METALKIT_FRAMEWORK MetalKit REQUIRED) | |
| message(STATUS "Metal framework found") | |
| ggml_add_backend_library(ggml-metal | |
| ggml-metal.m | |
| ) | |
| target_link_libraries(ggml-metal PRIVATE | |
| ${FOUNDATION_LIBRARY} | |
| ${METAL_FRAMEWORK} | |
| ${METALKIT_FRAMEWORK} | |
| ) | |
| if (GGML_METAL_NDEBUG) | |
| add_compile_definitions(GGML_METAL_NDEBUG) | |
| endif() | |
| if (GGML_METAL_USE_BF16) | |
| add_compile_definitions(GGML_METAL_USE_BF16) | |
| endif() | |
| # copy metal files to bin directory | |
| configure_file(../ggml-common.h ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-common.h COPYONLY) | |
| configure_file(ggml-metal.metal ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.metal COPYONLY) | |
| configure_file(ggml-metal-impl.h ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal-impl.h COPYONLY) | |
| if (GGML_METAL_EMBED_LIBRARY) | |
| enable_language(ASM) | |
| add_compile_definitions(GGML_METAL_EMBED_LIBRARY) | |
| set(METALLIB_COMMON "${CMAKE_CURRENT_SOURCE_DIR}/../ggml-common.h") | |
| set(METALLIB_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/ggml-metal.metal") | |
| set(METALLIB_IMPL "${CMAKE_CURRENT_SOURCE_DIR}/ggml-metal-impl.h") | |
| file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/autogenerated") | |
| # merge ggml-common.h and ggml-metal.metal into a single file | |
| set(METALLIB_EMBED_ASM "${CMAKE_BINARY_DIR}/autogenerated/ggml-metal-embed.s") | |
| set(METALLIB_SOURCE_EMBED "${CMAKE_BINARY_DIR}/autogenerated/ggml-metal-embed.metal") | |
| set(METALLIB_SOURCE_EMBED_TMP "${CMAKE_BINARY_DIR}/autogenerated/ggml-metal-embed.metal.tmp") | |
| add_custom_command( | |
| OUTPUT ${METALLIB_EMBED_ASM} | |
| COMMAND echo "Embedding Metal library" | |
| COMMAND sed -e '/__embed_ggml-common.h__/r ${METALLIB_COMMON}' -e '/__embed_ggml-common.h__/d' < ${METALLIB_SOURCE} > ${METALLIB_SOURCE_EMBED_TMP} | |
| COMMAND sed -e '/\#include \"ggml-metal-impl.h\"/r ${METALLIB_IMPL}' -e '/\#include \"ggml-metal-impl.h\"/d' < ${METALLIB_SOURCE_EMBED_TMP} > ${METALLIB_SOURCE_EMBED} | |
| COMMAND echo ".section __DATA,__ggml_metallib" > ${METALLIB_EMBED_ASM} | |
| COMMAND echo ".globl _ggml_metallib_start" >> ${METALLIB_EMBED_ASM} | |
| COMMAND echo "_ggml_metallib_start:" >> ${METALLIB_EMBED_ASM} | |
| COMMAND echo ".incbin \\\"${METALLIB_SOURCE_EMBED}\\\"" >> ${METALLIB_EMBED_ASM} | |
| COMMAND echo ".globl _ggml_metallib_end" >> ${METALLIB_EMBED_ASM} | |
| COMMAND echo "_ggml_metallib_end:" >> ${METALLIB_EMBED_ASM} | |
| DEPENDS ../ggml-common.h ggml-metal.metal ggml-metal-impl.h | |
| COMMENT "Generate assembly for embedded Metal library" | |
| ) | |
| target_sources(ggml-metal PRIVATE ${METALLIB_EMBED_ASM}) | |
| else() | |
| if (GGML_METAL_SHADER_DEBUG) | |
| # custom command to do the following: | |
| # xcrun -sdk macosx metal -fno-fast-math -c ggml-metal.metal -o ggml-metal.air | |
| # xcrun -sdk macosx metallib ggml-metal.air -o default.metallib | |
| # | |
| # note: this is the only way I found to disable fast-math in Metal. it's ugly, but at least it works | |
| # disabling fast math is needed in order to pass tests/test-backend-ops | |
| # note: adding -fno-inline fixes the tests when using MTL_SHADER_VALIDATION=1 | |
| # note: unfortunately, we have to call it default.metallib instead of ggml.metallib | |
| # ref: https://github.com/ggerganov/whisper.cpp/issues/1720 | |
| set(XC_FLAGS -fno-fast-math -fno-inline -g) | |
| else() | |
| set(XC_FLAGS -O3) | |
| endif() | |
| # Append macOS metal versioning flags | |
| if (GGML_METAL_MACOSX_VERSION_MIN) | |
| message(STATUS "Adding -mmacosx-version-min=${GGML_METAL_MACOSX_VERSION_MIN} flag to metal compilation") | |
| list (APPEND XC_FLAGS -mmacosx-version-min=${GGML_METAL_MACOSX_VERSION_MIN}) | |
| endif() | |
| if (GGML_METAL_STD) | |
| message(STATUS "Adding -std=${GGML_METAL_STD} flag to metal compilation") | |
| list (APPEND XC_FLAGS -std=${GGML_METAL_STD}) | |
| endif() | |
| add_custom_command( | |
| OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.metallib | |
| COMMAND xcrun -sdk macosx metal ${XC_FLAGS} -c ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.metal -o ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.air | |
| COMMAND xcrun -sdk macosx metallib ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.air -o ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.metallib | |
| COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.air | |
| COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-common.h | |
| COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.metal | |
| DEPENDS ggml-metal.metal ggml-common.h | |
| COMMENT "Compiling Metal kernels" | |
| ) | |
| # FIXME: only add to the ggml-metal target? | |
| add_custom_target( | |
| ggml-metal-lib ALL | |
| DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.metallib | |
| ) | |
| endif() # GGML_METAL_EMBED_LIBRARY | |