Sigil 0.17.18
A Slate preparation release. sigil app install can now install and launch a Sigil GUI desktop application, interface built in, so a graphical app like Slate installs with one command and runs from your application menu or your shell like any other program. Two runtime fixes land alongside it that matter for any long-running Sigil app: a memory leak that slowly grew until the app froze is cured, and idle CPU use drops sharply. Native builds are more trustworthy too: a compile that would once have silently shipped a broken artifact now fails loudly, and a changed source is never silently ignored. A correctness fix also lands for bitwise operations on large integers, which could silently return wrong values. Bytecode projects build without changes; native builds should be rebuilt from clean after upgrading, since the native module ABI changed.
sigil app install installs GUI desktop apps
You can now install a Sigil GUI desktop app with one command. sigil app install <source> builds the app, adds it to your application menu with its icon, and puts it on your PATH, so you launch it from the menu or by name in a terminal like any other program. No more manual guix shell, hand-set LD_LIBRARY_PATH, or hand-written .desktop file. A local checkout works as a source too (sigil app install ./my-app) for offline and dev installs, and update works from any directory afterward.
Installed apps behave well day to day: launches stay fast even after a guix gc or guix pull, a "Starting" notification appears if an app takes a few seconds to warm up so it never looks dead, and app remove is now instant.
Packages can build their assets at install time
A GUI web app needs its built interface embedded in the shipped binary. A package can now declare a before-build step that runs before its native build, so an app like Slate produces its web bundle and bakes it in during sigil app install. The installed app is self-contained, with nothing to stage or serve separately.
A memory leak in long-running apps is fixed
Every code evaluation leaked a small amount of memory that was never reclaimed. This is invisible in ordinary batch use, but a graphical app like Slate evaluates code on every frame and every keystroke, so the leak grew to roughly 40MB a minute, reached 2.6GB, and eventually froze the app after about an hour of active use. Memory use is now flat across a 30,000-evaluation run.
Idle CPU use drops sharply
The async scheduler did far more work than it needed to on every timer wake, which a graphical app's constant polling multiplied into a real cost: Slate burned about half a CPU core just sitting idle. That idle cost is now roughly seven times cheaper, dropping a typical idle workload from about half a core to about a tenth, with no change to how timers, goroutines, or sleep behave.
New async primitive: wait on any of a set of file descriptors
await-readable-fds blocks a goroutine until any file descriptor in a given set becomes readable, or until an optional timeout elapses, then resumes once. It is the raw file descriptor companion to await-readable-any, letting a program wait on a whole set of descriptors through the scheduler instead of a blocking poll, so other goroutines keep running while it waits. This is what a program uses to drive an external event loop, such as a native GUI toolkit's main loop, at near zero idle cost: it sleeps on the loop's poll descriptors and wakes only when something actually happens.
A changed source file is never silently ignored
In some cases a source edit could fail to take effect: the build treated an out-of-date bytecode file as current and shipped a build that quietly lacked the change. The build now checks its cache correctly, so a changed source always recompiles while an unchanged source still reuses its cached result.
Bitwise operations on large integers return correct results
bitwise-and, bitwise-ior, and bitwise-xor could silently return wrong values for large positive integers, first appearing at 2^63: (bitwise-ior 0 (expt 2 63)) came back negative, and a varint-style codec that reassembles a large integer with shift and ior corrupted values like (expt 7 500) on the way back in. No error was raised, so the corruption was easy to miss. All three operations now return correct results across the full integer range, arithmetic-shift and bitwise-not were verified unaffected, and regression tests cover the boundary in both the bytecode and native backends.
Native builds fail loudly instead of shipping something broken
In rare cases the native backend could hit a compile error, produce a broken artifact anyway, and still exit successfully. Because the build looked like it succeeded, the bad artifact was cached and served silently, and the failure surfaced only much later at runtime. A native build now either produces a correct result or stops with a clear error and writes no artifact, so a broken compile can never be silently cached. A nondeterministic miscompile in workspace builds is fixed in the same pass.
Exact float bytes with the IEEE-754 bytevector accessors
Sigil now ships the standard IEEE-754 bytevector accessors: bytevector-ieee-double-ref and bytevector-ieee-double-set! for 8-byte doubles, and bytevector-ieee-single-ref and bytevector-ieee-single-set! for 4-byte floats. They read and write a float's exact bits at a byte offset, bounds-checked, with an optional endianness argument (little, big, or native, defaulting to native). Because they are runtime primitives they behave identically in native and WebAssembly builds, and they are both exact and faster than deriving a float's bits by arithmetic. A library that moves floats through bytes, such as an audio buffer or a binary codec, can now use one exact primitive instead of a C cast that does not exist under WebAssembly or a slower arithmetic workaround. Reading a float from arbitrary bytes always returns a valid number: a bit pattern that would otherwise decode to an invalid, unusable value is normalized to a safe not-a-number, so untrusted input can never smuggle a corrupt value in through a float. Existing projects build without changes.