Skip to content

cmake : handle whitepsaces in path during metal build #14126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 12, 2025

Conversation

ggerganov
Copy link
Member

fix #14108

@github-actions github-actions bot added ggml changes relating to the ggml tensor library for machine learning Apple Metal https://en.wikipedia.org/wiki/Metal_(API) labels Jun 11, 2025
@danbev
Copy link
Collaborator

danbev commented Jun 12, 2025

I've given this a try using a path that contains a space (/Users/danbev/work/ai/llama space/) but got the following error at runtime:

ggml_metal_init: found device: Apple M3
ggml_metal_init: picking default device: Apple M3
ggml_metal_load_library: using embedded metal library
ggml_metal_load_library: error: Error Domain=MTLLibraryErrorDomain Code=3 "program_source:65:35: error: unknown type name 'block_q4_0'
void dequantize_q4_0(device const block_q4_0 * xb, short il, thread type4x4 & reg) {
                                  ^
program_source:84:38: error: unknown type name 'block_q4_0'
void dequantize_q4_0_t4(device const block_q4_0 * xb, short il, thread type4 & reg) {
                                     ^

Inspecting the generated metal file it looks like the sed replacement did not work:

$ head build/autogenerated/ggml-metal-embed.metal
#define GGML_COMMON_DECL_METAL
#define GGML_COMMON_IMPL_METAL
#if defined(GGML_METAL_EMBED_LIBRARY)
#else
#include "ggml-common.h"
#endif

#include <metal_stdlib>

using namespace metal;

Notice the empty GGML_METAL_EMBED_LIBRARY block.

I've tried a few different things to try to get this to work and the following seems to work for this case:

diff --git a/ggml/src/ggml-metal/CMakeLists.txt b/ggml/src/ggml-metal/CMakeLists.txt
index 58ea3073..b5e0ac22 100644
--- a/ggml/src/ggml-metal/CMakeLists.txt
+++ b/ggml/src/ggml-metal/CMakeLists.txt
@@ -46,16 +46,17 @@ if (GGML_METAL_EMBED_LIBRARY)
     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 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 .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}")

Inspecting the generated metal file using the above diff:

$ head build/autogenerated/ggml-metal-embed.metal
#define GGML_COMMON_DECL_METAL
#define GGML_COMMON_IMPL_METAL
#if defined(GGML_METAL_EMBED_LIBRARY)
#ifndef GGML_COMMON_DECL

#if defined(GGML_COMMON_DECL_C)
#include <stdint.h>

typedef uint16_t ggml_half;
typedef uint32_t ggml_half2;

This time the replacement has been performed.

And the generated assembly source file looks like this which is the same as the original change:

$ cat build/autogenerated/ggml-metal-embed.s
.section __DATA,__ggml_metallib
.globl _ggml_metallib_start
_ggml_metallib_start:
.incbin "/Users/danbev/work/ai/llama space/build/autogenerated/ggml-metal-embed.metal"
.globl _ggml_metallib_end
_ggml_metallib_end:

And there is no longer an error at runtime.

@ggerganov ggerganov requested a review from danbev June 12, 2025 06:54
@ggerganov ggerganov merged commit e2c0b6e into master Jun 12, 2025
54 checks passed
@ggerganov ggerganov deleted the gg/metal-fix-ws-in-path branch June 12, 2025 07:14
@dannoll
Copy link

dannoll commented Jun 12, 2025

Thanks @danbev!

Confirming that your fix worked perfectly. The embedded Metal library now works correctly. I was struggling with the same issue and spent quite a bit of time trying different quoting approaches and VERBATIM, but could not get it to work. Really appreciate you taking the time to figure this out and for the quick turnaround. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Apple Metal https://en.wikipedia.org/wiki/Metal_(API) ggml changes relating to the ggml tensor library for machine learning
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Compile bug: [macOS] Metal shader compilation produces a binary but with non-functional Metal support due to corrupted Metal source embedding
3 participants