llama-cpp-capacitor 0.1.1 → 0.1.3
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 +20 -0
- package/README.md +26 -0
- package/android/src/main/jniLibs/arm64-v8a/libllama-cpp-arm64.so +0 -0
- package/build-native.sh +229 -0
- package/cpp/README.md +13 -2
- package/dist/docs.json +1338 -5435
- package/ios/CMakeLists-arm64.txt +149 -0
- package/ios/CMakeLists-x86_64.txt +176 -0
- package/ios/CMakeLists.txt +149 -0
- package/ios/Frameworks/llama-cpp.framework/Versions/A/llama-cpp +0 -0
- package/package.json +9 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'LlamaCppCapacitor'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.homepage = package['repository']['url']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.ios.deployment_target = '15.0'
|
|
15
|
+
s.dependency 'Capacitor'
|
|
16
|
+
s.swift_version = '5.1'
|
|
17
|
+
|
|
18
|
+
# Include the native llama-cpp framework
|
|
19
|
+
s.vendored_frameworks = 'ios/Frameworks/llama-cpp.framework'
|
|
20
|
+
end
|
package/README.md
CHANGED
|
@@ -121,6 +121,21 @@ cd android
|
|
|
121
121
|
- **iOS**: `ios/build/LlamaCpp.framework/`
|
|
122
122
|
- **Android**: `android/src/main/jniLibs/{arch}/libllama-cpp-{arch}.so`
|
|
123
123
|
|
|
124
|
+
### **Updating the native source (e.g. for vision model support)**
|
|
125
|
+
|
|
126
|
+
The native `cpp/` layer is based on [llama.cpp](https://github.com/ggerganov/llama.cpp). To pull in a newer upstream version (e.g. for vision model support) **without overwriting** the Capacitor adapter code, use the **bootstrap script** (included in this repo):
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
./scripts/bootstrap.sh [branch-or-tag-or-commit]
|
|
130
|
+
# Example: ./scripts/bootstrap.sh master
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
This syncs upstream into `cpp/` and keeps project-specific files (`cap-*.cpp/h`, `tools/mtmd/`, etc.) intact. After running it, reconcile any API changes in the adapter code, then rebuild with `npm run build:native` or `./build-native.sh`. See [cpp/README.md](cpp/README.md) and [docs/IOS_IMPLEMENTATION_GUIDE.md](docs/IOS_IMPLEMENTATION_GUIDE.md).
|
|
134
|
+
|
|
135
|
+
### **iOS implementation (step-by-step)**
|
|
136
|
+
|
|
137
|
+
For a **step-by-step guide** on how methods are implemented on the iOS side (Swift bridge → native framework, adding/updating C symbols, and updating the native layer for vision), see **[docs/IOS_IMPLEMENTATION_GUIDE.md](docs/IOS_IMPLEMENTATION_GUIDE.md)**.
|
|
138
|
+
|
|
124
139
|
### iOS Setup
|
|
125
140
|
|
|
126
141
|
1. Install the plugin:
|
|
@@ -696,6 +711,17 @@ const logListener = addNativeLogListener((level, text) => {
|
|
|
696
711
|
});
|
|
697
712
|
```
|
|
698
713
|
|
|
714
|
+
## 📦 Publishing
|
|
715
|
+
|
|
716
|
+
To publish the package to npm:
|
|
717
|
+
|
|
718
|
+
1. **Build** (runs automatically on `npm publish` via `prepublishOnly`): `npm run build` — produces `dist/` (plugin bundles, ESM, docs).
|
|
719
|
+
2. **Optional — include native libs in the tarball**: `npm run build:all` (requires macOS/NDK) — builds iOS framework and Android `.so` into `ios/Frameworks` and `android/src/main/jniLibs`.
|
|
720
|
+
3. **Verify pack**: `npm run pack` (JS only) or `npm run pack:full` (JS + native) — lists files that would be published.
|
|
721
|
+
4. **Publish**: `npm publish`.
|
|
722
|
+
|
|
723
|
+
See [NPM_PUBLISH_GUIDE.md](NPM_PUBLISH_GUIDE.md) for 2FA/token setup and troubleshooting.
|
|
724
|
+
|
|
699
725
|
## 🤝 Contributing
|
|
700
726
|
|
|
701
727
|
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
Binary file
|
package/build-native.sh
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Build script for llama-cpp Capacitor plugin
|
|
4
|
+
# This script compiles the native llama.cpp library for iOS and Android
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# Colors for output
|
|
9
|
+
RED='\033[0;31m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
BLUE='\033[0;34m'
|
|
13
|
+
NC='\033[0m' # No Color
|
|
14
|
+
|
|
15
|
+
# Function to print colored output
|
|
16
|
+
print_status() {
|
|
17
|
+
echo -e "${BLUE}[INFO]${NC} $1"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
print_success() {
|
|
21
|
+
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
print_warning() {
|
|
25
|
+
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
print_error() {
|
|
29
|
+
echo -e "${RED}[ERROR]${NC} $1"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Check if we're on macOS for iOS builds
|
|
33
|
+
check_macos() {
|
|
34
|
+
if [[ "$OSTYPE" != "darwin"* ]]; then
|
|
35
|
+
print_warning "iOS builds require macOS. Skipping iOS build."
|
|
36
|
+
return 1
|
|
37
|
+
fi
|
|
38
|
+
return 0
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Check if Android SDK is available
|
|
42
|
+
check_android_sdk() {
|
|
43
|
+
if [ -z "$ANDROID_HOME" ] && [ -z "$ANDROID_SDK_ROOT" ]; then
|
|
44
|
+
print_warning "Android SDK not found. Please set ANDROID_HOME or ANDROID_SDK_ROOT."
|
|
45
|
+
print_warning "Skipping Android build."
|
|
46
|
+
return 1
|
|
47
|
+
fi
|
|
48
|
+
return 0
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Detect NDK path: ndk/<version>/build/cmake/android.toolchain.cmake
|
|
52
|
+
# Uses latest versioned NDK under $ANDROID_SDK/ndk/ (e.g. ndk/29.0.13113456).
|
|
53
|
+
detect_ndk() {
|
|
54
|
+
local sdk="${ANDROID_HOME:-$ANDROID_SDK_ROOT}"
|
|
55
|
+
local ndk_root="$sdk/ndk"
|
|
56
|
+
if [ ! -d "$ndk_root" ]; then
|
|
57
|
+
echo ""
|
|
58
|
+
return 1
|
|
59
|
+
fi
|
|
60
|
+
local latest=""
|
|
61
|
+
local latest_ver=0
|
|
62
|
+
for v in "$ndk_root"/*; do
|
|
63
|
+
[ -d "$v" ] || continue
|
|
64
|
+
local base=$(basename "$v")
|
|
65
|
+
if [[ "$base" =~ ^[0-9] ]]; then
|
|
66
|
+
local ver=$(echo "$base" | sed 's/[^0-9]//g' | head -c 10)
|
|
67
|
+
ver=${ver:-0}
|
|
68
|
+
if [ "$ver" -gt "$latest_ver" ] 2>/dev/null; then
|
|
69
|
+
latest_ver=$ver
|
|
70
|
+
latest=$v
|
|
71
|
+
fi
|
|
72
|
+
fi
|
|
73
|
+
done
|
|
74
|
+
if [ -n "$latest" ] && [ -f "$latest/build/cmake/android.toolchain.cmake" ]; then
|
|
75
|
+
echo "$latest"
|
|
76
|
+
return 0
|
|
77
|
+
fi
|
|
78
|
+
echo ""
|
|
79
|
+
return 1
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Build iOS library
|
|
83
|
+
build_ios() {
|
|
84
|
+
print_status "Building iOS library..."
|
|
85
|
+
|
|
86
|
+
if ! check_macos; then
|
|
87
|
+
return 1
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# Always start from a clean iOS build directory to avoid stale Xcode settings
|
|
91
|
+
rm -rf ios/build
|
|
92
|
+
mkdir -p ios/build
|
|
93
|
+
cd ios/build
|
|
94
|
+
|
|
95
|
+
# Configure with CMake
|
|
96
|
+
# IMPORTANT: build iOS framework as **ARM64-only**.
|
|
97
|
+
# Including x86_64 here makes CMake/Xcode try to link an x86_64 slice,
|
|
98
|
+
# but we only compile ARM-specific kernels (arch/arm), which leads to
|
|
99
|
+
# undefined symbols like lm_ggml_gemm_* for x86_64.
|
|
100
|
+
cmake .. \
|
|
101
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
102
|
+
-DCMAKE_OSX_ARCHITECTURES="arm64" \
|
|
103
|
+
-DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
|
|
104
|
+
-DCMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE=NO
|
|
105
|
+
|
|
106
|
+
# Build
|
|
107
|
+
cmake --build . --config Release
|
|
108
|
+
|
|
109
|
+
# CMake builds the framework directly (FRAMEWORK TRUE in CMakeLists.txt)
|
|
110
|
+
# Verify the framework was created
|
|
111
|
+
if [ -d "llama-cpp.framework" ]; then
|
|
112
|
+
print_success "iOS framework built successfully at: $(pwd)/llama-cpp.framework"
|
|
113
|
+
|
|
114
|
+
# Strip debug symbols to reduce app store size (~0.5–1 MB)
|
|
115
|
+
BINARY="llama-cpp.framework/Versions/A/llama-cpp"
|
|
116
|
+
if [ -f "$BINARY" ]; then
|
|
117
|
+
if xcrun strip -x -S "$BINARY" 2>/dev/null; then
|
|
118
|
+
print_status "Stripped debug symbols from iOS framework"
|
|
119
|
+
fi
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Copy framework to package location for npm publishing
|
|
123
|
+
mkdir -p ../Frameworks
|
|
124
|
+
cp -R llama-cpp.framework ../Frameworks/
|
|
125
|
+
print_success "iOS framework copied to ios/Frameworks/ for npm package"
|
|
126
|
+
else
|
|
127
|
+
print_error "iOS framework not found after build"
|
|
128
|
+
cd ../..
|
|
129
|
+
return 1
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
cd ../..
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# Build Android library
|
|
136
|
+
build_android() {
|
|
137
|
+
print_status "Building Android library..."
|
|
138
|
+
|
|
139
|
+
if ! check_android_sdk; then
|
|
140
|
+
return 1
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
ANDROID_NDK=$(detect_ndk)
|
|
144
|
+
if [ -z "$ANDROID_NDK" ]; then
|
|
145
|
+
print_error "Android NDK not found. Install NDK via Android Studio (SDK Manager → NDK)."
|
|
146
|
+
print_error "Expected: \$ANDROID_HOME/ndk/<version>/build/cmake/android.toolchain.cmake"
|
|
147
|
+
return 1
|
|
148
|
+
fi
|
|
149
|
+
print_status "Using NDK: $ANDROID_NDK"
|
|
150
|
+
|
|
151
|
+
TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake"
|
|
152
|
+
if [ ! -f "$TOOLCHAIN_FILE" ]; then
|
|
153
|
+
print_error "Toolchain file not found: $TOOLCHAIN_FILE"
|
|
154
|
+
return 1
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
rm -rf android/build
|
|
158
|
+
mkdir -p android/build
|
|
159
|
+
cd android/build
|
|
160
|
+
|
|
161
|
+
# Build only arm64-v8a to minimize app store size.
|
|
162
|
+
# build.gradle uses abiFilters 'arm64-v8a'; armeabi-v7a is not included in the app.
|
|
163
|
+
# Skipping armeabi-v7a saves ~25–48 MB in package and keeps app size minimal.
|
|
164
|
+
arch="arm64-v8a"
|
|
165
|
+
print_status "Building for $arch (only ABI shipped in app)..."
|
|
166
|
+
rm -rf CMakeCache.txt CMakeFiles Makefile cmake_install.cmake 2>/dev/null || true
|
|
167
|
+
find . -maxdepth 1 -name '*.so' -delete 2>/dev/null || true
|
|
168
|
+
|
|
169
|
+
cmake ../src/main \
|
|
170
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
171
|
+
-DANDROID_ABI=$arch \
|
|
172
|
+
-DANDROID_PLATFORM=android-21 \
|
|
173
|
+
-DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \
|
|
174
|
+
-DANDROID_STL=c++_shared
|
|
175
|
+
|
|
176
|
+
cmake --build . --config Release
|
|
177
|
+
|
|
178
|
+
mkdir -p ../src/main/jniLibs/$arch
|
|
179
|
+
if [ -f "libllama-cpp-arm64.so" ]; then
|
|
180
|
+
PREBUILT="$ANDROID_NDK/toolchains/llvm/prebuilt"
|
|
181
|
+
if [ -d "$PREBUILT/darwin-x86_64" ]; then
|
|
182
|
+
STRIP_TOOL="$PREBUILT/darwin-x86_64/bin/llvm-strip"
|
|
183
|
+
elif [ -d "$PREBUILT/darwin-aarch64" ]; then
|
|
184
|
+
STRIP_TOOL="$PREBUILT/darwin-aarch64/bin/llvm-strip"
|
|
185
|
+
else
|
|
186
|
+
STRIP_TOOL=$(find "$ANDROID_NDK/toolchains" -name "llvm-strip" -type f 2>/dev/null | head -1)
|
|
187
|
+
fi
|
|
188
|
+
if [ -f "$STRIP_TOOL" ]; then
|
|
189
|
+
"$STRIP_TOOL" --strip-debug libllama-cpp-arm64.so
|
|
190
|
+
print_status "Stripped debug symbols from library"
|
|
191
|
+
fi
|
|
192
|
+
cp "libllama-cpp-arm64.so" "../src/main/jniLibs/$arch/"
|
|
193
|
+
fi
|
|
194
|
+
print_success "Built for $arch"
|
|
195
|
+
|
|
196
|
+
print_success "Android library built successfully"
|
|
197
|
+
cd ../..
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
# Main build function
|
|
201
|
+
main() {
|
|
202
|
+
print_status "Starting llama-cpp Capacitor plugin build..."
|
|
203
|
+
|
|
204
|
+
# Check dependencies
|
|
205
|
+
if ! command -v cmake &> /dev/null; then
|
|
206
|
+
print_error "CMake is required but not installed"
|
|
207
|
+
exit 1
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
if ! command -v make &> /dev/null; then
|
|
211
|
+
print_error "Make is required but not installed"
|
|
212
|
+
exit 1
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
# Build iOS
|
|
216
|
+
if check_macos; then
|
|
217
|
+
build_ios
|
|
218
|
+
fi
|
|
219
|
+
|
|
220
|
+
# Build Android
|
|
221
|
+
if check_android_sdk; then
|
|
222
|
+
build_android
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
print_success "Build completed successfully!"
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
# Run main function
|
|
229
|
+
main "$@"
|
package/cpp/README.md
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
# Note
|
|
2
2
|
|
|
3
|
-
-
|
|
4
|
-
-
|
|
3
|
+
- The **project-specific** files in this folder (never overwritten by bootstrap) are:
|
|
4
|
+
- `cap-llama.cpp` / `cap-llama.h` – Capacitor bridge (context, model load)
|
|
5
|
+
- `cap-completion.cpp` / `cap-completion.h` – completion
|
|
6
|
+
- `cap-tts.cpp` / `cap-tts.h` – TTS
|
|
7
|
+
- `cap-embedding.cpp` / `cap-embedding.h` – embeddings
|
|
8
|
+
- `cap-mtmd.hpp` – multimodal/vision
|
|
9
|
+
- `tools/mtmd/` – multimodal/vision tooling
|
|
10
|
+
- All other sources are synced from [llama.cpp](https://github.com/ggerganov/llama.cpp).
|
|
11
|
+
- **Update native source** (e.g. for a newer llama.cpp or vision support): run from repo root:
|
|
12
|
+
```bash
|
|
13
|
+
./scripts/bootstrap.sh [branch-or-tag-or-commit]
|
|
14
|
+
```
|
|
15
|
+
See [scripts/bootstrap.sh](../scripts/bootstrap.sh) and [docs/IOS_IMPLEMENTATION_GUIDE.md](../docs/IOS_IMPLEMENTATION_GUIDE.md).
|