diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 720f8ae..e72388f 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -461,17 +461,58 @@ jobs:
# job *after* the bundle was uploaded (and typically published server-side), while
# the signed jars + .asc files already exist in each module's target/ (signing happens at
# verify). Collecting on failure lets the github-snapshot job still attach them.
- - name: Collect signed artifacts
+ # NOTE: the fat jar (jar-with-dependencies) is EXCLUDED here — it is no longer attached/
+ # deployed to Central (srcmorph-cli/pom.xml sets false), so it is unsigned
+ # in target/ at this point. It is built + signed + collected by the next step instead. This
+ # step runs BEFORE that one so the deploy-signed plain/sources/javadoc jars are captured
+ # before the classifier loop rebuilds (and clobbers) srcmorph-cli/target.
+ - name: Collect signed Central artifacts (plain/sources/javadoc; fat jars handled next)
if: ${{ !cancelled() }}
- # All three reactor modules produce their own jars/asc files (root pom has no jar).
run: |
mkdir -p signed-snapshot-assets
- cp srcmorph/target/*.jar signed-snapshot-assets/ 2>/dev/null || true
- cp srcmorph/target/*.jar.asc signed-snapshot-assets/ 2>/dev/null || true
- cp srcmorph-cli/target/*.jar signed-snapshot-assets/ 2>/dev/null || true
- cp srcmorph-cli/target/*.jar.asc signed-snapshot-assets/ 2>/dev/null || true
- cp srcmorph-maven-plugin/target/*.jar signed-snapshot-assets/ 2>/dev/null || true
- cp srcmorph-maven-plugin/target/*.jar.asc signed-snapshot-assets/ 2>/dev/null || true
+ for m in srcmorph srcmorph-cli srcmorph-maven-plugin; do
+ for f in "$m"/target/*.jar "$m"/target/*.jar.asc; do
+ [ -e "$f" ] || continue
+ case "$f" in *-jar-with-dependencies.jar|*-jar-with-dependencies.jar.asc) continue ;; esac
+ cp "$f" signed-snapshot-assets/
+ done
+ done
+ # Build one srcmorph-cli fat jar per net.ladenthin:llama native classifier + the default
+ # all-platform CPU fat jar, GPG-sign each, and add them to the GitHub-Release assets. These
+ # are GitHub-only (never Maven Central): each bundles exactly one llama native binary, so a
+ # GPU jar runs only on its own OS/arch/backend, while the default (no classifier) bundles the
+ # multi-platform CPU natives and runs anywhere. Signing uses the key setup-java already
+ # imported (armored detached .asc, same shape Central produces).
+ - name: Build & sign classifier fat jars (GitHub-only assets, never Central)
+ if: ${{ !cancelled() }}
+ env:
+ MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+ run: |
+ set -euo pipefail
+ if [ -n "${MAVEN_GPG_PASSPHRASE:-}" ]; then echo "::add-mask::${MAVEN_GPG_PASSPHRASE}"; fi
+ # Source of truth: the set in java-llama.cpp llama/pom.xml for the pinned
+ # ${llama.version} (all published to Maven Central). Keep in sync on a llama bump.
+ CLASSIFIERS=(
+ cuda13-linux-x86-64 cuda13-windows-x86-64
+ vulkan-linux-x86-64 vulkan-linux-aarch64 vulkan-windows-x86-64
+ opencl-windows-x86-64 opencl-windows-aarch64 opencl-android-aarch64
+ rocm-linux-x86-64 rocm-windows-x86-64
+ sycl-fp16-linux-x86-64 sycl-fp32-linux-x86-64 sycl-windows-x86-64
+ openvino-linux-x86-64 openvino-windows-x86-64
+ msvc-windows
+ )
+ build() { mvn -B --no-transfer-progress -pl srcmorph-cli -am -DskipTests -Dmaven.javadoc.skip=true -Dllama.classifier="$1" package; }
+ for c in "${CLASSIFIERS[@]}"; do
+ build "$c"
+ f=$(ls srcmorph-cli/target/srcmorph-cli-*-jar-with-dependencies.jar)
+ cp "$f" "${f%.jar}-${c}.jar"
+ done
+ # default CPU build LAST so the unsuffixed fat jar is the all-platform CPU variant
+ build ""
+ for f in srcmorph-cli/target/srcmorph-cli-*-jar-with-dependencies*.jar; do
+ printf '%s' "$MAVEN_GPG_PASSPHRASE" | gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 --detach-sign --armor "$f"
+ cp "$f" "$f".asc signed-snapshot-assets/
+ done
- uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
@@ -542,17 +583,58 @@ jobs:
# job *after* the bundle was uploaded (and typically published server-side), while
# the signed jars + .asc files already exist in each module's target/ (signing happens at
# verify). Collecting on failure lets the github-release job still attach them.
- - name: Collect signed artifacts
+ # NOTE: the fat jar (jar-with-dependencies) is EXCLUDED here — it is no longer attached/
+ # deployed to Central (srcmorph-cli/pom.xml sets false), so it is unsigned
+ # in target/ at this point. It is built + signed + collected by the next step instead. This
+ # step runs BEFORE that one so the deploy-signed plain/sources/javadoc jars are captured
+ # before the classifier loop rebuilds (and clobbers) srcmorph-cli/target.
+ - name: Collect signed Central artifacts (plain/sources/javadoc; fat jars handled next)
if: ${{ !cancelled() }}
- # All three reactor modules produce their own jars/asc files (root pom has no jar).
run: |
mkdir -p signed-release-assets
- cp srcmorph/target/*.jar signed-release-assets/ 2>/dev/null || true
- cp srcmorph/target/*.jar.asc signed-release-assets/ 2>/dev/null || true
- cp srcmorph-cli/target/*.jar signed-release-assets/ 2>/dev/null || true
- cp srcmorph-cli/target/*.jar.asc signed-release-assets/ 2>/dev/null || true
- cp srcmorph-maven-plugin/target/*.jar signed-release-assets/ 2>/dev/null || true
- cp srcmorph-maven-plugin/target/*.jar.asc signed-release-assets/ 2>/dev/null || true
+ for m in srcmorph srcmorph-cli srcmorph-maven-plugin; do
+ for f in "$m"/target/*.jar "$m"/target/*.jar.asc; do
+ [ -e "$f" ] || continue
+ case "$f" in *-jar-with-dependencies.jar|*-jar-with-dependencies.jar.asc) continue ;; esac
+ cp "$f" signed-release-assets/
+ done
+ done
+ # Build one srcmorph-cli fat jar per net.ladenthin:llama native classifier + the default
+ # all-platform CPU fat jar, GPG-sign each, and add them to the GitHub-Release assets. These
+ # are GitHub-only (never Maven Central): each bundles exactly one llama native binary, so a
+ # GPU jar runs only on its own OS/arch/backend, while the default (no classifier) bundles the
+ # multi-platform CPU natives and runs anywhere. Signing uses the key setup-java already
+ # imported (armored detached .asc, same shape Central produces).
+ - name: Build & sign classifier fat jars (GitHub-only assets, never Central)
+ if: ${{ !cancelled() }}
+ env:
+ MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+ run: |
+ set -euo pipefail
+ if [ -n "${MAVEN_GPG_PASSPHRASE:-}" ]; then echo "::add-mask::${MAVEN_GPG_PASSPHRASE}"; fi
+ # Source of truth: the set in java-llama.cpp llama/pom.xml for the pinned
+ # ${llama.version} (all published to Maven Central). Keep in sync on a llama bump.
+ CLASSIFIERS=(
+ cuda13-linux-x86-64 cuda13-windows-x86-64
+ vulkan-linux-x86-64 vulkan-linux-aarch64 vulkan-windows-x86-64
+ opencl-windows-x86-64 opencl-windows-aarch64 opencl-android-aarch64
+ rocm-linux-x86-64 rocm-windows-x86-64
+ sycl-fp16-linux-x86-64 sycl-fp32-linux-x86-64 sycl-windows-x86-64
+ openvino-linux-x86-64 openvino-windows-x86-64
+ msvc-windows
+ )
+ build() { mvn -B --no-transfer-progress -pl srcmorph-cli -am -DskipTests -Dmaven.javadoc.skip=true -Dllama.classifier="$1" package; }
+ for c in "${CLASSIFIERS[@]}"; do
+ build "$c"
+ f=$(ls srcmorph-cli/target/srcmorph-cli-*-jar-with-dependencies.jar)
+ cp "$f" "${f%.jar}-${c}.jar"
+ done
+ # default CPU build LAST so the unsuffixed fat jar is the all-platform CPU variant
+ build ""
+ for f in srcmorph-cli/target/srcmorph-cli-*-jar-with-dependencies*.jar; do
+ printf '%s' "$MAVEN_GPG_PASSPHRASE" | gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 --detach-sign --armor "$f"
+ cp "$f" "$f".asc signed-release-assets/
+ done
- uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
diff --git a/srcmorph-cli/README.md b/srcmorph-cli/README.md
index 29874ca..0213369 100644
--- a/srcmorph-cli/README.md
+++ b/srcmorph-cli/README.md
@@ -14,7 +14,19 @@ java -jar srcmorph-cli--jar-with-dependencies.jar -jar-with-dependencies.jar`, built by `mvn package`) bundles every
-dependency, including a logback binding, so it runs standalone. Both `.json`/`.js` (parsed via a
+dependency, including a logback binding, so it runs standalone.
+
+**Download:** the pre-built fat jars are attached to each
+[GitHub Release](https://github.com/bernardladenthin/srcmorph/releases) (with a `.asc` GPG signature),
+**not** Maven Central. The unsuffixed `srcmorph-cli--jar-with-dependencies.jar` bundles the
+multi-platform **CPU** `net.ladenthin:llama` native and runs on any OS/arch. For GPU acceleration there
+is one classifier variant per llama native backend —
+`srcmorph-cli--jar-with-dependencies-.jar` (e.g. `-cuda13-linux-x86-64`,
+`-vulkan-windows-x86-64`) — each bundling exactly that one backend's binary, so it runs only on the
+matching OS/arch with that GPU runtime present. Pick the plain CPU jar unless you specifically want a
+GPU build.
+
+Both `.json`/`.js` (parsed via a
Jackson `ObjectMapper`) and `.yaml`/`.yml` (parsed via `YAMLMapper`) are supported — pick whichever you
prefer; both mappers are configured strictly (`FAIL_ON_UNKNOWN_PROPERTIES`), so a typo'd key fails the
run immediately rather than being silently ignored. On startup the CLI logs the parsed configuration
diff --git a/srcmorph-cli/pom.xml b/srcmorph-cli/pom.xml
index 1d442fe..c4495db 100644
--- a/srcmorph-cli/pom.xml
+++ b/srcmorph-cli/pom.xml
@@ -488,8 +488,18 @@ SPDX-License-Identifier: Apache-2.0
IS the deliverable artifact (the thing a user actually downloads and runs with
`java -jar`), not an occasional extra. Binding it in every `mvn package` (and therefore
every `mvn verify` / release build) keeps it in lockstep with the plain jar rather than
- depending on a profile flag being remembered at release time. It rides `mvn -P release
- deploy` as the `jar-with-dependencies` classifier alongside the plain jar.
+ depending on a profile flag being remembered at release time.
+
+ `false`: the fat jar is a GitHub-Release-only asset and must NOT be
+ deployed to Maven Central. A jar-with-dependencies on Central is redundant (consumers
+ depend on the plain `srcmorph-cli` jar + its resolved dependency graph, never the fat
+ jar) and, because it bundles the `net.ladenthin:llama` native binary, is both large and
+ platform-specific. Leaving it attached uploaded a 74 MB fat jar to Central on every
+ release. With attach=false the file is still produced in target/ (so the CI build's
+ upload-artifact and the release job's classifier-fat-jar loop still pick it up) but is
+ neither installed to ~/.m2 nor deployed to Central. Signing + GitHub attachment (for
+ this default CPU jar and one fat jar per net.ladenthin:llama GPU classifier) is done
+ explicitly by the publish-release / publish-snapshot jobs in .github/workflows/publish.yml.
-->
org.apache.maven.plugins
@@ -503,6 +513,7 @@ SPDX-License-Identifier: Apache-2.0
net.ladenthin.srcmorph.cli.Main
+ false