Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ff8350d
add Linux MUSL, XCFramework and Signed and Notarized Apple builds
Gioee Aug 29, 2025
c177ba8
fix(makefile): correct indentation for ARGS assignment in build section
Gioee Aug 29, 2025
7907bd1
fix(workflow/linux-musl): install git
Gioee Aug 29, 2025
5818a26
fix(workflow): update conditional checks for linux-musl
Gioee Aug 29, 2025
72b0bc2
fix(workflow): add g++ to linux-musl x86_64 and arm64 dependency inst…
Gioee Aug 29, 2025
e1964dd
fix(workflow): add cmake to linux-musl x86_64 and arm64 dependency in…
Gioee Aug 29, 2025
5b932ee
fix(workflow/linux-musl): add OpenCL and Vulkan installation for linu…
Gioee Aug 30, 2025
36eb66e
fix(workflow/linux-musl): add shaderc to vulkan installation for linu…
Gioee Aug 30, 2025
6e47d48
fix(workflow/linux-musl): add python3 to dependency installation for …
Gioee Aug 30, 2025
ddc4aba
fix(workflow/linux-musl): enhance vulkan installation by adding mesa-…
Gioee Aug 30, 2025
a901081
fix(workflow/linux-musl): add vulkan-icd-loader to linux-musl-gpu vul…
Gioee Aug 30, 2025
3f23313
fix(workflow/linux-musl): update vulkan installation to include vulka…
Gioee Aug 30, 2025
f2a905c
fix(workflow/linux-musl): remove duplicate vulkan-loader in linux-mus…
Gioee Aug 30, 2025
81227cf
fix(workflow/linux-musl): enhance linux-musl-gpu vulkan installation
Gioee Aug 30, 2025
1adbd7c
fix(workflow/linux-musl): update linux-musl-gpu vulkan installation t…
Gioee Aug 30, 2025
402416f
fix(workflow/linux-musl): update linux-musl-gpu vulkan installation t…
Gioee Aug 30, 2025
ae8178c
fix(workflow/linux-musl): enhance linux-musl-gpu vulkan installation …
Gioee Aug 30, 2025
9d76570
fix(workflow/linux-musl): update linux-musl-gpu vulkan installation t…
Gioee Aug 30, 2025
c649830
fix(workflow/linux-musl): disable Vulkan support for linux-musl-gpu b…
Gioee Aug 30, 2025
aab46af
fix(workflow/linux-musl): remove Vulkan support from linux-musl-gpu b…
Gioee Aug 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 94 additions & 24 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ permissions:
jobs:
build:
runs-on: ${{ matrix.os }}
name: ${{ matrix.name }}${{ matrix.arch && format('-{0}', matrix.arch) || '' }} build${{ matrix.arch != 'arm64-v8a' && matrix.name != 'isim' && matrix.name != 'ios' && ' + test' || ''}}
container: ${{ matrix.container && matrix.container || '' }}
name: ${{ matrix.name }}${{ matrix.arch && format('-{0}', matrix.arch) || '' }} build${{ matrix.arch != 'arm64-v8a' && matrix.name != 'ios-sim' && matrix.name != 'ios' && matrix.name != 'apple-xcframework' && ' + test' || ''}}
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
- os: macos-15
name: macos
make: LLAMA="-DGGML_NATIVE=OFF -DGGML_METAL=ON -DGGML_ACCELERATE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=Apple" WHISPER="-DWHISPER_COREML=ON -DWHISPER_COREML_ALLOW_FALLBACK=ON"
- os: ubuntu-22.04
Expand All @@ -26,14 +27,32 @@ jobs:
arch: x86_64
name: linux-gpu
make: LLAMA="-DGGML_NATIVE=OFF -DGGML_CPU=ON -DGGML_VULKAN=ON -DGGML_OPENCL=ON"
- os: LinuxARM64
- os: ubuntu-22.04-arm
arch: arm64
name: linux-cpu
make: LLAMA="-DGGML_NATIVE=OFF -DGGML_CPU=ON -DGGML_CPU_ARM_ARCH=armv8.2-a"
- os: LinuxARM64
- os: ubuntu-22.04-arm
arch: arm64
name: linux-gpu
make: LLAMA="-DGGML_NATIVE=OFF -DGGML_CPU=ON -DGGML_VULKAN=ON -DGGML_OPENCL=ON"
- os: ubuntu-22.04
arch: x86_64
name: linux-musl-cpu
container: alpine:latest
make: LLAMA="-DGGML_NATIVE=OFF -DGGML_CPU=ON -DGGML_AVX2=ON"
- os: ubuntu-22.04
arch: x86_64
name: linux-musl-gpu
container: alpine:latest
make: LLAMA="-DGGML_NATIVE=OFF -DGGML_CPU=ON -DGGML_OPENCL=ON"
- os: ubuntu-22.04-arm
arch: arm64
name: linux-musl-cpu
make: LLAMA="-DGGML_NATIVE=OFF -DGGML_CPU=ON -DGGML_CPU_ARM_ARCH=armv8.2-a"
- os: ubuntu-22.04-arm
arch: arm64
name: linux-musl-gpu
make: LLAMA="-DGGML_NATIVE=OFF -DGGML_CPU=ON -DGGML_OPENCL=ON"
- os: windows-2022
arch: x86_64
name: windows-cpu
Expand All @@ -42,28 +61,35 @@ jobs:
arch: x86_64
name: windows-gpu
make: LLAMA="-DGGML_NATIVE=OFF -DGGML_CPU=ON -DGGML_VULKAN=ON -DGGML_OPENCL=ON"
- os: ubuntu-latest
- os: ubuntu-22.04
arch: x86_64
name: android
make: PLATFORM=android ARCH=x86_64
sqlite-amalgamation-zip: https://sqlite.org/2025/sqlite-amalgamation-3490100.zip
- os: ubuntu-latest
- os: ubuntu-22.04
arch: arm64-v8a
name: android
make: PLATFORM=android ARCH=arm64-v8a LLAMA="-DGGML_CPU_ARM_ARCH=armv8.2-a+dotprod"
- os: macos-latest
- os: macos-15
name: ios
make: PLATFORM=ios LLAMA="-DGGML_NATIVE=OFF -DGGML_METAL=ON -DGGML_ACCELERATE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=Apple" WHISPER="-DWHISPER_COREML=ON -DWHISPER_COREML_ALLOW_FALLBACK=ON"
- os: macos-latest
name: isim
make: PLATFORM=isim LLAMA="-DGGML_NATIVE=OFF -DGGML_METAL=ON -DGGML_ACCELERATE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=Apple" WHISPER="-DWHISPER_COREML=ON -DWHISPER_COREML_ALLOW_FALLBACK=ON"
- os: macos-15
name: ios-sim
make: PLATFORM=ios-sim LLAMA="-DGGML_NATIVE=OFF -DGGML_METAL=ON -DGGML_ACCELERATE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=Apple" WHISPER="-DWHISPER_COREML=ON -DWHISPER_COREML_ALLOW_FALLBACK=ON"
- os: macos-15
name: apple-xcframework
make: xcframework LLAMA="-DGGML_NATIVE=OFF -DGGML_METAL=ON -DGGML_ACCELERATE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=Apple" WHISPER="-DWHISPER_COREML=ON -DWHISPER_COREML_ALLOW_FALLBACK=ON"

defaults:
run:
shell: bash
shell: ${{ matrix.container && 'sh' || 'bash' }}

steps:

- name: linux-musl x86_64 install dependencies
if: contains(matrix.name, 'linux-musl') && matrix.arch == 'x86_64'
run: apk update && apk add --no-cache git gcc g++ make cmake sqlite musl-dev linux-headers python3

- uses: actions/checkout@v4.2.2
with:
submodules: true
Expand Down Expand Up @@ -116,10 +142,29 @@ jobs:
${{ matrix.name == 'windows-gpu' && 'mingw-w64-x86_64-opencl-headers' || '' }}
${{ matrix.name == 'windows-gpu' && 'mingw-w64-x86_64-opencl-icd' || '' }}

- name: macos install dependencies
if: matrix.name == 'macos'
run: brew link sqlite --force

- name: linux-musl arm64 setup container
if: contains(matrix.name, 'linux-musl') && matrix.arch == 'arm64'
run: |
docker run -d --name alpine \
--platform linux/arm64 \
-v ${{ github.workspace }}:/workspace \
-w /workspace \
alpine:latest \
tail -f /dev/null
docker exec alpine sh -c "apk update && apk add --no-cache gcc g++ make cmake sqlite musl-dev linux-headers python3"

- name: linux install opencl
if: matrix.name == 'linux-gpu'
run: sudo apt-get install -y opencl-headers ocl-icd-opencl-dev

- name: linux-musl install opencl
if: matrix.name == 'linux-musl-gpu'
run: ${{ matrix.arch == 'arm64' && 'docker exec alpine' || '' }} apk add --no-cache opencl-headers opencl-icd-loader-dev

- name: linux-x86_64 install vulkan
if: matrix.name == 'linux-gpu' && matrix.arch == 'x86_64'
run: |
Expand Down Expand Up @@ -190,7 +235,7 @@ jobs:

- name: unix build llama.cpp
if: matrix.os != 'windows-2022' && steps.cache-llama.outputs.cache-hit != 'true'
run: make build/llama.cpp.stamp ${{ matrix.make && matrix.make || ''}}
run: ${{ contains(matrix.name, 'linux-musl') && matrix.arch == 'arm64' && 'docker exec alpine' || '' }} make build/llama.cpp.stamp ${{ matrix.make && matrix.make || ''}}

- name: windows build whisper.cpp
if: matrix.os == 'windows-2022' && steps.cache-whisper.outputs.cache-hit != 'true'
Expand All @@ -201,7 +246,7 @@ jobs:

- name: unix build whisper.cpp
if: matrix.os != 'windows-2022' && steps.cache-whisper.outputs.cache-hit != 'true'
run: make build/whisper.cpp.stamp ${{ matrix.make && matrix.make || ''}}
run: ${{ contains(matrix.name, 'linux-musl') && matrix.arch == 'arm64' && 'docker exec alpine' || '' }} make build/whisper.cpp.stamp ${{ matrix.make && matrix.make || ''}}

- name: windows build miniaudio
if: matrix.os == 'windows-2022' && steps.cache-miniaudio.outputs.cache-hit != 'true'
Expand All @@ -210,7 +255,7 @@ jobs:

- name: unix build miniaudio
if: matrix.os != 'windows-2022' && steps.cache-miniaudio.outputs.cache-hit != 'true'
run: make build/miniaudio.stamp ${{ matrix.make && matrix.make || ''}}
run: ${{ contains(matrix.name, 'linux-musl') && matrix.arch == 'arm64' && 'docker exec alpine' || '' }} make build/miniaudio.stamp ${{ matrix.make && matrix.make || ''}}

- name: windows build sqlite-ai
if: matrix.os == 'windows-2022'
Expand All @@ -221,11 +266,36 @@ jobs:

- name: unix build sqlite-ai
if: matrix.os != 'windows-2022'
run: make extension ${{ matrix.make && matrix.make || ''}}
run: ${{ contains(matrix.name, 'linux-musl') && matrix.arch == 'arm64' && 'docker exec alpine' || '' }} make extension ${{ matrix.make && matrix.make || ''}}

- name: macos install sqlite3 without SQLITE_OMIT_LOAD_EXTENSION
if: matrix.name == 'macos'
run: brew link sqlite --force
- name: create keychain for codesign
if: matrix.os == 'macos-15'
run: |
echo "${{ secrets.APPLE_CERTIFICATE }}" | base64 --decode > certificate.p12
security create-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" build.keychain
security import certificate.p12 -k build.keychain -P "${{ secrets.CERTIFICATE_PASSWORD }}" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "${{ secrets.KEYCHAIN_PASSWORD }}" build.keychain

- name: codesign dylib
if: matrix.os == 'macos-15' && matrix.name != 'apple-xcframework'
run: codesign --sign "${{ secrets.APPLE_TEAM_ID }}" --timestamp --options runtime dist/ai.dylib

- name: codesign and notarize xcframework
if: matrix.name == 'apple-xcframework'
run: |
find dist/ai.xcframework -name "*.framework" -exec echo "Signing: {}" \; -exec codesign --sign "${{ secrets.APPLE_TEAM_ID }}" --timestamp --options runtime {} \; # Sign each individual framework FIRST
codesign --sign "${{ secrets.APPLE_TEAM_ID }}" --timestamp --options runtime dist/ai.xcframework # Then sign the xcframework wrapper
ditto -c -k --keepParent dist/ai.xcframework dist/ai.xcframework.zip
xcrun notarytool submit dist/ai.xcframework.zip --apple-id "${{ secrets.APPLE_ID }}" --password "${{ secrets.APPLE_PASSWORD }}" --team-id "${{ secrets.APPLE_TEAM_ID }}" --wait
rm dist/ai.xcframework.zip

- name: cleanup keychain for codesign
if: matrix.os == 'macos-15'
run: |
rm certificate.p12
security delete-keychain build.keychain

- name: android setup test environment
if: matrix.name == 'android' && matrix.arch != 'arm64-v8a'
Expand Down Expand Up @@ -280,7 +350,7 @@ jobs:

- name: unix test sqlite-ai
if: contains(matrix.name, 'linux') || matrix.name == 'macos'
run: make test ${{ matrix.make && matrix.make || ''}}
run: ${{ contains(matrix.name, 'linux-musl') && matrix.arch == 'arm64' && 'docker exec alpine' || '' }} make test ${{ matrix.make && matrix.make || ''}}

- uses: actions/upload-artifact@v4.6.2
if: always()
Expand All @@ -290,7 +360,7 @@ jobs:
if-no-files-found: error

release:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
name: release
needs: build
if: github.ref == 'refs/heads/main'
Expand Down Expand Up @@ -324,9 +394,10 @@ jobs:
for folder in "artifacts"/*; do
if [ -d "$folder" ]; then
name=$(basename "$folder")
zip -jq "${name}-${{ steps.tag.outputs.version }}.zip" "$folder"/*
tar -cJf "${name}-${{ steps.tag.outputs.version }}.tar.xz" -C "$folder" .
tar -czf "${name}-${{ steps.tag.outputs.version }}.tar.gz" -C "$folder" .
if [[ "$name" != "ai-apple-xcframework" ]]; then
tar -czf "${name}-${{ steps.tag.outputs.version }}.tar.gz" -C "$folder" .
fi
(cd "$folder" && zip -rq "../../${name}-${{ steps.tag.outputs.version }}.zip" .)
fi
done

Expand All @@ -337,6 +408,5 @@ jobs:
tag_name: ${{ steps.tag.outputs.version }}
files: |
ai-*-${{ steps.tag.outputs.version }}.zip
ai-*-${{ steps.tag.outputs.version }}.tar.xz
ai-*-${{ steps.tag.outputs.version }}.tar.gz
make_latest: true
88 changes: 72 additions & 16 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -79,23 +79,17 @@ else ifeq ($(PLATFORM),macos)
MINIAUDIO_OPTIONS += -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
STRIP = strip -x -S $@
else ifeq ($(PLATFORM),android)
# Set ARCH to find Android NDK's Clang compiler, the user should set the ARCH
ifeq ($(filter %,$(ARCH)),)
ifndef ARCH # Set ARCH to find Android NDK's Clang compiler, the user should set the ARCH
$(error "Android ARCH must be set to ARCH=x86_64 or ARCH=arm64-v8a")
endif
# Set ANDROID_NDK path to find android build tools
# e.g. on MacOS: export ANDROID_NDK=/Users/username/Library/Android/sdk/ndk/25.2.9519653
ifeq ($(filter %,$(ANDROID_NDK)),)
ifndef ANDROID_NDK # Set ANDROID_NDK path to find android build tools; e.g. on MacOS: export ANDROID_NDK=/Users/username/Library/Android/sdk/ndk/25.2.9519653
$(error "Android NDK must be set")
endif

BIN = $(ANDROID_NDK)/toolchains/llvm/prebuilt/$(HOST)-x86_64/bin
PATH := $(BIN):$(PATH)

ifneq (,$(filter $(ARCH),arm64 arm64-v8a))
override ARCH := aarch64
endif

CC = $(BIN)/$(ARCH)-linux-android26-clang
CXX = $(CC)++
TARGET := $(DIST_DIR)/ai.so
Expand All @@ -116,7 +110,7 @@ else ifeq ($(PLATFORM),ios)
WHISPER_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 -DWHISPER_COREML=ON
MINIAUDIO_OPTIONS += -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 -DCMAKE_C_FLAGS="-x objective-c"
STRIP = strip -x -S $@
else ifeq ($(PLATFORM),isim)
else ifeq ($(PLATFORM),ios-sim)
TARGET := $(DIST_DIR)/ai.dylib
SDK := -isysroot $(shell xcrun --sdk iphonesimulator --show-sdk-path) -miphonesimulator-version-min=14.0
LLAMA_LIBS += $(BUILD_GGML)/lib/libggml-metal.a
Expand Down Expand Up @@ -182,7 +176,7 @@ $(DEF_FILE):
ifeq ($(PLATFORM),windows)
@echo "LIBRARY ai.dll" > $@
@echo "EXPORTS" >> $@
@echo " sqlite3_ai_init" >> $@
@echo " sqlite3_ai_init" >> $@
endif

# Make sure the build and dist directories exist
Expand Down Expand Up @@ -243,6 +237,67 @@ version:
clean:
rm -rf $(BUILD_DIR)/* $(DIST_DIR)/* *.gcda *.gcno *.gcov *.sqlite

.NOTPARALLEL: %.dylib
%.dylib:
rm -rf $(BUILD_DIR) && $(MAKE) PLATFORM=$*
mv $(DIST_DIR)/ai.dylib $(DIST_DIR)/$@

define PLIST
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\
<plist version=\"1.0\">\
<dict>\
<key>CFBundleDevelopmentRegion</key>\
<string>en</string>\
<key>CFBundleExecutable</key>\
<string>ai</string>\
<key>CFBundleIdentifier</key>\
<string>ai.sqlite.ai</string>\
<key>CFBundleInfoDictionaryVersion</key>\
<string>6.0</string>\
<key>CFBundlePackageType</key>\
<string>FMWK</string>\
<key>CFBundleSignature</key>\
<string>????</string>\
<key>CFBundleVersion</key>\
<string>$(shell make version)</string>\
<key>CFBundleShortVersionString</key>\
<string>$(shell make version)</string>\
<key>MinimumOSVersion</key>\
<string>11.0</string>\
</dict>\
</plist>
endef

define MODULEMAP
framework module ai {\
umbrella header \"sqlite-ai.h\"\
export *\
}
endef

LIB_NAMES = ios.dylib ios-sim.dylib macos.dylib
FMWK_NAMES = ios-arm64 ios-arm64_x86_64-simulator macos-arm64_x86_64
$(DIST_DIR)/%.xcframework: $(LIB_NAMES)
@$(foreach i,1 2 3,\
lib=$(word $(i),$(LIB_NAMES)); \
fmwk=$(word $(i),$(FMWK_NAMES)); \
mkdir -p $(DIST_DIR)/$$fmwk/ai.framework/Headers; \
mkdir -p $(DIST_DIR)/$$fmwk/ai.framework/Modules; \
cp src/sqlite-ai.h $(DIST_DIR)/$$fmwk/ai.framework/Headers; \
printf "$(PLIST)" > $(DIST_DIR)/$$fmwk/ai.framework/Info.plist; \
printf "$(MODULEMAP)" > $(DIST_DIR)/$$fmwk/ai.framework/Modules/module.modulemap; \
mv $(DIST_DIR)/$$lib $(DIST_DIR)/$$fmwk/ai.framework/ai; \
install_name_tool -id "@rpath/ai.framework/ai" $(DIST_DIR)/$$fmwk/ai.framework/ai; \
)
xcodebuild -create-xcframework $(foreach fmwk,$(FMWK_NAMES),-framework $(DIST_DIR)/$(fmwk)/ai.framework) -output $@
rm -rf $(foreach fmwk,$(FMWK_NAMES),$(DIST_DIR)/$(fmwk))

xcframework: $(DIST_DIR)/ai.xcframework

version:
@echo $(shell sed -n 's/^#define SQLITE_AI_VERSION[[:space:]]*"\([^"]*\)".*/\1/p' src/sqlite-ai.h)

# Help message
help:
@echo "SQLite AI Extension Makefile"
Expand All @@ -255,12 +310,13 @@ help:
@echo " windows (default on Windows)"
@echo " android (needs ARCH to be set to x86_64 or arm64-v8a and ANDROID_NDK to be set)"
@echo " ios (only on macOS)"
@echo " isim (only on macOS)"
@echo " ios-sim (only on macOS)"
@echo ""
@echo "Targets:"
@echo " all - Build the extension (default)"
@echo " clean - Remove built files"
@echo " test - Test the extension"
@echo " help - Display this help message"
@echo " all - Build the extension (default)"
@echo " clean - Remove built files"
@echo " test - Test the extension"
@echo " help - Display this help message"
@echo " xcframework - Build the Apple XCFramework"

.PHONY: all clean test extension help
.PHONY: all clean test extension help version xcframework
2 changes: 1 addition & 1 deletion src/sqlite-ai.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
extern "C" {
#endif

#define SQLITE_AI_VERSION "0.6.0"
#define SQLITE_AI_VERSION "0.6.1"

SQLITE_AI_API int sqlite3_ai_init (sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi);

Expand Down
Loading