Skip to content

deed 0.5.1: Windows on ARM, nostr 0.16.0 - #37

Merged
sepehr-safari merged 9 commits into
mainfrom
fix/windows-aarch64
Oct 11, 2026
Merged

sepehr-safari merged 9 commits into
mainfrom
fix/windows-aarch64

Conversation

@sepehr-safari

Copy link
Copy Markdown
Contributor

Closes #35.

The aarch64 Windows build crashed at startup because of a linker bug: in a stripped build, the LLD in Zig 0.16 reads the offset of each thread-local access as a page count, so the load lands 32 KiB past the variable. Unstripped builds are fine, so that target is built unstripped now (the debug information goes to a .pdb that is not shipped). The exception can go once Zig links with an LLD that has llvm/llvm-project#200060.

  • The release ships a windows-aarch64 zip again and runs it on a windows-11-arm runner before publishing. install.ps1 picks it on ARM64, also from an x64 PowerShell under emulation, and falls back to x86_64 only for an older release that has none.
  • CI builds the ARM build on Linux and runs it and the whole test suite on windows-11-arm, and checks which build the installer put in place.
  • The deaf-relay write test now holds on every platform instead of being skipped on Windows, and the test HTTP server reads a POST body before it closes.
  • Built on nostr 0.16.0. A command cancelled while waiting for randomness now reports the cancel.
  • The README's tagline: fastest and smallest nostr command line, built for AI agents and humans.
  • Version 0.5.1.

A stripped build for aarch64 Windows crashed at its first thread-local access, before `deed version` printed anything. Any stripped Zig program that touches a threadlocal does the same on that target, and the unstripped build runs.

Stripping drops the local symbols, so each thread-local access is relocated against the .tls section with the variable's byte offset in the add that takes the upper bits. The LLD that Zig 0.16 links with reads that offset as a number of 4 KiB pages, so a variable 8 bytes in is looked for 32 KiB in. LLD fixed this in llvm/llvm-project#200060.

Until the pinned Zig links with a fixed LLD, build.zig leaves aarch64 Windows unstripped. The debug information goes to a .pdb beside the .exe there, so the binary only grows by the stack trace code, about 250 KB.

I also added a CI job that cross-builds the release configuration and the test binary on Linux and runs both on a windows-11-arm runner. The Zig compiler for aarch64 Windows crashes while building deed on that runner, so the tests are built elsewhere, with a new `zig build test-bin` step.

Refs #35
Releases now carry deed-<version>-windows-aarch64.zip with its .sha256, built from the tag like the others and run on a windows-11-arm runner before the draft is lifted. The publish check expects twelve assets.

install.ps1 picks the ARM64 build on an ARM64 machine. Older releases have no ARM64 zip, so on a 404 for it the installer falls back to the x86_64 build, which Windows on ARM runs under emulation. Any other download failure is still reported as one.

CI runs the installer checks on windows-11-arm as well as windows-latest.

Closes #35
On a windows-11-arm runner two tests failed that pass on x86_64 Windows.

The deaf-relay write test needs a write that blocks, and Windows completes a large loopback send without the peer reading, so the write finished and no timeout came. The nostr library skips its own tests of this kind on Windows for the same reason. I skip this one there too, and added a test that covers the deadline in writeBy with a write that waits until cancelled, so it no longer depends on a socket filling up.

The HTTP test server answered without reading the request body and then closed. Closing a socket with unread bytes resets the connection, and Windows then drops the part of the response the client had not read yet, so "a POST sends its body" failed now and then. The server now reads the body to its end before it answers.
The test skipped on all Windows but only failed on Windows on ARM, where one 8 MB send completes without the peer reading and so returned before the deadline.

The write now repeats the event, bounded at 256 sends, so it reaches a send that waits for room on any platform where a socket fills, and still ends where one never does. The skip is gone.
An x64 PowerShell on a Windows on ARM machine reports AMD64 in its environment, so the installer chose the x86_64 build there. It now reads the machine's own architecture from the registry first and keeps the environment variables as the fallback.

The message after a failed fallback named windows-x86_64 even when the release had no Windows build at all. It now says the tag may not exist or has no Windows build.
After the install on each Windows runner, read the machine field of the installed deed.exe. It must be ARM64 on the arm runner when the release carries an ARM64 zip, and x86_64 otherwise.
The 0.16.0 error sets of the keys, NIP-44, NIP-04, NIP-59 and NIP-46 code gain Canceled, which is returned when a cancel lands while waiting for randomness.

deed's own draws of randomness (the NIP-04 iv, the NIP-44 nonce, the websocket mask of a COUNT frame, the gift wrap timestamp, a new mnemonic) turned every error into a random-number failure. A cancel now stays a cancel.
Version in build.zig.zon and src/main.zig, the installer's examples, and the release notes for 0.5.1.
The README's tagline now says what the benchmarks show: deed starts faster and ships smaller than the other nostr command lines that talk to relays.
@sepehr-safari
sepehr-safari merged commit 7e4360f into main Oct 11, 2026
17 of 18 checks passed
@sepehr-safari
sepehr-safari deleted the fix/windows-aarch64 branch October 11, 2026 15:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The aarch64 Windows build crashes at startup

1 participant