<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slosh.git/Makefile.windows, branch docs-new</title>
<subtitle>an opinionated terminal multiplexer in C with programmable pane chrome</subtitle>
<id>https://git.sl0p.foo/slosh.git/atom/Makefile.windows?h=docs-new</id>
<link rel='self' href='https://git.sl0p.foo/slosh.git/atom/Makefile.windows?h=docs-new'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/'/>
<updated>2026-08-28T13:38:27Z</updated>
<entry>
<title>windows release: a zip in dist/, built beside the linux tarballs</title>
<updated>2026-08-28T13:38:27Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-28T13:38:27Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=67e0330e5f18e4fe7f87db978071c6afa77ee91b'/>
<id>urn:sha1:67e0330e5f18e4fe7f87db978071c6afa77ee91b</id>
<content type='text'>
make -f Makefile.windows dist stages slosh.exe as
slosh-&lt;version&gt;-windows-&lt;arch&gt;.zip -- a zip, not a tarball, because Windows
is the machine that will open it -- carrying the same licensing paperwork as
the linux tarballs, with docs/windows.md riding along instead of the
manpages. `make release` now builds both architectures via release-windows,
so the windows zips land under the same SHA256SUMS as everything else.
</content>
</entry>
<entry>
<title>windows build: re-stamp version.h when the version changes</title>
<updated>2026-08-28T12:25:55Z</updated>
<author>
<name>Peter Geissler</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-28T12:25:55Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=31e7b44ac85eb634bcf2f51ce3dfa47da55868c4'/>
<id>urn:sha1:31e7b44ac85eb634bcf2f51ce3dfa47da55868c4</id>
<content type='text'>
The rule had version.h as an order-only prerequisite of its output
directory, and nothing else. Order-only means "make this first if it is
missing", so the file was written once and then never again: the
version is derived from `git describe`, not from a file, so no
timestamp on disk ever moves when it goes stale, and make had no reason
to look.

Every Windows binary after the first therefore carried whatever the
version had been the day the build directory was created. The one on
the test box reported 0.1.0-2-gba48db9 -- a commit that no longer
exists, since the rebase rewrote it -- while being built from a tree
six commits later. `--version` was not just stale, it was pointing at
history that had been thrown away, which is worse than saying nothing.

So FORCE, and write through a temp file that replaces the real one only
when the text differs -- the same shape the main Makefile already uses
for build/version.h, and for the same reason. `make` after a commit
rebuilds; `make` twice in a row still does nothing.

Makefile.macos does not generate a version.h of its own -- it takes the
main Makefile's -- so it never had this.
</content>
</entry>
<entry>
<title>docs: the Windows build is a cross-compile, and only that</title>
<updated>2026-08-28T12:22:57Z</updated>
<author>
<name>Peter Geissler</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-28T12:22:57Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=7941820413d82b3d62d7fc2ac15ef0e1b3b69ee4'/>
<id>urn:sha1:7941820413d82b3d62d7fc2ac15ef0e1b3b69ee4</id>
<content type='text'>
The docs offered a native build as an equal alternative -- "the same
command builds natively on the Windows box itself, with zig on PATH and
a make" -- and it does not work. Makefile.windows needs sed, cat,
mkdir -p and shell grouping, none of which cmd.exe has; and on ARM64
`zig cc` in zig 0.16.0 dies with an access violation on a one-line C
file, so the compiler cannot run there at all. The zip that does it
matches the published shasum, so this is upstream rather than a bad
download.

Nobody following those two sentences reached a binary. So they are
gone, along with the "# host arch, native" usage line in the makefile
and the "cross-compiles too" aside in the two install sections, which
both implied that building on the box was the normal path and the
cross-compile a bonus. It is the other way round, and now the pages
say so once, in the same words each time.

`builds and runs natively` on the doc's first line loses `builds`:
what is native about slosh.exe is the binary, not where it was made.
</content>
</entry>
<entry>
<title>windows: a native port, on ConPTY and AF_UNIX</title>
<updated>2026-08-27T22:23:19Z</updated>
<author>
<name>Peter Geissler</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-27T22:11:24Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=d1b5a64c3855b07074b3c958739df4e16f6084a5'/>
<id>urn:sha1:d1b5a64c3855b07074b3c958739df4e16f6084a5</id>
<content type='text'>
slosh builds and runs on Windows 10/11, x86-64 and ARM64, as one exe
with no runtime dependency beyond the OS: panes, splits, tabs,
detachable sessions, the config file and its live reload, the control
socket, the mouse.

The port is a compatibility layer rather than a fork. compat/win holds
stub &lt;poll.h&gt;, &lt;sys/socket.h&gt;, &lt;termios.h&gt; and friends that redirect to
include/compat_win.h, which is force-included ahead of every translation
unit -- so the existing sources keep their POSIX includes and their
POSIX call sites, and the platform differences are answered in one
place.

Two decisions carry most of it.

Everything the event loop waits on is a socket. On POSIX a pty master,
an inotify descriptor and a unix socket are all file descriptors, so one
poll() covers them; Windows has no such union, and WSAPoll waits on
SOCKETs and nothing else. Rather than rewrite server.c's loop around
WaitForMultipleObjects -- which caps at 64 objects and cannot express
POLLOUT -- each non-socket source gets a pump thread that copies it into
one end of a loopback socketpair. The loop is then the POSIX one
unchanged, and only what sits behind the descriptor differs.

Socket descriptors are tagged rather than guessed: a wrapped SOCKET
comes back as SL_SOCK_BASE + slot, so read, write, close and poll can
tell a socket from a CRT descriptor with certainty instead of inferring
it from the numeric range. That is why socket() and accept() are shimmed
too -- an untagged descriptor escaping into the loop is the one failure
mode this scheme has, and it is worth closing completely.

Three things bit hard enough to be worth naming.

A pseudoconsole does not stop the child inheriting your stdio.
CreateProcess copies the parent's standard handles into the child when
STARTF_USESTDHANDLES is absent, and those win. With slosh's own stdout
redirected -- a pipe under ssh, a file under --script, a log under the
daemon -- the shell wrote its banner into slosh's output instead of into
the pane, and the pane had a correct title (ConPTY emits that itself)
over an empty body. The three handles are cleared for the duration of
the call, leaving the child nothing to inherit.

A ConPTY never reports EOF. The output pipe belongs to the
pseudoconsole, not to the child, so it stays open after the child exits
and pane_pump()'s read() -- the entire mechanism by which a pane learns
its program is gone -- never returns 0. A pane whose shell had been told
`exit` sat there looking alive forever. So the exit is waited for on the
process handle, and ClosePseudoConsole is what then produces the EOF.
That third thread is also why the per-pty state is reference counted: a
pump blocked on a dead pipe must not be waited for, or pty_close would
hang the session on the one program that misbehaves, so whoever finishes
last frees.

cmd.exe does not use CommandLineToArgvW's quoting. A literal quote is
\" to an ordinary program and a backslash-then-end-of-quoted-section to
cmd, so building `cmd /c notepad "C:\...\config.kdl"` the first way
handed the editor \"C:\...\config.kdl\", backslashes and all, and
notepad answered "Not a valid file name" about a path that existed.
cmd /c now gets the rest of the line verbatim -- the caller composed a
complete command with its own quoting, exactly as it does for sh -c.

Paths are mixed, and only some programs mind. slosh joins with '/' while
the environment supplies '\', so the config landed at
C:\Users\you/.config/slosh/config.kdl. The CRT opens that without
complaint, which is why --check reported it fine, but a GUI file dialog
rejects it outright. Anything handed to another program now goes through
sl_path_native() first; the internal representation is left alone.

The rest is small. Panes run %ComSpec%, sessions live in
%LOCALAPPDATA%\slosh rather than $XDG_RUNTIME_DIR because a session
socket must not follow a roaming profile to another host, there is no
SIGWINCH so a resize is noticed by comparing the console size on a
bounded poll, no fork so the daemon is a fresh detached process that
reconstructs its arguments on the command line, and no process group on
a pty so the foreground program is the youngest descendant of the pane's
shell. C-a e prefers whichever console editor is actually installed --
notepad is a GUI program, so a pane running it draws nothing and looks
broken -- and says so when it has to fall back.

make -f Makefile.windows ARCH=x86_64 (or aarch64) cross-compiles from a
mac or Linux, and builds natively on the box with zig on PATH.
</content>
</entry>
</feed>
