notes/build.md
The CLI is built with Bazelisk (Bazel launcher); the SDK bridge and native plugins are built with CMake. Bazel fetches all CLI-side dependencies automatically.
Install Bazelisk:
winget install --id Bazel.Bazeliskbazelisk from your package manager[!IMPORTANT] Build in this order. In local-SDK mode (the default) the CLI links against the SDK bridge at
sdk/pkg-geniex/— Bazel expectssdk/pkg-geniex/lib/geniex.dll(Windows) orsdk/pkg-geniex/lib/libgeniex.so(Linux) to already exist. So build and install the SDK (Build the SDK) first, then build the CLI (Build and run the CLI).
gpedit.msc → Computer Configuration → Windows Settings → Security Settings → Local Policies → User Rights Assignment, or set HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\LocalAccountTokenFilterPolicy = 1 (DWORD).startup --windows_enable_symlinks in .bazelrc — but be aware this can break other SDK paths.The arm64-windows-snapdragon-release preset requires:
HEXAGON_SDK_ROOT, HEXAGON_TOOLS_ROOTOPENCL_SDK_ROOT (headers + OpenCL.lib; runtime ICD ships with the Snapdragon GPU driver)inf2cat.exe.pfx) and Windows test-signing enabled — see run.md § Self-signed fallback for cert generation and test-signing setup[!NOTE] The Hexagon toolchain has a 250-character path limit. Shorten the source path with
substbefore building:powershellsubst G: C:\path\to\geniex cd G:\sdk
cd sdk
cmake --preset arm64-windows-snapdragon-release -B build
cmake --build build -j
cmake --install build --prefix pkg-geniex
Build the SDK inside the derived Snapdragon Linux toolchain container — it extends ghcr.io/snapdragon-toolchain/arm64-linux with build-essential, ccache, rustup, the aarch64-unknown-linux-gnu Rust target, and the cc-rs cross-compiler symlinks baked in (see .github/docker/toolchain-linux.Dockerfile). Run from the repo root.
One-shot:
docker run --rm -u $(id -u):$(id -g) \
--volume $(pwd):/workspace \
--workdir /workspace/sdk \
-e CCACHE_DIR=/workspace/.ccache \
--platform linux/amd64 \
docker.io/qualcomm/geniex-toolchain-linux:v0.0.1 \
bash -c 'cmake --preset arm64-linux-snapdragon-debug -B build-linux . \
&& cmake --build build-linux -j \
&& cmake --install build-linux --prefix pkg-geniex'
Interactive:
docker run --rm -it -u $(id -u):$(id -g) \
--volume $(pwd):/workspace \
--workdir /workspace/sdk \
-e CCACHE_DIR=/workspace/.ccache \
--platform linux/amd64 \
docker.io/qualcomm/geniex-toolchain-linux:v0.0.1 bash
# then, inside the container:
cmake --preset arm64-linux-snapdragon-debug -B build-linux .
cmake --build build-linux -j
cmake --install build-linux --prefix pkg-geniex
Build the SDK inside the derived Snapdragon Android toolchain container — it extends ghcr.io/snapdragon-toolchain/arm64-android with build-essential, ccache, rustup, and the aarch64-linux-android Rust target baked in (see .github/docker/toolchain-android.Dockerfile). Run from the repo root.
One-shot:
docker run --rm -u $(id -u):$(id -g) \
--volume $(pwd):/workspace \
--workdir /workspace/sdk \
-e CCACHE_DIR=/workspace/.ccache \
--platform linux/amd64 \
docker.io/qualcomm/geniex-toolchain-android:v0.0.1 \
bash -c 'cmake --preset arm64-android-snapdragon-debug -B build-android . \
&& cmake --build build-android -j \
&& cmake --install build-android --prefix pkg-geniex'
Interactive:
docker run --rm -it -u $(id -u):$(id -g) \
--volume $(pwd):/workspace \
--workdir /workspace/sdk \
-e CCACHE_DIR=/workspace/.ccache \
--platform linux/amd64 \
docker.io/qualcomm/geniex-toolchain-android:v0.0.1 bash
# then, inside the container:
cmake --preset arm64-android-snapdragon-debug -B build-android .
cmake --build build-android -j
cmake --install build-android --prefix pkg-geniex
Deploy and smoke-test on device:
adb push pkg-geniex /data/local/tmp/geniex
adb push Qwen3-0.6B-Q4_0.gguf /data/local/tmp/geniex/modelfiles/llama_cpp/
adb shell "cd /data/local/tmp/geniex && \
LD_LIBRARY_PATH=./lib:./lib/llama_cpp \
GENIEX_PLUGIN_PATH=./lib \
./bin/geniex_test_llm"
The Android demo app is no longer hosted in this repo — it lives in qualcomm/ai-hub-apps. Build the AAR here, then point the demo app at it.
With the SDK built and installed into sdk/pkg-geniex/, build and run the CLI. Quick smoke test:
bazelisk run //cli -- infer Qwen/Qwen3-0.6B-GGUF
//cliis a convenience alias for//cli/cmd/geniex:geniex. Both are used interchangeably in these docs.
Flags for bazelisk build and bazelisk run:
| Flag | Meaning |
|---|---|
--//sdk:sdk_type={local,s3,bazel} | SDK source. local (default) links against sdk/pkg-geniex; s3 and bazel are WIP. |
--config={linux_arm64,windows_arm64} | Cross-compile to the target platform (Go toolchain + CGO + oci_image base). sdk/pkg-geniex/ must match. |
Development targets:
bazelisk run //cli/release/linux:docker — build and load the Docker image for the Linux release.Package release artifacts:
| Target | Output |
|---|---|
bazelisk build //cli:artifact | bazel-bin/cli/artifact.zip |
bazelisk build //cli/release/windows | bazel-bin/cli/release/windows/geniex-cli-setup.exe |
bazelisk build //cli/release/linux | bazel-bin/cli/release/linux/geniex-cli-docker.tar |
Generated executable (for manual invocation): bazel-bin/cli/cmd/geniex/geniex_/, with runtime files under geniex.runfiles/_main.
Use bazelisk coverage instead of bazelisk test:
bazelisk coverage //... --combined_report=lcov
Bazel's default --instrumentation_filter only covers packages that own a test target, so every Go package ships at least a placeholder package_test.go to keep itself in the denominator. Combined lcov lands at bazel-out/_coverage/_coverage_report.dat. Render it with genhtml bazel-out/_coverage/_coverage_report.dat -o coverage-html (gitignored), or summarize on the CLI with lcov --list <report>.