bb91afde
build: include muxg in release and install targets
a73x 2026-09-06 05:15
Commit message
Makefile
| Old | New | ||
|---|---|---|---|
| @@ -45,9 +45,7 @@ deps: | |||
| 45 | build: mac-sdk | 45 | build: mac-sdk |
| 46 | $(ZIG) build | 46 | $(ZIG) build |
| 47 | 47 | ||
| 48 | # Only the ONE user-facing binary: everything else in zig-out/bin | 48 | # Install the two product binaries; the other build artifacts are test fixtures. |
| 49 | # (ptyclient, wsclient, rawmode, ...) is a test fixture that would shadow | ||
| 50 | # nothing useful on PATH. | ||
| 51 | BINDIR ?= $(HOME)/.local/bin | 49 | BINDIR ?= $(HOME)/.local/bin |
| 52 | # ReleaseSafe, like `release` — not the Debug tree `build` leaves in | 50 | # ReleaseSafe, like `release` — not the Debug tree `build` leaves in |
| 53 | # zig-out. ghostty gates its page-integrity check on ITS optimize mode, and | 51 | # zig-out. ghostty gates its page-integrity check on ITS optimize mode, and |
| @@ -70,19 +68,19 @@ INSTDIR ?= dist/install | |||
| 70 | # 92ms -> 114ms (musl memcpy on 15MB of paint bytes, paid once per | 68 | # 92ms -> 114ms (musl memcpy on 15MB of paint bytes, paid once per |
| 71 | # reattach); the solo and client legs moved inside their noise. | 69 | # reattach); the solo and client legs moved inside their noise. |
| 72 | # | 70 | # |
| 73 | # The target the installed and released binaries are built for. Static | 71 | # The installed mux target is static musl on Linux, for the reason above; |
| 74 | # musl on Linux, for the reason above; another OS names its triple here. | 72 | # muxg uses the native target so it can link the host's GUI libraries. |
| 75 | # The `?=` at the top of this file is what sets it, so a Mac gets its own. | 73 | # The `?=` at the top of this file is what sets it, so a Mac gets its own. |
| 76 | install: mac-sdk | 74 | install: mac-sdk |
| 77 | $(ZIG) build -Dtarget=$(MUX_TARGET) -Doptimize=ReleaseSafe -p $(INSTDIR) | 75 | $(ZIG) build -Dtarget=$(MUX_TARGET) -Doptimize=ReleaseSafe -p $(INSTDIR) |
| 76 | $(ZIG) build native -Doptimize=ReleaseSafe -p $(INSTDIR) | ||
| 78 | install -d $(BINDIR) | 77 | install -d $(BINDIR) |
| 79 | install -m755 $(INSTDIR)/bin/mux $(BINDIR)/ | 78 | install -m755 $(INSTDIR)/bin/mux $(INSTDIR)/bin/muxg $(BINDIR)/ |
| 80 | rm -f $(BINDIR)/muxd $(BINDIR)/muxa $(BINDIR)/muxweb | 79 | rm -f $(BINDIR)/muxd $(BINDIR)/muxa $(BINDIR)/muxweb |
| 81 | 80 | ||
| 82 | # The artifact a release publishes, built the way every release since | 81 | # mux keeps its static musl build on Linux. muxg needs the host's dynamic GUI |
| 83 | # v0.0.1-4 has been: static musl so one binary runs on any x86_64 Linux, | 82 | # libraries, so build it separately with the native target in the same prefix. |
| 84 | # ReleaseSafe because the safety checks are worth more than the last few | 83 | # Both use ReleaseSafe and are stripped before packaging. |
| 85 | # percent and they survive stripping — only DWARF goes, 17MB to ~3MB each. | ||
| 86 | # | 84 | # |
| 87 | # TARRED, and that is the point of having a target at all. Publishing the | 85 | # TARRED, and that is the point of having a target at all. Publishing the |
| 88 | # binary bare loses the exec bit: it downloads 0644, and the first | 86 | # binary bare loses the exec bit: it downloads 0644, and the first |
| @@ -120,17 +118,20 @@ SHA256 ?= sha256sum | |||
| 120 | RELTAR = $(RELDIR)/mux-v$(VERSION)-$(RELEASE_TARGET).tar.gz | 118 | RELTAR = $(RELDIR)/mux-v$(VERSION)-$(RELEASE_TARGET).tar.gz |
| 121 | # The version guard below asks the STRIPPED artifact what it is, so a | 119 | # The version guard below asks the STRIPPED artifact what it is, so a |
| 122 | # stale stage directory cannot ship under a bumped number. | 120 | # stale stage directory cannot ship under a bumped number. |
| 123 | release: | 121 | release: mac-sdk |
| 124 | @test -n "$(VERSION)" || { echo "release: no version found in build.zig"; exit 1; } | 122 | @test -n "$(VERSION)" || { echo "release: no version found in build.zig"; exit 1; } |
| 125 | $(ZIG) build -Dtarget=$(RELEASE_BUILD_TARGET) -Doptimize=ReleaseSafe -p $(RELDIR)/stage | 123 | $(ZIG) build -Dtarget=$(RELEASE_BUILD_TARGET) -Doptimize=ReleaseSafe -p $(RELDIR)/stage |
| 124 | $(ZIG) build native -Doptimize=ReleaseSafe -p $(RELDIR)/stage | ||
| 126 | rm -rf $(RELBIN) $(RELTAR) | 125 | rm -rf $(RELBIN) $(RELTAR) |
| 127 | install -d $(RELBIN) | 126 | install -d $(RELBIN) |
| 128 | install -m755 $(RELDIR)/stage/bin/mux $(RELBIN)/ | 127 | install -m755 $(RELDIR)/stage/bin/mux $(RELDIR)/stage/bin/muxg $(RELBIN)/ |
| 129 | strip $(RELBIN)/mux | 128 | strip $(RELBIN)/mux $(RELBIN)/muxg |
| 130 | @got=$$($(RELBIN)/mux --version | awk '{print $$2}'); \ | 129 | @for bin in mux muxg; do \ |
| 130 | got=$$($(RELBIN)/$$bin --version | awk '{print $$2}'); \ | ||
| 131 | [ "$$got" = "$(VERSION)" ] || { \ | 131 | [ "$$got" = "$(VERSION)" ] || { \ |
| 132 | echo "release: mux reports $$got, expected $(VERSION)"; exit 1; } | 132 | echo "release: $$bin reports $$got, expected $(VERSION)"; exit 1; }; \ |
| 133 | tar czf $(RELTAR) -C $(RELBIN) mux | 133 | done |
| 134 | tar czf $(RELTAR) -C $(RELBIN) mux muxg | ||
| 134 | @echo | 135 | @echo |
| 135 | @$(SHA256) $(RELTAR) | 136 | @$(SHA256) $(RELTAR) |
| 136 | @echo "install: tar xzf $(RELTAR) -C ~/.local/bin" | 137 | @echo "install: tar xzf $(RELTAR) -C ~/.local/bin" |
README.md
| Old | New | ||
|---|---|---|---|
| @@ -16,13 +16,14 @@ dependency). The Makefile points at a pinned toolchain path; override with | |||
| 16 | ```sh | 16 | ```sh |
| 17 | make build # first build fetches + compiles the QUIC deps: ~30MB, a few minutes, once | 17 | make build # first build fetches + compiles the QUIC deps: ~30MB, a few minutes, once |
| 18 | make test && make e2e # verify | 18 | make test && make e2e # verify |
| 19 | make install # the one binary to ~/.local/bin (override BINDIR) | 19 | make install # mux + muxg in ReleaseSafe to ~/.local/bin (override BINDIR) |
| 20 | ``` | 20 | ``` |
| 21 | 21 | ||
| 22 | The native client is an opt-in, dynamically linked second | 22 | The native client is a dynamically linked second |
| 23 | binary. It needs SDL3, freetype2, fontconfig, HarfBuzz and OpenGL development | 23 | binary. It needs SDL3, freetype2, fontconfig, HarfBuzz and OpenGL development |
| 24 | packages; OpenGL functions are loaded through SDL, with no direct libGL | 24 | packages; OpenGL functions are loaded through SDL, with no direct libGL |
| 25 | link. It is outside the default build and CI gates: | 25 | link. `make install` and `make release` build it alongside `mux`; it is outside |
| 26 | the default development build and CI gates: | ||
| 26 | 27 | ||
| 27 | ```sh | 28 | ```sh |
| 28 | make native # Debug development build and no-window unit tests | 29 | make native # Debug development build and no-window unit tests |
| @@ -122,9 +123,12 @@ that runs on any x86_64 Linux: | |||
| 122 | ~/Downloads/zig-x86_64-linux-0.15.2/zig build -Dtarget=x86_64-linux-musl | 123 | ~/Downloads/zig-x86_64-linux-0.15.2/zig build -Dtarget=x86_64-linux-musl |
| 123 | ``` | 124 | ``` |
| 124 | 125 | ||
| 125 | `make release` does the whole release build instead — static musl on | 126 | `make release` builds both `mux` and `muxg` in `ReleaseSafe`, strips them, |
| 126 | Linux, `ReleaseSafe`, stripped, checked against `build.zig`'s version, and | 127 | checks both against `build.zig`'s version, and packages them in `dist/`. |
| 127 | tarred into `dist/`. The tarball is what to hand another machine, because it | 128 | On Linux, `mux` remains static musl; `muxg` uses the build host's native target |
| 129 | and needs compatible CPU, libc, SDL3, FreeType, fontconfig, and HarfBuzz libraries | ||
| 130 | on the destination, plus an OpenGL-capable display. These libraries are not | ||
| 131 | bundled. The tarball is what to hand another machine, because it | ||
| 128 | carries the exec bit that a bare downloaded binary does not: | 132 | carries the exec bit that a bare downloaded binary does not: |
| 129 | 133 | ||
| 130 | ```sh | 134 | ```sh |
| @@ -132,7 +136,7 @@ make release | |||
| 132 | ssh HOST 'mkdir -p ~/.local/bin && tar xzf - -C ~/.local/bin' < dist/mux-vVERSION-x86_64-linux-musl.tar.gz | 136 | ssh HOST 'mkdir -p ~/.local/bin && tar xzf - -C ~/.local/bin' < dist/mux-vVERSION-x86_64-linux-musl.tar.gz |
| 133 | ``` | 137 | ``` |
| 134 | 138 | ||
| 135 | A release is one tarball per OS, named for the target it holds: | 139 | A release is one tarball per OS, retaining the daemon target's name: |
| 136 | `mux-vVERSION-x86_64-linux-musl.tar.gz` and | 140 | `mux-vVERSION-x86_64-linux-musl.tar.gz` and |
| 137 | `mux-vVERSION-aarch64-macos.tar.gz`. Each is cut on that OS — `make release` | 141 | `mux-vVERSION-aarch64-macos.tar.gz`. Each is cut on that OS — `make release` |
| 138 | builds for the host it runs on — and both are published under | 142 | builds for the host it runs on — and both are published under |
| @@ -145,8 +149,8 @@ curl -fsSL https://git.a73x.sh/mux/releases/vVERSION/mux-vVERSION-x86_64-linux-m | |||
| 145 | curl -fsSL https://git.a73x.sh/mux/releases/vVERSION/mux-vVERSION-aarch64-macos.tar.gz | tar xzf - -C ~/.local/bin | 149 | curl -fsSL https://git.a73x.sh/mux/releases/vVERSION/mux-vVERSION-aarch64-macos.tar.gz | tar xzf - -C ~/.local/bin |
| 146 | ``` | 150 | ``` |
| 147 | 151 | ||
| 148 | On an Apple-silicon Mac the same build and install commands work, with two | 152 | On an Apple-silicon Mac the same build and install commands work, with the |
| 149 | things to install first and one binary you cannot cross-compile — see | 153 | toolchain and native dependencies installed first — see |
| 150 | [macOS](#macos). | 154 | [macOS](#macos). |
| 151 | 155 | ||
| 152 | ## Quick start, local | 156 | ## Quick start, local |
| @@ -850,7 +854,7 @@ system `zig` is neither used nor enough. | |||
| 850 | xcode-select --install | 854 | xcode-select --install |
| 851 | brew install cmake | 855 | brew install cmake |
| 852 | make build # first build fetches + compiles the QUIC deps, as on Linux | 856 | make build # first build fetches + compiles the QUIC deps, as on Linux |
| 853 | make install # an aarch64 binary in ~/.local/bin | 857 | make install # mux + muxg in ~/.local/bin; also needs the native libraries listed above |
| 854 | ``` | 858 | ``` |
| 855 | 859 | ||
| 856 | The Mac tarball of a release is cut by `make release-mac`, which runs | 860 | The Mac tarball of a release is cut by `make release-mac`, which runs |
build.zig
| Old | New | ||
|---|---|---|---|
| @@ -860,7 +860,7 @@ comptime { | |||
| 860 | } | 860 | } |
| 861 | 861 | ||
| 862 | pub fn build(b: *std.Build) void { | 862 | pub fn build(b: *std.Build) void { |
| 863 | // Single source for both binaries' --version. Bumped at tag time. | 863 | // Single source for the product binaries' --version. Bumped at tag time. |
| 864 | const version = "0.0.1-17"; | 864 | const version = "0.0.1-17"; |
| 865 | const version_opts = b.addOptions(); | 865 | const version_opts = b.addOptions(); |
| 866 | version_opts.addOption([]const u8, "version", version); | 866 | version_opts.addOption([]const u8, "version", version); |
| @@ -1145,6 +1145,7 @@ pub fn build(b: *std.Build) void { | |||
| 1145 | // there is deliberately no libGL link here. | 1145 | // there is deliberately no libGL link here. |
| 1146 | const native_mod = mods[comptime idxOf("native")]; | 1146 | const native_mod = mods[comptime idxOf("native")]; |
| 1147 | const muxg_mod = mods[comptime idxOf("muxg")]; | 1147 | const muxg_mod = mods[comptime idxOf("muxg")]; |
| 1148 | muxg_mod.addImport("build_options", build_opts_mod); | ||
| 1148 | const muxg_exe = b.addExecutable(.{ .name = "muxg", .root_module = muxg_mod }); | 1149 | const muxg_exe = b.addExecutable(.{ .name = "muxg", .root_module = muxg_mod }); |
| 1149 | linkerFor(muxg_exe); | 1150 | linkerFor(muxg_exe); |
| 1150 | for ([_][]const u8{ "sdl3", "freetype2", "fontconfig", "harfbuzz" }) |lib| | 1151 | for ([_][]const u8{ "sdl3", "freetype2", "fontconfig", "harfbuzz" }) |lib| |
src/cli/muxg.zig
| Old | New | ||
|---|---|---|---|
| @@ -54,7 +54,7 @@ pub fn main() !u8 { | |||
| 54 | if (try client.resolver.helper(alloc, args[1..])) |code| return code; | 54 | if (try client.resolver.helper(alloc, args[1..])) |code| return code; |
| 55 | 55 | ||
| 56 | var o: Arguments = .{}; | 56 | var o: Arguments = .{}; |
| 57 | cliflags.parseStrict(Arguments, &o, args[1..]) catch |e| return cliflags.exitFor(e, usage, "muxg", std.fmt.comptimePrint("0.0.1 ({s})", .{@tagName(@import("builtin").mode)})); | 57 | cliflags.parseStrict(Arguments, &o, args[1..]) catch |e| return cliflags.exitFor(e, usage, "muxg", std.fmt.comptimePrint("{s} ({s})", .{ @import("build_options").version, @tagName(@import("builtin").mode) })); |
| 58 | const named: usize = @as(usize, @intFromBool(o.sock != null)) + @intFromBool(o.via != null) + o._targets; | 58 | const named: usize = @as(usize, @intFromBool(o.sock != null)) + @intFromBool(o.via != null) + o._targets; |
| 59 | if (named > 1) { | 59 | if (named > 1) { |
| 60 | std.debug.print("muxg: name one transport: HOST, --sock, --via or quic://\n{s}", .{usage}); | 60 | std.debug.print("muxg: name one transport: HOST, --sock, --via or quic://\n{s}", .{usage}); |