Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/musl.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Static Linux builds
'on':
push:
branches:
- '**'
pull_request: null
permissions:
contents: read
concurrency:
group: musl-${{ github.ref }}
cancel-in-progress: true
jobs:
musl:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-musl
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v7.0.1
with:
persist-credentials: false
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install musl toolchain
run: 'sudo apt-get update

sudo apt-get install -y musl-tools binutils

'
- name: Cache cargo artifacts
uses: Swatinem/rust-cache@v2
- name: Build static musl release binary
env:
CC: musl-gcc
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER: musl-gcc
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER: musl-gcc
RUSTFLAGS: -C target-feature=+crt-static
run: cargo build --locked --release --target ${{ matrix.target }}
- name: Verify static musl release binary
env:
TARGET: ${{ matrix.target }}
run: "set -euo pipefail\nbinary=\"target/$TARGET/release/kagi\"\nreadelf --program-headers\
\ \"$binary\" > program-headers.txt\nreadelf --dynamic \"$binary\" > dynamic-section.txt\n\
if grep -q 'INTERP' program-headers.txt || grep -q '(NEEDED)' dynamic-section.txt;\
\ then\n echo \"Expected a static musl binary without a dynamic loader or\
\ shared libraries\" >&2\n exit 1\nfi\n\"$binary\" --version\n\"$binary\"\
\ --help\n"
39 changes: 39 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ jobs:
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
archive_ext: tar.gz
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
archive_ext: tar.gz
# Build ARM64 musl natively so musl-gcc also compiles ring correctly.
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-musl
archive_ext: tar.gz
- os: macos-15-intel
target: x86_64-apple-darwin
archive_ext: tar.gz
Expand Down Expand Up @@ -91,14 +98,46 @@ jobs:
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu

- name: Install musl toolchain
if: endsWith(matrix.target, '-linux-musl')
run: |
sudo apt-get update
sudo apt-get install -y musl-tools binutils

- name: Cache cargo artifacts
uses: Swatinem/rust-cache@v2

- name: Build release binary
if: "!endsWith(matrix.target, '-linux-musl')"
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: ${{ matrix.target == 'aarch64-unknown-linux-gnu' && 'aarch64-linux-gnu-gcc' || '' }}
run: cargo build --locked --release --target ${{ matrix.target }}

- name: Build static musl release binary
if: endsWith(matrix.target, '-linux-musl')
env:
CC: musl-gcc
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER: musl-gcc
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER: musl-gcc
RUSTFLAGS: -C target-feature=+crt-static
run: cargo build --locked --release --target ${{ matrix.target }}

- name: Verify static musl release binary
if: endsWith(matrix.target, '-linux-musl')
env:
TARGET: ${{ matrix.target }}
run: |
set -euo pipefail
binary="target/$TARGET/release/kagi"
readelf --program-headers "$binary" > program-headers.txt
readelf --dynamic "$binary" > dynamic-section.txt
if grep -q 'INTERP' program-headers.txt || grep -q '(NEEDED)' dynamic-section.txt; then
echo "Expected a static musl binary without a dynamic loader or shared libraries" >&2
exit 1
fi
"$binary" --version
"$binary" --help

- name: Package release archive (unix)
if: runner.os != 'Windows'
env:
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## [Unreleased]

### Added

- Static Linux release binaries for `x86_64-unknown-linux-musl` and `aarch64-unknown-linux-musl`, with archives, bare binaries, and SHA-256 checksums (#200).

## [0.21.1]

### Fixed
Expand Down
16 changes: 9 additions & 7 deletions docs/content/docs/guides/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,13 @@ For users who want full control over the installation process or need to install
1. Visit the [GitHub Releases page](https://github.com/Microck/kagi-cli/releases)
2. Choose the latest release (or a specific version)
3. Download the appropriate asset for your platform:
- macOS Intel: `kagi-x86_64-apple-darwin.tar.gz`
- macOS Apple Silicon: `kagi-aarch64-apple-darwin.tar.gz`
- Linux x86_64: `kagi-x86_64-unknown-linux-gnu.tar.gz`
- Linux ARM64: `kagi-aarch64-unknown-linux-gnu.tar.gz`
- Windows x64: `kagi-x86_64-pc-windows-msvc.zip`
- macOS Intel: `kagi-vX.Y.Z-x86_64-apple-darwin.tar.gz`
- macOS Apple Silicon: `kagi-vX.Y.Z-aarch64-apple-darwin.tar.gz`
- Linux x86_64: `kagi-vX.Y.Z-x86_64-unknown-linux-gnu.tar.gz`
- Linux ARM64: `kagi-vX.Y.Z-aarch64-unknown-linux-gnu.tar.gz`
- Linux x86_64 (static, including Alpine/NixOS): `kagi-vX.Y.Z-x86_64-unknown-linux-musl.tar.gz`
- Linux ARM64 (static, including Alpine/NixOS): `kagi-vX.Y.Z-aarch64-unknown-linux-musl.tar.gz`
- Windows x64: `kagi-vX.Y.Z-x86_64-pc-windows-msvc.zip`

### Step 2: Extract the Binary

Expand Down Expand Up @@ -382,11 +384,11 @@ xattr -d com.apple.quarantine $(which kagi)
- Fedora 32+
- CentOS/RHEL 8+
- Arch Linux
- Other distros (e.g. Alpine): no prebuilt musl binary is published yet, so build from source (see below)
- Alpine and NixOS: choose the static `*-unknown-linux-musl` release asset for your architecture

**Dependencies:**

The binary is statically linked and has no runtime dependencies beyond the Linux kernel.
The `*-unknown-linux-musl` binaries are statically linked and do not require glibc or a dynamic loader. The `*-unknown-linux-gnu` binaries require glibc.

**Shell Completion:**

Expand Down
5 changes: 3 additions & 2 deletions docs/content/docs/guides/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -500,8 +500,9 @@ ldd $(which kagi)

**2. Use musl build (static):**
```bash
# Download musl version instead of gnu
wget https://github.com/Microck/kagi-cli/releases/download/.../kagi-x86_64-unknown-linux-musl.tar.gz
# Replace vX.Y.Z with a release tag that includes musl assets.
# Use aarch64-unknown-linux-musl for ARM64.
wget https://github.com/Microck/kagi-cli/releases/download/vX.Y.Z/kagi-vX.Y.Z-x86_64-unknown-linux-musl.tar.gz
```

**3. Install missing libraries:**
Expand Down
3 changes: 3 additions & 0 deletions docs/release-runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,12 @@ git push origin vX.Y.Z
- builds release artifacts for:
- `x86_64-unknown-linux-gnu`
- `aarch64-unknown-linux-gnu`
- `x86_64-unknown-linux-musl` (static)
- `aarch64-unknown-linux-musl` (static, built on a native ARM64 runner)
- `x86_64-apple-darwin`
- `aarch64-apple-darwin`
- `x86_64-pc-windows-msvc`
- checks musl binaries for dynamic loaders/shared-library dependencies and smoke-tests `--version` and `--help`
- uploads archives plus raw binaries
- generates `kagi-vX.Y.Z-checksums.txt`
- extracts release notes from `CHANGELOG.md`
Expand Down
Loading