Skip to content

Commit c560813

Browse files
committed
Add OpenCL/Adreno GPU backend for Android arm64
Idea ported from LLaMAndroid (Rattlyy/LLaMAndroid): build a second Android arm64 artifact with the OpenCL backend enabled and Adreno-tuned kernels embedded, so users on Qualcomm Snapdragon devices get real GPU acceleration instead of CPU-only inference. The existing CPU Android JAR stays as the default fallback for devices without an OpenCL ICD. - CMakeLists.txt: route GGML_OPENCL builds to resources_android_opencl/ - pom.xml: add opencl-android profile + classifier opencl-android-aarch64 - publish.yml: new crosscompile-android-aarch64-opencl job wired into package, publish-snapshot, and publish-release - CLAUDE.md: document the three wiring points https://claude.ai/code/session_01CQFUfYpg9m65CBt5RRaFRr
1 parent 5495d23 commit c560813

4 files changed

Lines changed: 137 additions & 5 deletions

File tree

.github/workflows/publish.yml

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,22 @@ jobs:
137137
name: Linux-Android-aarch64-libraries
138138
path: ${{ github.workspace }}/src/main/resources/net/ladenthin/llama/
139139

140+
crosscompile-android-aarch64-opencl:
141+
name: Cross-Compile Android aarch64 (OpenCL/Adreno)
142+
needs: startgate
143+
runs-on: ubuntu-latest
144+
steps:
145+
- uses: actions/checkout@v6
146+
- name: Build libraries
147+
shell: bash
148+
run: |
149+
.github/dockcross/dockcross-android-arm64 .github/build.sh "-DANDROID_PLATFORM=android-24 -DOS_NAME=Linux-Android -DOS_ARCH=aarch64 -DGGML_OPENCL=ON -DGGML_OPENCL_EMBED_KERNELS=ON -DGGML_OPENCL_USE_ADRENO_KERNELS=ON"
150+
- name: Upload artifacts
151+
uses: actions/upload-artifact@v7
152+
with:
153+
name: android-libraries-opencl
154+
path: ${{ github.workspace }}/src/main/resources_android_opencl/net/ladenthin/llama/
155+
140156
# ---------------------------------------------------------------------------
141157
# Native build jobs — produce release artifacts + run C++ unit tests
142158
# ---------------------------------------------------------------------------
@@ -582,6 +598,7 @@ jobs:
582598
- crosscompile-linux-x86_64-cuda
583599
- crosscompile-linux-aarch64
584600
- crosscompile-android-aarch64
601+
- crosscompile-android-aarch64-opencl
585602
- build-windows-x86
586603
- test-cpp-linux-x86_64
587604
- test-macos-arm64-metal-15
@@ -601,12 +618,16 @@ jobs:
601618
with:
602619
name: linux-libraries-cuda
603620
path: ${{ github.workspace }}/src/main/resources_linux_cuda/net/ladenthin/llama/
621+
- uses: actions/download-artifact@v8
622+
with:
623+
name: android-libraries-opencl
624+
path: ${{ github.workspace }}/src/main/resources_android_opencl/net/ladenthin/llama/
604625
- uses: actions/setup-java@v5
605626
with:
606627
distribution: 'temurin'
607628
java-version: ${{ env.JAVA_VERSION }}
608629
- name: Build JARs
609-
run: mvn --batch-mode --no-transfer-progress -P release,cuda -Dmaven.test.skip=true -Dgpg.skip=true package
630+
run: mvn --batch-mode --no-transfer-progress -P release,cuda,opencl-android -Dmaven.test.skip=true -Dgpg.skip=true package
610631
- name: Upload JARs
611632
uses: actions/upload-artifact@v7
612633
with:
@@ -663,7 +684,7 @@ jobs:
663684

664685
publish-snapshot:
665686
name: Publish Snapshot to Central
666-
needs: [check-snapshot, crosscompile-linux-x86_64-cuda]
687+
needs: [check-snapshot, crosscompile-linux-x86_64-cuda, crosscompile-android-aarch64-opencl]
667688
if: needs.check-snapshot.result == 'success'
668689
runs-on: ubuntu-latest
669690
environment: maven-central
@@ -680,6 +701,10 @@ jobs:
680701
with:
681702
name: linux-libraries-cuda
682703
path: ${{ github.workspace }}/src/main/resources_linux_cuda/net/ladenthin/llama/
704+
- uses: actions/download-artifact@v8
705+
with:
706+
name: android-libraries-opencl
707+
path: ${{ github.workspace }}/src/main/resources_android_opencl/net/ladenthin/llama/
683708
- name: Set up Maven Central Repository
684709
uses: actions/setup-java@v5
685710
with:
@@ -691,7 +716,7 @@ jobs:
691716
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
692717
gpg-passphrase: MAVEN_GPG_PASSPHRASE
693718
- name: Publish snapshot
694-
run: mvn --batch-mode -P release,cuda -Dmaven.test.skip=true deploy
719+
run: mvn --batch-mode -P release,cuda,opencl-android -Dmaven.test.skip=true deploy
695720
env:
696721
MAVEN_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
697722
MAVEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN }}
@@ -735,7 +760,7 @@ jobs:
735760
publish-release:
736761
name: Publish Release to Central
737762
if: needs.check-tag.result == 'success'
738-
needs: [check-tag, crosscompile-linux-x86_64-cuda]
763+
needs: [check-tag, crosscompile-linux-x86_64-cuda, crosscompile-android-aarch64-opencl]
739764
runs-on: ubuntu-latest
740765
environment: maven-central
741766
permissions:
@@ -751,6 +776,10 @@ jobs:
751776
with:
752777
name: linux-libraries-cuda
753778
path: ${{ github.workspace }}/src/main/resources_linux_cuda/net/ladenthin/llama/
779+
- uses: actions/download-artifact@v8
780+
with:
781+
name: android-libraries-opencl
782+
path: ${{ github.workspace }}/src/main/resources_android_opencl/net/ladenthin/llama/
754783
- name: Set up Maven Central Repository
755784
uses: actions/setup-java@v5
756785
with:
@@ -762,7 +791,7 @@ jobs:
762791
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
763792
gpg-passphrase: MAVEN_GPG_PASSPHRASE
764793
- name: Publish release
765-
run: mvn --batch-mode -P release,cuda -Dmaven.test.skip=true deploy
794+
run: mvn --batch-mode -P release,cuda,opencl-android -Dmaven.test.skip=true deploy
766795
env:
767796
MAVEN_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
768797
MAVEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN }}

CLAUDE.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,40 @@ git add .github/build_cuda_linux.sh pom.xml CLAUDE.md
3838
git commit -m "Upgrade CUDA from 13.2 to 13.3"
3939
```
4040

41+
## OpenCL / Adreno backend on Android
42+
43+
A second Android arm64 artifact is built with the OpenCL backend enabled and
44+
Adreno-tuned kernels embedded. It ships under the Maven classifier
45+
`opencl-android-aarch64` and is consumed only when callers explicitly request it.
46+
The default Android arm64 JAR remains CPU-only.
47+
48+
Three places wire it together (mirrors the CUDA classifier pattern):
49+
50+
1. **`CMakeLists.txt`**`elseif(GGML_OPENCL)` branch routes artifacts to
51+
`src/main/resources_android_opencl/net/ladenthin/llama/${OS_NAME}/${OS_ARCH}/`.
52+
2. **`.github/workflows/publish.yml`**`crosscompile-android-aarch64-opencl`
53+
job runs the dockcross-android-arm64 build with
54+
`-DGGML_OPENCL=ON -DGGML_OPENCL_EMBED_KERNELS=ON -DGGML_OPENCL_USE_ADRENO_KERNELS=ON`
55+
and uploads as artifact `android-libraries-opencl`. The `package`,
56+
`publish-snapshot`, and `publish-release` jobs download it into
57+
`resources_android_opencl/` and activate the `opencl-android` Maven profile.
58+
3. **`pom.xml`** — the `opencl-android` profile produces a second JAR with
59+
`<classifier>opencl-android-aarch64</classifier>` from the
60+
`${project.build.outputDirectory}_opencl_android` tree.
61+
62+
Local sanity build:
63+
```bash
64+
.github/dockcross/dockcross-android-arm64 .github/build.sh \
65+
"-DANDROID_PLATFORM=android-24 -DOS_NAME=Linux-Android -DOS_ARCH=aarch64 \
66+
-DGGML_OPENCL=ON -DGGML_OPENCL_EMBED_KERNELS=ON \
67+
-DGGML_OPENCL_USE_ADRENO_KERNELS=ON"
68+
```
69+
Artifacts land in `src/main/resources_android_opencl/net/ladenthin/llama/Linux-Android/aarch64/`.
70+
71+
At runtime the device must provide an OpenCL ICD (`libOpenCL.so`); Qualcomm
72+
Adreno drivers do. Devices without an ICD should use the default CPU-only
73+
Android JAR.
74+
4175
## Upgrading/Downgrading llama.cpp Version
4276

4377
To change the llama.cpp version, update the following **three** files:

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ endif()
186186
if(GGML_CUDA)
187187
set(JLLAMA_DIR ${CMAKE_SOURCE_DIR}/src/main/resources_linux_cuda/net/ladenthin/llama/${OS_NAME}/${OS_ARCH})
188188
message(STATUS "GPU (CUDA Linux) build - Installing files to ${JLLAMA_DIR}")
189+
elseif(GGML_OPENCL)
190+
set(JLLAMA_DIR ${CMAKE_SOURCE_DIR}/src/main/resources_android_opencl/net/ladenthin/llama/${OS_NAME}/${OS_ARCH})
191+
message(STATUS "GPU (OpenCL Android) build - Installing files to ${JLLAMA_DIR}")
189192
else()
190193
set(JLLAMA_DIR ${CMAKE_SOURCE_DIR}/src/main/resources/net/ladenthin/llama/${OS_NAME}/${OS_ARCH})
191194
message(STATUS "CPU build - Installing files to ${JLLAMA_DIR}")

pom.xml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,22 @@ SPDX-License-Identifier: MIT
146146
${project.build.outputDirectory}_cuda</outputDirectory>
147147
</configuration>
148148
</execution>
149+
<!-- Separate build pass for opencl-android classifier -->
150+
<execution>
151+
<id>opencl-android</id>
152+
<phase>compile</phase>
153+
<goals>
154+
<goal>compile</goal>
155+
</goals>
156+
<configuration>
157+
<compilerArgs>
158+
<arg>-h</arg>
159+
<arg>src/main/cpp</arg>
160+
</compilerArgs>
161+
<outputDirectory>
162+
${project.build.outputDirectory}_opencl_android</outputDirectory>
163+
</configuration>
164+
</execution>
149165
</executions>
150166
</plugin>
151167
<plugin>
@@ -173,6 +189,27 @@ SPDX-License-Identifier: MIT
173189
</resources>
174190
</configuration>
175191
</execution>
192+
<!-- Copy custom opencl-android libs to the output directory -->
193+
<execution>
194+
<id>copy-resources-opencl-android</id>
195+
<phase>process-classes</phase>
196+
<goals>
197+
<goal>copy-resources</goal>
198+
</goals>
199+
<configuration>
200+
<outputDirectory>
201+
${project.build.outputDirectory}_opencl_android</outputDirectory>
202+
<resources>
203+
<resource>
204+
<directory>
205+
${basedir}/src/main/resources_android_opencl/</directory>
206+
<includes>
207+
<include>**/*.*</include>
208+
</includes>
209+
</resource>
210+
</resources>
211+
</configuration>
212+
</execution>
176213
</executions>
177214
</plugin>
178215
<plugin>
@@ -295,5 +332,34 @@ SPDX-License-Identifier: MIT
295332
</plugins>
296333
</build>
297334
</profile>
335+
336+
<profile>
337+
<id>opencl-android</id>
338+
<build>
339+
<plugins>
340+
<plugin>
341+
<groupId>org.apache.maven.plugins</groupId>
342+
<artifactId>maven-jar-plugin</artifactId>
343+
<version>3.5.0</version>
344+
<executions>
345+
<!-- Pick class files AND libs from custom output
346+
directory -->
347+
<execution>
348+
<id>opencl-android</id>
349+
<phase>package</phase>
350+
<goals>
351+
<goal>jar</goal>
352+
</goals>
353+
<configuration>
354+
<classifier>opencl-android-aarch64</classifier>
355+
<classesDirectory>
356+
${project.build.outputDirectory}_opencl_android</classesDirectory>
357+
</configuration>
358+
</execution>
359+
</executions>
360+
</plugin>
361+
</plugins>
362+
</build>
363+
</profile>
298364
</profiles>
299365
</project>

0 commit comments

Comments
 (0)