@@ -13,6 +13,7 @@ fn main() {
1313
1414 let mut ggml = cc:: Build :: new ( ) ;
1515 let mut ggml_cuda = if cublas_enabled { Some ( cc:: Build :: new ( ) ) } else { None } ;
16+ let mut ggml_metal= if cfg ! ( target_os = "macos" ) { Some ( cc:: Build :: new ( ) ) } else { None } ;
1617 let mut llama_cpp = cc:: Build :: new ( ) ;
1718
1819 ggml. cpp ( false ) ;
@@ -60,20 +61,22 @@ fn main() {
6061 llama_cpp. define ( "GGML_USE_ACCELERATE" , None ) ;
6162 llama_cpp. define ( "ACCELERATE_NEW_LAPACK" , None ) ;
6263 llama_cpp. define ( "ACCELERATE_LAPACK_ILP64" , None ) ;
63- println ! ( "cargo:rustc-link-lib =framework=Accelerate" ) ;
64+ println ! ( "cargo:rustc-link-arg =framework=Accelerate" ) ;
6465
6566 // MK_LDFLAGS += -framework Foundation -framework Metal -framework MetalKit
6667 // https://github.com/ggerganov/llama.cpp/blob/3c0d25c4756742ebf15ad44700fabc0700c638bd/Makefile#L509-L511
67- println ! ( "cargo:rustc-link-lib =framework Foundation" ) ;
68- println ! ( "cargo:rustc-link-lib =framework Metal" ) ;
69- println ! ( "cargo:rustc-link-lib =framework MetalKit" ) ;
70-
68+ println ! ( "cargo:rustc-link-arg =framework= Foundation" ) ;
69+ println ! ( "cargo:rustc-link-arg =framework= Metal" ) ;
70+ println ! ( "cargo:rustc-link-arg =framework= MetalKit" ) ;
71+ }
7172
72- // https://github.com/ggerganov/llama.cpp/blob/3c0d25c4756742ebf15ad44700fabc0700c638bd/Makefile#L517-L520
73- ggml
74- . file ( "llama.cpp/ggml-metal.m" )
75- . file ( "llama.cpp/ggml-metal.h" ) ;
73+ if let Some ( ggml_metal) = & mut ggml_metal {
74+ metal_hack ( ggml_metal) ;
75+ ggml_metal
76+ . file ( "llama.cpp/ggml-metal" )
77+ . include ( "llama.cpp" ) ;
7678 }
79+
7780 if cfg ! ( target_os = "dragonfly" ) {
7881 llama_cpp. define ( "__BSD_VISIBLE" , None ) ;
7982 }
@@ -83,6 +86,12 @@ fn main() {
8386 ggml_cuda. compile ( "ggml-cuda" ) ;
8487 }
8588
89+
90+ if let Some ( ggml_metal) = ggml_metal {
91+ println ! ( "compiling ggml-metal" ) ;
92+ ggml_metal. compile ( "ggml-metal" )
93+ }
94+
8695 if cfg ! ( target_os = "linux" ) {
8796 ggml. define ( "_GNU_SOURCE" , None ) ;
8897 }
@@ -97,6 +106,7 @@ fn main() {
97106
98107 llama_cpp
99108 . define ( "_XOPEN_SOURCE" , Some ( "600" ) )
109+ . include ( "llama.cpp" )
100110 . std ( "c++17" )
101111 . file ( "llama.cpp/llama.cpp" ) ;
102112
@@ -124,3 +134,43 @@ fn main() {
124134 . write_to_file ( out_path. join ( "bindings.rs" ) )
125135 . expect ( "failed to write bindings to file" ) ;
126136}
137+
138+
139+ // courtesy of https://github.com/rustformers/llm
140+ fn metal_hack ( build : & mut cc:: Build ) {
141+ const GGML_METAL_METAL_PATH : & str = "llama.cpp/ggml-metal.metal" ;
142+ const GGML_METAL_PATH : & str = "llama.cpp/ggml-metal.m" ;
143+
144+ let out_dir = PathBuf :: from ( env:: var ( "OUT_DIR" ) . expect ( "OUT_DIR is not defined" ) ) ;
145+
146+ let ggml_metal_path = {
147+ let ggml_metal_metal = std:: fs:: read_to_string ( GGML_METAL_METAL_PATH )
148+ . expect ( "Could not read ggml-metal.metal" )
149+ . replace ( '\\' , "\\ \\ " )
150+ . replace ( '\n' , "\\ n" )
151+ . replace ( '\r' , "\\ r" )
152+ . replace ( '\"' , "\\ \" " ) ;
153+
154+ let ggml_metal =
155+ std:: fs:: read_to_string ( GGML_METAL_PATH ) . expect ( "Could not read ggml-metal.m" ) ;
156+
157+ let needle = r#"NSString * src = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:&error];"# ;
158+ if !ggml_metal. contains ( needle) {
159+ panic ! ( "ggml-metal.m does not contain the needle to be replaced; the patching logic needs to be reinvestigated. Contact a `llama-cpp-sys-2` developer!" ) ;
160+ }
161+
162+ // Replace the runtime read of the file with a compile-time string
163+ let ggml_metal = ggml_metal. replace (
164+ needle,
165+ & format ! ( r#"NSString * src = @"{ggml_metal_metal}";"# ) ,
166+ ) ;
167+
168+ let patched_ggml_metal_path = out_dir. join ( "ggml-metal.m" ) ;
169+ std:: fs:: write ( & patched_ggml_metal_path, ggml_metal)
170+ . expect ( "Could not write temporary patched ggml-metal.m" ) ;
171+
172+ patched_ggml_metal_path
173+ } ;
174+
175+ build. file ( ggml_metal_path) ;
176+ }
0 commit comments