| 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.cpp |
| ggml-metal-device.m |
| ggml-metal-device.cpp |
| ggml-metal-common.cpp |
| ggml-metal-context.m |
| ggml-metal-ops.cpp |
| ) |
|
|
| target_link_libraries(ggml-metal PRIVATE |
| ${FOUNDATION_LIBRARY} |
| ${METAL_FRAMEWORK} |
| ${METALKIT_FRAMEWORK} |
| ) |
|
|
| if (GGML_METAL_NDEBUG) |
| add_compile_definitions(GGML_METAL_NDEBUG) |
| 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) |
|
|
| set(METALLIB_COMMON "${CMAKE_CURRENT_SOURCE_DIR}/../ggml-common.h") |
| if (GGML_METAL_EMBED_LIBRARY) |
| enable_language(ASM) |
|
|
| add_compile_definitions(GGML_METAL_EMBED_LIBRARY) |
|
|
| 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" |
| VERBATIM |
| ) |
|
|
| 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 |
| # note: adding -g causes segmentation fault during compile |
| #set(XC_FLAGS -fno-fast-math -fno-inline -g) |
| set(XC_FLAGS -fno-fast-math -fno-inline) |
| 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 - | |
| xcrun -sdk macosx metallib - -o ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.metallib |
| COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-common.h |
| COMMAND rm -f ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ggml-metal.metal |
| DEPENDS ggml-metal.metal ${METALLIB_COMMON} |
| 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 |
|
|
| if (NOT GGML_METAL_EMBED_LIBRARY) |
| install( |
| FILES src/ggml-metal/ggml-metal.metal |
| PERMISSIONS |
| OWNER_READ |
| OWNER_WRITE |
| GROUP_READ |
| WORLD_READ |
| DESTINATION ${CMAKE_INSTALL_BINDIR}) |
|
|
| install( |
| FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.metallib |
| DESTINATION ${CMAKE_INSTALL_BINDIR} |
| ) |
| endif() |
|
|