llama-cpp-capacitor 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LlamaCppCapacitor.podspec +3 -0
- package/build-native.sh +34 -12
- package/ios/Frameworks/llama-cpp.framework/{Versions/A/llama-cpp → llama-cpp} +0 -0
- package/ios/Sources/LlamaCppPlugin/LlamaCpp.swift +21 -15
- package/package.json +3 -2
- /package/ios/Frameworks/llama-cpp.framework/{Versions/A/Resources/Info.plist → Info.plist} +0 -0
package/build-native.sh
CHANGED
|
@@ -93,36 +93,53 @@ build_ios() {
|
|
|
93
93
|
cd ios/build
|
|
94
94
|
|
|
95
95
|
# Configure with CMake
|
|
96
|
+
# IMPORTANT: CMAKE_OSX_SYSROOT=iphoneos ensures we build for iOS, not macOS.
|
|
97
|
+
# Without it, the framework would be built for macOS and fail to link in an iOS app.
|
|
96
98
|
# IMPORTANT: build iOS framework as **ARM64-only**.
|
|
97
99
|
# Including x86_64 here makes CMake/Xcode try to link an x86_64 slice,
|
|
98
100
|
# but we only compile ARM-specific kernels (arch/arm), which leads to
|
|
99
101
|
# undefined symbols like lm_ggml_gemm_* for x86_64.
|
|
100
102
|
cmake .. \
|
|
101
103
|
-DCMAKE_BUILD_TYPE=Release \
|
|
104
|
+
-DCMAKE_OSX_SYSROOT=iphoneos \
|
|
102
105
|
-DCMAKE_OSX_ARCHITECTURES="arm64" \
|
|
103
106
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
|
|
104
107
|
-DCMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE=NO
|
|
105
108
|
|
|
106
|
-
# Build
|
|
107
|
-
|
|
109
|
+
# Build (parallel: -j uses available CPU cores)
|
|
110
|
+
JOBS=$(sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 4)
|
|
111
|
+
cmake --build . --config Release -- -j"$JOBS"
|
|
108
112
|
|
|
109
113
|
# CMake builds the framework directly (FRAMEWORK TRUE in CMakeLists.txt)
|
|
110
114
|
# Verify the framework was created
|
|
111
115
|
if [ -d "llama-cpp.framework" ]; then
|
|
112
116
|
print_success "iOS framework built successfully at: $(pwd)/llama-cpp.framework"
|
|
113
117
|
|
|
114
|
-
#
|
|
115
|
-
BINARY="
|
|
116
|
-
if [ -f "
|
|
118
|
+
# Binary location: CMake may produce flat (llama-cpp) or Versions/A/ layout
|
|
119
|
+
BINARY=""
|
|
120
|
+
if [ -f "llama-cpp.framework/llama-cpp" ]; then
|
|
121
|
+
BINARY="llama-cpp.framework/llama-cpp"
|
|
122
|
+
elif [ -f "llama-cpp.framework/Versions/A/llama-cpp" ]; then
|
|
123
|
+
BINARY="llama-cpp.framework/Versions/A/llama-cpp"
|
|
124
|
+
fi
|
|
125
|
+
if [ -n "$BINARY" ]; then
|
|
117
126
|
if xcrun strip -x -S "$BINARY" 2>/dev/null; then
|
|
118
127
|
print_status "Stripped debug symbols from iOS framework"
|
|
119
128
|
fi
|
|
120
129
|
fi
|
|
121
130
|
|
|
122
|
-
#
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
131
|
+
# Build flat framework (single binary, no duplication) for npm publishing
|
|
132
|
+
if [ -z "$BINARY" ] || [ ! -f "$BINARY" ]; then
|
|
133
|
+
print_error "iOS framework binary not found"
|
|
134
|
+
cd ../..
|
|
135
|
+
return 1
|
|
136
|
+
fi
|
|
137
|
+
rm -rf ../Frameworks/llama-cpp.framework
|
|
138
|
+
mkdir -p ../Frameworks/llama-cpp.framework/Resources
|
|
139
|
+
cp "$BINARY" ../Frameworks/llama-cpp.framework/llama-cpp
|
|
140
|
+
[ -f llama-cpp.framework/Info.plist ] && cp llama-cpp.framework/Info.plist ../Frameworks/llama-cpp.framework/
|
|
141
|
+
[ -f llama-cpp.framework/Versions/A/Resources/Info.plist ] && cp llama-cpp.framework/Versions/A/Resources/Info.plist ../Frameworks/llama-cpp.framework/Resources/
|
|
142
|
+
print_success "iOS framework copied to ios/Frameworks/ for npm package (flat, no duplication)"
|
|
126
143
|
else
|
|
127
144
|
print_error "iOS framework not found after build"
|
|
128
145
|
cd ../..
|
|
@@ -173,7 +190,8 @@ build_android() {
|
|
|
173
190
|
-DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \
|
|
174
191
|
-DANDROID_STL=c++_shared
|
|
175
192
|
|
|
176
|
-
|
|
193
|
+
JOBS=$(sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 4)
|
|
194
|
+
cmake --build . --config Release -- -j"$JOBS"
|
|
177
195
|
|
|
178
196
|
mkdir -p ../src/main/jniLibs/$arch
|
|
179
197
|
if [ -f "libllama-cpp-arm64.so" ]; then
|
|
@@ -201,6 +219,10 @@ build_android() {
|
|
|
201
219
|
main() {
|
|
202
220
|
print_status "Starting llama-cpp Capacitor plugin build..."
|
|
203
221
|
|
|
222
|
+
# Always start clean - remove previous build outputs
|
|
223
|
+
rm -rf ios/build ios/Frameworks android/build
|
|
224
|
+
print_status "Cleaned build directories"
|
|
225
|
+
|
|
204
226
|
# Check dependencies
|
|
205
227
|
if ! command -v cmake &> /dev/null; then
|
|
206
228
|
print_error "CMake is required but not installed"
|
|
@@ -225,5 +247,5 @@ main() {
|
|
|
225
247
|
print_success "Build completed successfully!"
|
|
226
248
|
}
|
|
227
249
|
|
|
228
|
-
# Run main function
|
|
229
|
-
main
|
|
250
|
+
# Run main function (ignore any args npm may pass)
|
|
251
|
+
main
|
|
Binary file
|
|
@@ -150,6 +150,8 @@ struct MinjaCaps {
|
|
|
150
150
|
// MARK: - Main Implementation
|
|
151
151
|
@objc public class LlamaCpp: NSObject {
|
|
152
152
|
private var contexts: [Int: LlamaContext] = [:]
|
|
153
|
+
private var nativeContexts: [Int64: UnsafeMutableRawPointer] = [:]
|
|
154
|
+
private var contextIdToNative: [Int: Int64] = [:]
|
|
153
155
|
private var contextCounter: Int = 0
|
|
154
156
|
private var contextLimit: Int = 10
|
|
155
157
|
private var nativeLogEnabled: Bool = false
|
|
@@ -262,18 +264,16 @@ struct MinjaCaps {
|
|
|
262
264
|
|
|
263
265
|
let nativeContextId = initFunc(modelPath, paramsJson.cString(using: .utf8)!)
|
|
264
266
|
if nativeContextId > 0 {
|
|
265
|
-
// Store the
|
|
266
|
-
|
|
267
|
-
//
|
|
268
|
-
|
|
267
|
+
// Store the LlamaContext for Swift bookkeeping
|
|
268
|
+
contexts[contextId] = context
|
|
269
|
+
// Store the native context pointer and mapping for C layer
|
|
270
|
+
let nativePtr = UnsafeMutableRawPointer(bitPattern: Int(nativeContextId))
|
|
271
|
+
nativeContexts[nativeContextId] = nativePtr
|
|
272
|
+
contextIdToNative[contextId] = nativeContextId
|
|
269
273
|
|
|
270
274
|
// Register with embedding system if available
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if let registerFunc = registerEmbeddingContextFunc {
|
|
274
|
-
// Note: The actual context pointer should come from the native initContext function
|
|
275
|
-
// This is a placeholder - the real implementation needs to get the actual pointer
|
|
276
|
-
registerFunc(Int64(contextId), contexts[Int64(contextId)]!)
|
|
275
|
+
if let registerFunc = registerEmbeddingContextFunc, let ptr = nativePtr {
|
|
276
|
+
registerFunc(nativeContextId, ptr)
|
|
277
277
|
}
|
|
278
278
|
} else {
|
|
279
279
|
completion(.failure(.operationFailed("Failed to initialize native context")))
|
|
@@ -322,34 +322,40 @@ struct MinjaCaps {
|
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
func releaseContext(contextId: Int, completion: @escaping (LlamaResult<Void>) -> Void) {
|
|
325
|
-
guard
|
|
325
|
+
guard contexts[contextId] != nil else {
|
|
326
326
|
completion(.failure(.contextNotFound))
|
|
327
327
|
return
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
let nativeId = contextIdToNative[contextId] ?? Int64(contextId)
|
|
331
|
+
|
|
330
332
|
// Unregister from embedding system if available
|
|
331
333
|
if let unregisterFunc = unregisterEmbeddingContextFunc {
|
|
332
|
-
unregisterFunc(
|
|
334
|
+
unregisterFunc(nativeId)
|
|
333
335
|
}
|
|
334
336
|
|
|
335
337
|
// Call native release function
|
|
336
338
|
if let releaseFunc = releaseContextFunc {
|
|
337
|
-
releaseFunc(
|
|
339
|
+
releaseFunc(nativeId)
|
|
338
340
|
}
|
|
339
341
|
|
|
340
342
|
contexts.removeValue(forKey: contextId)
|
|
343
|
+
nativeContexts.removeValue(forKey: nativeId)
|
|
344
|
+
contextIdToNative.removeValue(forKey: contextId)
|
|
341
345
|
completion(.success(()))
|
|
342
346
|
}
|
|
343
347
|
|
|
344
348
|
func releaseAllContexts(completion: @escaping (LlamaResult<Void>) -> Void) {
|
|
345
349
|
// Unregister all contexts from embedding system
|
|
346
350
|
if let unregisterFunc = unregisterEmbeddingContextFunc {
|
|
347
|
-
for
|
|
348
|
-
unregisterFunc(
|
|
351
|
+
for (_, nativeId) in contextIdToNative {
|
|
352
|
+
unregisterFunc(nativeId)
|
|
349
353
|
}
|
|
350
354
|
}
|
|
351
355
|
|
|
352
356
|
contexts.removeAll()
|
|
357
|
+
nativeContexts.removeAll()
|
|
358
|
+
contextIdToNative.removeAll()
|
|
353
359
|
completion(.success(()))
|
|
354
360
|
}
|
|
355
361
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llama-cpp-capacitor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "A native Capacitor plugin that embeds llama.cpp directly into mobile apps, enabling offline AI inference with chat-first API design. Complete iOS and Android support: text generation, chat, multimodal, TTS, LoRA, embeddings, and more.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"type": "module",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
"build:all": "npm run build && npm run build:native",
|
|
73
73
|
"build:ios": "cd ios && cmake -B build -S . && cmake --build build --config Release",
|
|
74
74
|
"build:android": "cd android && gradlew.bat assembleRelease",
|
|
75
|
+
"prepack": "npm run build:native",
|
|
75
76
|
"pack": "npm run build && npm pack --dry-run",
|
|
76
77
|
"pack:full": "npm run build:all && npm pack --dry-run",
|
|
77
78
|
"test": "jest",
|
|
@@ -84,7 +85,7 @@
|
|
|
84
85
|
"clean:native": "rimraf ios/build ios/Frameworks android/build android/src/main/jniLibs",
|
|
85
86
|
"clean:test": "rimraf test/output test/coverage",
|
|
86
87
|
"watch": "tsc --watch",
|
|
87
|
-
"prepublishOnly": "npm run build"
|
|
88
|
+
"prepublishOnly": "npm run build && npm run build:native"
|
|
88
89
|
},
|
|
89
90
|
"devDependencies": {
|
|
90
91
|
"@capacitor/android": "^7.0.0",
|
|
File without changes
|