Skip to content

fix(linux): repair the Linux build (#50) - #51

Merged
oreofeolurin merged 2 commits into
devfrom
fix/linux-build
Aug 29, 2026
Merged

fix(linux): repair the Linux build (#50)#51
oreofeolurin merged 2 commits into
devfrom
fix/linux-build

Conversation

@oreofeolurin

Copy link
Copy Markdown
Contributor

Fixes #50. Found by the CI in #49 on its first run.

flo does not compile on Linux, and the next release tag would have failed

release.yml runs zig build --release=safe -Dtarget=<linux>. On dev today:

$ zig build --release=safe -Dtarget=x86_64-linux
src/node/dashboard/host_stats.zig:180:24: error: root source file struct 'fs' has no member named 'openFileAbsolute'
error: 1 compilation errors

Tagging v0.1.0-dev.10 would have failed both Linux build jobs and both Docker publishes. The last green release was v0.1.0-dev.9 on 2026-05-28; the break landed a week later in 4dd595a. No CI on PRs and no release in three months, so nothing caught it.

Three Zig 0.16 removals, all Linux-only

File Symbol Fix
host_stats.zig:180 std.fs.openFileAbsolute stdx.fs.readFile
host_stats.zig:186 File.readAll (same call — open + readAll + close collapse into one)
reactor.zig:277,287 std.posix.timerfd_create / timerfd_settime raw std.os.linux syscalls, errno mapped the way stdx.net already does

Why every local build stayed green

Zig analyses lazily. host_stats.zig reads /proc and the timerfd calls sit behind else if (comptime is_linux) — on a macOS host neither branch is ever analysed, so they can reference symbols that don't exist and nothing complains.

This is the third time this trap has bitten in this codebase, after the metrics exporter and util/http/response.zig both turning out to be dead code that had never compiled. On this project, "it builds locally" says nothing about code behind a platform or feature gate — which is the strongest argument for the CI in #49.

Worth noting stdx.fs.openFileAbsolute already existed. The stdx wrappers are there precisely to track the std API this codebase targets; host_stats.zig called std.fs directly and bypassed the convention.

Verification

zig build --release=safe -Dtarget=x86_64-linux     # fails on dev, passes here
zig build --release=safe -Dtarget=aarch64-linux    # green

I confirmed the failure against a stashed baseline rather than assuming — that's the check that establishes releases were genuinely broken, not just cross-compilation.

macOS zig build, test-unit and test-integration all still pass. Native Linux Debug is covered by #49's CI.

Note: cross-compiled Debug Linux builds still fail in checksum_hw.zig (an x86 self-hosted-backend encoder bug, and an aarch64 crc feature gate). Neither affects native Debug or release builds — CI's native x86 job compiles it fine — so it's out of scope here.

Suggested merge order

  1. This PR — unbreaks Linux
  2. ci: run build and the three test suites on every PR #49 (CI) — rebase, should then go green
  3. Rebase fix(stream): rebuild name registry and record counts on recovery (#42 items 2, 3) #45, fix(cluster): honor [cluster] enabled, implement cluster status, explain io_uring (#42 items 5, 6, 7) #47, fix(stream): key stream metadata by namespace-qualified name (#46) #48 so CI actually checks them, then merge each

`flo` did not compile on Linux, and the next release tag would have failed:
release.yml runs `zig build --release=safe -Dtarget=<linux>`, which errors on
current dev.

Three Zig 0.16 API removals, all in Linux-only branches:

- `std.fs.openFileAbsolute` and `File.readAll` in host_stats.zig, which reads
  /proc. Replaced with `stdx.fs.readFile`, which also collapses open + readAll
  + close into one call.
- `std.posix.timerfd_create` / `timerfd_settime` in reactor.zig. Replaced with
  the raw `std.os.linux` syscalls, mapping errno the way stdx.net already does.

Zig analyses lazily, so a macOS host never compiles either branch — the code
could reference symbols that do not exist while every local build stayed green.
Same trap that previously hid the metrics exporter and util/http/response.zig
being dead code.

Worth noting `stdx.fs.openFileAbsolute` already existed. The stdx wrappers are
there exactly to track the std API this codebase targets; host_stats.zig
called std.fs directly and bypassed the convention.

Verified:

  zig build --release=safe -Dtarget=x86_64-linux    # fails on dev, passes here
  zig build --release=safe -Dtarget=aarch64-linux   # both release targets green

macOS build, test-unit and test-integration all still pass. Native Linux Debug
is covered by the CI in #49, which is what surfaced this.
@oreofeolurin
oreofeolurin merged commit 59035d9 into dev Aug 29, 2026
oreofeolurin added a commit that referenced this pull request Aug 29, 2026
Nothing gated pull requests. The only workflows here were release.yml and
docker-publish.yml, both tag-triggered, so a PR could be merged having been
built and tested only on a contributor's machine.

Adds a CI workflow on pull_request and on pushes to dev/main:

- web console — `npm run build`, which runs `tsc -b` first, so a TypeScript
  error fails here rather than in the release build (the console is compiled
  into the Zig binary)
- build — `zig build`
- test-unit, test-integration, test-e2e — as a matrix with fail-fast off, so
  one failing suite does not mask the other two

The console is built once and handed to the Zig jobs as an artifact instead of
being rebuilt three times.

No `zig fmt --check` gate yet: 12 files on dev are already unformatted, so it
would fail every PR on day one, and two of them are touched by a PR currently
in flight. Reformatting is a separate cleanup, best landed when nothing is open.

Its first run already earned its keep: it caught that the Linux build was
broken and that the next release tag would have failed (#50, fixed in #51).
oreofeolurin added a commit that referenced this pull request Aug 29, 2026
Nothing gated pull requests. The only workflows here were release.yml and
docker-publish.yml, both tag-triggered, so a PR could be merged having been
built and tested only on a contributor's machine.

Adds a CI workflow on pull_request and on pushes to dev/main:

- web console — `npm run build`, which runs `tsc -b` first, so a TypeScript
  error fails here rather than in the release build (the console is compiled
  into the Zig binary)
- build — `zig build`
- test-unit, test-integration, test-e2e — as a matrix with fail-fast off, so
  one failing suite does not mask the other two

The console is built once and handed to the Zig jobs as an artifact instead of
being rebuilt three times.

No `zig fmt --check` gate yet: 12 files on dev are already unformatted, so it
would fail every PR on day one, and two of them are touched by a PR currently
in flight. Reformatting is a separate cleanup, best landed when nothing is open.

Its first run already earned its keep: it caught that the Linux build was
broken and that the next release tag would have failed (#50, fixed in #51).
oreofeolurin added a commit that referenced this pull request Aug 29, 2026
Nothing gated pull requests. The only workflows here were release.yml and
docker-publish.yml, both tag-triggered, so a PR could be merged having been
built and tested only on a contributor's machine.

Adds a CI workflow on pull_request and on pushes to dev/main:

- web console — `npm run build`, which runs `tsc -b` first, so a TypeScript
  error fails here rather than in the release build (the console is compiled
  into the Zig binary)
- build — `zig build`
- test-unit, test-integration, test-e2e — as a matrix with fail-fast off, so
  one failing suite does not mask the other two

The console is built once and handed to the Zig jobs as an artifact instead of
being rebuilt three times.

No `zig fmt --check` gate yet: 12 files on dev are already unformatted, so it
would fail every PR on day one, and two of them are touched by a PR currently
in flight. Reformatting is a separate cleanup, best landed when nothing is open.

Its first run already earned its keep: it caught that the Linux build was
broken and that the next release tag would have failed (#50, fixed in #51).
oreofeolurin added a commit that referenced this pull request Aug 29, 2026
Nothing gated pull requests. The only workflows here were release.yml and
docker-publish.yml, both tag-triggered, so a PR could be merged having been
built and tested only on a contributor's machine.

Adds a CI workflow on pull_request and on pushes to dev/main:

- web console — `npm run build`, which runs `tsc -b` first, so a TypeScript
  error fails here rather than in the release build (the console is compiled
  into the Zig binary)
- build — `zig build`
- test-unit, test-integration, test-e2e — as a matrix with fail-fast off, so
  one failing suite does not mask the other two

The console is built once and handed to the Zig jobs as an artifact instead of
being rebuilt three times.

No `zig fmt --check` gate yet: 12 files on dev are already unformatted, so it
would fail every PR on day one, and two of them are touched by a PR currently
in flight. Reformatting is a separate cleanup, best landed when nothing is open.

Its first run already earned its keep: it caught that the Linux build was
broken and that the next release tag would have failed (#50, fixed in #51).
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.

Linux build is broken: Zig 0.16 API removals in Linux-only code, and the next release tag would fail

1 participant