diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..df536dc --- /dev/null +++ b/.github/workflows/release.yml @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index a9555d5..cd26204 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 @@ -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, @@ -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 diff --git a/Makefile b/Makefile index cb05b77..aea7b07 100644 --- a/Makefile +++ b/Makefile @@ -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: diff --git a/README.md b/README.md index e9a153c..4be63d4 100644 --- a/README.md +++ b/README.md @@ -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 ``` diff --git a/cmake/BoothConfigVersion.cmake.in b/cmake/BoothConfigVersion.cmake.in index ce63aef..fdacda3 100644 --- a/cmake/BoothConfigVersion.cmake.in +++ b/cmake/BoothConfigVersion.cmake.in @@ -1,18 +1,23 @@ -# Version check for find_package(Booth ). 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 ). +# +# 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() diff --git a/docs/cmake.md b/docs/cmake.md index d560bb0..56ea253 100644 --- a/docs/cmake.md +++ b/docs/cmake.md @@ -19,12 +19,17 @@ That puts `kath` in `/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=`. Version matching is same-major: 5.1 is -satisfied by any later 5.x, never by 6.x. +`-DCMAKE_PREFIX_PATH=`. + +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. diff --git a/examples/cmake/CMakeLists.txt b/examples/cmake/CMakeLists.txt index 17e9a92..da0b024 100644 --- a/examples/cmake/CMakeLists.txt +++ b/examples/cmake/CMakeLists.txt @@ -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) diff --git a/src/barracuda.h b/src/barracuda.h index 9192623..a2c4c60 100644 --- a/src/barracuda.h +++ b/src/barracuda.h @@ -5,11 +5,14 @@ #include #include -/* ---- 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)