An early draft of this project's own design document promised that packaging a Ring program would produce a single self-contained file. It was written before anyone tested whether that was possible.
It was not. This post is about what actually ships, and about a habit worth more than the answer: the claim came first, and the measurement came second, and it should have been the other way round.
What was assumed
The idea seemed reasonable. Ring can already turn your
program into a compact compiled form — a .ringo file — with no
C compiler involved. Attach that to a small copy of Ring itself and you
have one file the user double-clicks. Plenty of tools in other languages do
exactly this.
Two things had to be true for it to work. Both were checked directly, and both were false.
| the assumption | what the test showed |
|---|---|
| Ring looks for a matching bytecode file next to the program when run with no arguments | No. It does not look |
| Bytecode can be appended to the end of the executable and still be found | No. Appending does nothing |
So the honest artefact is a
pair: yourprogram.exe and
yourprogram.ringo, copied together and invoked together. That
is what the documentation says now, in the same plain words, because a
small true claim is worth more than a large one that fails on someone
else's machine.
A correction, courtesy of Ring's own author
The day after this post went out, the author of Ring read it and pointed at an old, documented distribution trick. He was right in substance, we were right in the letter, and the difference earned its own finding.
Measured again, source in hand: Ring never looks for a
bytecode file matching the program's name — the table above
stands. But before reading a single argument, it looks in the current
directory for a file named literally ring.ringo (or
ring.ring) and runs it if found. Name the bytecode
ring.ringo and the pair launches with no arguments at
all — double-click included. The packaged program inherits this,
because its runtime is Ring's own entry point: verified by
renaming the bytecode beside a freshly packaged hello.exe
and running it bare.
So our published sentence was bigger than our
measurement: a same-named bytecode is not found; a
fixed-named one is. The same mechanism hides a trap, recorded as
finding F-35: a stray ring.ringo in your working directory
silently hijacks every Ring invocation — even
ring myfile.ring -go runs the stray file and ignores
everything you typed.
What you actually get
Two files, and nothing else required on the target machine — no Ring installation, no compiler, no runtime to install first. Copy them to an empty folder on a machine that has never seen Ring and the program runs. That is verified in the test suite by doing exactly that.
Then is this a replacement for Ring's own packaging tool?
No, and it is not trying to be. Ring ships
ring2exe, which produces a true single executable — by writing
out a C file and handing it to a real C compiler on your machine.
That is a different bargain, not a worse one:
ring2exe
One self-contained file. Requires a working C compiler — Visual C++, GCC or Clang — installed and configured on the machine doing the packaging.
ringpp build
A pair of files. Requires no compiler at all, on any machine, ever — and can produce packages for five different systems from whichever one you happen to be sitting at.
If you need one file, use
ring2exe — or Ring2EXE++, Youssef Saeed's
cross-platform extension of it. They are the right tools for that, and
Ring++ neither changes nor competes with them.
And what does "dependency-free" precisely mean?
It is a phrase that invites hand-waving, so here is the exact scope.
The library needs nothing but ordinary Ring. No extension to
compile, no DLL, no toolchain. One load line.
The command-line tool needs nothing but itself. No C compiler on the user's machine, ever.
Two things are built into the tool before it reaches you, and they are named on the front page rather than tucked away: Ring's own grammar, written by Youssef Saeed, and the Zig toolchain that compiles the binary. Both are our cost to carry, not yours — nothing is fetched or built when you install.
The distinction that matters: dependency-free is a promise about your machine, not a boast about ours.