Repository navigation
examples/windows-fatjar: build your own fat jar and run it; stale template and GPU docs fixed #244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
69050dd
015c46b
0f53d46
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| <!-- | ||
| SPDX-FileCopyrightText: 2026 Bernard Ladenthin <bernard.ladenthin@gmail.com> | ||
|
|
||
| SPDX-License-Identifier: MIT | ||
| --> | ||
|
|
||
| # srcmorph on Windows: build your own fat jar, then run it | ||
|
|
||
| Two steps, four files, all in [`examples/windows-fatjar/`](../examples/windows-fatjar/): | ||
|
|
||
| | File | What it does | | ||
| |---|---| | ||
| | `pom.xml` | names srcmorph and **the llama natives this machine needs** (the classifiers) | | ||
| | `build.bat` | one `mvn package` on a JDK 8 → `target\srcmorph.jar` | | ||
| | `srcmorph.yaml` | what to index, with which prompt and which model | | ||
| | `run.bat` | `java -jar target\srcmorph.jar srcmorph.yaml` | | ||
|
|
||
| Needed on the machine: a JDK 8 or newer, Maven, and a GGUF model. Nothing else: no C++ toolchain and | ||
| no GPU SDK. The Vulkan module uses the GPU driver that is already installed. | ||
|
|
||
| Why build the jar yourself: the fat jar on the GitHub release carries the CPU natives of every | ||
| desktop platform (~111 MiB with Vulkan). Your own carries only the ones you name (32 MiB for the two | ||
| below), and you choose the GPU module. | ||
|
|
||
| > [!NOTE] | ||
| > This is for **srcmorph 1.3.0** (on `net.ladenthin:llama` 6.0.0). Until 1.3.0 is released the pom | ||
| > uses `1.3.0-SNAPSHOT` from Central's snapshot repository; then set the version to `1.3.0` and delete | ||
| > the `<repositories>` block. | ||
|
|
||
| ## Step 1 — pick the classifiers, build the jar | ||
|
|
||
| The pom declares one **library** jar for the OS/arch and, optionally, **GPU module** jars of the same | ||
| OS/arch. For a Windows x86-64 machine with an Intel Core Ultra (Arc iGPU), as shipped: | ||
|
|
||
| | Classifier | Size | Why | | ||
| |---|--:|---| | ||
| | `cpu-windows-x86-64` | 16.6 MiB | `jllama.dll`, llama/ggml and all CPU variants; ggml picks the best one at start (`alderlake` on a Core Ultra: AVX2 + AVX-VNNI, no AVX-512) | | ||
| | `vulkan-windows-x86-64` | 12.0 MiB | the iGPU (or any GPU) through the driver's `vulkan-1.dll`; without a working driver ggml skips it and runs on the CPU | | ||
|
|
||
| Other machines swap the classifiers: for example `cuda13-windows-x86-64` for an NVIDIA GPU (it needs | ||
| the CUDA 13 runtime on `PATH`), or `cpu-linux-x86-64` on Linux. The full table is in the java-llama.cpp | ||
| README, [Choosing the natives | ||
| jars](https://github.com/bernardladenthin/java-llama.cpp#choosing-the-natives-jars). | ||
| `openvino-*` is opt-in and can be slower than the CPU. Leave it out unless you want to experiment | ||
| with the NPU. | ||
|
|
||
| Set `JAVA_HOME` in `build.bat` to your JDK, then: | ||
|
|
||
| ```bat | ||
| build.bat | ||
| ``` | ||
|
|
||
| The result is `target\srcmorph.jar`. | ||
|
|
||
| ## Step 2 — the configuration, then run | ||
|
|
||
| Edit `srcmorph.yaml`. Its comments explain every key. The ones to set: | ||
|
|
||
| - **`baseDirectory`, `outputDirectory`, `subtrees`, `fileExtensions`**: which files to index, and | ||
| where the `.ai.md` files go. | ||
| - **`modelDirectory`, `modelPath`**: the GGUF. A good start on a laptop is | ||
| `granite-4.0-h-tiny-Q4_K_M.gguf`, the fastest on a CPU in [the benchmark](ai-index-benchmark/COMPARISON.md). | ||
| - **`promptDefinitions`**: the instruction to the model (the system prompt, **no placeholders**). | ||
| srcmorph sends each file's name and source as the user message itself. | ||
| - **`fieldGenerations`**: which prompt and model each file gets. One `fallback` rule covers every file. | ||
|
|
||
| What a run does: for every matching file, srcmorph sends the prompt and the source to the model and | ||
| writes the answer next to the source's path under `outputDirectory`, as `<file>.ai.md`. | ||
|
|
||
| Run it in two passes: | ||
|
|
||
| 1. With `command: Plan` (the shipped value), `run.bat` loads no model and writes nothing. It prints | ||
| which file gets which model, and which files are larger than the model's window. | ||
| 2. Then set `command: GenerateFileIndex`, or `All` to add package and project summaries, and run | ||
| `run.bat` again. | ||
|
|
||
| A second run regenerates only three kinds of files: a changed file, a file whose settings changed, | ||
| and a file whose summary is empty. An empty summary usually means `maxOutputTokens` was too small for | ||
| the model. | ||
|
|
||
| ## Check what loaded | ||
|
|
||
| The start of the run names the CPU variant, the backends and the devices: | ||
|
|
||
| ``` | ||
| load_backend: loaded Vulkan backend from <dir>\ggml-vulkan.dll | ||
| load_backend: loaded CPU backend from <dir>\ggml-cpu-alderlake.dll | ||
| load_backends_next_to_this_library: 3 backend(s) registered [RPC, Vulkan, CPU], 2 device(s): Vulkan0 (Vulkan), CPU (CPU) | ||
| [jllama] native backend 'cpu' loaded from <dir> with GPU module(s) vulkan; 18 file(s) in place for ggml to load | ||
| ``` | ||
|
|
||
| - **`with no GPU module`**: the Vulkan jar is not in the build. | ||
| - **Two Vulkan devices** (an iGPU and a discrete GPU): choose one with `devices: Vulkan1` in the | ||
| `aiDefinition`. | ||
| - **`gpuLayers: 0`**, or `-Dnet.ladenthin.llama.backend=cpu` before `-jar` in `run.bat`: runs on the | ||
| CPU only. That is the comparison to measure. | ||
|
|
||
| ## Two settings worth measuring | ||
|
|
||
| - **`threads`**: 4 is the default and enough for these models. A Core Ultra mixes P-, E- and slow | ||
| LP-E-cores, and ggml waits for the slowest thread, so more threads can be slower. Never set more | ||
| than the machine has cores: an oversubscribed run is orders of magnitude slower, not a little. | ||
| - **`gpuLayers: 99` against `0`**: the iGPU shares memory and a 15 W budget with the CPU, so measure | ||
| before deciding. `command: Calibrate` prints each model's prefill and decode speed. | ||
|
|
||
| ## Tested | ||
|
|
||
| On Windows, `cmd.exe`, srcmorph 1.3.0-SNAPSHOT: | ||
| - `build.bat` ran on a JDK 8 (1.8.0_504) and produced a 32 MiB jar holding only the Windows x86-64 | ||
| natives. | ||
| - `Plan` ran on the same JDK 8. | ||
| - `run.bat` indexed 6 Java files with Qwen3-0.6B on the Vulkan module, in 17 s, on a JDK 21. The test | ||
| machine has no JDK 8 installed. | ||
| - The test machine is a Ryzen with an AMD iGPU and an RTX 3070, which is why the log above was | ||
| written down for a Core Ultra rather than copied from it. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| REM SPDX-FileCopyrightText: 2026 Bernard Ladenthin <bernard.ladenthin@gmail.com> | ||
| REM | ||
| REM SPDX-License-Identifier: MIT OR Apache-2.0 | ||
|
|
||
| @echo off | ||
| rem Builds target\srcmorph.jar from pom.xml (the CLI plus the natives the pom names). Adapt JAVA_HOME. | ||
| cd /d "%~dp0" | ||
| set "JAVA_HOME=C:\Program Files\Java\openjdk1.8.0_491" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Preserve the configured Java installation. If a user has a valid Based on learnings, test and build scripts should avoid hardcoded machine-specific paths, use configured paths or a sensible default, and validate the resolved path.
|
||
| set "PATH=%JAVA_HOME%\bin;%PATH%" | ||
|
|
||
| mvn -B package | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!-- | ||
| SPDX-FileCopyrightText: 2026 Bernard Ladenthin <bernard.ladenthin@gmail.com> | ||
|
|
||
| SPDX-License-Identifier: MIT OR Apache-2.0 | ||
| --> | ||
| <!-- | ||
| Builds target\srcmorph.jar: the srcmorph CLI plus exactly the llama natives this machine needs. | ||
| Run build.bat once, then run.bat. The classifiers below are the only thing to adapt per machine: | ||
| one library jar for the OS/arch (cpu-...) and, optionally, GPU module jars of the same OS/arch. | ||
| The table of classifiers is in the java-llama.cpp README, "Choosing the natives jars". | ||
| --> | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
| <groupId>local</groupId> | ||
| <artifactId>srcmorph-local</artifactId> | ||
| <version>1</version> | ||
| <packaging>pom</packaging> | ||
|
|
||
| <properties> | ||
| <srcmorph.version>1.3.0-SNAPSHOT</srcmorph.version> | ||
| <llama.version>6.0.0</llama.version> | ||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| </properties> | ||
|
|
||
| <!-- Only needed while srcmorph.version is a -SNAPSHOT; delete it once 1.3.0 is on Maven Central. --> | ||
| <repositories> | ||
| <repository> | ||
| <id>central-snapshots</id> | ||
| <url>https://central.sonatype.com/repository/maven-snapshots/</url> | ||
| <releases><enabled>false</enabled></releases> | ||
| <snapshots><enabled>true</enabled></snapshots> | ||
| </repository> | ||
| </repositories> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>net.ladenthin</groupId> | ||
| <artifactId>srcmorph-cli</artifactId> | ||
| <version>${srcmorph.version}</version> | ||
| <exclusions> | ||
| <!-- the CPU natives of every desktop platform (~100 MiB); the jars below replace it --> | ||
| <exclusion> | ||
| <groupId>net.ladenthin</groupId> | ||
| <artifactId>llama-platform</artifactId> | ||
| </exclusion> | ||
| </exclusions> | ||
| </dependency> | ||
| <!-- the library: jllama.dll, llama/ggml and the CPU backend modules for Windows x86-64 --> | ||
| <dependency> | ||
| <groupId>net.ladenthin</groupId> | ||
| <artifactId>llama</artifactId> | ||
| <version>${llama.version}</version> | ||
| <classifier>cpu-windows-x86-64</classifier> | ||
| </dependency> | ||
| <!-- optional GPU module: any GPU with a Vulkan driver (Intel Arc/iGPU, AMD, NVIDIA). | ||
| Without a working driver ggml skips it and runs on the CPU. --> | ||
| <dependency> | ||
| <groupId>net.ladenthin</groupId> | ||
| <artifactId>llama</artifactId> | ||
| <version>${llama.version}</version> | ||
| <classifier>vulkan-windows-x86-64</classifier> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| <build> | ||
| <plugins> | ||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-assembly-plugin</artifactId> | ||
| <version>3.7.1</version> | ||
| <configuration> | ||
| <descriptorRefs> | ||
| <descriptorRef>jar-with-dependencies</descriptorRef> | ||
| </descriptorRefs> | ||
| <finalName>srcmorph</finalName> | ||
| <appendAssemblyId>false</appendAssemblyId> | ||
| <archive> | ||
| <manifest> | ||
| <mainClass>net.ladenthin.srcmorph.cli.Main</mainClass> | ||
| </manifest> | ||
| </archive> | ||
| </configuration> | ||
| <executions> | ||
| <execution> | ||
| <phase>package</phase> | ||
| <goals> | ||
| <goal>single</goal> | ||
| </goals> | ||
| </execution> | ||
| </executions> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
| </project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| REM SPDX-FileCopyrightText: 2026 Bernard Ladenthin <bernard.ladenthin@gmail.com> | ||
| REM | ||
| REM SPDX-License-Identifier: MIT OR Apache-2.0 | ||
|
|
||
| @echo off | ||
| rem Runs srcmorph with srcmorph.yaml from this directory. Adapt JAVA_HOME. | ||
| cd /d "%~dp0" | ||
| set "JAVA_HOME=C:\Program Files\Java\openjdk1.8.0_491" | ||
| set "PATH=%JAVA_HOME%\bin;%PATH%" | ||
|
|
||
| java -jar target\srcmorph.jar srcmorph.yaml |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| # SPDX-FileCopyrightText: 2026 Bernard Ladenthin <bernard.ladenthin@gmail.com> | ||
| # | ||
| # SPDX-License-Identifier: MIT OR Apache-2.0 | ||
|
|
||
| # What run.bat does with it: every file under baseDirectory/subtrees with one of the fileExtensions | ||
| # is matched to a rule in fieldGenerations. The rule names a prompt (promptDefinitions) and a model | ||
| # (aiDefinitions). srcmorph sends the prompt as the system message and the file's name and source as | ||
| # the user message, and writes the model's answer to outputDirectory as <file>.ai.md. | ||
| # | ||
| # command: | ||
| # Plan prints which file gets which model and prompt; loads nothing, writes nothing | ||
| # GenerateFileIndex one .ai.md per source file | ||
| # All GenerateFileIndex, then one summary per package and one for the project | ||
| # Start with Plan, then switch to GenerateFileIndex. A second run only redoes changed files. | ||
| command: Plan | ||
|
|
||
| srcMorph: | ||
| # Use forward slashes in Windows paths here: in a double-quoted YAML string, "C:\x" is an escape. | ||
| baseDirectory: "C:/path/to/project" | ||
| outputDirectory: "C:/path/to/project/target/srcmorph-ai" | ||
| subtrees: | ||
| - "src/main/java" | ||
| fileExtensions: | ||
| - ".java" | ||
|
|
||
| generationProvider: llamacpp-jni # "mock" runs without a model, for a dry test of the setup | ||
| modelDirectory: "C:/models" # a relative modelPath below is relative to this directory | ||
|
|
||
| promptDefinitions: | ||
| - key: java | ||
| template: "Summarize this Java file as structured Markdown: purpose, public API, collaborators." | ||
|
|
||
| aiDefinitions: | ||
| - key: local | ||
| modelPath: granite-4.0-h-tiny-Q4_K_M.gguf | ||
| contextSize: 16384 # tokens; a file larger than this is handled by onOversize | ||
| maxOutputTokens: 1024 | ||
| temperature: 0.15 | ||
| threads: 4 # the default; more only after measuring, never more than cores | ||
| gpuLayers: 99 # 99 = everything on the GPU (Vulkan), 0 = CPU only | ||
|
|
||
| fieldGenerations: | ||
| - promptKey: java | ||
| aiDefinitionKey: local | ||
| fallback: true # the rule for every file no other rule matches | ||
| onOversize: sample # default "fail" stops the run on a file larger than the window |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Qualify the fixed
15 Wpower claim.The guide targets
Core Ultragenerally, but15 Wis model-dependent. Intel lists 15 W for Core Ultra 5 125U and 28 W for Core Ultra 7 155H. (intel.com) Tell readers to use the platform's configured power limit, or present 15 W as an example for a specific U-series model, before recommendinggpuLayersmeasurements.