I presume this will improve performance. Also, if I've understood
correctly, WASM-based compiled web code is capable of automatically
growing its memory, which the previous asm.js build of the puzzles
could not do, and occasionally caused people to complain that if they
tried to play a _really big_ game in their browser, the JS would
eventually freeze because the emulated memory ran out.
I've been putting off doing this for ages because my previous
Emscripten build setup was so finicky that I didn't like to meddle
with it. But now that the new cmake system in this source tree makes
things generally easier, and particularly since I've just found out
that the up-to-date Emscripten is available as a Docker image (namely
"emscripten/emsdk"), this seemed like a good moment to give it a try.
The source and build changes required for this update weren't too
onerous. I was half expecting a huge API upheaval, and indeed there
was _some_ change, but very little:
- in the JS initPuzzle function, move the call to Module.callMain()
into Module.onRuntimeInitialized instead of doing it at the top
level, because New Emscripten's .js output likes to load the
accompanying .wasm file asynchronously, so you can't call the WASM
main() until it actually exists.
- in the JS-side library code, replace all uses of Emscripten's
Pointer_stringify() function with the new name UTF8ToString(). (The
new version also has an ASCIIToString(), so I guess the reason for
the name change is that now you get to choose which character set
you meant. I need to use UTF-8, so that the × and ÷ signs in Keen
will work.)
- set EXTRA_EXPORTED_RUNTIME_METHODS=[cwrap,callMain] on the emcc
link command line, otherwise they aren't available for my JS setup
code to call.
- (removed -s ASM_JS=1 from the link options, though I'm not actually
sure it made any difference one way or the other in the new WASM
world)
- be prepared for a set of .wasm files to show up as build products
alongside the .js ones.
- stop building with -DCMAKE_BUILD_TYPE=Release! I'm not sure why
that was needed, but if I leave that flag on my cmake command line,
the output .js file fails to embed my emccpre.js, so the initial
call to initPuzzle() fails from the HTML wrapper page, meaning
nothing at all happens.
It's better to be lax for normal users trying to build the puzzles
from source to actually run them. That way, warning changes in some
particular compiler I haven't seen yet won't break the build.
Instead, I've invented a cmake setting -DSTRICT=ON which turns on all
those flags. So I can build with them myself, to ensure the code is as
portable as possible. And that flag is set in Buildscr, so that my
official builds won't complete until that warning mode is satisfied.
This reinstates the feature of the previous build system, that the C
icon files for the GTK puzzles were included in the source tarball, so
that users building from that instead of from the raw git repo would
not need to run the fiddly piece of build that regenerates them.
Running that fiddly piece of build is much easier in the CMake world
(because it's integrated with the main makefile), but it has a build
dependency on ImageMagick which is easily avoided.
The makefile will still build the icons if it _can_. But in the case
where it can't, it will use pre-built icon source files if they're
available, and only fall back to no-icon.c if it can't even do that.
(So a user checking out from git and building without ImageMagick
present will still be able to build _something_ playable.)
This completely removes the old system of mkfiles.pl + Recipe + .R
files that I used to manage the various per-platform makefiles and
other build scripts in this code base. In its place is a
CMakeLists.txt setup, which is still able to compile for Linux,
Windows, MacOS, NestedVM and Emscripten.
The main reason for doing this is because mkfiles.pl was a horrible
pile of unmaintainable cruft. It was hard to keep up to date (e.g.
didn't reliably support the latest Visual Studio project files); it
was so specific to me that nobody else could maintain it (or was even
interested in trying, and who can blame them?), and it wasn't even
easy to _use_ if you weren't me. And it didn't even produce very good
makefiles.
In fact I've been wanting to hurl mkfiles.pl in the bin for years, but
was blocked by CMake not quite being able to support my clang-cl based
system for cross-compiling for Windows on Linux. But CMake 3.20 was
released this month and fixes the last bug in that area (it had to do
with preprocessing of .rc files), so now I'm unblocked!
CMake is not perfect, but it's better at mkfiles.pl's job than
mkfiles.pl was, and it has the great advantage that lots of other
people already know about it.
Other advantages of the CMake system:
- Easier to build with. At least for the big three platforms, it's
possible to write down a list of build commands that's actually the
same everywhere ("cmake ." followed by "cmake --build ."). There's
endless scope for making your end-user cmake commands more fancy
than that, for various advantages, but very few people _have_ to.
- Less effort required to add a new puzzle. You just add a puzzle()
statement to the top-level CMakeLists.txt, instead of needing to
remember eight separate fiddly things to put in the .R file. (Look
at the reduction in CHECKLST.txt!)
- The 'unfinished' subdirectory is now _built_ unconditionally, even
if the things in it don't go into the 'make install' target. So
they won't bit-rot in future.
- Unix build: unified the old icons makefile with the main build, so
that each puzzle builds without an icon, runs to build its icon,
then relinks with it.
- Windows build: far easier to switch back and forth between debug
and release than with the old makefiles.
- MacOS build: CMake has its own .dmg generator, which is surely
better thought out than my ten-line bodge.
- net reduction in the number of lines of code in the code base. In
fact, that's still true _even_ if you don't count the deletion of
mkfiles.pl itself - that script didn't even have the virtue of
allowing everything else to be done exceptionally concisely.
I had this idea today and immediately wondered why I'd never had it
before!
To generate the puzzle screenshots used on the website and as program
icons, we run the GTK front end with the --screenshot option, which
sets up GTK, insists on connecting to an X server (or other display),
draws the state of a puzzle on a Cairo surface, writes that surface
out to a .png file, and exits.
But there's no reason we actually need the GTK setup during that
process, especially because the surface we do the drawing on is our
_own_ surface, not even one provided to us by GTK. We could just set
up a Cairo surface by itself, draw on it, and save it to a file.
Calling gtk_init is not only pointless, but actively inconvenient,
because it means the build script depends on having an X server
available for the sole purpose of making gtk_init not complain.
So now I've simplified things, by adding a 'headless' flag in
new_window and the frontend structure, which suppresses all uses of
actual GTK, leaving only the Cairo surface setup and enough supporting
stuff (like colours) to generate the puzzle image. One awkward build
dependency removed.
This means that --screenshot no longer works in GTK 2, which I don't
care about, because it only needs to run on _one_ platform.
If I want to rebuild just the Javascript puzzles (for example) in
circumstances where I don't expect to need a great many
edit-compile-link cycles, it's easier to get bob to do it for me than
to remember how to set up the development tools on my path. But it
takes ages to run the whole build script if I also have to wait for
the Windows, Mac and Java puzzles to be built, not to mention the
initial Unix build that runs for no purpose other than generating the
icon images.
So now I can run the build with various time-consuming parts
conditioned out, for development purposes. Of course, the default is
still to build absolutely everything.
This should make it less annoying for me to do local testing of the JS
output of a build, before I push a change. There's a new
build.out/jstest directory containing .html files suitable for loading
in a local browser, which refer to the JS files via an appropriate
relative path to the existing build.out/js directory.
This also switches them to being 64-bit, which I think is
probably acceptable in this modern age, especially for such
a non-essential piece of software. If anyone complains I can
always reinstate a parallel 32-bit build.
To support the switch to 64-bit, this commit also changes the default
install directory in the MSI to 'Program Files' rather than 'Program
Files (x86)'.
I'm getting rid of these installers in general, and also I'm about to
switch the Windows builds over to my new-look non-Windows non-Wine
system, which can't run the Inno Setup builder anyway.
Between 5.5.6 and 5.5.9 the default output file name changed. To
defend against that potentially happening again, I'm now explicitly
specifying the output file name in the .iss source file (or rather, in
winiss.pl, which constructs it).
I've reused most of the install script I wrote for PuTTY recently,
minus the selectable-features dialog, and plus some preliminary Mason
templating to automatically build the right set of puzzle binaries
into the installer.
Stable GUIDs are autogenerated by the same technique I use in PuTTY's
Visual Studio project file generation: hash a fixed pile of randomly
generated bits (that is, randomly generated _once_ and used forever)
with each filename or other identifier and use those as your random
number source.
Where facilities exist, that is. Like the approach I took with PuTTY
yesterday, Buildscr will now run a code-signing script over the binary
if you specify one in the bob config, and otherwise should fall back
to just leaving that step out.
This should simplify the process of adding a new puzzle, by automating
the part where I have to manually edit index.html separately from the
main build step.
Thanks to Stephen Norman for most of the work, particularly working
out what all the metadata had to be in the first place. This patch is
mostly his work, and all I've done is fiddle with the plumbing that
gets the right version number into the right places.
A long time ago, it seemed like a good idea to arrange that binaries
of my puzzles would automatically cease to identify themselves as a
particular upstream version number if any changes were made to the
source code, so that if someone made a local tweak and distributed the
result then I wouldn't get blamed for the results. Since then I've
decided the whole idea is more trouble than it's worth, so I'm
retiring it completely.
[originally from svn r10264]
I'm going through all my projects and reworking them to avoid
depending on the monotonic integer-valued source control revision
identifier provided by Subversion, so I can migrate everything to git
without my builds and versioning breaking.
Puzzles's version number is now of the form YYYYMMDD.vvvvvv, where
vvvvvv is some string of source control information (currently still
the SVN-style "rNNNNN", but free to change in future). The date
provides monotonicity between my official automated builds, and the
second component is the one I'll be most interested in when people
send bug reports.
[originally from svn r10263]
Makefile.am, and there's a new mkauto.sh which builds a corresponding
configure script.
The old makefile has been renamed from 'Makefile' to 'Makefile.gtk',
indicating that the intended new _default_ approach is to use the
autoconf world. Makefile.gtk is provided as an emergency fallback in
case anything fails with the new stuff that used to work with it.
The new configure script does not support the same $(BINPREFIX) system
as the old Makefile did. However, as I understand it, it should be
possible to configure using --program-prefix="sgt-" (for example) and
then the binaries should all be renamed appropriately at install time.
The Makefile.am is quite painful. The Puzzles codebase relies heavily
on compiling individual object files multiple times with different the
cpp flags per build deliverable (program or library) and not per
source file. Solution: anything built with non-default compile options
has to go in its own little library. But that doesn't work either in
the general case, because as soon as you have more than one such
library linked into an application, Unix ld semantics bite you if the
objects in the libraries both refer to each other. So I ended up
building all those little libraries but not _using_ them - instead the
link commands for the programs needing those objects refer to the
objects directly, under the silly names that automake gives them.
(That's less fragile than it sounds, because it does _document_ the
names of the intermediate object files. But still, yuck.)
[originally from svn r9886]
to it giving each game's "internal" name (as seen in the source file,
.R etc) and also a brief description of the game. The idea of the
latter is that it should be usable as a comment field in .desktop
files and similar.
[originally from svn r9858]
applets, here's an alternative webification in Javascript, using
Emscripten in asm.js mode (so that as browsers incorporate asm.js
optimisation, the game generation should run really fast).
[originally from svn r9781]
web pages for the Java applets. Previously, those have all been
maintained by hand in my website's svn area, which is a bit silly. Now
we have a file per puzzle in the 'html' subdirectory which contains
the puzzle's name, one or two attributes, and the instructions snippet
to go below the puzzle applet; and then there's a Perl script that
builds all the real web pages out of that by adding in the parts
common across all files: the header, footer, and middle fragment with
the <applet> tag and resizing bits and pieces.
One piece _not_ checked in here is the footer text specific to my
hosting at chiark, which I think does still belong in the www area. So
Buildscr doesn't actually build the web pages; it just delivers the
bits and pieces by which my nightly snapshot script will be able to
run the program that _does_ build them, passing that footer as an
extra argument.
[originally from svn r9780]
(more finished) puzzles in 'unfinished', as Java applets only. (The
rationale being: puzzles in 'unfinished' can be played locally by
people who go to the extra effort of downloading and building the
source, but to play them in Java is particularly inconvenient unless I
build the Java version myself. I just won't link it from the front
page.)
[originally from svn r9073]
it got rid of the bogus backgrounds on all the text; but on the
other hand it mysteriously caused all the images to become black and
white! Serves me right for testing with Bridges which was B&W to
start with. Instead, we'll just tell xvfb to use a 24-bit display
and let it sort out the visuals for itself; that seems to work better.
[originally from svn r7932]
infrastructure to the mkfiles.pl framework for the convenience of
the build script: it generates `wingames.lst', a list of the Windows
binaries which are ship-worthy games as opposed to nullgame or
command-line auxiliary programs.
[originally from svn r7206]