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
101 changes: 101 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Prebuilt binaries, so getting Booth does not require a C toolchain and a
# working `make`. Runs on a version tag, or by hand from the Actions tab if
# you want to check the packaging without tagging anything.
name: Release binaries

on:
push:
tags: ['v*']
workflow_dispatch:

permissions:
contents: write

jobs:
build:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# -static on Linux and Windows gives a binary with no runtime
# dependencies at all. Without it the Windows build wants MinGW's
# libssp-0.dll, which nobody downloading a release will have.
- { os: ubuntu-latest, name: linux-x86_64, ld: '-static', ext: '' }
- { os: windows-latest, name: windows-x86_64, ld: '-static', ext: '.exe' }
# Apple ships no static libc, so this one links against libSystem.
# That is fine, every macOS has it.
- { os: macos-latest, name: macos-arm64, ld: '', ext: '' }

steps:
- uses: actions/checkout@v4

- name: Set up MSYS2
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
install: mingw-w64-x86_64-gcc make

- name: Build
shell: ${{ runner.os == 'Windows' && 'msys2 {0}' || 'bash' }}
run: make LDFLAGS="${{ matrix.ld }}" -j4

- name: Smoke test
shell: ${{ runner.os == 'Windows' && 'msys2 {0}' || 'bash' }}
run: |
./kath${{ matrix.ext }} --version
printf '__global__ void k(float *o){ o[0] = 1.0f; }\n' > smoke.cu
./kath${{ matrix.ext }} --nvidia-ptx smoke.cu -o smoke.ptx
test -s smoke.ptx
echo "compiled a kernel, binary works"

# A release archive is the binary plus the message catalogues --lang
# reads and the licence. Everything else is source.
- name: Package
shell: ${{ runner.os == 'Windows' && 'msys2 {0}' || 'bash' }}
run: |
VER=$(awk '$2 == "BC_VERSION_STRING" {gsub(/"/, "", $3); print $3}' src/barracuda.h)
DIR="booth-$VER-${{ matrix.name }}"
mkdir -p "$DIR/lang"
cp kath${{ matrix.ext }} "$DIR/"
cp lang/en.txt lang/mi.txt "$DIR/lang/"
cp LICENSE README.md "$DIR/"
if [ "${{ runner.os }}" = "Windows" ]; then
powershell -Command "Compress-Archive -Path '$DIR' -DestinationPath '$DIR.zip'"
else
tar czf "$DIR.tar.gz" "$DIR"
fi
ls -la booth-$VER-*

- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}
path: |
booth-*.tar.gz
booth-*.zip
if-no-files-found: error

publish:
name: Attach to release
needs: build
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/download-artifact@v4
with:
merge-multiple: true

# Checksums so anyone who cares can verify what they downloaded.
- name: Checksums
run: |
ls -la
sha256sum booth-* > SHA256SUMS
cat SHA256SUMS

- uses: softprops/action-gh-release@v2
with:
files: |
booth-*
SHA256SUMS
71 changes: 70 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,67 @@ Booth — Changelog

## Unreleased

## 2026-08-07

Version 0.5.2.

First, a correction. The last release went out tagged v5.01, which was
meant to be 0.5.1 and wasn't, and it left Booth looking four major
versions further along than it actually is. It isn't. This release puts
the numbering back where it belongs, and sorry to anyone who pinned the
old one or took the version at face value. The tag stays where it is so
nothing breaks underneath you, but the compiler now reports what it is.

The theme this cycle, without meaning to be, was the compiler telling
the truth. Semantic errors used to be printed and then ignored by every
mode except `--sema`, so the backend ran on source that had already been
rejected, wrote an output file and exited zero. Asking for several
backends at once wrote all of them over the same `-o` path and left you
whichever finished last, under the name you chose, again exiting zero.
Metal quietly narrowed a double-precision kernel to float and said
nothing, which is a real problem if you were counting on the precision.
`--amdgpu` ignored `-o` entirely and mixed a diagnostic into the
assembly on stdout. All four are fixed, and all four had been sitting
there being cheerfully wrong for a while.

The structural change is the backend contract. Every target now sits
behind a `be_desc_t` and registers itself in one list, and a backend
owns its own command line rather than reaching into a shared config
struct and the driver's argument loop. Adding a target used to mean
reading 420 KB of AMD backend to work out what was expected; now it
means reading one header and copying the skeleton. `main.c` lost about
a third of its length in the process, and the frontend stopped needing
to know what an AMD target enum is.

Booth also installs now. `make install` puts `kath`, the message
catalogues and a CMake package config into a prefix, so a downstream
project can `find_package(Booth)` and compile kernels as part of its own
build with `booth_add_kernel()`. There is a worked example under
`examples/cmake/` and CI builds it against a staged install on every
push, along with a check that the target list in the package config
hasn't drifted from what the backends actually accept.

Getting Booth no longer requires being able to build it. Every release
now carries prebuilt binaries for Linux, macOS and Windows, statically
linked so they have no runtime dependencies whatsoever, with checksums.
Unpack and run. This mattered more than I realised: the Windows build
had been quietly depending on MinGW's `libssp-0.dll`, so handing someone
the binary would not have worked on a machine without a toolchain, which
is exactly the machine they wanted it for.

There are coverage numbers for the first time, 74.1% of lines and 58.4%
of branches, reported by CI on every PR. That immediately turned up the
SSA register allocator having never been executed by a test at all, and
the six fixtures now pinning its behaviour also pin a real bug in it,
which is at least honest.

Thanks to Jorge Galvez, whose do-concurrent ocean benchmarks found three
genuine frontend bugs in an afternoon, and who let me test against his
code. Thanks to @maou3434 for the bare HIP warp and lane intrinsics,
which is their first contribution here and a very welcome one. And
thanks to @FileDelta for asking a simple question about the runtimes
that turned over considerably more than either of us expected.

### Frontend

- double-precision `fmax`, `fmin` and `fmod`. The ocean kernels in
Expand Down Expand Up @@ -145,6 +206,13 @@ Booth — Changelog
kernels with `booth_add_kernel()`
(Zane Hambly, 2026-08-06)

- prebuilt binaries on every release for Linux, macOS and Windows, statically
linked where the platform allows it so they carry no runtime dependencies,
with SHA256 checksums. The Windows build previously needed MinGW's
`libssp-0.dll` present, which made the binary useless to anyone without a
toolchain
(Zane Hambly, 2026-08-07)

### CI and tests

- #140: numeric regression against SLATEC known-good values, across cpu,
Expand Down Expand Up @@ -194,7 +262,8 @@ Booth — Changelog

## 2026-07-14

Version 5.01. So long, and thanks for all the fish.
Version 5.01, which should have read 0.5.1. See the 0.5.2 note above.
So long, and thanks for all the fish.
BarraCUDA was a good pun and a bad description, so it swam off: the
compiler is Booth now, the binary is `kath`, and the version jumps
to mark the line. First release under the new name; the rename note
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,10 @@ install: $(TARGET)
install -m 755 $(TARGET)$(EXE) $(BINDIR)/$(TARGET)$(EXE)
install -m 644 lang/en.txt lang/mi.txt $(SHAREDIR)/lang/
sed -e 's/@BOOTH_VERSION@/$(VERSION)/g' -e 's/@BOOTH_VERSION_MAJOR@/$(VER_MAJOR)/g' \
-e 's/@BOOTH_VERSION_MINOR@/$(VER_MINOR)/g' \
cmake/BoothConfig.cmake.in > $(CMAKEDIR)/BoothConfig.cmake
sed -e 's/@BOOTH_VERSION@/$(VERSION)/g' -e 's/@BOOTH_VERSION_MAJOR@/$(VER_MAJOR)/g' \
-e 's/@BOOTH_VERSION_MINOR@/$(VER_MINOR)/g' \
cmake/BoothConfigVersion.cmake.in > $(CMAKEDIR)/BoothConfigVersion.cmake

uninstall:
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,20 @@ That last one still surprises me a bit. You can write a Triton kernel, matmul an

It also borrows a pile of operational discipline from the mainframe world: real crash dumps when a kernel faults, structured output routed by class, parameter snapshots on entry. See [docs/mainframe.md](docs/mainframe.md) if that sounds like your kind of thing.

## Getting it

If you're lazy like me and just want to run and go, then you can install it [here](https://github.com/Zaneham/Booth/releases/latest). It comes with no dependencies and you don't have to run `make` to use it. There's a build for Linux, macOS and Windows.

```bash
tar xzf booth-*-linux-x86_64.tar.gz
cd booth-*-linux-x86_64
./kath --version
```

## Build

If you'd rather build it, or you're on something I don't ship a binary for:

```bash
make
```
Expand Down
25 changes: 15 additions & 10 deletions cmake/BoothConfigVersion.cmake.in
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# Version check for find_package(Booth <version>). Same-major compatibility:
# a consumer asking for 5.1 is satisfied by any later 5.x, never by 6.x.
# Version check for find_package(Booth <version>).
#
# While the major version is 0 the minor has to match too, because 0.x is
# where the shape is still allowed to change and 0.6 promises nothing to
# someone who asked for 0.5. From 1.0 onward the usual same-major rule
# applies and a consumer asking for 1.2 is happy with any later 1.x.

set(PACKAGE_VERSION "@BOOTH_VERSION@")

if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
set(PACKAGE_VERSION_COMPATIBLE FALSE)
elseif(NOT PACKAGE_FIND_VERSION_MAJOR STREQUAL "@BOOTH_VERSION_MAJOR@")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
elseif("@BOOTH_VERSION_MAJOR@" STREQUAL "0" AND
NOT PACKAGE_FIND_VERSION_MINOR STREQUAL "@BOOTH_VERSION_MINOR@")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
if(PACKAGE_FIND_VERSION_MAJOR STREQUAL "@BOOTH_VERSION_MAJOR@")
set(PACKAGE_VERSION_COMPATIBLE TRUE)
else()
set(PACKAGE_VERSION_COMPATIBLE FALSE)
endif()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
endif()

if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
set(PACKAGE_VERSION_EXACT TRUE)
endif()
if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
set(PACKAGE_VERSION_EXACT TRUE)
endif()
11 changes: 8 additions & 3 deletions docs/cmake.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@ That puts `kath` in `<prefix>/bin`, the `--lang` catalogues in
## Finding it

```cmake
find_package(Booth 5.1 REQUIRED)
find_package(Booth 0.5 REQUIRED)
```

If the prefix is not one CMake already searches, point it there with
`-DCMAKE_PREFIX_PATH=<prefix>`. Version matching is same-major: 5.1 is
satisfied by any later 5.x, never by 6.x.
`-DCMAKE_PREFIX_PATH=<prefix>`.

While Booth is on 0.x the minor version has to match, so asking for 0.5 is
satisfied by 0.5.2 but not by 0.6. That is deliberate: 0.x is where things
are still allowed to move, and a package config that quietly accepted 0.6
would be promising something Booth is not ready to promise. From 1.0 the
usual same-major rule takes over.

You get `Booth_VERSION`, `Booth_EXECUTABLE`, `Booth_LANG_DIR`, and a
`Booth::kath` imported target.
Expand Down
2 changes: 1 addition & 1 deletion examples/cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
cmake_minimum_required(VERSION 3.10)
project(booth_cmake_example LANGUAGES NONE)

find_package(Booth 5.1 REQUIRED)
find_package(Booth 0.5 REQUIRED)
message(STATUS "Booth ${Booth_VERSION} at ${Booth_EXECUTABLE}")

booth_add_kernel(vadd_ptx SOURCE vadd.cu BACKEND nvidia-ptx)
Expand Down
13 changes: 8 additions & 5 deletions src/barracuda.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
#include <stdio.h>
#include <string.h>

/* ---- Version ---- */
#define BC_VERSION_MAJOR 5
#define BC_VERSION_MINOR 1
#define BC_VERSION_PATCH 0
#define BC_VERSION_STRING "5.01"
/* ---- Version ----
* The 0.5 release was tagged v5.01, which was a typo for 0.5.1 and made the
* compiler look four major versions further along than it is. Corrected here;
* everything downstream derives from these three numbers. */
#define BC_VERSION_MAJOR 0
#define BC_VERSION_MINOR 5
#define BC_VERSION_PATCH 2
#define BC_VERSION_STRING "0.5.2"

/* The universe has limits. So do our buffers. No malloc, no madness. */
#define BC_MAX_SOURCE (4 * 1024 * 1024)
Expand Down
Loading