1+ name : build, test and release sqlite-ai
2+ on :
3+ push :
4+ workflow_dispatch :
5+
6+ permissions :
7+ contents : write
8+
9+ jobs :
10+ build :
11+ runs-on : ${{ matrix.os }}
12+ name : ${{ matrix.name }}${{ matrix.arch && format('-{0}', matrix.arch) || '' }} build${{ matrix.arch != 'arm64-v8a' && matrix.name != 'isim' && matrix.name != 'ios' && ' + test' || ''}}
13+ timeout-minutes : 20
14+ strategy :
15+ fail-fast : false
16+ matrix :
17+ include :
18+ # Linux builds
19+ - os : ubuntu-latest
20+ arch : x86_64
21+ name : linux-cpu
22+ make : LLAMA="-DGGML_NATIVE=ON"
23+ - os : ubuntu-latest
24+ arch : x86_64
25+ name : linux-cpu-avx2
26+ make : LLAMA="-DGGML_NATIVE=OFF -DGGML_AVX2=ON -DGGML_FMA=ON -DGGML_F16C=ON"
27+ - os : ubuntu-latest
28+ arch : x86_64
29+ name : linux-cpu-avx512
30+ make : LLAMA="-DGGML_NATIVE=OFF -DGGML_AVX512=ON -DGGML_AVX512_VNNI=ON"
31+ - os : ubuntu-latest
32+ arch : x86_64
33+ name : linux-openblas
34+ make : LLAMA="-DGGML_NATIVE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS"
35+ - os : ubuntu-latest
36+ arch : x86_64
37+ name : linux-vulkan
38+ make : LLAMA="-DGGML_NATIVE=OFF -DGGML_VULKAN=ON"
39+ - os : ubuntu-latest
40+ arch : x86_64
41+ name : linux-opencl
42+ make : LLAMA="-DGGML_NATIVE=ON -DGGML_OPENCL=ON"
43+
44+ # Linux ARM64 builds
45+ - os : LinuxARM64
46+ arch : arm64
47+ name : linux-arm64-cpu
48+ make : LLAMA="-DGGML_NATIVE=ON"
49+ - os : LinuxARM64
50+ arch : arm64
51+ name : linux-arm64-neon
52+ make : LLAMA="-DGGML_NATIVE=OFF -DGGML_CPU_ARM_ARCH=armv8.2-a"
53+ - os : LinuxARM64
54+ arch : arm64
55+ name : linux-arm64-openblas
56+ make : LLAMA="-DGGML_NATIVE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS"
57+ - os : LinuxARM64
58+ arch : arm64
59+ name : linux-arm64-vulkan
60+ make : LLAMA="-DGGML_NATIVE=OFF -DGGML_VULKAN=ON"
61+ - os : LinuxARM64
62+ arch : arm64
63+ name : linux-arm64-opencl
64+ make : LLAMA="-DGGML_NATIVE=ON -DGGML_OPENCL=ON"
65+
66+ # macOS builds
67+ - os : macos-latest
68+ name : macos
69+ make : LLAMA="-DGGML_NATIVE=ON -DGGML_METAL=ON -DGGML_ACCELERATE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=Apple" WHISPER="-DGGML_METAL=ON -DGGML_ACCELERATE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=Apple -DWHISPER_COREML=ON -DWHISPER_COREML_ALLOW_FALLBACK=ON"
70+
71+ # Windows builds (commented out but ready to enable)
72+ # - os: windows-latest
73+ # arch: x86_64
74+ # name: windows-cpu
75+ # make: LLAMA="-DGGML_NATIVE=ON"
76+ # - os: windows-latest
77+ # arch: x86_64
78+ # name: windows-vulkan
79+ # make: LLAMA="-DGGML_NATIVE=OFF -DGGML_VULKAN=ON"
80+
81+ # Android builds
82+ - os : ubuntu-latest
83+ arch : arm64-v8a
84+ name : android
85+ make : PLATFORM=android ARCH=arm64-v8a
86+ - os : ubuntu-latest
87+ arch : x86_64
88+ name : android
89+ make : PLATFORM=android ARCH=x86_64
90+ sqlite-amalgamation-zip : https://sqlite.org/2025/sqlite-amalgamation-3490100.zip
91+
92+ # iOS builds
93+ - os : macos-latest
94+ name : ios
95+ make : PLATFORM=ios
96+ - os : macos-latest
97+ name : isim
98+ make : PLATFORM=isim
99+
100+ defaults :
101+ run :
102+ shell : bash
103+
104+ steps :
105+
106+ - uses : actions/checkout@v4.2.2
107+ with :
108+ submodules : true
109+
110+ - uses : msys2/setup-msys2@v2.27.0
111+ if : matrix.os == 'windows-latest'
112+ with :
113+ msystem : mingw64
114+ install : >-
115+ mingw-w64-x86_64-cc
116+ mingw-w64-x86_64-cmake
117+ make
118+
119+ - name : linux install dependencies
120+ if : startsWith(matrix.name, 'linux-')
121+ run : |
122+ sudo apt-get update -y
123+ sudo apt-get install -y build-essential wget git cmake sqlite3 libcurl4-openssl-dev
124+
125+ - name : linux install openblas
126+ if : contains(matrix.name, 'openblas')
127+ run : |
128+ sudo apt-get install -y libopenblas-dev
129+
130+ - name : linux install opencl
131+ if : contains(matrix.name, 'opencl')
132+ run : |
133+ sudo apt-get install -y opencl-headers ocl-icd-opencl-dev
134+
135+ - name : linux install vulkan (x86_64)
136+ if : contains(matrix.name, 'vulkan') && matrix.arch == 'x86_64'
137+ run : |
138+ wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
139+ sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-jammy.list https://packages.lunarg.com/vulkan/lunarg-vulkan-jammy.list
140+ sudo apt-get update -y
141+ sudo apt-get install -y mesa-vulkan-drivers
142+ # Vulkan is no longer packed for Ubuntu
143+ wget https://sdk.lunarg.com/sdk/download/latest/linux/vulkan-sdk.tar.xz?Human=true -O vulkan-sdk.tar.xz
144+ tar -xf vulkan-sdk.tar.xz
145+ cd $(ls -d 1.* | head -n1)
146+ source setup-env.sh
147+ echo "VULKAN_SDK=$VULKAN_SDK" >> $GITHUB_ENV
148+ echo "PATH=$PATH" >> $GITHUB_ENV
149+ echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> $GITHUB_ENV
150+ echo "VK_ADD_LAYER_PATH=$VK_ADD_LAYER_PATH" >> $GITHUB_ENV
151+
152+ - name : linux install vulkan (arm64)
153+ if : contains(matrix.name, 'vulkan') && matrix.arch == 'arm64'
154+ run : |
155+ sudo dpkg --add-architecture arm64
156+
157+ # Add arch-specific repositories for non-amd64 architectures
158+ cat << EOF | sudo tee /etc/apt/sources.list.d/arm64-ports.list
159+ deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ noble main universe
160+ deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ noble-updates main universe
161+ deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ noble-security main universe
162+ deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ noble-backports main universe
163+ EOF
164+
165+ sudo apt-get update || true ;# Prevent failure due to missing URLs.
166+
167+ sudo apt-get install -y --no-install-recommends \
168+ build-essential \
169+ glslc \
170+ crossbuild-essential-arm64 \
171+ libvulkan-dev:arm64
172+
173+ - name : windows build sqlite-ai
174+ if : matrix.name == 'windows'
175+ run : make extension ${{ matrix.make && matrix.make || ''}}
176+ shell : msys2 {0}
177+
178+ - name : build sqlite-ai
179+ if : matrix.name != 'windows'
180+ run : make extension ${{ matrix.make && matrix.make || ''}}
181+
182+ - name : windows install sqlite3
183+ if : matrix.os == 'windows-latest'
184+ run : choco install sqlite -y
185+
186+ - name : macos install sqlite3 without SQLITE_OMIT_LOAD_EXTENSION
187+ if : matrix.name == 'macos'
188+ run : brew link sqlite --force
189+
190+ - name : android setup test environment
191+ if : matrix.name == 'android' && matrix.arch != 'arm64-v8a'
192+ run : |
193+
194+ echo "::group::enable kvm group perms"
195+ echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
196+ sudo udevadm control --reload-rules
197+ sudo udevadm trigger --name-match=kvm
198+ echo "::endgroup::"
199+
200+ echo "::group::download and build sqlite3 without SQLITE_OMIT_LOAD_EXTENSION"
201+ curl -O ${{ matrix.sqlite-amalgamation-zip }}
202+ unzip sqlite-amalgamation-*.zip
203+ export ${{ matrix.make }}
204+ $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/${{ matrix.arch }}-linux-android26-clang sqlite-amalgamation-*/shell.c sqlite-amalgamation-*/sqlite3.c -o sqlite3 -ldl
205+ # remove unused folders to save up space
206+ rm -rf sqlite-amalgamation-*.zip sqlite-amalgamation-*
207+ echo "::endgroup::"
208+
209+ echo "::group::prepare the test script"
210+ make test PLATFORM=$PLATFORM ARCH=$ARCH || echo "It should fail. Running remaining commands in the emulator"
211+ cat > commands.sh << EOF
212+ mv -f /data/local/tmp/sqlite3 /system/xbin
213+ cd /data/local/tmp
214+ $(make test PLATFORM=$PLATFORM ARCH=$ARCH -n)
215+ EOF
216+ # remove big unused folders to avoid emulator errors
217+ rm -rf build modules
218+ echo "::endgroup::"
219+
220+ - name : android test sqlite-ai
221+ if : matrix.name == 'android' && matrix.arch != 'arm64-v8a'
222+ uses : reactivecircus/android-emulator-runner@v2.34.0
223+ with :
224+ api-level : 26
225+ arch : ${{ matrix.arch }}
226+ script : |
227+ adb root
228+ adb remount
229+ adb push ${{ github.workspace }}/. /data/local/tmp/
230+ adb shell "sh /data/local/tmp/commands.sh"
231+
232+ - name : test sqlite-ai
233+ if : startsWith(matrix.name, 'linux-') || startsWith(matrix.name, 'windows-') || matrix.name == 'macos'
234+ run : make test
235+
236+ - uses : actions/upload-artifact@v4.6.2
237+ if : always()
238+ with :
239+ name : ai-${{ matrix.name }}${{ matrix.arch && format('-{0}', matrix.arch) || '' }}
240+ path : dist/ai.*
241+ if-no-files-found : error
242+
243+ release :
244+ runs-on : ubuntu-latest
245+ name : release
246+ needs : build
247+ if : github.ref == 'refs/heads/main'
248+
249+ steps :
250+
251+ - uses : actions/checkout@v4.2.2
252+
253+ - uses : actions/download-artifact@v4.2.1
254+ with :
255+ path : artifacts
256+
257+ - name : release tag version from sqlite-ai.h
258+ id : tag
259+ run : |
260+ VERSION=$(make version)
261+ if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
262+ LATEST=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r '.name')
263+ if [[ "$VERSION" != "$LATEST" || "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]]; then
264+ echo "version=$VERSION" >> $GITHUB_OUTPUT
265+ else
266+ echo "::warning file=src/sqlite-ai.h::To release a new version, please update the SQLITE_AI_VERSION in src/sqlite-ai.h to be different than the latest $LATEST"
267+ fi
268+ exit 0
269+ fi
270+ echo "❌ SQLITE_AI_VERSION not found in sqlite-ai.h"
271+ exit 1
272+
273+ - name : zip artifacts
274+ run : |
275+ for folder in "artifacts"/*; do
276+ if [ -d "$folder" ]; then
277+ name=$(basename "$folder")
278+ zip -jq "${name}-${{ steps.tag.outputs.version }}.zip" "$folder"/*
279+ tar -cJf "${name}-${{ steps.tag.outputs.version }}.tar.xz" -C "$folder" .
280+ tar -czf "${name}-${{ steps.tag.outputs.version }}.tar.gz" -C "$folder" .
281+ fi
282+ done
283+
284+ - uses : softprops/action-gh-release@v2.2.1
285+ if : steps.tag.outputs.version != ''
286+ with :
287+ generate_release_notes : true
288+ tag_name : ${{ steps.tag.outputs.version }}
289+ files : |
290+ ai-*-${{ steps.tag.outputs.version }}.zip
291+ ai-*-${{ steps.tag.outputs.version }}.tar.xz
292+ ai-*-${{ steps.tag.outputs.version }}.tar.gz
293+ make_latest : true
0 commit comments