diff --git a/.gitignore b/.gitignore index d4ed12e3..2037a33 100644 --- a/.gitignore +++ b/.gitignore @@ -93,7 +93,6 @@ /*.dmg /*.res /*.inf -/list.c /gamedesc.txt /build.log /build.out diff --git a/Buildscr b/Buildscr index 21a3bdf..ba6ffca 100644 --- a/Buildscr +++ b/Buildscr @@ -9,11 +9,7 @@ module puzzles set Version $(!builddate).$(vcsid) -# Start by substituting the right version number in configure.ac. -in puzzles do perl -i~ -pe 's/6.66/$(Version)/' configure.ac -in puzzles do rm configure.ac~ - -# And put it into the documentation as a versionid. +# Put the version number into the documentation as a versionid. # use perl to avoid inconsistent behaviour of echo '\v' in puzzles do perl -e 'print "\n\\versionid Simon Tatham'\''s Portable Puzzle Collection, version $$ARGV[0]\n"' $(Version) >> puzzles.but in puzzles do perl -e 'print "\n\\versionid Simon Tatham'\''s Portable Puzzle Collection, version $$ARGV[0]\n"' $(Version) >> devel.but @@ -26,36 +22,35 @@ in puzzles do echo '$#define VER "Version $(Version)"' >> version.h # icky in principle because it presumes that my version numbers don't # need XML escaping, but frankly, if they ever do then I should fix # them!) -in puzzles do perl -i -pe 's/Unidentified build/$(Version)/' osx-info.plist +in puzzles do perl -i -pe 's/Unidentified build/$(Version)/' osx/Info.plist + +# The very first thing we do is to make the source archive, before we +# fill up the build directory with extra files. +delegate - + # Build Windows Help and text versions of the manual for convenience. + in puzzles do halibut --winhelp=puzzles.hlp --text=puzzles.txt puzzles.but + # Build a text version of the HACKING document. + in puzzles do halibut --text=HACKING devel.but + # Get rid of some cruft that isn't really useful in a source tarball. + in puzzles do rm -f Buildscr CHECKLST.txt .gitignore webpage.pl + in . do ln -s puzzles puzzles-$(Version) + in . do tar -chzf puzzles-$(Version).tar.gz puzzles-$(Version) + return puzzles-$(Version).tar.gz +enddelegate ifneq "$(NOICONS)" yes then - # First build some local binaries, to run the icon build. - in puzzles do perl mkfiles.pl -U CFLAGS='-Wwrite-strings -Werror' - in puzzles do make -j$(nproc) - - # Now build the screenshots and icons. - in puzzles/icons do make web winicons gtkicons -j$(nproc) - - # Destroy the local binaries and autoconf detritus, mostly to avoid - # wasting network bandwidth by transferring them to the delegate - # servers. - in puzzles do make distclean - + # Run enough of a native Unix build to produce the icons needed for + # the Windows builds and the website. + in puzzles do cmake -B build-icons . + in puzzles/build-icons do make -j$(nproc) icons VERBOSE=1 endif -# Re-run mkfiles.pl now that it knows the icons are there. (Or for the -# first time, if we didn't bother building the icons.) -in puzzles do perl mkfiles.pl - -# Rebuild the configure script. -in puzzles do ./mkauto.sh - ifneq "$(NOMACOS)" yes then - # Build the OS X .dmg archive. + # Build the OS X binaries and .dmg archive. delegate osx - in puzzles do make -f Makefile.osx clean - in puzzles do make -f Makefile.osx release VER=-DVER=$(Version) XFLAGS='-Wwrite-strings -Werror' -j$(nproc) - return puzzles/Puzzles.dmg + in puzzles do cmake -B build-osx -DCMAKE_BUILD_TYPE=Release . + in puzzles/build-osx do make -j$(nproc) package VERBOSE=1 + return puzzles/build-osx/Puzzles.dmg enddelegate endif @@ -63,71 +58,28 @@ ifneq "$(NOWINDOWS)" yes then # Build the Windows binaries and installer, and the CHM file. in puzzles do make -f Makefile.doc clean in puzzles do make -f Makefile.doc -j$(nproc) # build help files for installer - in puzzles do mason.pl --args '{"version":"$(Version)","descfile":"gamedesc.txt"}' winwix.mc > puzzles.wxs - in puzzles do perl winiss.pl $(Version) gamedesc.txt > puzzles.iss - ifneq "$(VISUAL_STUDIO)" "yes" then - in puzzles with clangcl64 do mkdir win64 && Platform=x64 make -f Makefile.clangcl BUILDDIR=win64/ VER=-DVER=$(Version) XFLAGS='-Wwrite-strings -Werror' -j$(nproc) - in puzzles with clangcl32 do mkdir win32 && Platform=x86 make -f Makefile.clangcl BUILDDIR=win32/ SUBSYSVER=,5.01 VER=-DVER=$(Version) XFLAGS='-Wwrite-strings -Werror' -j$(nproc) - # Code-sign the binaries, if the local bob config provides a script - # to do so. We assume here that the script accepts an -i option to - # provide a 'more info' URL, and an optional -n option to provide a - # program name, and that it can take multiple .exe filename - # arguments and sign them all in place. - ifneq "$(cross_winsigncode)" "" in puzzles do $(cross_winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ win64/*.exe win32/*.exe - # Build installers. - in puzzles with wixonlinux do candle -arch x64 puzzles.wxs -dWin64=yes -dBindir=win64/ && light -ext WixUIExtension -sval puzzles.wixobj - in puzzles with wixonlinux do candle -arch x86 puzzles.wxs -dWin64=no -dBindir=win32/ && light -ext WixUIExtension -sval puzzles.wixobj -o puzzles32.msi - ifneq "$(cross_winsigncode)" "" in puzzles do $(cross_winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ -n "Simon Tatham's Portable Puzzle Collection Installer" puzzles.msi puzzles32.msi - else - delegate windows - in puzzles with visualstudio do/win nmake -f Makefile.vc clean - in puzzles with visualstudio do/win nmake -f Makefile.vc VER=-DVER=$(Version) - ifneq "$(winsigncode)" "" in puzzles do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ win64/*.exe - # Build installers. - in puzzles with wix do/win candle puzzles.wxs -dWin64=yes -dBindir=win64/ && light -ext WixUIExtension -sval puzzles.wixobj - in puzzles with innosetup do/win iscc puzzles.iss - return puzzles/win64/*.exe - return puzzles/puzzles.msi - enddelegate - endif - in puzzles do chmod +x win32/*.exe win64/*.exe + + in puzzles do cmake -B build-win64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_TOOLCHAIN_FILE=$(cmake_toolchain_clangcl64) . + in puzzles do cmake -B build-win32 -DCMAKE_BUILD_TYPE=Release -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_TOOLCHAIN_FILE=$(cmake_toolchain_clangcl32) . + in puzzles/build-win64 do make -j$(nproc) VERBOSE=1 + in puzzles/build-win32 do make -j$(nproc) VERBOSE=1 + + in puzzles do mason.pl --args '{"version":"$(Version)","descfile":"build-win64/gamedesc.txt"}' winwix.mc > puzzles.wxs + + # Code-sign the binaries, if the local bob config provides a script + # to do so. We assume here that the script accepts an -i option to + # provide a 'more info' URL, and an optional -n option to provide a + # program name, and that it can take multiple .exe filename + # arguments and sign them all in place. + ifneq "$(cross_winsigncode)" "" in puzzles do $(cross_winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ build-win64/*.exe build-win32/*.exe + # Build installers. + in puzzles with wixonlinux do candle -arch x64 puzzles.wxs -dWin64=yes -dBindir=build-win64/ && light -ext WixUIExtension -sval puzzles.wixobj + in puzzles with wixonlinux do candle -arch x86 puzzles.wxs -dWin64=no -dBindir=build-win32/ && light -ext WixUIExtension -sval puzzles.wixobj -o puzzles32.msi + ifneq "$(cross_winsigncode)" "" in puzzles do $(cross_winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ -n "Simon Tatham's Portable Puzzle Collection Installer" puzzles.msi puzzles32.msi + + in puzzles do chmod +x build-win32/*.exe build-win64/*.exe endif -# Build the Pocket PC binaries and CAB. -# -# NOTE: This part of the build script requires the Windows delegate -# server to have the cabwiz program on its PATH. This will -# typically be at -# -# C:\Program Files\Windows CE Tools\WCE420\POCKET PC 2003\Tools -# -# but it might not be if you've installed it somewhere else, or -# have a different version. -# -# NOTE ALSO: This part of the build is commented out, for the -# moment, because cabwiz does unhelpful things when run from within -# a bob delegate process (or, more generally, when run from any -# terminal-based remote login to a Windows machine, including -# Cygwin opensshd and Windows Telnet). The symptom is that cabwiz -# just beeps and sits there. Until I figure out how to build the -# .cab from an automated process (and I'm willing to consider silly -# approaches such as a third-party CAB generator), I don't think I -# can sensibly enable this build. - -#in puzzles do perl wceinf.pl gamedesc.txt > puzzles.inf -#delegate windows -# in puzzles do cmd /c 'wcearmv4 & nmake -f Makefile.wce clean' -# in puzzles do cmd /c 'wcearmv4 & nmake -f Makefile.wce VER=-DVER=$(Version)' -# # Nasty piece of sh here which saves the return code from cabwiz, -# # outputs its errors and/or warnings, and then propagates the -# # return code back to bob. If only cabwiz could output to -# # standard error LIKE EVERY OTHER COMMAND-LINE UTILITY IN THE -# # WORLD, I wouldn't have to do this. -# in puzzles do cat puzzles.inf -# in puzzles do cmd /c 'wcearmv4 & bash -c cabwiz puzzles.inf /err cabwiz.err /cpu ARMV4'; a=$$?; cat cabwiz.err; exit $$a -# return puzzles/puzzles.armv4.cab -#enddelegate - # Build the HTML docs. in puzzles do mkdir doc in puzzles do mkdir devel @@ -136,34 +88,34 @@ in puzzles/devel do halibut --html -Chtml-contents-filename:index.html -Chtml-in ifneq "$(NOWINDOWS)" yes then # Move the deliver-worthy Windows binaries (those specified in - # gamedesc.txt, which is generated by mkfiles.pl and helpfully + # gamedesc.txt, which is generated by CMakeLists.txt and helpfully # excludes the command-line auxiliary utilities such as solosolver, # and nullgame.exe) into a subdirectory for easy access. in puzzles do mkdir winbin64 winbin32 - in puzzles/win64 do mv `cut -f2 -d: ../gamedesc.txt` ../winbin64 - in puzzles/win32 do mv `cut -f2 -d: ../gamedesc.txt` ../winbin32 + in puzzles/build-win64 do mv `cut -f2 -d: gamedesc.txt` ../winbin64 + in puzzles/build-win32 do mv `cut -f2 -d: gamedesc.txt` ../winbin32 # Make a zip file of the Windows binaries and help files. in puzzles do zip -j puzzles.zip winbin64/*.exe puzzles.chm puzzles.hlp puzzles.cnt in puzzles do zip -j puzzles32.zip winbin32/*.exe puzzles.chm puzzles.hlp puzzles.cnt endif -# Create the source archive. (That writes the archive into the -# _parent_ directory, so be careful when we deliver it.) -in puzzles do ./makedist.sh $(Version) - # Build the autogenerated pieces of the main web page. -in puzzles do perl webpage.pl +in puzzles do cmake -B build-gamedesc . -DCMAKE_TOOLCHAIN_FILE=../cmake/windows-dummy-toolchain.cmake +in puzzles do perl webpage.pl build-gamedesc/gamedesc.txt -ifneq "$(JAVA_UNFINISHED)" "" in puzzles do perl -i~ -pe 'print "!srcdir unfinished/\n" if /!srcdir icons/' Recipe -ifneq "$(JAVA_UNFINISHED)" "" in puzzles do ln -s unfinished/group.R . -ifneq "$(JAVA_UNFINISHED)" "" in puzzles do perl mkfiles.pl +# Group is playable, even if still a bit unpolished and strange, so we +# can at least make the web versions of it (which are unobtrusive if +# you don't deliberately navigate to the web pages). +set web_unfinished_option -DPUZZLES_ENABLE_UNFINISHED=group ifneq "$(NOJAVA)" yes then # Build the Java applets. delegate nestedvm - in puzzles do make -f Makefile.nestedvm NESTEDVM="$$NESTEDVM" VER=-DVER=$(Version) XFLAGS="-Wwrite-strings -Werror" -j$(nproc) - return puzzles/*.jar + in puzzles do cmake -B build-nestedvm -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/nestedvm-toolchain.cmake -DNESTEDVM="$$NESTEDVM" $(web_unfinished_option) . + in puzzles/build-nestedvm do make -j$(nproc) VERBOSE=1 + return puzzles/build-nestedvm/*.jar + return puzzles/build-nestedvm/unfinished/group.jar enddelegate endif @@ -171,11 +123,11 @@ endif # have the right dependencies installed for Emscripten, I do this by a # delegation. ifneq "$(NOJS)" yes then - in puzzles do mkdir js # so we can tell output .js files from emcc*.js delegate emscripten - in puzzles do make -f Makefile.emcc OUTPREFIX=js/ clean - in puzzles do make -f Makefile.emcc OUTPREFIX=js/ XFLAGS="-Wwrite-strings -Werror" -j$(nproc) - return puzzles/js/*.js + in puzzles do emcmake cmake -B build-emscripten -DCMAKE_BUILD_TYPE=Release $(web_unfinished_option) . + in puzzles/build-emscripten do make -j$(nproc) VERBOSE=1 + return puzzles/build-emscripten/*.js + return puzzles/build-emscripten/unfinished/group.js enddelegate # Build a set of wrapping HTML pages for easy testing of the @@ -198,7 +150,7 @@ in puzzles do echo RedirectMatch temp '(.*/)'puzzles-installer.msi '$$1'puzzles- # Phew, we're done. Deliver everything! ifneq "$(NOICONS)" yes then - deliver puzzles/icons/*-web.png $@ + deliver puzzles/build-icons/icons/*-web.png $@ endif ifneq "$(NOWINDOWS)" yes then deliver puzzles/winbin64/*.exe $@ @@ -215,13 +167,15 @@ deliver puzzles/.htaccess $@ deliver puzzles/doc/*.html doc/$@ deliver puzzles/devel/*.html devel/$@ ifneq "$(NOMACOS)" yes then - deliver puzzles/Puzzles.dmg $@ + deliver puzzles/build-osx/Puzzles.dmg $@ endif ifneq "$(NOJAVA)" yes then - deliver puzzles/*.jar java/$@ + deliver puzzles/build-nestedvm/*.jar java/$@ + deliver puzzles/build-nestedvm/unfinished/*.jar java/$@ endif ifneq "$(NOJS)" yes then - deliver puzzles/js/*.js js/$@ + deliver puzzles/build-emscripten/*.js js/$@ + deliver puzzles/build-emscripten/unfinished/*.js js/$@ deliver puzzles/jstest/*.html jstest/$@ deliver puzzles/html/*.html html/$@ deliver puzzles/html/*.pl html/$@ diff --git a/CHECKLST.txt b/CHECKLST.txt index 2bef909..e849542 100644 --- a/CHECKLST.txt +++ b/CHECKLST.txt @@ -6,20 +6,9 @@ Things to remember when adding a new puzzle Write the source file for the new puzzle (duhh). -Create a .R file for it which: - - defines a _EXTRA symbol for it if it requires auxiliary - object files (make sure that symbol doesn't contain the icon) - - adds it to the `ALL' definition, to ensure it is compiled into - the OS X binary - - adds it as a GTK build target, with the optional GTK icon - - adds it as a Windows build target, with the optional resource - file - - adds auxiliary solver binaries if any - - adds it to $(GAMES) in both the automake and GTK makefiles, for - `make install' - - adds it to list.c for the OS X binary - - adds it to gamedesc.txt, with its Windows executable name, display - name, and slightly longer description. +Write a puzzle() statement in CMakeLists.txt containing all the +necessary metadata. Optionally also a solver() statement, and any +cliprogram() statements for extra auxiliary tools. If the puzzle is by a new author, modify the copyright notice in LICENCE and in puzzles.but. (Also in index.html, but that's listed @@ -47,15 +36,10 @@ html/.html . Make a screenshot: - create an appropriate save file in `icons' - - add the puzzle name to icons/Makefile - - set up a REDO property in icons/Makefile if the screenshot wants - to display a move halfway through an animation - - set up a CROP property in icons/Makefile if the icon wants to be - a sub-rectangle of the whole screenshot - -Don't forget to `git add' the new source file, the new .R file and the -save file in `icons', the new .html file, and any other new files that -might have been involved. + - define _redo in icons/icons.cmake if the screenshot + wants to display a move halfway through an animation + - define _crop in icons/icons.cmake if the icon wants to + be a sub-rectangle of the whole screenshot Check in! diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..86c6c08 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,264 @@ +cmake_minimum_required(VERSION 3.16) + +project(puzzles + LANGUAGES C) + +include(cmake/setup.cmake) + +add_library(common + combi.c divvy.c drawing.c dsf.c findloop.c grid.c latin.c + laydomino.c loopgen.c malloc.c matching.c midend.c misc.c penrose.c + ps.c random.c sort.c tdq.c tree234.c version.c + ${platform_common_sources}) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +puzzle(blackbox + DISPLAYNAME "Black Box" + DESCRIPTION "Ball-finding puzzle" + OBJECTIVE "Find the hidden balls in the box by bouncing laser beams \ +off them.") + +puzzle(bridges + DISPLAYNAME "Bridges" + DESCRIPTION "Bridge-placing puzzle" + OBJECTIVE "Connect all the islands with a network of bridges.") + +puzzle(cube + DISPLAYNAME "Cube" + DESCRIPTION "Rolling cube puzzle" + OBJECTIVE "Pick up all the blue squares by rolling the cube over them.") + +puzzle(dominosa + DISPLAYNAME "Dominosa" + DESCRIPTION "Domino tiling puzzle" + OBJECTIVE "Tile the rectangle with a full set of dominoes.") +solver(dominosa) + +puzzle(fifteen + DISPLAYNAME "Fifteen" + DESCRIPTION "Sliding block puzzle" + OBJECTIVE "Slide the tiles around to arrange them into order.") +solver(fifteen) + +puzzle(filling + DISPLAYNAME "Filling" + DESCRIPTION "Polyomino puzzle" + OBJECTIVE "Mark every square with the area of its containing region.") +solver(filling) + +puzzle(flip + DISPLAYNAME "Flip" + DESCRIPTION "Tile inversion puzzle" + OBJECTIVE "Flip groups of squares to light them all up at once.") + +puzzle(flood + DISPLAYNAME "Flood" + DESCRIPTION "Flood-filling puzzle" + OBJECTIVE "Turn the grid the same colour in as few flood fills as possible.") + +puzzle(galaxies + DISPLAYNAME "Galaxies" + DESCRIPTION "Symmetric polyomino puzzle" + OBJECTIVE "Divide the grid into rotationally symmetric regions each \ +centred on a dot.") +solver(galaxies) +cliprogram(galaxiespicture galaxies.c + COMPILE_DEFINITIONS STANDALONE_PICTURE_GENERATOR) + +puzzle(guess + DISPLAYNAME "Guess" + DESCRIPTION "Combination-guessing puzzle" + OBJECTIVE "Guess the hidden combination of colours.") + +puzzle(inertia + DISPLAYNAME "Inertia" + DESCRIPTION "Gem-collecting puzzle" + OBJECTIVE "Collect all the gems without running into any of the mines.") + +puzzle(keen + DISPLAYNAME "Keen" + DESCRIPTION "Arithmetic Latin square puzzle" + OBJECTIVE "Complete the latin square in accordance with the \ +arithmetic clues.") +solver(keen latin.c) + +puzzle(lightup + DISPLAYNAME "Light Up" + DESCRIPTION "Light-bulb placing puzzle" + OBJECTIVE "Place bulbs to light up all the squares.") +solver(lightup) + +puzzle(loopy + DISPLAYNAME "Loopy" + DESCRIPTION "Loop-drawing puzzle" + OBJECTIVE "Draw a single closed loop, given clues about number of \ +adjacent edges.") +solver(loopy) + +puzzle(magnets + DISPLAYNAME "Magnets" + DESCRIPTION "Magnet-placing puzzle" + OBJECTIVE "Place magnets to satisfy the clues and avoid like poles \ +touching.") +solver(magnets) + +puzzle(map + DISPLAYNAME "Map" + DESCRIPTION "Map-colouring puzzle" + OBJECTIVE "Colour the map so that adjacent regions are never the \ +same colour.") +solver(map) + +puzzle(mines + DISPLAYNAME "Mines" + DESCRIPTION "Mine-finding puzzle" + OBJECTIVE "Find all the mines without treading on any of them.") +cliprogram(mineobfusc mines.c COMPILE_DEFINITIONS STANDALONE_OBFUSCATOR) + +puzzle(net + # The Windows Net shouldn't be called 'net.exe', since Windows + # already has a reasonably important utility program by that name! + WINDOWS_EXE_NAME netgame + + DISPLAYNAME "Net" + DESCRIPTION "Network jigsaw puzzle" + OBJECTIVE "Rotate each tile to reassemble the network.") + +puzzle(netslide + DISPLAYNAME "Netslide" + DESCRIPTION "Toroidal sliding network puzzle" + OBJECTIVE "Slide a row at a time to reassemble the network.") + +puzzle(nullgame) + +puzzle(palisade + DISPLAYNAME "Palisade" + DESCRIPTION "Grid-division puzzle" + OBJECTIVE "Divide the grid into equal-sized areas in accordance with\ + the clues.") + +puzzle(pattern + DISPLAYNAME "Pattern" + DESCRIPTION "Pattern puzzle" + OBJECTIVE "Fill in the pattern in the grid, given only the lengths \ +of runs of black squares.") +solver(pattern) +cliprogram(patternpicture pattern.c + COMPILE_DEFINITIONS STANDALONE_PICTURE_GENERATOR) + +puzzle(pearl + DISPLAYNAME "Pearl" + DESCRIPTION "Loop-drawing puzzle" + OBJECTIVE "Draw a single closed loop, given clues about corner and \ +straight squares.") +solver(pearl) +cliprogram(pearlbench pearl.c COMPILE_DEFINITIONS STANDALONE_SOLVER) + +puzzle(pegs + DISPLAYNAME "Pegs" + DESCRIPTION "Peg solitaire puzzle" + OBJECTIVE "Jump pegs over each other to remove all but one.") + +puzzle(range + DISPLAYNAME "Range" + DESCRIPTION "Visible-distance puzzle" + OBJECTIVE "Place black squares to limit the visible distance from \ +each numbered cell.") + +puzzle(rect + DISPLAYNAME "Rectangles" + DESCRIPTION "Rectangles puzzle" + OBJECTIVE "Divide the grid into rectangles with areas equal to the \ +numbers.") + +puzzle(samegame + DISPLAYNAME "Same Game" + DESCRIPTION "Block-clearing puzzle" + OBJECTIVE "Clear the grid by removing touching groups of the same \ +colour squares.") + +puzzle(signpost + DISPLAYNAME "Signpost" + DESCRIPTION "Square-connecting puzzle" + OBJECTIVE "Connect the squares into a path following the arrows.") +solver(signpost) + +puzzle(singles + DISPLAYNAME "Singles" + DESCRIPTION "Number-removing puzzle" + OBJECTIVE "Black out the right set of duplicate numbers.") +solver(singles) + +puzzle(sixteen + DISPLAYNAME "Sixteen" + DESCRIPTION "Toroidal sliding block puzzle" + OBJECTIVE "Slide a row at a time to arrange the tiles into order.") + +puzzle(slant + DISPLAYNAME "Slant" + DESCRIPTION "Maze-drawing puzzle" + OBJECTIVE "Draw a maze of slanting lines that matches the clues.") +solver(slant) + +puzzle(solo + DISPLAYNAME "Solo" + DESCRIPTION "Number placement puzzle" + OBJECTIVE "Fill in the grid so that each row, column and square \ +block contains one of every digit.") +solver(solo) + +puzzle(tents + DISPLAYNAME "Tents" + DESCRIPTION "Tent-placing puzzle" + OBJECTIVE "Place a tent next to each tree.") +solver(tents) + +puzzle(towers + DISPLAYNAME "Towers" + DESCRIPTION "Tower-placing Latin square puzzle" + OBJECTIVE "Complete the latin square of towers in accordance with \ +the clues.") +solver(towers latin.c) + +puzzle(tracks + DISPLAYNAME "Tracks" + DESCRIPTION "Path-finding railway track puzzle" + OBJECTIVE "Fill in the railway track according to the clues.") +solver(tracks) + +puzzle(twiddle + DISPLAYNAME "Twiddle" + DESCRIPTION "Rotational sliding block puzzle" + OBJECTIVE "Rotate the tiles around themselves to arrange them into order.") + +puzzle(undead + DISPLAYNAME "Undead" + DESCRIPTION "Monster-placing puzzle" + OBJECTIVE "Place ghosts, vampires and zombies so that the right \ +numbers of them can be seen in mirrors.") + +puzzle(unequal + DISPLAYNAME "Unequal" + DESCRIPTION "Latin square puzzle" + OBJECTIVE "Complete the latin square in accordance with the > signs.") +solver(unequal latin.c) + +puzzle(unruly + DISPLAYNAME "Unruly" + DESCRIPTION "Black and white grid puzzle" + OBJECTIVE "Fill in the black and white grid to avoid runs of three.") +solver(unruly) + +puzzle(untangle + DISPLAYNAME "Untangle" + DESCRIPTION "Planar graph layout puzzle" + OBJECTIVE "Reposition the points so that the lines do not cross.") + +add_subdirectory(unfinished) + +cliprogram(obfusc obfusc.c) +cliprogram(latincheck latin.c COMPILE_DEFINITIONS STANDALONE_LATIN_TEST) +cliprogram(matching matching.c COMPILE_DEFINITIONS STANDALONE_MATCHING_TEST) + +build_platform_extras() diff --git a/README b/README index 0083012..dd76edc 100644 --- a/README +++ b/README @@ -2,48 +2,12 @@ This is the README accompanying the source code to Simon Tatham's puzzle collection. The collection's web site is at . -If you've obtained the source code by downloading a .tar.gz archive -from the Puzzles web site, you should find several Makefiles in the -source code. However, if you've checked the source code out from the -Puzzles git repository, you won't find the Makefiles: they're -automatically generated by `mkfiles.pl', so run that to create them. +The puzzle collection is built using CMake . To +compile in the simplest way (on any of Linux, Windows or Mac), run +these commands in the source directory: -The Makefiles include: - - - `Makefile.am', together with the static `configure.ac', is intended - as input to automake. Run `mkauto.sh' to turn these into a - configure script and Makefile.in, after which you can then run - `./configure' to create an actual Unix Makefile. - - - `Makefile.vc' should work under MS Visual C++ on Windows. Run - 'nmake /f Makefile.vc' in a Visual Studio command prompt. - - - `Makefile.cyg' should work under Cygwin / MinGW. With appropriate - tweaks and setting of TOOLPATH, it should work for both compiling - on Windows and cross-compiling on Unix. - - - `Makefile.osx' should work under Mac OS X, provided the Xcode - tools are installed. It builds a single monolithic OS X - application capable of running any of the puzzles, or even more - than one of them at a time. - - - `Makefile.wce' should work under MS eMbedded Visual C++ on - Windows and the Pocket PC SDK; it builds Pocket PC binaries. - -Many of these Makefiles build a program called `nullgame' in -addition to the actual game binaries. This program doesn't do -anything; it's just a template for people to start from when adding -a new game to the collection, and it's compiled every time to ensure -that it _does_ compile and link successfully (because otherwise it -wouldn't be much use as a template). Once it's built, you can run it -if you really want to (but it's very boring), and then you should -ignore it. - -DO NOT EDIT THE MAKEFILES DIRECTLY, if you plan to send any changes -back to the maintainer. The makefiles are generated automatically by -the Perl script `mkfiles.pl' from the file `Recipe' and the various -.R files. If you need to change the makefiles as part of a patch, -you should change Recipe, *.R, and/or mkfiles.pl. + cmake . + cmake --build . The manual is provided in Windows Help format for the Windows build; in text format for anyone who needs it; and in HTML for the Mac OS X diff --git a/Recipe b/Recipe deleted file mode 100644 index f94b1f9..0000000 --- a/Recipe +++ /dev/null @@ -1,171 +0,0 @@ -# -*- makefile -*- -# -# This file describes which puzzle binaries are made up from which -# object and resource files. It is processed into the various -# Makefiles by means of a Perl script. Makefile changes should -# really be made by editing this file and/or the Perl script, not -# by editing the actual Makefiles. - -!name puzzles - -!makefile gtk Makefile.gtk -!makefile am Makefile.am -!makefile vc Makefile.vc -!makefile wce Makefile.wce -!makefile cygwin Makefile.cyg -!makefile osx Makefile.osx -!makefile gnustep Makefile.gnustep -!makefile nestedvm Makefile.nestedvm -!makefile emcc Makefile.emcc -!makefile clangcl Makefile.clangcl - -!srcdir icons/ - -WINDOWS_COMMON = printing - + user32.lib gdi32.lib comctl32.lib comdlg32.lib winspool.lib -WINDOWS = windows WINDOWS_COMMON -COMMON = midend drawing misc malloc random version -GTK = gtk printing ps -# Objects needed for auxiliary command-line programs. -STANDALONE = nullfe random misc malloc - -ALL = list - -LATIN_DEPS = matching tree234 -LATIN = latin LATIN_DEPS -LATIN_SOLVER = latin[STANDALONE_SOLVER] LATIN_DEPS - -# First half of list.c. -!begin >list.c -/* - * list.c: List of pointers to puzzle structures, for monolithic - * platforms. - * - * This file is automatically generated by mkfiles.pl. Do not edit - * it directly, or the changes will be lost next time mkfiles.pl runs. - * Instead, edit Recipe and/or its *.R subfiles. - */ -#include "puzzles.h" -#define GAMELIST(A) \ -!end - -# Now each .R file adds part of the macro definition of GAMELIST to list.c. -!include *.R - -# Then we finish up list.c as follows: -!begin >list.c - -#define DECL(x) extern const game x; -#define REF(x) &x, -GAMELIST(DECL) -const game *gamelist[] = { GAMELIST(REF) }; -const int gamecount = lenof(gamelist); -!end - -# Unix standalone application for special-purpose obfuscation. -obfusc : [U] obfusc STANDALONE - -# Test program built from latin.c. -latincheck : [U] latin[STANDALONE_LATIN_TEST] LATIN_DEPS STANDALONE -latincheck : [C] latin[STANDALONE_LATIN_TEST] LATIN_DEPS STANDALONE - -# Test program built from matching.c. -matching : [U] matching[STANDALONE_MATCHING_TEST] tree234 STANDALONE -matching : [C] matching[STANDALONE_MATCHING_TEST] tree234 STANDALONE - -puzzles : [G] windows[COMBINED] WINDOWS_COMMON COMMON ALL noicon.res - -# Mac OS X unified application containing all the puzzles. -Puzzles : [MX] osx osx.icns osx-info.plist COMMON ALL -# For OS X, we must create the online help and include it in the -# application bundle.) Also we add -DCOMBINED to the compiler flags -# so as to inform the code that we're building a single binary for -# all the puzzles. Then I've also got some code in here to build a -# distributable .dmg disk image. -!begin osx -Puzzles_extra = Puzzles.app/Contents/Resources/Help/index.html -Puzzles.app/Contents/Resources/Help/index.html: \ - Puzzles.app/Contents/Resources/Help osx-help.but puzzles.but - cd Puzzles.app/Contents/Resources/Help; \ - halibut --html ../../../../osx-help.but ../../../../puzzles.but -Puzzles.app/Contents/Resources/Help: Puzzles.app/Contents/Resources - mkdir -p Puzzles.app/Contents/Resources/Help - -release: Puzzles.dmg -Puzzles.dmg: Puzzles - rm -f raw.dmg - hdiutil create -megabytes 5 -layout NONE raw.dmg - hdid -nomount raw.dmg > devicename - newfs_hfs -v "Simon Tatham's Puzzle Collection" `cat devicename` - hdiutil eject `cat devicename` - hdid raw.dmg | cut -f1 -d' ' > devicename - cp -R Puzzles.app /Volumes/"Simon Tatham's Puzzle Collection" - hdiutil eject `cat devicename` - rm -f Puzzles.dmg - hdiutil convert -format UDCO raw.dmg -o Puzzles.dmg - rm -f raw.dmg devicename -!end - -!begin am -bin_PROGRAMS = $(GAMES) -!end -!begin am_begin -GAMES = -!end - -# make install for Unix. -!begin gtk -install: - for i in $(GAMES); do \ - $(INSTALL_PROGRAM) -m 755 $(BINPREFIX)$$i $(DESTDIR)$(gamesdir)/$(BINPREFIX)$$i \ - || exit 1; \ - done -!end -!begin nestedvm -%.tmpdir/PuzzleEngine.class: %.mips - mkdir -p $(patsubst %.mips,%,$<).tmpdir - cd $(patsubst %.mips,%,$<).tmpdir && \ - java -cp $(NESTEDVM)/build:$(NESTEDVM)/upstream/build/classgen/build \ - org.ibex.nestedvm.Compiler -outformat class -d . \ - PuzzleEngine ../$< - -org: - mkdir -p org/ibex/nestedvm/util - cp $(NESTEDVM)/build/org/ibex/nestedvm/Registers.class org/ibex/nestedvm - cp $(NESTEDVM)/build/org/ibex/nestedvm/UsermodeConstants.class org/ibex/nestedvm - cp $(NESTEDVM)/build/org/ibex/nestedvm/Runtime*.class org/ibex/nestedvm - cp $(NESTEDVM)/build/org/ibex/nestedvm/util/Platform*.class org/ibex/nestedvm/util - cp $(NESTEDVM)/build/org/ibex/nestedvm/util/Seekable*.class org/ibex/nestedvm/util - -applet.manifest: - echo "Main-Class: PuzzleApplet" >applet.manifest - -PuzzleApplet.class: PuzzleApplet.java org - javac -source 1.7 -target 1.7 PuzzleApplet.java - -%.jar: %.tmpdir/PuzzleEngine.class PuzzleApplet.class applet.manifest org - cd $(patsubst %.jar,%,$@).tmpdir && ln -s ../applet.manifest ../org ../PuzzleApplet*.class . - cd $(patsubst %.jar,%,$@).tmpdir && jar cfm ../$@ applet.manifest PuzzleEngine.class PuzzleApplet*.class org - echo '' >$*.html -!end - -# A benchmarking and testing target for the GTK puzzles. -!begin gtk -test: benchmark.html benchmark.txt - -benchmark.html: benchmark.txt benchmark.pl - ./benchmark.pl benchmark.txt > $@ - -benchmark.txt: benchmark.sh $(GAMES) - ./benchmark.sh > $@ - -!end -!begin am -test: benchmark.html benchmark.txt - -benchmark.html: benchmark.txt benchmark.pl - ./benchmark.pl benchmark.txt > $@ - -benchmark.txt: benchmark.sh $(GAMES) - ./benchmark.sh > $@ -!end diff --git a/blackbox.R b/blackbox.R deleted file mode 100644 index 1162252..0000000 --- a/blackbox.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -blackbox : [X] GTK COMMON blackbox blackbox-icon|no-icon - -blackbox : [G] WINDOWS COMMON blackbox blackbox.res|noicon.res - -ALL += blackbox[COMBINED] - -!begin am gtk -GAMES += blackbox -!end - -!begin >list.c - A(blackbox) \ -!end - -!begin >gamedesc.txt -blackbox:blackbox.exe:Black Box:Ball-finding puzzle:Find the hidden balls in the box by bouncing laser beams off them. -!end diff --git a/bridges.R b/bridges.R deleted file mode 100644 index 75df309..0000000 --- a/bridges.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -BRIDGES_EXTRA = dsf findloop - -bridges : [X] GTK COMMON bridges BRIDGES_EXTRA bridges-icon|no-icon - -bridges : [G] WINDOWS COMMON bridges BRIDGES_EXTRA bridges.res|noicon.res - -ALL += bridges[COMBINED] BRIDGES_EXTRA - -!begin am gtk -GAMES += bridges -!end - -!begin >list.c - A(bridges) \ -!end - -!begin >gamedesc.txt -bridges:bridges.exe:Bridges:Bridge-placing puzzle:Connect all the islands with a network of bridges. -!end diff --git a/cmake/glob-symlinks.py b/cmake/glob-symlinks.py new file mode 100755 index 0000000..23a869c --- /dev/null +++ b/cmake/glob-symlinks.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +# Helper script used by the NestedVM cmake build script. +# +# Usage: glob-symlinks.py [ ...] +# +# Each pair of command-line arguments is treated as a source +# directory, followed by either a single filename or a wildcard. +# +# The result is to create symlinks in the program's working directory +# mirroring all the files matched by the filenames/wildcards, each +# pointing at the appropriate source directory. +# +# For example, this command +# glob-symlinks.py /foo \*.txt /bar wibble.blah +# might create symlinks as follows: +# this.txt -> /foo/this.txt +# that.txt -> /foo/that.txt +# wibble.blah -> /bar/wibble.blah +# +# CMake could mostly do this itself, except that some of the files +# that need symlinking during the NestedVM build (to make a tree that +# we archive up into a .jar file) are Java class files with some +# '$suffix' in the name, and CMake doesn't escape the $ signs, so that +# the suffix vanishes during shell expansion. + +import sys +import os +import glob + +def get_arg_pairs(): + args = iter(sys.argv) + next(args) # skip program name + while True: + try: + yield next(args), next(args) + except StopIteration: + break + +def get_globbed_pairs(): + for srcdir, pattern in get_arg_pairs(): + if glob.escape(pattern) == pattern: + # Assume that unglobbed filenames exist + #print("non-glob:", srcdir, pattern) + yield srcdir, pattern + else: + #print("globbing:", srcdir, pattern) + prefix = srcdir + "/" + for filename in glob.iglob(prefix + pattern): + assert filename.startswith(prefix) + filename = filename[len(prefix):] + #print(" ->", srcdir, filename) + yield srcdir, filename + +for srcdir, filename in get_globbed_pairs(): + dirname = os.path.dirname(filename) + if len(dirname) > 0: + try: + os.makedirs(dirname) + except FileExistsError: + pass + try: + os.symlink(os.path.join(srcdir, filename), filename) + except FileExistsError: + pass diff --git a/cmake/nestedvm-toolchain.cmake b/cmake/nestedvm-toolchain.cmake new file mode 100644 index 0000000..337410c --- /dev/null +++ b/cmake/nestedvm-toolchain.cmake @@ -0,0 +1,10 @@ +SET(CMAKE_SYSTEM_NAME NestedVM) +SET(CMAKE_SYSTEM_PROCESSOR mips) + +SET(CMAKE_C_COMPILER ${NESTEDVM}/upstream/install/bin/mips-unknown-elf-gcc) + +SET(CMAKE_FIND_ROOT_PATH ${NESTEDVM}/upstream/install) +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/cmake/platforms/emscripten.cmake b/cmake/platforms/emscripten.cmake new file mode 100644 index 0000000..d6b5cd2 --- /dev/null +++ b/cmake/platforms/emscripten.cmake @@ -0,0 +1,47 @@ +set(platform_common_sources emcc.c) +set(platform_gui_libs) +set(platform_libs) +set(CMAKE_EXECUTABLE_SUFFIX ".js") + +set(emcc_export_list + # Event handlers for mouse and keyboard input + _mouseup + _mousedown + _mousemove + _key + # Callback when the program activates timing + _timer_callback + # Callback from button presses in the UI outside the canvas + _command + # Game-saving and game-loading functions + _get_save_file + _free_save_file + _load_game + # Callbacks to return values from dialog boxes + _dlg_return_sval + _dlg_return_ival + # Callbacks when the resizing controls are used + _resize_puzzle + _restore_puzzle_size + # Main program, run at initialisation time + _main) + +list(TRANSFORM emcc_export_list PREPEND \") +list(TRANSFORM emcc_export_list APPEND \") +string(JOIN "," emcc_export_string ${emcc_export_list}) +set(CMAKE_C_LINK_FLAGS "-s ASM_JS=1 -s EXPORTED_FUNCTIONS='[${emcc_export_string}]'") +message("link=${CMAKE_C_LINK_EXECUTABLE}") + +set(build_cli_programs FALSE) + +function(get_platform_puzzle_extra_source_files OUTVAR NAME) + set(${OUTVAR} PARENT_SCOPE) +endfunction() + +function(set_platform_puzzle_target_properties NAME TARGET) + em_link_pre_js(${TARGET} ${CMAKE_SOURCE_DIR}/emccpre.js) + em_link_js_library(${TARGET} ${CMAKE_SOURCE_DIR}/emcclib.js) +endfunction() + +function(build_platform_extras) +endfunction() diff --git a/cmake/platforms/nestedvm.cmake b/cmake/platforms/nestedvm.cmake new file mode 100644 index 0000000..e5de2ee --- /dev/null +++ b/cmake/platforms/nestedvm.cmake @@ -0,0 +1,60 @@ +set(platform_common_sources nestedvm.c printing.c) +set(platform_libs -lm) + +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/applet.manifest + "Main-Class: PuzzleApplet\n") + +include(FindJava) +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/PuzzleApplet.class + COMMAND ${Java_JAVAC_EXECUTABLE} + -source 1.7 -target 1.7 -d . -cp ${NESTEDVM}/build + ${CMAKE_SOURCE_DIR}/PuzzleApplet.java + DEPENDS ${CMAKE_SOURCE_DIR}/PuzzleApplet.java) + +function(get_platform_puzzle_extra_source_files OUTVAR NAME) + set(${OUTVAR} PARENT_SCOPE) +endfunction() + +function(set_platform_puzzle_target_properties NAME TARGET) + set(build_subdir ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}-tmp) + + add_custom_command(OUTPUT ${build_subdir} + COMMAND ${CMAKE_COMMAND} -E make_directory ${build_subdir}) + add_custom_command(OUTPUT ${build_subdir}/PuzzleApplet.class + COMMAND ${CMAKE_SOURCE_DIR}/cmake/glob-symlinks.py + ${CMAKE_BINARY_DIR} applet.manifest + ${CMAKE_BINARY_DIR} PuzzleApplet\\*.class + ${NESTEDVM}/build org/ibex/nestedvm/Registers.class + ${NESTEDVM}/build org/ibex/nestedvm/UsermodeConstants.class + ${NESTEDVM}/build org/ibex/nestedvm/Runtime*.class + ${NESTEDVM}/build org/ibex/nestedvm/util/Platform\\*.class + ${NESTEDVM}/build org/ibex/nestedvm/util/Seekable\\*.class + WORKING_DIRECTORY ${build_subdir} + DEPENDS + ${build_subdir} + ${CMAKE_BINARY_DIR}/PuzzleApplet.class + ${CMAKE_SOURCE_DIR}/cmake/glob-symlinks.py) + + add_custom_command(OUTPUT ${build_subdir}/PuzzleEngine.class + COMMAND ${Java_JAVA_EXECUTABLE} + -cp ${NESTEDVM}/build:${NESTEDVM}/upstream/build/classgen/build + org.ibex.nestedvm.Compiler -outformat class -d . + PuzzleEngine ${CMAKE_CURRENT_BINARY_DIR}/${EXENAME} + DEPENDS + ${build_subdir} + ${CMAKE_CURRENT_BINARY_DIR}/${EXENAME} + WORKING_DIRECTORY ${build_subdir}) + + add_custom_target(${TARGET}-jar ALL + COMMAND ${Java_JAR_EXECUTABLE} + cfm ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.jar + applet.manifest PuzzleEngine.class PuzzleApplet*.class org + WORKING_DIRECTORY ${build_subdir} + DEPENDS + ${CMAKE_BINARY_DIR}/PuzzleApplet.class + ${build_subdir}/PuzzleApplet.class + ${build_subdir}/PuzzleEngine.class) +endfunction() + +function(build_platform_extras) +endfunction() diff --git a/cmake/platforms/osx.cmake b/cmake/platforms/osx.cmake new file mode 100644 index 0000000..4577a73 --- /dev/null +++ b/cmake/platforms/osx.cmake @@ -0,0 +1,58 @@ +set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) +find_program(HALIBUT halibut REQUIRED) +set(CPACK_GENERATOR DragNDrop) +set(CPACK_PACKAGE_FILE_NAME Puzzles) +set(CPACK_DMG_VOLUME_NAME "Simon Tatham's Puzzle Collection") +include(CPack) +set(build_individual_puzzles FALSE) + +function(get_platform_puzzle_extra_source_files OUTVAR NAME) + set(${OUTVAR} PARENT_SCOPE) +endfunction() + +function(set_platform_puzzle_target_properties NAME TARGET) +endfunction() + +function(build_platform_extras) + write_generated_games_header() + + set(resources + ${CMAKE_CURRENT_SOURCE_DIR}/osx/Puzzles.icns) + set_source_files_properties(${resources} PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) + + add_executable(puzzles MACOSX_BUNDLE + osx.m list.c ${puzzle_sources} + ${resources}) + + set_target_properties(puzzles PROPERTIES + OUTPUT_NAME Puzzles + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/osx/Info.plist) + + target_compile_definitions(puzzles PRIVATE COMBINED) + target_include_directories(puzzles PRIVATE ${generated_include_dir}) + target_link_libraries(puzzles common ${platform_gui_libs} ${platform_libs} + "-framework Cocoa") + + get_property(bundle_basename TARGET puzzles PROPERTY OUTPUT_NAME) + set(help_dir ${CMAKE_CURRENT_BINARY_DIR}/${bundle_basename}.app/Contents/Resources/Help) + message(${help_dir}) + add_custom_command(OUTPUT ${help_dir} + COMMAND ${CMAKE_COMMAND} -E make_directory ${help_dir} + DEPENDS puzzles) + add_custom_command(OUTPUT ${help_dir}/index.html + COMMAND ${HALIBUT} --html + ${CMAKE_CURRENT_SOURCE_DIR}/osx-help.but + ${CMAKE_CURRENT_SOURCE_DIR}/puzzles.but + DEPENDS + ${help_dir} + ${CMAKE_CURRENT_SOURCE_DIR}/osx-help.but + ${CMAKE_CURRENT_SOURCE_DIR}/puzzles.but + WORKING_DIRECTORY ${help_dir}) + add_custom_target(osx_help ALL + DEPENDS ${help_dir}/index.html) + + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Puzzles.app + USE_SOURCE_PERMISSIONS + DESTINATION .) +endfunction() diff --git a/cmake/platforms/unix.cmake b/cmake/platforms/unix.cmake new file mode 100644 index 0000000..1bed675 --- /dev/null +++ b/cmake/platforms/unix.cmake @@ -0,0 +1,68 @@ +find_package(PkgConfig REQUIRED) + +set(PUZZLES_GTK_FOUND FALSE) +macro(try_gtk_package VER PACKAGENAME) + if(NOT PUZZLES_GTK_FOUND AND + (NOT DEFINED PUZZLES_GTK_VERSION OR + PUZZLES_GTK_VERSION STREQUAL ${VER})) + pkg_check_modules(GTK ${PACKAGENAME}) + if(GTK_FOUND) + set(PUZZLES_GTK_FOUND TRUE) + endif() + endif() +endmacro() + +try_gtk_package(3 gtk+-3.0) +try_gtk_package(2 gtk+-2.0) + +if(NOT PUZZLES_GTK_FOUND) + message(FATAL_ERROR "Unable to find any usable version of GTK.") +endif() + +include_directories(${GTK_INCLUDE_DIRS}) +link_directories(${GTK_LIBRARY_DIRS}) + +set(platform_common_sources gtk.c printing.c) +set(platform_gui_libs ${GTK_LIBRARIES}) + +set(platform_libs -lm) + +set(build_icons TRUE) + +function(try_append_cflag flag) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}") + try_compile(compile_passed ${CMAKE_BINARY_DIR} + SOURCES ${CMAKE_SOURCE_DIR}/cmake/testbuild.c + OUTPUT_VARIABLE test_compile_output + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${GTK_INCLUDE_DIRS}") + if(compile_passed) + set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} PARENT_SCOPE) + endif() +endfunction() +if (CMAKE_C_COMPILER_ID MATCHES "GNU" OR + CMAKE_C_COMPILER_ID MATCHES "Clang") + try_append_cflag(-Wall) + try_append_cflag(-Werror) + try_append_cflag(-std=c89) + try_append_cflag(-pedantic) + try_append_cflag(-Wwrite-strings) +endif() + +function(get_platform_puzzle_extra_source_files OUTVAR NAME) + if(build_icons AND EXISTS ${CMAKE_SOURCE_DIR}/icons/${NAME}.sav) + build_icon(${NAME}) + set(c_icon_file ${CMAKE_BINARY_DIR}/icons/${NAME}-icon.c) + else() + set(c_icon_file ${CMAKE_SOURCE_DIR}/no-icon.c) + endif() + + set(${OUTVAR} ${c_icon_file} PARENT_SCOPE) +endfunction() + +function(set_platform_puzzle_target_properties NAME TARGET) + install(TARGETS ${TARGET}) +endfunction() + +function(build_platform_extras) +endfunction() diff --git a/cmake/platforms/windows.cmake b/cmake/platforms/windows.cmake new file mode 100644 index 0000000..dd27148 --- /dev/null +++ b/cmake/platforms/windows.cmake @@ -0,0 +1,40 @@ +set(platform_common_sources windows.c printing.c) + +set(platform_gui_libs + user32.lib gdi32.lib comctl32.lib comdlg32.lib winspool.lib) + +set(platform_libs) + +add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + +function(get_platform_puzzle_extra_source_files OUTVAR NAME) + set(${OUTVAR} ${CMAKE_SOURCE_DIR}/puzzles.rc PARENT_SCOPE) +endfunction() + +function(set_platform_puzzle_target_properties NAME TARGET) + if(DEFINED ICO_DIR AND EXISTS ${ICO_DIR}/${NAME}.ico) + target_compile_definitions(${TARGET} PRIVATE ICON_FILE=\"${ICO_DIR}/${NAME}.ico\") + endif() + set_target_properties(${TARGET} PROPERTIES WIN32_EXECUTABLE ON) +endfunction() + +function(build_platform_extras) + write_generated_games_header() + + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/gamedesc.txt "") + list(SORT puzzle_names) + foreach(name ${puzzle_names}) + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/gamedesc.txt "\ +${name}:\ +${exename_${name}}.exe:\ +${displayname_${name}}:\ +${description_${name}}:\ +${objective_${name}}\n") + endforeach() + + add_executable(puzzles windows.c list.c ${puzzle_sources}) + target_compile_definitions(puzzles PRIVATE COMBINED) + target_include_directories(puzzles PRIVATE ${generated_include_dir}) + target_link_libraries(puzzles common ${platform_gui_libs} ${platform_libs}) + set_target_properties(puzzles PROPERTIES WIN32_EXECUTABLE ON) +endfunction() diff --git a/cmake/setup.cmake b/cmake/setup.cmake new file mode 100644 index 0000000..8afa455 --- /dev/null +++ b/cmake/setup.cmake @@ -0,0 +1,133 @@ +set(build_individual_puzzles TRUE) +set(build_cli_programs TRUE) +set(build_icons FALSE) +set(need_c_icons FALSE) + +# Include one of platforms/*.cmake to define platform-specific stuff. +# Each of these is expected to: +# - define get_platform_puzzle_extra_source_files(), used below +# - define set_platform_puzzle_target_properties(), used below +# - define build_platform_extras(), called from the top-level CMakeLists.txt +# - override the above build_* settings, if necessary +if(CMAKE_SYSTEM_NAME MATCHES "Windows") + include(cmake/platforms/windows.cmake) +elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") + include(cmake/platforms/osx.cmake) +elseif(CMAKE_SYSTEM_NAME MATCHES "NestedVM") + include(cmake/platforms/nestedvm.cmake) +elseif(CMAKE_C_COMPILER MATCHES "emcc") + include(cmake/platforms/emscripten.cmake) +else() # assume Unix + include(cmake/platforms/unix.cmake) +endif() + +# Accumulate lists of the puzzles' bare names and source file +# locations, for use in build_platform_extras() implementations when +# they want to build things based on all the puzzles at once. +set(puzzle_names) +set(puzzle_sources) + +include(icons/icons.cmake) + +# The main function called from the top-level CMakeLists.txt to define +# each puzzle. +function(puzzle NAME) + cmake_parse_arguments(OPT + "" "DISPLAYNAME;DESCRIPTION;OBJECTIVE;WINDOWS_EXE_NAME" "" ${ARGN}) + + if(NOT DEFINED OPT_WINDOWS_EXE_NAME) + set(OPT_WINDOWS_EXE_NAME ${NAME}) + endif() + + if (CMAKE_SYSTEM_NAME MATCHES "Windows") + set(EXENAME ${OPT_WINDOWS_EXE_NAME}) + else() + set(EXENAME ${NAME}) + endif() + + set(exename_${NAME} ${EXENAME} PARENT_SCOPE) + set(displayname_${NAME} ${OPT_DISPLAYNAME} PARENT_SCOPE) + set(description_${NAME} ${OPT_DESCRIPTION} PARENT_SCOPE) + set(objective_${NAME} ${OPT_OBJECTIVE} PARENT_SCOPE) + + set(official TRUE) + if(NAME STREQUAL nullgame) + # nullgame is not a playable puzzle; it has to be built (to prove + # it still can build), but not installed, or included in the main + # list of puzzles, or compiled into all-in-one binaries, etc. In + # other words, it's not "officially" part of the puzzle + # collection. + set(official FALSE) + endif() + if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR}/unfinished) + # The same goes for puzzles in the 'unfinished' subdirectory, + # although we make an exception if configured to on the command + # line. + list(FIND PUZZLES_ENABLE_UNFINISHED ${NAME} enable_this_one) + if(enable_this_one EQUAL -1) + set(official FALSE) + endif() + endif() + + if (official) + set(puzzle_names ${puzzle_names} ${NAME} PARENT_SCOPE) + set(puzzle_sources ${puzzle_sources} ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}.c PARENT_SCOPE) + endif() + + get_platform_puzzle_extra_source_files(extra_files ${NAME}) + + if (build_individual_puzzles) + add_executable(${EXENAME} ${NAME}.c ${extra_files}) + target_link_libraries(${EXENAME} + common ${platform_gui_libs} ${platform_libs}) + set_platform_puzzle_target_properties(${NAME} ${EXENAME}) + endif() +endfunction() + +# The main function called from the top-level CMakeLists.txt to define +# a command-line helper tool. +function(cliprogram NAME) + cmake_parse_arguments(OPT + "" "COMPILE_DEFINITIONS" "" ${ARGN}) + + if(build_cli_programs) + add_executable(${NAME} ${CMAKE_SOURCE_DIR}/nullfe.c + ${OPT_UNPARSED_ARGUMENTS}) + target_link_libraries(${NAME} common ${platform_libs}) + if(OPT_COMPILE_DEFINITIONS) + target_compile_definitions(${NAME} PRIVATE ${OPT_COMPILE_DEFINITIONS}) + endif() + endif() +endfunction() + +# A small wrapper around cliprogram, taking advantage of the common +# formula that puzzle 'foo' often comes with 'foosolver'. +function(solver NAME) + cliprogram(${NAME}solver ${puzzle_src_prefix}${NAME}.c ${ARGN} + COMPILE_DEFINITIONS STANDALONE_SOLVER) +endfunction() + +function(write_generated_games_header) + set(generated_include_dir ${CMAKE_CURRENT_BINARY_DIR}/include) + set(generated_include_dir ${generated_include_dir} PARENT_SCOPE) + + file(MAKE_DIRECTORY ${generated_include_dir}) + file(WRITE ${generated_include_dir}/generated-games.h "") + list(SORT puzzle_names) + foreach(name ${puzzle_names}) + file(APPEND ${generated_include_dir}/generated-games.h "GAME(${name})\n") + endforeach() +endfunction() + +# This has to be run from the unfinished subdirectory, so that the +# updates to puzzle_names etc will be propagated to the top-level scope. +macro(export_variables_to_parent_scope) + set(puzzle_names ${puzzle_names} PARENT_SCOPE) + set(puzzle_sources ${puzzle_sources} PARENT_SCOPE) + foreach(name ${puzzle_names}) + set(exename_${name} ${exename_${name}} PARENT_SCOPE) + set(displayname_${name} ${displayname_${name}} PARENT_SCOPE) + set(description_${name} ${description_${name}} PARENT_SCOPE) + set(objective_${name} ${objective_${name}} PARENT_SCOPE) + endforeach() +endmacro() diff --git a/cmake/testbuild.c b/cmake/testbuild.c new file mode 100644 index 0000000..67a6879 --- /dev/null +++ b/cmake/testbuild.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +int dummy; diff --git a/cmake/windows-dummy-toolchain.cmake b/cmake/windows-dummy-toolchain.cmake new file mode 100644 index 0000000..493652b --- /dev/null +++ b/cmake/windows-dummy-toolchain.cmake @@ -0,0 +1,14 @@ +# Fake CMake toolchain file, good enough to make cmake's initial +# configuration think it's going to build for Windows, but not good +# enough to actually do any building. The purpose is so that I can run +# Puzzles's CMakeLists.txt in Windows mode as far as making +# gamedesc.txt. + +set(CMAKE_SYSTEM_NAME Windows) + +set(CMAKE_C_COMPILER /bin/false) +set(CMAKE_LINKER /bin/false) +set(CMAKE_MT /bin/false) +set(CMAKE_RC_COMPILER /bin/false) + +set(CMAKE_C_COMPILER_WORKS ON) diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 3a38c95..0000000 --- a/configure.ac +++ /dev/null @@ -1,85 +0,0 @@ -dnl Configure script for the Unix GTK build of puzzles. - -AC_INIT([puzzles], [6.66], [anakin@pobox.com]) -AC_CONFIG_SRCDIR([midend.c]) -AM_INIT_AUTOMAKE([foreign]) -AC_PROG_CC - -AC_ARG_WITH([gtk], - [AS_HELP_STRING([--with-gtk=VER], - [specify GTK version to use (`2' or `3')])], - [gtk_version_desired="$withval"], - [gtk_version_desired="any"]) - -case "$gtk_version_desired" in - 2 | 3 | any) ;; - yes) gtk_version_desired="any" ;; - *) AC_ERROR([Invalid GTK version specified]) -esac - -gtk=none - -case "$gtk_version_desired:$gtk" in - 3:none | any:none) - ifdef([AM_PATH_GTK_3_0],[ - AM_PATH_GTK_3_0([3.0.0], [gtk=3], []) - ],[AC_WARNING([generating configure script without GTK 3 autodetection])]) - ;; -esac - -case "$gtk_version_desired:$gtk" in - 2:none | any:none) - ifdef([AM_PATH_GTK_2_0],[ - AM_PATH_GTK_2_0([2.0.0], [gtk=2], []) - ],[AC_WARNING([generating configure script without GTK 2 autodetection])]) - ;; -esac - -if test "$gtk" = "none"; then - AC_MSG_ERROR([cannot build without GTK 2 or GTK 3]) -fi - -if test "x$GCC" = "xyes"; then - AC_MSG_CHECKING([for usable gcc warning flags]) - gccwarningflags= - for flag in -Wall -Werror -std=c89 -pedantic; do - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS$gccwarningflags $flag $GTK_CFLAGS" - LIBS="$GTK_LIBS $LIBS" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ - #include - #include - #include - #include - #include - #include - #include - #include - - #include - #include - - #include - #include - - #include - - #include - #include - #include - #include - ],[ - return 0; - ])], [gccwarningflags="$gccwarningflags $flag"], []) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - done - AC_MSG_RESULT($gccwarningflags) - CFLAGS="$CFLAGS$gccwarningflags" -fi - -AC_PROG_RANLIB -AC_PROG_INSTALL -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT diff --git a/cube.R b/cube.R deleted file mode 100644 index 85b081e..0000000 --- a/cube.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -cube : [X] GTK COMMON cube cube-icon|no-icon - -cube : [G] WINDOWS COMMON cube cube.res|noicon.res - -ALL += cube[COMBINED] - -!begin am gtk -GAMES += cube -!end - -!begin >list.c - A(cube) \ -!end - -!begin >gamedesc.txt -cube:cube.exe:Cube:Rolling cube puzzle:Pick up all the blue squares by rolling the cube over them. -!end diff --git a/devel.but b/devel.but index 8dbc462..7e7aa1f 100644 --- a/devel.but +++ b/devel.but @@ -4441,15 +4441,11 @@ So start by copying \c{nullgame.c} into your new source file. Then you'll gradually add functionality until the very boring Null Game turns into your real game. -Next you'll need to add your puzzle to the Makefiles, in order to -compile it conveniently. \e{Do not edit the Makefiles}: they are -created automatically by the script \c{mkfiles.pl}, from the file -called \c{Recipe}. Edit \c{Recipe}, and then re-run \c{mkfiles.pl}. - -Also, don't forget to add your puzzle to \c{list.c}: if you don't, -then it will still run fine on platforms which build each puzzle -separately, but Mac OS X and other monolithic platforms will not -include your new puzzle in their single binary. +Next you'll need to add your puzzle to the build scripts, in order to +compile it conveniently. Puzzles is a CMake project, so you do this by +adding a \cw{puzzle()} statement to CMakeLists.txt. Look at the +existing ones to see what those look like, and add one that looks +similar. Once your source file is building, you can move on to the fun bit. diff --git a/dominosa.R b/dominosa.R deleted file mode 100644 index b85e7dc..0000000 --- a/dominosa.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -DOMINOSA_EXTRA = laydomino dsf sort findloop - -dominosa : [X] GTK COMMON dominosa DOMINOSA_EXTRA dominosa-icon|no-icon - -dominosa : [G] WINDOWS COMMON dominosa DOMINOSA_EXTRA dominosa.res|noicon.res - -ALL += dominosa[COMBINED] DOMINOSA_EXTRA - -dominosasolver : [U] dominosa[STANDALONE_SOLVER] DOMINOSA_EXTRA STANDALONE -dominosasolver : [C] dominosa[STANDALONE_SOLVER] DOMINOSA_EXTRA STANDALONE - -!begin am gtk -GAMES += dominosa -!end - -!begin >list.c - A(dominosa) \ -!end - -!begin >gamedesc.txt -dominosa:dominosa.exe:Dominosa:Domino tiling puzzle:Tile the rectangle with a full set of dominoes. -!end diff --git a/emccx.json b/emccx.json deleted file mode 100644 index bdab346..0000000 --- a/emccx.json +++ /dev/null @@ -1,33 +0,0 @@ -// -*- js -*- -// -// List of entry points exported by the C side of the Emscripten -// puzzle builds. Passed in to emcc via the option '-s -// EXPORTED_FUNCTIONS=[list]'. -// -// This file isn't actually a valid list in its current state, since -// emcc doesn't like comments or newlines. However, it's a nicer -// source form to keep the comments and newlines in, so we sed them -// away at compile time. -[ - // Event handlers for mouse and keyboard input - '_mouseup', - '_mousedown', - '_mousemove', - '_key', - // Callback when the program activates timing - '_timer_callback', - // Callback from button presses in the UI outside the canvas - '_command', - // Game-saving and game-loading functions - '_get_save_file', - '_free_save_file', - '_load_game', - // Callbacks to return values from dialog boxes - '_dlg_return_sval', - '_dlg_return_ival', - // Callbacks when the resizing controls are used - '_resize_puzzle', - '_restore_puzzle_size', - // Main program, run at initialisation time - '_main' -] diff --git a/fifteen.R b/fifteen.R deleted file mode 100644 index b2292ac..0000000 --- a/fifteen.R +++ /dev/null @@ -1,22 +0,0 @@ -# -*- makefile -*- - -fifteen : [X] GTK COMMON fifteen fifteen-icon|no-icon - -fifteen : [G] WINDOWS COMMON fifteen fifteen.res|noicon.res - -fifteensolver : [U] fifteen[STANDALONE_SOLVER] STANDALONE -fifteensolver : [C] fifteen[STANDALONE_SOLVER] STANDALONE - -ALL += fifteen[COMBINED] - -!begin am gtk -GAMES += fifteen -!end - -!begin >list.c - A(fifteen) \ -!end - -!begin >gamedesc.txt -fifteen:fifteen.exe:Fifteen:Sliding block puzzle:Slide the tiles around to arrange them into order. -!end diff --git a/filling.R b/filling.R deleted file mode 100644 index cffbafa..0000000 --- a/filling.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -FILLING_EXTRA = dsf - -fillingsolver : [U] filling[STANDALONE_SOLVER] FILLING_EXTRA STANDALONE -fillingsolver : [C] filling[STANDALONE_SOLVER] FILLING_EXTRA STANDALONE - -filling : [X] GTK COMMON filling FILLING_EXTRA filling-icon|no-icon - -filling : [G] WINDOWS COMMON filling FILLING_EXTRA filling.res|noicon.res - -ALL += filling[COMBINED] FILLING_EXTRA - -!begin am gtk -GAMES += filling -!end - -!begin >list.c - A(filling) \ -!end - -!begin >gamedesc.txt -filling:filling.exe:Filling:Polyomino puzzle:Mark every square with the area of its containing region. -!end diff --git a/flip.R b/flip.R deleted file mode 100644 index 03241f0..0000000 --- a/flip.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -FLIP_EXTRA = tree234 - -flip : [X] GTK COMMON flip FLIP_EXTRA flip-icon|no-icon - -flip : [G] WINDOWS COMMON flip FLIP_EXTRA flip.res|noicon.res - -ALL += flip[COMBINED] FLIP_EXTRA - -!begin am gtk -GAMES += flip -!end - -!begin >list.c - A(flip) \ -!end - -!begin >gamedesc.txt -flip:flip.exe:Flip:Tile inversion puzzle:Flip groups of squares to light them all up at once. -!end diff --git a/flood.R b/flood.R deleted file mode 100644 index 359bbb5..0000000 --- a/flood.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -flood : [X] GTK COMMON flood flood-icon|no-icon - -flood : [G] WINDOWS COMMON flood flood.res|noicon.res - -ALL += flood[COMBINED] - -!begin am gtk -GAMES += flood -!end - -!begin >list.c - A(flood) \ -!end - -!begin >gamedesc.txt -flood:flood.exe:Flood:Flood-filling puzzle:Turn the grid the same colour in as few flood fills as possible. -!end diff --git a/galaxies.R b/galaxies.R deleted file mode 100644 index 957e5da..0000000 --- a/galaxies.R +++ /dev/null @@ -1,28 +0,0 @@ -# -*- makefile -*- - -GALAXIES_EXTRA = dsf - -galaxies : [X] GTK COMMON galaxies GALAXIES_EXTRA galaxies-icon|no-icon - -galaxies : [G] WINDOWS COMMON galaxies GALAXIES_EXTRA galaxies.res|noicon.res - -galaxiessolver : [U] galaxies[STANDALONE_SOLVER] GALAXIES_EXTRA STANDALONE m.lib -galaxiessolver : [C] galaxies[STANDALONE_SOLVER] GALAXIES_EXTRA STANDALONE - -galaxiespicture : [U] galaxies[STANDALONE_PICTURE_GENERATOR] GALAXIES_EXTRA STANDALONE - + m.lib -galaxiespicture : [C] galaxies[STANDALONE_PICTURE_GENERATOR] GALAXIES_EXTRA STANDALONE - -ALL += galaxies[COMBINED] GALAXIES_EXTRA - -!begin am gtk -GAMES += galaxies -!end - -!begin >list.c - A(galaxies) \ -!end - -!begin >gamedesc.txt -galaxies:galaxies.exe:Galaxies:Symmetric polyomino puzzle:Divide the grid into rotationally symmetric regions each centred on a dot. -!end diff --git a/guess.R b/guess.R deleted file mode 100644 index 0e1a00c..0000000 --- a/guess.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -guess : [X] GTK COMMON guess guess-icon|no-icon - -guess : [G] WINDOWS COMMON guess guess.res|noicon.res - -ALL += guess[COMBINED] - -!begin am gtk -GAMES += guess -!end - -!begin >list.c - A(guess) \ -!end - -!begin >gamedesc.txt -guess:guess.exe:Guess:Combination-guessing puzzle:Guess the hidden combination of colours. -!end diff --git a/icons/Makefile b/icons/Makefile deleted file mode 100644 index 6465806..0000000 --- a/icons/Makefile +++ /dev/null @@ -1,162 +0,0 @@ -# Makefile for Puzzles icons. - -PUZZLES = blackbox bridges cube dominosa fifteen filling flip flood \ - galaxies guess inertia keen lightup loopy magnets map mines \ - net netslide palisade pattern pearl pegs range rect \ - samegame signpost singles sixteen slant solo tents towers \ - twiddle tracks undead unequal unruly untangle - -BASE = $(patsubst %,%-base.png,$(PUZZLES)) -WEB = $(patsubst %,%-web.png,$(PUZZLES)) - -IBASE = $(patsubst %,%-ibase.png,$(PUZZLES)) -IBASE4 = $(patsubst %,%-ibase4.png,$(PUZZLES)) -P96D24 = $(patsubst %,%-96d24.png,$(PUZZLES)) -P96D8 = $(patsubst %,%-96d8.png,$(PUZZLES)) -P96D4 = $(patsubst %,%-96d4.png,$(PUZZLES)) -P48D24 = $(patsubst %,%-48d24.png,$(PUZZLES)) -P48D8 = $(patsubst %,%-48d8.png,$(PUZZLES)) -P48D4 = $(patsubst %,%-48d4.png,$(PUZZLES)) -P32D24 = $(patsubst %,%-32d24.png,$(PUZZLES)) -P32D8 = $(patsubst %,%-32d8.png,$(PUZZLES)) -P32D4 = $(patsubst %,%-32d4.png,$(PUZZLES)) -P16D24 = $(patsubst %,%-16d24.png,$(PUZZLES)) -P16D8 = $(patsubst %,%-16d8.png,$(PUZZLES)) -P16D4 = $(patsubst %,%-16d4.png,$(PUZZLES)) -ICONS = $(patsubst %,%.ico,$(PUZZLES)) -CICONS = $(patsubst %,%-icon.c,$(PUZZLES)) -RC = $(patsubst %,%.rc,$(PUZZLES)) - -BIN = ../ -PIC = ./ - -# Work around newer ImageMagick unilaterally distorting colours when -# converting to PNG. -CSP = -set colorspace RGB - -base: $(BASE) -web: $(WEB) -pngicons: $(P96D24) $(P48D24) $(P32D24) $(P16D24) -winicons: $(ICONS) $(RC) -gtkicons: $(CICONS) -all: base web pngicons winicons gtkicons - -# Build the base puzzle screenshots from which all the other images -# are derived. Some of them involve showing a move animation -# part-way through. -fifteen-base.png : override REDO=0.3 -flip-base.png : override REDO=0.3 -netslide-base.png : override REDO=0.3 -sixteen-base.png : override REDO=0.3 -twiddle-base.png : override REDO=0.3 -$(BASE): %-base.png: $(BIN)% $(PIC)%.sav - $(PIC)screenshot.sh $(BIN)$* $(PIC)$*.sav $@ $(REDO) - -# Build the screenshots for the web, by scaling the original base -# images to a uniform size. -$(WEB): %-web.png: %-base.png - $(PIC)square.pl 150 5 $^ $@ - -# Build the base _icon_ images, by careful cropping of the base -# images: icons are very small so it's often necessary to zoom in -# on a smaller portion of the screenshot. -blackbox-ibase.png : override CROP=352x352 144x144+0+208 -bridges-ibase.png : override CROP=264x264 107x107+157+157 -dominosa-ibase.png : override CROP=304x272 152x152+152+0 -fifteen-ibase.png : override CROP=240x240 120x120+0+120 -filling-ibase.png : override CROP=256x256 133x133+14+78 -flip-ibase.png : override CROP=288x288 145x145+120+72 -galaxies-ibase.png : override CROP=288x288 165x165+0+0 -guess-ibase.png : override CROP=263x420 178x178+75+17 -inertia-ibase.png : override CROP=321x321 128x128+193+0 -keen-ibase.png : override CROP=288x288 96x96+24+120 -lightup-ibase.png : override CROP=256x256 112x112+144+0 -loopy-ibase.png : override CROP=257x257 113x113+0+0 -magnets-ibase.png : override CROP=264x232 96x96+36+100 -mines-ibase.png : override CROP=240x240 110x110+130+130 -net-ibase.png : override CROP=193x193 113x113+0+80 -netslide-ibase.png : override CROP=289x289 144x144+0+0 -palisade-ibase.png : override CROP=288x288 192x192+0+0 -pattern-ibase.png : override CROP=384x384 223x223+0+0 -pearl-ibase.png : override CROP=216x216 94x94+108+15 -pegs-ibase.png : override CROP=263x263 147x147+116+0 -range-ibase.png : override CROP=256x256 98x98+111+15 -rect-ibase.png : override CROP=205x205 115x115+90+0 -signpost-ibase.png : override CROP=240x240 98x98+23+23 -singles-ibase.png : override CROP=224x224 98x98+15+15 -sixteen-ibase.png : override CROP=288x288 144x144+144+144 -slant-ibase.png : override CROP=321x321 160x160+160+160 -solo-ibase.png : override CROP=481x481 145x145+24+24 -tents-ibase.png : override CROP=320x320 165x165+142+0 -towers-ibase.png : override CROP=300x300 102x102+151+6 -tracks-ibase.png : override CROP=246x246 118x118+6+6 -twiddle-ibase.png : override CROP=192x192 102x102+69+21 -undead-ibase.png : override CROP=416x480 192x192+16+80 -unequal-ibase.png : override CROP=208x208 104x104+104+104 -untangle-ibase.png : override CROP=320x320 164x164+3+116 -$(IBASE): %-ibase.png: %-base.png - $(PIC)crop.sh $^ $@ $(CROP) - -# Convert the full-size icon images to 4-bit colour, because that -# seems to work better than reducing it in 24 bits and then -# dithering. -$(IBASE4): %-ibase4.png: %-ibase.png - convert -colors 16 +dither $(CSP) -map $(PIC)win16pal.xpm $^ $@ - -# Build the 24-bit PNGs for the icons, at four sizes. -$(P96D24): %-96d24.png: %-ibase.png - $(PIC)square.pl 96 4 $^ $@ -$(P48D24): %-48d24.png: %-ibase.png - $(PIC)square.pl 48 4 $^ $@ -$(P32D24): %-32d24.png: %-ibase.png - $(PIC)square.pl 32 2 $^ $@ -$(P16D24): %-16d24.png: %-ibase.png - $(PIC)square.pl 16 1 $^ $@ - -# The 8-bit icon PNGs are just custom-paletted quantisations of the -# 24-bit ones. -$(P96D8) $(P48D8) $(P32D8) $(P16D8): %d8.png: %d24.png - convert -colors 256 $^ $@ - -# But the depth-4 images work better if we re-shrink from the -# ibase4 versions of the images, and then normalise the colours -# again afterwards. (They're still not very good, but my hope is -# that on most modern Windows machines this won't matter too -# much...) -$(P96D4): %-96d4.png: %-ibase4.png - $(PIC)square.pl 96 1 $^ $@-tmp2.png - convert -colors 16 $(CSP) -map $(PIC)win16pal.xpm $@-tmp2.png $@ - rm -f $@-tmp2.png -$(P48D4): %-48d4.png: %-ibase4.png - $(PIC)square.pl 48 1 $^ $@-tmp2.png - convert -colors 16 $(CSP) -map $(PIC)win16pal.xpm $@-tmp2.png $@ - rm -f $@-tmp2.png -$(P32D4): %-32d4.png: %-ibase.png - $(PIC)square.pl 32 1 $^ $@-tmp2.png - convert -colors 16 $(CSP) -map $(PIC)win16pal.xpm $@-tmp2.png $@ - rm -f $@-tmp2.png -$(P16D4): %-16d4.png: %-ibase.png - $(PIC)square.pl 16 1 $^ $@-tmp2.png - convert -colors 16 $(CSP) -map $(PIC)win16pal.xpm $@-tmp2.png $@ - rm -f $@-tmp2.png - -# Build the actual Windows icons themselves, by feeding all those -# PNGs to my icon builder script. -$(ICONS): %.ico: %-48d24.png %-48d8.png %-48d4.png \ - %-32d24.png %-32d8.png %-32d4.png \ - %-16d24.png %-16d8.png %-16d4.png - $(PIC)icon.pl -24 $*-48d24.png $*-32d24.png $*-16d24.png \ - -8 $*-48d8.png $*-32d8.png $*-16d8.png \ - -4 $*-48d4.png $*-32d4.png $*-16d4.png > $@ - -# Build the .RC files which bind the icons into the applications. -$(RC): %.rc: - echo '#include "puzzles.rc2"' > $@ - echo '200 ICON "$*.ico"' >> $@ - -# Build the GTK icon source files. -$(CICONS): %-icon.c: %-16d24.png %-32d24.png %-48d24.png %-96d24.png - $(PIC)cicon.pl $^ > $@ - -clean: - rm -f *.png *.ico *.rc *-icon.c diff --git a/icons/cicon.pl b/icons/cicon.pl index 3578bd3..a9f214e 100755 --- a/icons/cicon.pl +++ b/icons/cicon.pl @@ -5,12 +5,13 @@ $k = 0; @xpms = (); +$convert = shift @ARGV; foreach $f (@ARGV) { # XPM format is generated directly by ImageMagick, so that's easy # enough. We just have to adjust the declaration line so that it # has the right name, linkage and storage class. @lines = (); - open XPM, "convert $f xpm:- |"; + open XPM, "-|", $convert, $f, "xpm:-"; push @lines, $_ while ; close XPM; die "XPM from $f in unexpected format\n" unless $lines[1] =~ /^static.*\{$/; diff --git a/icons/crop.sh b/icons/crop.sh index 0d15d3c..5261709 100755 --- a/icons/crop.sh +++ b/icons/crop.sh @@ -13,25 +13,27 @@ # this script will give a build error and alert me to the fact that # I need to fiddle with the icon makefile. -infile="$1" -outfile="$2" -insize="$3" -crop="$4" +identify="$1" +convert="$2" +infile="$3" +outfile="$4" +insize="$5" +crop="$6" # Special case: if no input size or crop parameter was specified at # all, we just copy the input to the output file. -if test $# -lt 3; then +if test -z "$insize"; then cp "$infile" "$outfile" exit 0 fi # Check the input image size. -realsize=`identify -format %wx%h "$infile"` +realsize=$("$identify" -format %wx%h "$infile") if test "x$insize" != "x$realsize"; then echo "crop.sh: '$infile' has wrong initial size: $realsize != $insize" >&2 exit 1 fi # And crop. -convert -crop "$crop" "$infile" "$outfile" +"$convert" -crop "$crop" "$infile" "$outfile" diff --git a/icons/icon.pl b/icons/icon.pl index fcb1aa3..f5df10b 100755 --- a/icons/icon.pl +++ b/icons/icon.pl @@ -85,9 +85,12 @@ @dat = (); $depth = undef; +$convert = "convert"; foreach $_ (@ARGV) { if (/^-(24|8|4|1)$/) { $depth = $1; + } elsif (/^--convert=(.*)$/) { + $convert = $1; } elsif (defined $depth) { &readicon($_, $depth); } else { @@ -127,7 +130,7 @@ sub readicon { # point, to avoid having to do it ourselves (.BMP and hence # .ICO are bottom-up). my $data = []; - open IDATA, "convert -set colorspace sRGB -flip -depth 8 $filename rgba:- |"; + open IDATA, "-|", $convert, "-set", "colorspace", "sRGB", "-flip", "-depth", "8", $filename, "rgba:-"; push @$data, $rgb while (read IDATA,$rgb,4,0) == 4; close IDATA; # Check we have the right amount of data. diff --git a/icons/icons.cmake b/icons/icons.cmake new file mode 100644 index 0000000..5bd9285 --- /dev/null +++ b/icons/icons.cmake @@ -0,0 +1,237 @@ +if(NOT build_icons) + # This entire subdirectory does nothing on platforms where we can't + # build the icons in any case. + return() +endif() + +find_program(CONVERT convert REQUIRED) +find_program(IDENTIFY identify REQUIRED) + +# For puzzles which have animated moves, it's nice to show the sample +# image part way through the animation of a move. This setting will +# cause a 'redo' action immediately after loading the save file, +# causing the first undone move in the undo chain to be redone, and +# then it will stop this far through the move animation to take the +# screenshot. +set(fifteen_redo 0.3) +set(flip_redo 0.3) +set(netslide_redo 0.3) +set(sixteen_redo 0.3) +set(twiddle_redo 0.3) + +# For many puzzles, we'd prefer that the icon zooms in on a couple of +# squares of the playing area rather than trying to show the whole of +# a game. These settings configure that. Each one indicates the +# expected full size of the screenshot image, followed by the area we +# want to crop to. +# +# (The expected full size is a safety precaution: if a puzzle changes +# its default display size, then that won't match, and we'll get a +# build error here rather than silently continuing to take the wrong +# subrectangle of the resized puzzle display.) +set(blackbox_crop 352x352 144x144+0+208) +set(bridges_crop 264x264 107x107+157+157) +set(dominosa_crop 304x272 152x152+152+0) +set(fifteen_crop 240x240 120x120+0+120) +set(filling_crop 256x256 133x133+14+78) +set(flip_crop 288x288 145x145+120+72) +set(galaxies_crop 288x288 165x165+0+0) +set(guess_crop 263x420 178x178+75+17) +set(inertia_crop 321x321 128x128+193+0) +set(keen_crop 288x288 96x96+24+120) +set(lightup_crop 256x256 112x112+144+0) +set(loopy_crop 257x257 113x113+0+0) +set(magnets_crop 264x232 96x96+36+100) +set(mines_crop 240x240 110x110+130+130) +set(net_crop 193x193 113x113+0+80) +set(netslide_crop 289x289 144x144+0+0) +set(palisade_crop 288x288 192x192+0+0) +set(pattern_crop 384x384 223x223+0+0) +set(pearl_crop 216x216 94x94+108+15) +set(pegs_crop 263x263 147x147+116+0) +set(range_crop 256x256 98x98+111+15) +set(rect_crop 205x205 115x115+90+0) +set(signpost_crop 240x240 98x98+23+23) +set(singles_crop 224x224 98x98+15+15) +set(sixteen_crop 288x288 144x144+144+144) +set(slant_crop 321x321 160x160+160+160) +set(solo_crop 481x481 145x145+24+24) +set(tents_crop 320x320 165x165+142+0) +set(towers_crop 300x300 102x102+151+6) +set(tracks_crop 246x246 118x118+6+6) +set(twiddle_crop 192x192 102x102+69+21) +set(undead_crop 416x480 192x192+16+80) +set(unequal_crop 208x208 104x104+104+104) +set(untangle_crop 320x320 164x164+3+116) + +add_custom_target(icons) + +# All sizes of icon we make for any purpose. +set(all_icon_sizes 96 48 32 16) + +# Sizes of icon we put into the Windows .ico files. +set(win_icon_sizes 48 32 16) + +# Border thickness for each icon size. +set(border_96 4) +set(border_48 4) +set(border_32 2) +set(border_16 1) + +set(icon_srcdir ${CMAKE_SOURCE_DIR}/icons) +set(icon_bindir ${CMAKE_BINARY_DIR}/icons) + +function(build_icon name) + set(output_icon_files) + + # Compile the GTK puzzle binary without an icon, so that we can run + # it to generate a screenshot to make the icon out of. + add_executable(${NAME}-icon-maker ${NAME}.c + ${CMAKE_SOURCE_DIR}/no-icon.c) + target_link_libraries(${NAME}-icon-maker + common ${platform_gui_libs} ${platform_libs}) + set_target_properties(${NAME}-icon-maker PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${icon_bindir}) + + # Now run that binary to generate a screenshot of the puzzle in + # play, which will be the base image we make everything else out + # out. + if(DEFINED ${name}_redo) + set(redo_arg --redo ${name}_redo) + else() + set(redo_arg) + endif() + add_custom_command(OUTPUT ${icon_bindir}/${name}-base.png + COMMAND ${icon_bindir}/${name}-icon-maker + ${redo_arg} + --screenshot ${icon_bindir}/${name}-base.png + --load ${icon_srcdir}/${name}.sav + DEPENDS + ${name}-icon-maker) + + # Shrink it to a fixed-size square image for the web page, + # trimming boring border parts of the original image in the + # process. Done by square.pl. + add_custom_command(OUTPUT ${icon_bindir}/${name}-web.png + COMMAND ${icon_srcdir}/square.pl + ${CONVERT} 150 5 + ${icon_bindir}/${name}-base.png + ${icon_bindir}/${name}-web.png + DEPENDS + ${icon_srcdir}/square.pl + ${icon_bindir}/${name}-base.png) + list(APPEND output_icon_files ${icon_bindir}/${name}-web.png) + + # Make the base image for all the icons, by cropping out the most + # interesting part of the whole screenshot. + add_custom_command(OUTPUT ${icon_bindir}/${name}-ibase.png + COMMAND ${icon_srcdir}/crop.sh + ${IDENTIFY} ${CONVERT} + ${icon_bindir}/${name}-base.png + ${icon_bindir}/${name}-ibase.png + ${${name}_crop} + DEPENDS + ${icon_srcdir}/crop.sh + ${icon_bindir}/${name}-base.png) + + # Coerce that base image down to colour depth of 4 bits, using the + # fixed 16-colour Windows palette. We do this before shrinking the + # image, because I've found that gives better results than just + # doing it after. + add_custom_command(OUTPUT ${icon_bindir}/${name}-ibase4.png + COMMAND ${CONVERT} + -colors 16 + +dither + -set colorspace RGB + -map ${icon_srcdir}/win16pal.xpm + ${icon_bindir}/${name}-ibase.png + ${icon_bindir}/${name}-ibase4.png + DEPENDS + ${icon_srcdir}/win16pal.xpm + ${icon_bindir}/${name}-ibase.png) + + foreach(size ${all_icon_sizes}) + # Make a 24-bit icon image at each size, by shrinking the base + # icon image. + add_custom_command(OUTPUT ${icon_bindir}/${name}-${size}d24.png + COMMAND ${icon_srcdir}/square.pl + ${CONVERT} ${size} ${border_${size}} + ${icon_bindir}/${name}-ibase.png + ${icon_bindir}/${name}-${size}d24.png + DEPENDS + ${icon_srcdir}/square.pl + ${icon_bindir}/${name}-ibase.png) + list(APPEND output_icon_files ${icon_bindir}/${name}-${size}d24.png) + + # And reduce the colour depth of that one to make an 8-bit + # version. + add_custom_command(OUTPUT ${icon_bindir}/${name}-${size}d8.png + COMMAND ${CONVERT} + -colors 256 + ${icon_bindir}/${name}-${size}d24.png + ${icon_bindir}/${name}-${size}d8.png + DEPENDS ${icon_bindir}/${name}-${size}d24.png) + list(APPEND output_icon_files ${icon_bindir}/${name}-${size}d8.png) + endforeach() + + foreach(size ${win_icon_sizes}) + # 4-bit icons are only needed for Windows. We make each one by + # first shrinking the large 4-bit image we made above ... + add_custom_command(OUTPUT ${icon_bindir}/${name}-${size}d4pre.png + COMMAND ${icon_srcdir}/square.pl + ${CONVERT} ${size} ${border_${size}} + ${icon_bindir}/${name}-ibase4.png + ${icon_bindir}/${name}-${size}d4pre.png + DEPENDS + ${icon_srcdir}/square.pl + ${icon_bindir}/${name}-ibase4.png) + + # ... and then re-coercing the output back to 16 colours, since + # that shrink operation will have introduced intermediate colour + # values again. + add_custom_command(OUTPUT ${icon_bindir}/${name}-${size}d4.png + COMMAND ${CONVERT} + -colors 16 + +dither + -set colorspace RGB + -map ${icon_srcdir}/win16pal.xpm + ${icon_bindir}/${name}-${size}d4pre.png + ${icon_bindir}/${name}-${size}d4.png + DEPENDS ${icon_bindir}/${name}-${size}d4pre.png) + list(APPEND output_icon_files ${icon_bindir}/${name}-${size}d4.png) + endforeach() + + # Make the Windows icon. + set(icon_pl_args) + set(icon_pl_deps) + foreach(depth 24 8 4) + list(APPEND icon_pl_args -${depth}) + foreach(size ${win_icon_sizes}) + list(APPEND icon_pl_args ${icon_bindir}/${name}-${size}d${depth}.png) + list(APPEND icon_pl_deps ${icon_bindir}/${name}-${size}d${depth}.png) + endforeach() + endforeach() + add_custom_command(OUTPUT ${icon_bindir}/${name}.ico + COMMAND ${icon_srcdir}/icon.pl + --convert=${CONVERT} + ${icon_pl_args} > ${icon_bindir}/${name}.ico + DEPENDS + ${icon_srcdir}/icon.pl + ${icon_pl_deps}) + list(APPEND output_icon_files ${icon_bindir}/${name}.ico) + + # Make a C source file containing XPMs of all the 24-bit images. + set(cicon_pl_infiles) + foreach(size ${all_icon_sizes}) + list(APPEND cicon_pl_infiles ${icon_bindir}/${name}-${size}d24.png) + endforeach() + add_custom_command(OUTPUT ${icon_bindir}/${name}-icon.c + COMMAND ${icon_srcdir}/cicon.pl + ${CONVERT} ${cicon_pl_infiles} > ${icon_bindir}/${name}-icon.c + DEPENDS + ${icon_srcdir}/cicon.pl + ${cicon_pl_infiles}) + + add_custom_target(${name}-icons DEPENDS ${output_icon_files}) + add_dependencies(icons ${name}-icons) +endfunction() diff --git a/icons/screenshot.sh b/icons/screenshot.sh deleted file mode 100755 index 0e2a06e..0000000 --- a/icons/screenshot.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -# Generate a screenshot from a puzzle save file. Takes the -# following arguments, in order: -# -# - the name of the puzzle binary -# - the name of the save file -# - the name of the output image file -# - (optionally) the proportion of the next move to redo before -# taking the screenshot. -# -# This script requires access to an X server in order to run, but -# seems to work fine under xvfb-run if you haven't got a real one -# available (or if you don't want to use it for some reason). - -binary="$1" -save="$2" -image="$3" -if test "x$4" != "x"; then - redo="--redo $4" -else - redo= -fi - -"$binary" $redo --screenshot "$image" --load "$save" diff --git a/icons/square.pl b/icons/square.pl index 815b94b..8a9a4bf 100755 --- a/icons/square.pl +++ b/icons/square.pl @@ -8,7 +8,7 @@ # - the input image file name # - the output image file name. -($osize, $oborder, $infile, $outfile) = @ARGV; +($convert, $osize, $oborder, $infile, $outfile) = @ARGV; # Determine the input image's size. $ident = `identify -format "%w %h" $infile`; @@ -17,7 +17,7 @@ $ident =~ /(\d+) (\d+)/ or die "unable to get size for $infile\n"; # Read the input image data. $data = []; -open IDATA, "convert -depth 8 $infile rgb:- |"; +open IDATA, "-|", $convert, "-depth", "8", $infile, "rgb:-"; push @$data, $rgb while (read IDATA,$rgb,3,0) == 3; close IDATA; # Check we have the right amount of data. @@ -82,7 +82,7 @@ $oh = $yend - $ystart + 1; die "internal computation problem" if $ow != $oh; # should be square # Now write out the resulting image, and resize it appropriately. -open IDATA, "| convert -size ${ow}x${oh} -depth 8 -resize ${osize}x${osize}! rgb:- $outfile"; +open IDATA, "|-", $convert, "-size", "${ow}x${oh}", "-depth", "8", "-resize", "${osize}x${osize}!", "rgb:-", $outfile; for ($y = $ystart; $y <= $yend; $y++) { for ($x = $xstart; $x <= $xend; $x++) { if ($x >= 0 && $x < $w && $y >= 0 && $y < $h) { diff --git a/inertia.R b/inertia.R deleted file mode 100644 index e6e86be..0000000 --- a/inertia.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -inertia : [X] GTK COMMON inertia inertia-icon|no-icon - -inertia : [G] WINDOWS COMMON inertia inertia.res|noicon.res - -ALL += inertia[COMBINED] - -!begin am gtk -GAMES += inertia -!end - -!begin >list.c - A(inertia) \ -!end - -!begin >gamedesc.txt -inertia:inertia.exe:Inertia:Gem-collecting puzzle:Collect all the gems without running into any of the mines. -!end diff --git a/keen.R b/keen.R deleted file mode 100644 index 46bd09a..0000000 --- a/keen.R +++ /dev/null @@ -1,25 +0,0 @@ -# -*- makefile -*- - -KEEN_EXTRA = dsf LATIN -KEEN_EXTRA_SOLVER = dsf LATIN_SOLVER - -keen : [X] GTK COMMON keen KEEN_EXTRA keen-icon|no-icon - -keen : [G] WINDOWS COMMON keen KEEN_EXTRA keen.res|noicon.res - -keensolver : [U] keen[STANDALONE_SOLVER] KEEN_EXTRA_SOLVER STANDALONE -keensolver : [C] keen[STANDALONE_SOLVER] KEEN_EXTRA_SOLVER STANDALONE - -ALL += keen[COMBINED] KEEN_EXTRA - -!begin am gtk -GAMES += keen -!end - -!begin >list.c - A(keen) \ -!end - -!begin >gamedesc.txt -keen:keen.exe:Keen:Arithmetic Latin square puzzle:Complete the latin square in accordance with the arithmetic clues. -!end diff --git a/lightup.R b/lightup.R deleted file mode 100644 index a474de8..0000000 --- a/lightup.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -LIGHTUP_EXTRA = combi - -lightup : [X] GTK COMMON lightup LIGHTUP_EXTRA lightup-icon|no-icon - -lightup : [G] WINDOWS COMMON lightup LIGHTUP_EXTRA lightup.res|noicon.res - -lightupsolver : [U] lightup[STANDALONE_SOLVER] LIGHTUP_EXTRA STANDALONE -lightupsolver : [C] lightup[STANDALONE_SOLVER] LIGHTUP_EXTRA STANDALONE - -ALL += lightup[COMBINED] LIGHTUP_EXTRA - -!begin am gtk -GAMES += lightup -!end - -!begin >list.c - A(lightup) \ -!end - -!begin >gamedesc.txt -lightup:lightup.exe:Light Up:Light-bulb placing puzzle:Place bulbs to light up all the squares. -!end diff --git a/list.c b/list.c new file mode 100644 index 0000000..7e3318c --- /dev/null +++ b/list.c @@ -0,0 +1,21 @@ +/* + * list.c: List of pointers to puzzle structures, for monolithic + * platforms. + * + * This file depends on the header "generated-games.h", which is + * constructed by CMakeLists.txt. + */ + +#include "puzzles.h" + +#define GAME(x) extern const game x; +#include "generated-games.h" +#undef GAME + +#define GAME(x) &x, +const game *gamelist[] = { +#include "generated-games.h" +}; +#undef GAME + +const int gamecount = lenof(gamelist); diff --git a/loopy.R b/loopy.R deleted file mode 100644 index f445600..0000000 --- a/loopy.R +++ /dev/null @@ -1,31 +0,0 @@ -# -*- makefile -*- - -LOOPY_EXTRA = tree234 dsf grid penrose loopgen - -loopy : [X] GTK COMMON loopy LOOPY_EXTRA loopy-icon|no-icon - -loopy : [G] WINDOWS COMMON loopy LOOPY_EXTRA loopy.res|noicon.res - -loopysolver : [U] loopy[STANDALONE_SOLVER] LOOPY_EXTRA STANDALONE m.lib -loopysolver : [C] loopy[STANDALONE_SOLVER] LOOPY_EXTRA STANDALONE - -#penrose : [U] penrose[TEST_PENROSE] STANDALONE m.lib -#penrose : [C] penrose[TEST_PENROSE] STANDALONE - -#test-basis : [U] penrose[TEST_VECTORS] tree234 STANDALONE m.lib -#test-basis : [C] penrose[TEST_VECTORS] tree234 STANDALONE - - -ALL += loopy[COMBINED] LOOPY_EXTRA - -!begin am gtk -GAMES += loopy -!end - -!begin >list.c - A(loopy) \ -!end - -!begin >gamedesc.txt -loopy:loopy.exe:Loopy:Loop-drawing puzzle:Draw a single closed loop, given clues about number of adjacent edges. -!end diff --git a/magnets.R b/magnets.R deleted file mode 100644 index e55e474..0000000 --- a/magnets.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -MAGNETS_EXTRA = laydomino - -magnets : [X] GTK COMMON magnets MAGNETS_EXTRA magnets-icon|no-icon - -magnets : [G] WINDOWS COMMON magnets MAGNETS_EXTRA magnets.res|noicon.res - -magnetssolver : [U] magnets[STANDALONE_SOLVER] MAGNETS_EXTRA STANDALONE m.lib -magnetssolver : [C] magnets[STANDALONE_SOLVER] MAGNETS_EXTRA STANDALONE - -ALL += magnets[COMBINED] MAGNETS_EXTRA - -!begin am gtk -GAMES += magnets -!end - -!begin >list.c - A(magnets) \ -!end - -!begin >gamedesc.txt -magnets:magnets.exe:Magnets:Magnet-placing puzzle:Place magnets to satisfy the clues and avoid like poles touching. -!end diff --git a/makedist.sh b/makedist.sh deleted file mode 100755 index 22b4f5d..0000000 --- a/makedist.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh - -# Build a Unix source distribution from the Puzzles SVN area. -# -# Pass a version number argument to have the archive tagged with that -# version number. Otherwise, the script will not version-tag the -# archive at all. - -version="$1" - -if test "x$version" != "x"; then - arcsuffix="-$version" - ver="-DVER=$version" -else - arcsuffix= - ver= -fi - -perl mkfiles.pl -./mkauto.sh - -mkdir tmp.$$ -mkdir tmp.$$/puzzles$arcsuffix -mkdir tmp.$$/puzzles$arcsuffix/icons - -# Build Windows Help and text versions of the manual for convenience. -halibut --winhelp=puzzles.hlp --text=puzzles.txt puzzles.but - -# Build a text version of the HACKING document. -halibut --text=HACKING devel.but - -for i in *.c *.m *.h *.R *.rc *.but *.plist *.icns LICENCE README Recipe \ - *.rc2 mkfiles.pl Makefile Makefile.* \ - HACKING puzzles.txt puzzles.hlp puzzles.cnt puzzles.chm \ - icons/Makefile icons/*.sav icons/*.pl icons/*.sh icons/win16pal.xpm \ - icons/*.png icons/*.ico icons/*.rc icons/*.c \ - configure.ac mkauto.sh aclocal.m4 \ - configure depcomp install-sh missing compile; do - case $i in - */*) ln -s ../../../$i tmp.$$/puzzles$arcsuffix/$i;; - *) ln -s ../../$i tmp.$$/puzzles$arcsuffix/$i;; - esac -done - -tar -C tmp.$$ -chzf - puzzles$arcsuffix > ../puzzles$arcsuffix.tar.gz - -rm -rf tmp.$$ diff --git a/map.R b/map.R deleted file mode 100644 index 1e702aa..0000000 --- a/map.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -MAP_EXTRA = dsf - -map : [X] GTK COMMON map MAP_EXTRA map-icon|no-icon - -map : [G] WINDOWS COMMON map MAP_EXTRA map.res|noicon.res - -mapsolver : [U] map[STANDALONE_SOLVER] MAP_EXTRA STANDALONE m.lib -mapsolver : [C] map[STANDALONE_SOLVER] MAP_EXTRA STANDALONE - -ALL += map[COMBINED] MAP_EXTRA - -!begin am gtk -GAMES += map -!end - -!begin >list.c - A(map) \ -!end - -!begin >gamedesc.txt -map:map.exe:Map:Map-colouring puzzle:Colour the map so that adjacent regions are never the same colour. -!end diff --git a/mines.R b/mines.R deleted file mode 100644 index 275c76c..0000000 --- a/mines.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -MINES_EXTRA = tree234 - -mines : [X] GTK COMMON mines MINES_EXTRA mines-icon|no-icon - -mines : [G] WINDOWS COMMON mines MINES_EXTRA mines.res|noicon.res - -mineobfusc : [U] mines[STANDALONE_OBFUSCATOR] MINES_EXTRA STANDALONE -mineobfusc : [C] mines[STANDALONE_OBFUSCATOR] MINES_EXTRA STANDALONE - -ALL += mines[COMBINED] MINES_EXTRA - -!begin am gtk -GAMES += mines -!end - -!begin >list.c - A(mines) \ -!end - -!begin >gamedesc.txt -mines:mines.exe:Mines:Mine-finding puzzle:Find all the mines without treading on any of them. -!end diff --git a/mkauto.sh b/mkauto.sh deleted file mode 100755 index 297212a..0000000 --- a/mkauto.sh +++ /dev/null @@ -1,2 +0,0 @@ -#! /bin/sh -autoreconf -i && rm -rf autom4te.cache diff --git a/mkfiles.pl b/mkfiles.pl deleted file mode 100755 index d92bcca..0000000 --- a/mkfiles.pl +++ /dev/null @@ -1,1953 +0,0 @@ -#!/usr/bin/env perl -# -# Cross-platform Makefile generator. -# -# Reads the file `Recipe' to determine the list of generated -# executables and their component objects. Then reads the source -# files to compute #include dependencies. Finally, writes out the -# various target Makefiles. - -# PuTTY specifics which could still do with removing: -# - Mac makefile is not portabilised at all. Include directories -# are hardwired, and also the libraries are fixed. This is -# mainly because I was too scared to go anywhere near it. -# - sbcsgen.pl is still run at startup. - -# Other things undone: -# - special-define objects (foo.o[PREPROCSYMBOL]) are not -# supported in the mac or vcproj makefiles. - -use warnings; -use IO::Handle; -use Cwd; -use File::Basename; - -while ($#ARGV >= 0) { - if ($ARGV[0] eq "-U") { - # Convenience for Unix users: -U means that after we finish what - # we're doing here, we also run mkauto.sh and then 'configure'. So - # it's a one-stop shop for regenerating the actual end-product - # Unix makefile. - # - # Arguments supplied after -U go to configure. - $do_unix = 1; - shift @ARGV; - @confargs = @ARGV; - @ARGV = (); - } else { - die "unrecognised command-line argument '$ARGV[0]'\n"; - } -} - -@filestack = (); -$in = new IO::Handle; -open $in, "Recipe" or do { - # We want to deal correctly with being run from one of the - # subdirs in the source tree. So if we can't find Recipe here, - # try one level up. - chdir ".."; - open $in, "Recipe" or die "unable to open Recipe file\n"; -}; -push @filestack, $in; - -# HACK: One of the source files in `charset' is auto-generated by -# sbcsgen.pl. We need to generate that _now_, before attempting -# dependency analysis. -eval 'chdir "charset"; require "sbcsgen.pl"; chdir ".."'; - -@srcdirs = ("./"); - -$divert = undef; # ref to array of refs of scalars in which text is - # currently being put -$help = ""; # list of newline-free lines of help text -$project_name = "project"; # this is a good enough default -%makefiles = (); # maps makefile types to output makefile pathnames -%makefile_extra = (); # maps makefile types to extra Makefile text -%programs = (); # maps prog name + type letter to listref of objects/resources -%groups = (); # maps group name to listref of objects/resources - -@allobjs = (); # all object file names - -readinput: while (1) { - $in = $filestack[$#filestack]; - while (not defined ($_ = <$in>)) { - close $filestack[$#filestack]; - pop @filestack; - last readinput if 0 == scalar @filestack; - $in = $filestack[$#filestack]; - } - chomp; - @_ = split; - - # If we're gathering help text, keep doing so. - if (defined $divert) { - if ((defined $_[0]) && $_[0] eq "!end") { - $divert = undef; - } else { - for my $ref (@$divert) { - ${$ref} .= "$_\n"; - } - } - next; - } - # Skip comments and blank lines. - next if /^\s*#/ or scalar @_ == 0; - - if ($_[0] eq "!begin" and $_[1] eq "help") { $divert = [\$help]; next; } - if ($_[0] eq "!name") { $project_name = $_[1]; next; } - if ($_[0] eq "!srcdir") { push @srcdirs, $_[1]; next; } - if ($_[0] eq "!makefile" and &mfval($_[1])) { $makefiles{$_[1]}=$_[2]; next;} - if ($_[0] eq "!specialobj" and &mfval($_[1])) { $specialobj{$_[1]}->{$_[2]} = 1; next;} - if ($_[0] eq "!cflags" and &mfval($_[1])) { - ($rest = $_) =~ s/^\s*\S+\s+\S+\s+\S+\s*//; # find rest of input line - $rest = 1 if $rest eq ""; - $cflags{$_[1]}->{$_[2]} = $rest; - next; - } - if ($_[0] eq "!begin") { - my @args = @_; - shift @args; - $divert = []; - for my $component (@args) { - if ($component =~ /^>(.*)/) { - push @$divert, \$auxfiles{$1}; - } elsif ($component =~ /^([^_]*)(_.*)?$/ and &mfval($1)) { - push @$divert, \$makefile_extra{$component}; - } - } - next; - } - if ($_[0] eq "!include") { - @newfiles = (); - for ($i = 1; $i <= $#_; $i++) { - push @newfiles, (sort glob $_[$i]); - } - for ($i = $#newfiles; $i >= 0; $i--) { - $file = $newfiles[$i]; - $f = new IO::Handle; - open $f, "<$file" or die "unable to open include file '$file'\n"; - push @filestack, $f; - } - next; - } - - # Now we have an ordinary line. See if it's an = line, a : line - # or a + line. - @objs = @_; - - if ($_[0] eq "+") { - $listref = $lastlistref; - $prog = undef; - die "$.: unexpected + line\n" if !defined $lastlistref; - } elsif ($_[1] eq "=") { - $groups{$_[0]} = []; - $listref = $groups{$_[0]}; - $prog = undef; - shift @objs; # eat the group name - } elsif ($_[1] eq "+=") { - $groups{$_[0]} = [] if !defined $groups{$_[0]}; - $listref = $groups{$_[0]}; - $prog = undef; - shift @objs; # eat the group name - } elsif ($_[1] eq ":") { - $listref = []; - $prog = $_[0]; - shift @objs; # eat the program name - } else { - die "$.: unrecognised line type: '$_'\n"; - } - shift @objs; # eat the +, the = or the : - - while (scalar @objs > 0) { - $i = shift @objs; - if ($groups{$i}) { - foreach $j (@{$groups{$i}}) { unshift @objs, $j; } - } elsif (($i eq "[G]" or $i eq "[C]" or $i eq "[M]" or - $i eq "[X]" or $i eq "[U]" or $i eq "[MX]") and defined $prog) { - $type = substr($i,1,(length $i)-2); - } else { - if ($i =~ /\?$/) { - # Object files with a trailing question mark are optional: - # the build can proceed fine without them, so we only use - # them if their primary source files are present. - $i =~ s/\?$//; - $i = undef unless defined &finddep($i); - } elsif ($i =~ /\|/) { - # Object file descriptions containing a vertical bar are - # lists of choices: we use the _first_ one whose primary - # source file is present. - @options = split /\|/, $i; - $j = undef; - foreach $k (@options) { - $j=$k, last if defined &finddep($k); - } - die "no alternative found for $i\n" unless defined $j; - $i = $j; - } - if (defined $i) { - push @$listref, $i; - push @allobjs, $i; - } - } - } - if ($prog and $type) { - die "multiple program entries for $prog [$type]\n" - if defined $programs{$prog . "," . $type}; - $programs{$prog . "," . $type} = $listref; - } - $lastlistref = $listref; -} - -foreach $aux (sort keys %auxfiles) { - open AUX, ">$aux"; - print AUX $auxfiles{$aux}; - close AUX; -} - -# Find object file names with predefines (in square brackets after -# the module name), and decide on actual object names for them. -foreach $i (@allobjs) { - if ($i !~ /\[/) { - $objname{$i} = $i; - $srcname{$i} = $i; - $usedobjname{$i} = 1; - } -} -foreach $i (@allobjs) { - if ($i =~ /^(.*)\[([^\]]*)/) { - $defs{$i} = [ split ",",$2 ]; - $srcname{$i} = $s = $1; - $index = 1; - while (1) { - $maxlen = length $s; - $maxlen = 8 if $maxlen < 8; - $chop = $maxlen - length $index; - $chop = length $s if $chop > length $s; - $chop = 0 if $chop < 0; - $name = substr($s, 0, $chop) . $index; - $index++, next if $usedobjname{$name}; - $objname{$i} = $name; - $usedobjname{$name} = 1; - last; - } - } -} - -# Now retrieve the complete list of objects and resource files, and -# construct dependency data for them. While we're here, expand the -# object list for each program, and complain if its type isn't set. -@prognames = sort keys %programs; -%depends = (); -@scanlist = (); -foreach $i (@prognames) { - ($prog, $type) = split ",", $i; - # Strip duplicate object names. - $prev = ''; - @list = grep { $status = ($prev ne $_); $prev=$_; $status } - sort @{$programs{$i}}; - $programs{$i} = [@list]; - foreach $jj (@list) { - $j = $srcname{$jj}; - $file = &finddep($j); - if (defined $file) { - $depends{$jj} = [$file]; - push @scanlist, $file; - } - } -} - -# Scan each file on @scanlist and find further inclusions. -# Inclusions are given by lines of the form `#include "otherfile"' -# (system headers are automatically ignored by this because they'll -# be given in angle brackets). Files included by this method are -# added back on to @scanlist to be scanned in turn (if not already -# done). -# -# Resource scripts (.rc) can also include a file by means of a line -# ending `ICON "filename"'. Files included by this method are not -# added to @scanlist because they can never include further files. -# -# In this pass we write out a hash %further which maps a source -# file name into a listref containing further source file names. - -%further = (); -while (scalar @scanlist > 0) { - $file = shift @scanlist; - next if defined $further{$file}; # skip if we've already done it - $further{$file} = []; - $dirfile = &findfile($file); - open IN, "$dirfile" or die "unable to open source file $file\n"; - while () { - chomp; - /^\s*#include\s+\"([^\"]+)\"/ and do { - push @{$further{$file}}, $1; - push @scanlist, $1; - next; - }; - /ICON\s+\"([^\"]+)\"\s*$/ and do { - push @{$further{$file}}, $1; - next; - } - } - close IN; -} - -# Now we're ready to generate the final dependencies section. For -# each key in %depends, we must expand the dependencies list by -# iteratively adding entries from %further. -foreach $i (keys %depends) { - %dep = (); - @scanlist = @{$depends{$i}}; - foreach $i (@scanlist) { $dep{$i} = 1; } - while (scalar @scanlist > 0) { - $file = shift @scanlist; - foreach $j (@{$further{$file}}) { - if (!$dep{$j}) { - $dep{$j} = 1; - push @{$depends{$i}}, $j; - push @scanlist, $j; - } - } - } -# printf "%s: %s\n", $i, join ' ',@{$depends{$i}}; -} - -# Validation of input. - -sub mfval($) { - my ($type) = @_; - # Returns true if the argument is a known makefile type. Otherwise, - # prints a warning and returns false; - if (grep { $type eq $_ } - ("vc","vcproj","cygwin","borland","lcc","gtk","am","mpw","nestedvm","osx","wce","gnustep","emcc","clangcl")) { - return 1; - } - warn "$.:unknown makefile type '$type'\n"; - return 0; -} - -# Utility routines while writing out the Makefiles. - -sub dirpfx { - my ($path) = shift @_; - my ($sep) = shift @_; - my $ret = ""; - my $i; - while (($i = index $path, $sep) >= 0) { - $path = substr $path, ($i + length $sep); - $ret .= "..$sep"; - } - return $ret; -} - -sub findfile { - my ($name) = @_; - my $dir; - my $i; - my $outdir = undef; - unless (defined $findfilecache{$name}) { - $i = 0; - foreach $dir (@srcdirs) { - $outdir = $dir, $i++ if -f "$dir$name"; - } - die "multiple instances of source file $name\n" if $i > 1; - $findfilecache{$name} = (defined $outdir ? $outdir . $name : undef); - } - return $findfilecache{$name}; -} - -sub finddep { - my $j = shift @_; - my $file; - # Find the first dependency of an object. - - # Dependencies for "x" start with "x.c" or "x.m" (depending on - # which one exists). - # Dependencies for "x.res" start with "x.rc". - # Dependencies for "x.rsrc" start with "x.r". - # Both types of file are pushed on the list of files to scan. - # Libraries (.lib) don't have dependencies at all. - if ($j =~ /^(.*)\.res$/) { - $file = "$1.rc"; - } elsif ($j =~ /^(.*)\.rsrc$/) { - $file = "$1.r"; - } elsif ($j !~ /\./) { - $file = "$j.c"; - $file = "$j.m" unless &findfile($file); - } else { - # For everything else, we assume it's its own dependency. - $file = $j; - } - $file = undef unless &findfile($file); - return $file; -} - -sub objects { - my ($prog, $otmpl, $rtmpl, $ltmpl, $prefix, $dirsep) = @_; - my @ret; - my ($i, $x, $y); - ($otmpl, $rtmpl, $ltmpl) = map { defined $_ ? $_ : "" } ($otmpl, $rtmpl, $ltmpl); - @ret = (); - foreach $ii (@{$programs{$prog}}) { - $i = $objname{$ii}; - $x = ""; - if ($i =~ /^(.*)\.(res|rsrc)/) { - $y = $1; - ($x = $rtmpl) =~ s/X/$y/; - } elsif ($i =~ /^(.*)\.lib/) { - $y = $1; - ($x = $ltmpl) =~ s/X/$y/; - } elsif ($i !~ /\./) { - ($x = $otmpl) =~ s/X/$i/; - } - push @ret, $x if $x ne ""; - } - return join " ", @ret; -} - -sub special { - my ($prog, $suffix) = @_; - my @ret; - my ($i, $x, $y); - @ret = (); - foreach $ii (@{$programs{$prog}}) { - $i = $objname{$ii}; - if (substr($i, (length $i) - (length $suffix)) eq $suffix) { - push @ret, $i; - } - } - return join " ", @ret; -} - -sub splitline { - my ($line, $width, $splitchar) = @_; - my $result = ""; - my $len; - $len = (defined $width ? $width : 76); - $splitchar = (defined $splitchar ? $splitchar : '\\'); - while (length $line > $len) { - $line =~ /^(.{0,$len})\s(.*)$/ or $line =~ /^(.{$len,}?\s(.*)$/; - $result .= $1; - $result .= " ${splitchar}\n\t\t" if $2 ne ''; - $line = $2; - $len = 60; - } - return $result . $line; -} - -sub deps { - my ($otmpl, $rtmpl, $prefix, $dirsep, $depchar, $splitchar) = @_; - my ($i, $x, $y); - my @deps; - my @ret; - @ret = (); - $depchar ||= ':'; - foreach $ii (sort keys %depends) { - $i = $objname{$ii}; - next if $specialobj{$mftyp}->{$i}; - if ($i =~ /^(.*)\.(res|rsrc)/) { - next if !defined $rtmpl; - $y = $1; - ($x = $rtmpl) =~ s/X/$y/; - } else { - ($x = $otmpl) =~ s/X/$i/; - } - @deps = @{$depends{$ii}}; - # Skip things which are their own dependency. - next if grep { $_ eq $i } @deps; - @deps = map { - $_ = &findfile($_); - s/\//$dirsep/g; - $_ = $prefix . $_; - } @deps; - push @ret, {obj => $x, deps => [@deps], defs => $defs{$ii}}; - } - return @ret; -} - -sub prognames { - my ($types) = @_; - my ($n, $prog, $type); - my @ret; - @ret = (); - foreach $n (@prognames) { - ($prog, $type) = split ",", $n; - push @ret, $n if index(":$types:", ":$type:") >= 0; - } - return @ret; -} - -sub progrealnames { - my ($types) = @_; - my ($n, $prog, $type); - my @ret; - @ret = (); - foreach $n (@prognames) { - ($prog, $type) = split ",", $n; - push @ret, $prog if index(":$types:", ":$type:") >= 0; - } - return @ret; -} - -sub manpages { - my ($types,$suffix) = @_; - - # assume that all UNIX programs have a man page - if($suffix eq "1" && $types =~ /:X:/) { - return map("$_.1", &progrealnames($types)); - } - return (); -} - -$orig_dir = cwd; - -# Now we're ready to output the actual Makefiles. - -if (defined $makefiles{'clangcl'}) { - $mftyp = 'clangcl'; - $dirpfx = &dirpfx($makefiles{'clangcl'}, "/"); - - ##-- Makefile for cross-compiling using clang-cl, lld-link, and - ## MinGW's windres for resource compilation. - # - # This makefile allows a complete Linux-based cross-compile, but - # using the real Visual Studio header files and libraries. In - # order to run it, you will need: - # - # - MinGW windres on your PATH. - # * On Ubuntu as of 16.04, you can apt-get install - # binutils-mingw-w64-x86-64 and binutils-mingw-w64-i686 - # which will provide (respectively) 64- and 32-bit versions, - # under the names to which RCCMD is defined below. - # - clang-cl and lld-link on your PATH. - # * I built these from the up-to-date LLVM project trunk git - # repositories, as of 2017-02-05. - # - case-mashed copies of the Visual Studio include directories. - # * On a real VS installation, run vcvars32.bat and look at - # the resulting value of %INCLUDE%. Take a full copy of each - # of those directories, and inside the copy, for each - # include file that has an uppercase letter in its name, - # make a lowercased symlink to it. Additionally, one of the - # directories will contain files called driverspecs.h and - # specstrings.h, and those will need symlinks called - # DriverSpecs.h and SpecStrings.h. - # * Now, on Linux, define the environment variable INCLUDE to - # be a list, separated by *semicolons* (in the Windows - # style), of those directories, but before all of them you - # must also include lib/clang/5.0.0/include from the clang - # installation area (which contains in particular a - # clang-compatible stdarg.h overriding the Visual Studio - # one). - # - similarly case-mashed copies of the library directories. - # * Again, on a real VS installation, run vcvars32 or - # vcvarsx86_amd64 (as appropriate), look at %LIB%, make a - # copy of each directory, and provide symlinks within that - # directory so that all the files can be opened as - # lowercase. - # * Then set LIB to be a semicolon-separated list of those - # directories (but you'll need to change which set of - # directories depending on whether you want to do a 32-bit - # or 64-bit build). - # - for a 64-bit build, set 'Platform=x64' in the environment as - # well, or else on the make command line. - # * This is a variable understood only by this makefile - none - # of the tools we invoke will know it - but it's consistent - # with the way the VS scripts like vcvarsx86_amd64.bat set - # things up, and since the environment has to change - # _anyway_ between 32- and 64-bit builds (different set of - # paths in $LIB) it's reasonable to have the choice of - # compilation target driven by another environment variable - # set in parallel with that one. - # - for older versions of the VS libraries you may also have to - # set EXTRA_console and/or EXTRA_windows to the name of an - # object file manually extracted from one of those libraries. - # * This is because old VS seems to manage its startup code by - # having libcmt.lib contain lots of *crt0.obj objects, one - # for each possible user entry point (main, WinMain and the - # wide-char versions of both), of which the linker arranges - # to include the right one by special-case code. But lld - # only seems to mimic half of that code - it does include - # the right crt0 object, but it doesn't also deliberately - # _avoid_ including the _wrong_ ones, and since all those - # objects define a common set of global symbols for other - # parts of the library to use, lld may well select an - # arbitrary one of them the first time it sees a reference - # to one of those global symbols, and then later also select - # the _right_ one for the application's entry point, causing - # a multiple-definitions crash. - # * So the workaround is to explicitly include the right - # *crt0.obj file on the linker command line before lld even - # begins searching libraries. Hence, for a console - # application, you might extract crt0.obj from the library - # in question and set EXTRA_console=crt0.obj, and for a GUI - # application, do the same with wincrt0.obj. Then this - # makefile will include the right one of those objects - # alongside the matching /subsystem linker option. - - open OUT, ">$makefiles{'clangcl'}"; select OUT; - print - "# Makefile for cross-compiling $project_name using clang-cl, lld-link,\n". - "# and MinGW's windres, using GNU make on Linux.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - print $help; - print - "\n". - "CCCMD = clang-cl\n". - "ifeq (\$(Platform),x64)\n". - "CCTARGET = x86_64-pc-windows-msvc18.0.0\n". - "RCCMD = x86_64-w64-mingw32-windres\n". - "else\n". - "CCTARGET = i386-pc-windows-msvc18.0.0\n". - "RCCMD = i686-w64-mingw32-windres\n". - "endif\n". - "CC = \$(CCCMD) --target=\$(CCTARGET)\n". - &splitline("RC = \$(RCCMD) --preprocessor=\$(CCCMD) ". - "--preprocessor-arg=/TC --preprocessor-arg=/E")."\n". - "LD = lld-link\n". - "\n". - "# C compilation flags\n". - &splitline("CFLAGS = /nologo /W3 /O1 " . - (join " ", map {"-I$dirpfx$_"} @srcdirs) . - " /D_WINDOWS /D_WIN32_WINDOWS=0x401 /DWINVER=0x401 ". - "/D_CRT_SECURE_NO_WARNINGS")."\n". - "LFLAGS = /incremental:no /dynamicbase /nxcompat\n". - &splitline("RCFLAGS = ".(join " ", map {"-I$dirpfx$_"} @srcdirs). - " -DWIN32 -D_WIN32 -DWINVER=0x0400 --define MINGW32_FIX=1")."\n". - "\n". - "\n"; - print &splitline("all:" . join "", map { " \$(BUILDDIR)$_.exe" } &progrealnames("G:C")); - print "\n\n"; - foreach $p (&prognames("G:C")) { - ($prog, $type) = split ",", $p; - $objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", undef); - print &splitline("\$(BUILDDIR)$prog.exe: " . $objstr), "\n"; - - $objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", "X.lib"); - $subsys = ($type eq "G") ? "windows" : "console"; - print &splitline("\t\$(LD) \$(LFLAGS) \$(XLFLAGS) ". - "/out:\$(BUILDDIR)$prog.exe ". - "/lldmap:\$(BUILDDIR)$prog.map ". - "/subsystem:$subsys\$(SUBSYSVER) ". - "\$(EXTRA_$subsys) $objstr")."\n\n"; - } - foreach $d (&deps("\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", $dirpfx, "/", "vc")) { - print &splitline(sprintf("%s: %s", $d->{obj}, - join " ", @{$d->{deps}})), "\n"; - if ($d->{obj} =~ /\.res$/) { - print "\t\$(RC) \$(RCFLAGS) ".$d->{deps}->[0]." -o ".$d->{obj}."\n\n"; - } else { - $deflist = join "", map { " /D$_" } @{$d->{defs}}; - print "\t\$(CC) /Fo".$d->{obj}." \$(COMPAT) \$(CFLAGS) \$(XFLAGS)$deflist /c \$<\n\n"; - } - } - print "\nclean:\n". - &splitline("\trm -f \$(BUILDDIR)*.obj \$(BUILDDIR)*.exe ". - "\$(BUILDDIR)*.res \$(BUILDDIR)*.map ". - "\$(BUILDDIR)*.exe.manifest")."\n"; - select STDOUT; close OUT; -} - -if (defined $makefiles{'cygwin'}) { - $mftyp = 'cygwin'; - $dirpfx = &dirpfx($makefiles{'cygwin'}, "/"); - - ##-- CygWin makefile - open OUT, ">$makefiles{'cygwin'}"; select OUT; - print - "# Makefile for $project_name under cygwin.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - # gcc command line option is -D not /D - ($_ = $help) =~ s/=\/D/=-D/gs; - print $_; - print - "\n". - "# You can define this path to point at your tools if you need to\n". - "# TOOLPATH = c:\\cygwin\\bin\\ # or similar, if you're running Windows\n". - "# TOOLPATH = /pkg/mingw32msvc/i386-mingw32msvc/bin/\n". - "CC = \$(TOOLPATH)gcc\n". - "RC = \$(TOOLPATH)windres\n". - "# Uncomment the following two lines to compile under Winelib\n". - "# CC = winegcc\n". - "# RC = wrc\n". - "# You may also need to tell windres where to find include files:\n". - "# RCINC = --include-dir c:\\cygwin\\include\\\n". - "\n". - &splitline("CFLAGS = -mno-cygwin -Wall -O2 -D_WINDOWS -DDEBUG -DWIN32S_COMPAT". - " -D_NO_OLDNAMES -DNO_MULTIMON -DNO_HTMLHELP " . - (join " ", map {"-I$dirpfx$_"} @srcdirs)) . - "\n". - "LDFLAGS = -mno-cygwin -s\n". - &splitline("RCFLAGS = \$(RCINC) --define WIN32=1 --define _WIN32=1". - " --define WINVER=0x0400 --define MINGW32_FIX=1 " . - (join " ", map {"--include $dirpfx$_"} @srcdirs) )."\n". - "\n"; - print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C")); - print "\n\n"; - foreach $p (&prognames("G:C")) { - ($prog, $type) = split ",", $p; - $objstr = &objects($p, "X.o", "X.res.o", undef); - print &splitline($prog . ".exe: " . $objstr), "\n"; - my $mw = $type eq "G" ? " -mwindows" : ""; - $libstr = &objects($p, undef, undef, "-lX"); - print &splitline("\t\$(CC)" . $mw . " \$(LDFLAGS) -o \$@ " . - "-Wl,-Map,$prog.map " . - $objstr . " $libstr", 69), "\n\n"; - } - foreach $d (&deps("X.o", "X.res.o", $dirpfx, "/")) { - print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})), - "\n"; - if ($d->{obj} =~ /\.res\.o$/) { - print "\t\$(RC) \$(FWHACK) \$(RCFL) \$(RCFLAGS) \$< \$\@\n"; - } else { - $deflist = join "", map { " -D$_" } @{$d->{defs}}; - print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(CFLAGS)" . - " \$(XFLAGS)$deflist -c \$< -o \$\@\n"; - } - } - print "\n"; - print $makefile_extra{'cygwin'} || ""; - print "\nclean:\n". - "\trm -f *.o *.exe *.res.o *.map\n". - "\n"; - select STDOUT; close OUT; - -} - -##-- Borland makefile -if (defined $makefiles{'borland'}) { - $mftyp = 'borland'; - $dirpfx = &dirpfx($makefiles{'borland'}, "\\"); - - %stdlibs = ( # Borland provides many Win32 API libraries intrinsically - "advapi32" => 1, - "comctl32" => 1, - "comdlg32" => 1, - "gdi32" => 1, - "imm32" => 1, - "shell32" => 1, - "user32" => 1, - "winmm" => 1, - "winspool" => 1, - "wsock32" => 1, - ); - open OUT, ">$makefiles{'borland'}"; select OUT; - print - "# Makefile for $project_name under Borland C.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - # bcc32 command line option is -D not /D - ($_ = $help) =~ s/=\/D/=-D/gs; - print $_; - print - "\n". - "# If you rename this file to `Makefile', you should change this line,\n". - "# so that the .rsp files still depend on the correct makefile.\n". - "MAKEFILE = Makefile.bor\n". - "\n". - "# C compilation flags\n". - "CFLAGS = -D_WINDOWS -DWINVER=0x0401\n". - "\n". - "# Get include directory for resource compiler\n". - "!if !\$d(BCB)\n". - "BCB = \$(MAKEDIR)\\..\n". - "!endif\n". - "\n"; - print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C")); - print "\n\n"; - foreach $p (&prognames("G:C")) { - ($prog, $type) = split ",", $p; - $objstr = &objects($p, "X.obj", "X.res", undef); - print &splitline("$prog.exe: " . $objstr . " $prog.rsp"), "\n"; - my $ap = ($type eq "G") ? "-aa" : "-ap"; - print "\tilink32 $ap -Gn -L\$(BCB)\\lib \@$prog.rsp\n\n"; - } - foreach $p (&prognames("G:C")) { - ($prog, $type) = split ",", $p; - print $prog, ".rsp: \$(MAKEFILE)\n"; - $objstr = &objects($p, "X.obj", undef, undef); - @objlist = split " ", $objstr; - @objlines = (""); - foreach $i (@objlist) { - if (length($objlines[$#objlines] . " $i") > 50) { - push @objlines, ""; - } - $objlines[$#objlines] .= " $i"; - } - $c0w = ($type eq "G") ? "c0w32" : "c0x32"; - print "\techo $c0w + > $prog.rsp\n"; - for ($i=0; $i<=$#objlines; $i++) { - $plus = ($i < $#objlines ? " +" : ""); - print "\techo$objlines[$i]$plus >> $prog.rsp\n"; - } - print "\techo $prog.exe >> $prog.rsp\n"; - $objstr = &objects($p, "X.obj", "X.res", undef); - @libs = split " ", &objects($p, undef, undef, "X"); - @libs = grep { !$stdlibs{$_} } @libs; - unshift @libs, "cw32", "import32"; - $libstr = join ' ', @libs; - print "\techo nul,$libstr, >> $prog.rsp\n"; - print "\techo " . &objects($p, undef, "X.res", undef) . " >> $prog.rsp\n"; - print "\n"; - } - foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\")) { - print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})), - "\n"; - if ($d->{obj} =~ /\.res$/) { - print &splitline("\tbrcc32 \$(FWHACK) \$(RCFL) " . - "-i \$(BCB)\\include -r -DNO_WINRESRC_H -DWIN32". - " -D_WIN32 -DWINVER=0x0401 \$*.rc",69)."\n"; - } else { - $deflist = join "", map { " -D$_" } @{$d->{defs}}; - print &splitline("\tbcc32 -w-aus -w-ccc -w-par -w-pia \$(COMPAT)" . - " \$(FWHACK) \$(CFLAGS) \$(XFLAGS)$deflist ". - (join " ", map {"-I$dirpfx$_"} @srcdirs) . - " /o$d->{obj} /c ".$d->{deps}->[0],69)."\n"; - } - } - print "\n"; - print $makefile_extra{'borland'} || ""; - print "\nclean:\n". - "\t-del *.obj\n". - "\t-del *.exe\n". - "\t-del *.res\n". - "\t-del *.pch\n". - "\t-del *.aps\n". - "\t-del *.il*\n". - "\t-del *.pdb\n". - "\t-del *.rsp\n". - "\t-del *.tds\n". - "\t-del *.\$\$\$\$\$\$\n"; - select STDOUT; close OUT; -} - -if (defined $makefiles{'vc'}) { - $mftyp = 'vc'; - $dirpfx = &dirpfx($makefiles{'vc'}, "\\"); - - ##-- Visual C++ makefile - open OUT, ">$makefiles{'vc'}"; select OUT; - print - "# Makefile for $project_name under Visual C.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - print $help; - print - "\n". - "# If you rename this file to `Makefile', you should change this line,\n". - "# so that the .rsp files still depend on the correct makefile.\n". - "MAKEFILE = Makefile.vc\n". - "\n". - "# C compilation flags\n". - "CFLAGS = /nologo /W3 /O1 /D_WINDOWS /D_WIN32_WINDOWS=0x401 /DWINVER=0x401 /I.\n". - "LFLAGS = /incremental:no /fixed\n". - "\n"; - print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C")); - print "\n\n"; - foreach $p (&prognames("G:C")) { - ($prog, $type) = split ",", $p; - $objstr = &objects($p, "X.obj", "X.res", undef); - print &splitline("$prog.exe: " . $objstr . " $prog.rsp"), "\n"; - print "\tlink \$(LFLAGS) -out:$prog.exe -map:$prog.map \@$prog.rsp\n\n"; - } - foreach $p (&prognames("G:C")) { - ($prog, $type) = split ",", $p; - print $prog, ".rsp: \$(MAKEFILE)\n"; - $objstr = &objects($p, "X.obj", "X.res", "X.lib"); - @objlist = split " ", $objstr; - @objlines = (""); - foreach $i (@objlist) { - if (length($objlines[$#objlines] . " $i") > 50) { - push @objlines, ""; - } - $objlines[$#objlines] .= " $i"; - } - $subsys = ($type eq "G") ? "windows" : "console"; - print "\techo /nologo /subsystem:$subsys > $prog.rsp\n"; - for ($i=0; $i<=$#objlines; $i++) { - print "\techo$objlines[$i] >> $prog.rsp\n"; - } - print "\n"; - } - foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\")) { - print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})), - "\n"; - if ($d->{obj} =~ /\.res$/) { - print "\trc \$(FWHACK) \$(RCFL) -r -DWIN32 -D_WIN32 ". - "-DWINVER=0x0400 -fo".$d->{obj}." ".$d->{deps}->[0]."\n"; - } else { - $deflist = join "", map { " /D$_" } @{$d->{defs}}; - print "\tcl \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS)$deflist". - " /c ".$d->{deps}->[0]." /Fo$d->{obj}\n"; - } - } - print "\n"; - print $makefile_extra{'vc'} || ""; - print "\nclean: tidy\n". - "\t-del *.exe\n\n". - "tidy:\n". - "\t-del *.obj\n". - "\t-del *.res\n". - "\t-del *.pch\n". - "\t-del *.aps\n". - "\t-del *.ilk\n". - "\t-del *.pdb\n". - "\t-del *.rsp\n". - "\t-del *.dsp\n". - "\t-del *.dsw\n". - "\t-del *.ncb\n". - "\t-del *.opt\n". - "\t-del *.plg\n". - "\t-del *.map\n". - "\t-del *.idb\n". - "\t-del debug.log\n"; - select STDOUT; close OUT; -} - -if (defined $makefiles{'wce'}) { - $mftyp = 'wce'; - $dirpfx = &dirpfx($makefiles{'wce'}, "\\"); - - ##-- eMbedded Visual C PocketPC makefile - open OUT, ">$makefiles{'wce'}"; select OUT; - print - "# Makefile for $project_name on PocketPC using eMbedded Visual C.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - print $help; - print - "\n". - "# If you rename this file to `Makefile', you should change this line,\n". - "# so that the .rsp files still depend on the correct makefile.\n". - "MAKEFILE = Makefile.wce\n". - "\n". - "# This makefile expects the environment to have been set up by one\n". - "# of the PocketPC batch files wcearmv4.bat and wceemulator.bat. No\n". - "# other build targets are currently supported, because they would\n". - "# need a section in this if statement.\n". - "!if \"\$(TARGETCPU)\" == \"emulator\"\n". - "PLATFORM_DEFS=/D \"_i386_\" /D \"i_386_\" /D \"_X86_\" /D \"x86\"\n". - "CC=cl\n". - "BASELIBS=commctrl.lib coredll.lib corelibc.lib aygshell.lib\n". - "MACHINE=IX86\n". - "!else\n". - "PLATFORM_DEFS=/D \"ARM\" /D \"_ARM_\" /D \"ARMV4\"\n". - "CC=clarm\n". - "BASELIBS=commctrl.lib coredll.lib aygshell.lib\n". - "MACHINE=ARM\n". - "!endif\n". - "\n". - "# C compilation flags\n". - "CFLAGS = /nologo /W3 /O1 /MC /D _WIN32_WCE=420 /D \"WIN32_PLATFORM_PSPC=400\" /D UNDER_CE=420 \\\n". - " \$(PLATFORM_DEFS) \\\n". - " /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /D \"NO_HTMLHELP\"\n". - "\n". - "LFLAGS = /nologo /incremental:no \\\n". - " /base:0x00010000 /stack:0x10000,0x1000 /entry:WinMainCRTStartup \\\n". - " /nodefaultlib:libc.lib /nodefaultlib:libcmt.lib /nodefaultlib:msvcrt.lib /nodefaultlib:OLDNAMES.lib \\\n". - " /subsystem:windowsce,4.20 /align:4096 /MACHINE:\$(MACHINE)\n". - "\n". - "RCFL = /d UNDER_CE=420 /d _WIN32_WCE=420 /d \"WIN32_PLATFORM_PSPC=400\" \\\n". - " \$(PLATFORM_DEFS) \\\n". - " /d \"NDEBUG\" /d \"UNICODE\" /d \"_UNICODE\"\n". - "\n"; - print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G")); - print "\n\n"; - foreach $p (&prognames("G")) { - ($prog, $type) = split ",", $p; - $objstr = &objects($p, "X.obj", "X.res", undef); - print &splitline("$prog.exe: " . $objstr . " $prog.rsp"), "\n"; - print "\tlink \$(LFLAGS) -out:$prog.exe -map:$prog.map \@$prog.rsp\n\n"; - } - foreach $p (&prognames("G")) { - ($prog, $type) = split ",", $p; - print $prog, ".rsp: \$(MAKEFILE)\n"; - $objstr = &objects($p, "X.obj", "X.res", undef); - @objlist = split " ", $objstr; - @objlines = (""); - foreach $i (@objlist) { - if (length($objlines[$#objlines] . " $i") > 50) { - push @objlines, ""; - } - $objlines[$#objlines] .= " $i"; - } - print "\techo \$(BASELIBS) > $prog.rsp\n"; - for ($i=0; $i<=$#objlines; $i++) { - print "\techo$objlines[$i] >> $prog.rsp\n"; - } - print "\n"; - } - foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\")) { - print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})), - "\n"; - if ($d->{obj} =~ /\.res$/) { - print "\trc \$(FWHACK) \$(RCFL) -r -fo". - $d->{obj}." ".$d->{deps}->[0]."\n"; - } else { - $deflist = join "", map { " /D$_" } @{$d->{defs}}; - print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS)$deflist". - " /c ".$d->{deps}->[0]." /Fo$d->{obj}\n"; - } - } - print "\n"; - print $makefile_extra{'wce'} || ""; - print "\nclean: tidy\n". - "\t-del *.exe\n\n". - "tidy:\n". - "\t-del *.obj\n". - "\t-del *.res\n". - "\t-del *.pch\n". - "\t-del *.aps\n". - "\t-del *.ilk\n". - "\t-del *.pdb\n". - "\t-del *.rsp\n". - "\t-del *.dsp\n". - "\t-del *.dsw\n". - "\t-del *.ncb\n". - "\t-del *.opt\n". - "\t-del *.plg\n". - "\t-del *.map\n". - "\t-del *.idb\n". - "\t-del debug.log\n"; - select STDOUT; close OUT; -} - -if (defined $makefiles{'vcproj'}) { - $mftyp = 'vcproj'; - - ##-- MSVC 6 Workspace and projects - # - # Note: All files created in this section are written in binary - # mode, because although MSVC's command-line make can deal with - # LF-only line endings, MSVC project files really _need_ to be - # CRLF. Hence, in order for mkfiles.pl to generate usable project - # files even when run from Unix, I make sure all files are binary - # and explicitly write the CRLFs. - # - # Create directories if necessary - mkdir $makefiles{'vcproj'} - if(! -d $makefiles{'vcproj'}); - chdir $makefiles{'vcproj'}; - @deps = &deps("X.obj", "X.res", "", "\\"); - %all_object_deps = map {$_->{obj} => $_->{deps}} @deps; - # Create the project files - # Get names of all Windows projects (GUI and console) - my @prognames = &prognames("G:C"); - foreach $progname (@prognames) { - create_project(\%all_object_deps, $progname); - } - # Create the workspace file - open OUT, ">$project_name.dsw"; binmode OUT; select OUT; - print - "Microsoft Developer Studio Workspace File, Format Version 6.00\r\n". - "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r\n". - "\r\n". - "###############################################################################\r\n". - "\r\n"; - # List projects - foreach $progname (@prognames) { - ($windows_project, $type) = split ",", $progname; - print "Project: \"$windows_project\"=\".\\$windows_project\\$windows_project.dsp\" - Package Owner=<4>\r\n"; - } - print - "\r\n". - "Package=<5>\r\n". - "{{{\r\n". - "}}}\r\n". - "\r\n". - "Package=<4>\r\n". - "{{{\r\n". - "}}}\r\n". - "\r\n". - "###############################################################################\r\n". - "\r\n". - "Global:\r\n". - "\r\n". - "Package=<5>\r\n". - "{{{\r\n". - "}}}\r\n". - "\r\n". - "Package=<3>\r\n". - "{{{\r\n". - "}}}\r\n". - "\r\n". - "###############################################################################\r\n". - "\r\n"; - select STDOUT; close OUT; - chdir $orig_dir; - - sub create_project { - my ($all_object_deps, $progname) = @_; - # Construct program's dependency info - %seen_objects = (); - %lib_files = (); - %source_files = (); - %header_files = (); - %resource_files = (); - @object_files = split " ", &objects($progname, "X.obj", "X.res", "X.lib"); - foreach $object_file (@object_files) { - next if defined $seen_objects{$object_file}; - $seen_objects{$object_file} = 1; - if($object_file =~ /\.lib$/io) { - $lib_files{$object_file} = 1; - next; - } - $object_deps = $all_object_deps{$object_file}; - foreach $object_dep (@$object_deps) { - if($object_dep =~ /\.c$/io) { - $source_files{$object_dep} = 1; - next; - } - if($object_dep =~ /\.h$/io) { - $header_files{$object_dep} = 1; - next; - } - if($object_dep =~ /\.(rc|ico)$/io) { - $resource_files{$object_dep} = 1; - next; - } - } - } - $libs = join " ", sort keys %lib_files; - @source_files = sort keys %source_files; - @header_files = sort keys %header_files; - @resources = sort keys %resource_files; - ($windows_project, $type) = split ",", $progname; - mkdir $windows_project - if(! -d $windows_project); - chdir $windows_project; - $subsys = ($type eq "G") ? "windows" : "console"; - open OUT, ">$windows_project.dsp"; binmode OUT; select OUT; - print - "# Microsoft Developer Studio Project File - Name=\"$windows_project\" - Package Owner=<4>\r\n". - "# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n". - "# ** DO NOT EDIT **\r\n". - "\r\n". - "# TARGTYPE \"Win32 (x86) Application\" 0x0101\r\n". - "\r\n". - "CFG=$windows_project - Win32 Debug\r\n". - "!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n". - "!MESSAGE use the Export Makefile command and run\r\n". - "!MESSAGE \r\n". - "!MESSAGE NMAKE /f \"$windows_project.mak\".\r\n". - "!MESSAGE \r\n". - "!MESSAGE You can specify a configuration when running NMAKE\r\n". - "!MESSAGE by defining the macro CFG on the command line. For example:\r\n". - "!MESSAGE \r\n". - "!MESSAGE NMAKE /f \"$windows_project.mak\" CFG=\"$windows_project - Win32 Debug\"\r\n". - "!MESSAGE \r\n". - "!MESSAGE Possible choices for configuration are:\r\n". - "!MESSAGE \r\n". - "!MESSAGE \"$windows_project - Win32 Release\" (based on \"Win32 (x86) Application\")\r\n". - "!MESSAGE \"$windows_project - Win32 Debug\" (based on \"Win32 (x86) Application\")\r\n". - "!MESSAGE \r\n". - "\r\n". - "# Begin Project\r\n". - "# PROP AllowPerConfigDependencies 0\r\n". - "# PROP Scc_ProjName \"\"\r\n". - "# PROP Scc_LocalPath \"\"\r\n". - "CPP=cl.exe\r\n". - "MTL=midl.exe\r\n". - "RSC=rc.exe\r\n". - "\r\n". - "!IF \"\$(CFG)\" == \"$windows_project - Win32 Release\"\r\n". - "\r\n". - "# PROP BASE Use_MFC 0\r\n". - "# PROP BASE Use_Debug_Libraries 0\r\n". - "# PROP BASE Output_Dir \"Release\"\r\n". - "# PROP BASE Intermediate_Dir \"Release\"\r\n". - "# PROP BASE Target_Dir \"\"\r\n". - "# PROP Use_MFC 0\r\n". - "# PROP Use_Debug_Libraries 0\r\n". - "# PROP Output_Dir \"Release\"\r\n". - "# PROP Intermediate_Dir \"Release\"\r\n". - "# PROP Ignore_Export_Lib 0\r\n". - "# PROP Target_Dir \"\"\r\n". - "# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n". - "# ADD CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n". - "# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n". - "# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n". - "# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n". - "# ADD RSC /l 0x809 /d \"NDEBUG\"\r\n". - "BSC32=bscmake.exe\r\n". - "# ADD BASE BSC32 /nologo\r\n". - "# ADD BSC32 /nologo\r\n". - "LINK32=link.exe\r\n". - "# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:$subsys /machine:I386\r\n". - "# ADD LINK32 $libs /nologo /subsystem:$subsys /machine:I386\r\n". - "# SUBTRACT LINK32 /pdb:none\r\n". - "\r\n". - "!ELSEIF \"\$(CFG)\" == \"$windows_project - Win32 Debug\"\r\n". - "\r\n". - "# PROP BASE Use_MFC 0\r\n". - "# PROP BASE Use_Debug_Libraries 1\r\n". - "# PROP BASE Output_Dir \"Debug\"\r\n". - "# PROP BASE Intermediate_Dir \"Debug\"\r\n". - "# PROP BASE Target_Dir \"\"\r\n". - "# PROP Use_MFC 0\r\n". - "# PROP Use_Debug_Libraries 1\r\n". - "# PROP Output_Dir \"Debug\"\r\n". - "# PROP Intermediate_Dir \"Debug\"\r\n". - "# PROP Ignore_Export_Lib 0\r\n". - "# PROP Target_Dir \"\"\r\n". - "# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n". - "# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n". - "# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n". - "# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n". - "# ADD BASE RSC /l 0x809 /d \"_DEBUG\"\r\n". - "# ADD RSC /l 0x809 /d \"_DEBUG\"\r\n". - "BSC32=bscmake.exe\r\n". - "# ADD BASE BSC32 /nologo\r\n". - "# ADD BSC32 /nologo\r\n". - "LINK32=link.exe\r\n". - "# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:$subsys /debug /machine:I386 /pdbtype:sept\r\n". - "# ADD LINK32 $libs /nologo /subsystem:$subsys /debug /machine:I386 /pdbtype:sept\r\n". - "# SUBTRACT LINK32 /pdb:none\r\n". - "\r\n". - "!ENDIF \r\n". - "\r\n". - "# Begin Target\r\n". - "\r\n". - "# Name \"$windows_project - Win32 Release\"\r\n". - "# Name \"$windows_project - Win32 Debug\"\r\n". - "# Begin Group \"Source Files\"\r\n". - "\r\n". - "# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n"; - foreach $source_file (@source_files) { - print - "# Begin Source File\r\n". - "\r\n". - "SOURCE=..\\..\\$source_file\r\n"; - if($source_file =~ /ssh\.c/io) { - # Disable 'Edit and continue' as Visual Studio can't handle the macros - print - "\r\n". - "!IF \"\$(CFG)\" == \"$windows_project - Win32 Release\"\r\n". - "\r\n". - "!ELSEIF \"\$(CFG)\" == \"$windows_project - Win32 Debug\"\r\n". - "\r\n". - "# ADD CPP /Zi\r\n". - "\r\n". - "!ENDIF \r\n". - "\r\n"; - } - print "# End Source File\r\n"; - } - print - "# End Group\r\n". - "# Begin Group \"Header Files\"\r\n". - "\r\n". - "# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n"; - foreach $header_file (@header_files) { - print - "# Begin Source File\r\n". - "\r\n". - "SOURCE=..\\..\\$header_file\r\n". - "# End Source File\r\n"; - } - print - "# End Group\r\n". - "# Begin Group \"Resource Files\"\r\n". - "\r\n". - "# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n"; - foreach $resource_file (@resources) { - print - "# Begin Source File\r\n". - "\r\n". - "SOURCE=..\\..\\$resource_file\r\n". - "# End Source File\r\n"; - } - print - "# End Group\r\n". - "# End Target\r\n". - "# End Project\r\n"; - select STDOUT; close OUT; - chdir ".."; - } -} - -if (defined $makefiles{'gtk'}) { - $mftyp = 'gtk'; - $dirpfx = &dirpfx($makefiles{'gtk'}, "/"); - - ##-- X/GTK/Unix makefile - open OUT, ">$makefiles{'gtk'}"; select OUT; - print - "# Makefile for $project_name under X/GTK and Unix.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - # gcc command line option is -D not /D - ($_ = $help) =~ s/=\/D/=-D/gs; - print $_; - print - "\n". - "# You can define this path to point at your tools if you need to\n". - "# TOOLPATH = /opt/gcc/bin\n". - "CC := \$(TOOLPATH)\$(CC)\n". - "# You can manually set this to `gtk-config' or `pkg-config gtk+-1.2'\n". - "# (depending on what works on your system) if you want to enforce\n". - "# building with GTK 1.2, or you can set it to `pkg-config gtk+-2.0'\n". - "# if you want to enforce 2.0. The default is to try 2.0 and fall back\n". - "# to 1.2 if it isn't found.\n". - "GTK_CONFIG = sh -c 'pkg-config gtk+-2.0 \$\$0 2>/dev/null || gtk-config \$\$0'\n". - "\n". - &splitline("CFLAGS := -O2 -Wall -Werror -ansi -pedantic -g " . - (join " ", map {"-I$dirpfx$_"} @srcdirs) . - " `\$(GTK_CONFIG) --cflags` \$(CFLAGS)")."\n". - "XLIBS = `\$(GTK_CONFIG) --libs` -lm\n". - "ULIBS = -lm#\n". - "INSTALL=install\n", - "INSTALL_PROGRAM=\$(INSTALL)\n", - "INSTALL_DATA=\$(INSTALL)\n", - "prefix=/usr/local\n", - "exec_prefix=\$(prefix)\n", - "bindir=\$(exec_prefix)/bin\n", - "gamesdir=\$(exec_prefix)/games\n", - "mandir=\$(prefix)/man\n", - "man1dir=\$(mandir)/man1\n", - "\n"; - print &splitline("all:" . join "", map { " \$(BINPREFIX)$_" } - &progrealnames("X:U")); - print "\n\n"; - foreach $p (&prognames("X:U")) { - ($prog, $type) = split ",", $p; - $objstr = &objects($p, "X.o", undef, undef); - print &splitline("\$(BINPREFIX)" . $prog . ": " . $objstr), "\n"; - $libstr = &objects($p, undef, undef, "-lX"); - print &splitline("\t\$(CC) -o \$@ $objstr $libstr \$(XLFLAGS) \$(${type}LIBS)", 69), - "\n\n"; - } - foreach $d (&deps("X.o", undef, $dirpfx, "/")) { - print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})), - "\n"; - $deflist = join "", map { " -D$_" } @{$d->{defs}}; - print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS)$deflist" . - " -c \$< -o \$\@\n"; - } - print "\n"; - print $makefile_extra{'gtk'} || ""; - print "\nclean:\n". - "\trm -f *.o". (join "", map { " \$(BINPREFIX)$_" } &progrealnames("X:U")) . "\n"; - select STDOUT; close OUT; -} - -if (defined $makefiles{'am'}) { - $mftyp = 'am'; - die "Makefile.am in a subdirectory is not supported\n" - if &dirpfx($makefiles{'am'}, "/") ne ""; - - ##-- Unix/autoconf Makefile.am - open OUT, ">$makefiles{'am'}"; select OUT; - print - "# Makefile.am for $project_name under Unix with Autoconf/Automake.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n\n"; - - print $makefile_extra{'am_begin'} || ""; - - # All programs go in noinstprogs by default. If you want them - # installed anywhere else, you have to also add them to - # bin_PROGRAMS using '!begin am'. (Automake doesn't seem to mind - # having a program name in _both_ of bin_PROGRAMS and - # noinst_PROGRAMS.) - @noinstprogs = (); - foreach $p (&prognames("X:U")) { - ($prog, $type) = split ",", $p; - push @noinstprogs, $prog; - } - print &splitline(join " ", "noinst_PROGRAMS", "=", @noinstprogs), "\n"; - - %objtosrc = (); - %amspeciallibs = (); - %amlibobjname = (); - %allsources = (); - foreach $d (&deps("X", undef, "", "/", "am")) { - my $obj = $d->{obj}; - my $use_archive = 0; - - if (defined $d->{defs}) { - # This file needs to go in an archive, so that we can - # change the preprocess flags to include some -Ds - $use_archive = 1; - $archivecppflags{$obj} = [map { " -D$_" } @{$d->{defs}}]; - } - if (defined $cflags{'am'} && $cflags{'am'}->{$obj}) { - # This file needs to go in an archive, so that we can - # change the compile flags as specified in Recipe - $use_archive = 1; - $archivecflags{$obj} = [$cflags{'am'}->{$obj}]; - } - if ($use_archive) { - $amspeciallibs{$obj} = "lib${obj}.a"; - $amlibobjname{$obj} = "lib${obj}_a-" . - basename($d->{deps}->[0], ".c", ".m") . - ".\$(OBJEXT)"; - } - $objtosrc{$obj} = $d->{deps}; - map { $allsources{$_} = 1 } @{$d->{deps}}; - } - - # 2014-02-22: as of automake-1.14 we begin to get complained at if - # we don't use this option - print "AUTOMAKE_OPTIONS = subdir-objects\n\n"; - - # Complete list of source and header files. Not used by the - # auto-generated parts of this makefile, but Recipe might like to - # have it available as a variable so that mandatory-rebuild things - # (version.o) can conveniently be made to depend on it. - print &splitline(join " ", "allsources", "=", - sort {$a cmp $b} keys %allsources), "\n\n"; - - @amcppflags = map {"-I\$(srcdir)/$_"} @srcdirs; - print &splitline(join " ", "AM_CPPFLAGS", "=", @amcppflags, "\n"); - - @amcflags = ("\$(GTK_CFLAGS)", "\$(WARNINGOPTS)"); - print &splitline(join " ", "AM_CFLAGS", "=", @amcflags), "\n"; - - %amlibsused = (); - foreach $p (&prognames("X:U")) { - ($prog, $type) = split ",", $p; - @progsources = ("${prog}_SOURCES", "="); - %sourcefiles = (); - @ldadd = (); - $objstr = &objects($p, "X", undef, undef); - foreach $obj (split / /,$objstr) { - if ($amspeciallibs{$obj}) { - $amlibsused{$obj} = 1; - push @ldadd, $amlibobjname{$obj}; - } else { - map { $sourcefiles{$_} = 1 } @{$objtosrc{$obj}}; - } - } - push @progsources, sort { $a cmp $b } keys %sourcefiles; - print &splitline(join " ", @progsources), "\n"; - if ($type eq "X") { - push @ldadd, "\$(GTK_LIBS)"; - } - push @ldadd, "-lm"; - print &splitline(join " ", "${prog}_LDADD", "=", @ldadd), "\n"; - print "\n"; - } - - foreach $obj (sort { $a cmp $b } keys %amlibsused) { - print &splitline(join " ", "lib${obj}_a_SOURCES", "=", - @{$objtosrc{$obj}}), "\n"; - print &splitline(join " ", "lib${obj}_a_CPPFLAGS", "=", - @amcflags, @{$archivecppflags{$obj}}), "\n" - if $archivecppflags{$obj}; - print &splitline(join " ", "lib${obj}_a_CFLAGS", "=", - @amcflags, @{$archivecflags{$obj}}), "\n" - if $archivecflags{$obj}; - } - print &splitline(join " ", "noinst_LIBRARIES", "=", - sort { $a cmp $b } - map { $amspeciallibs{$_} } - keys %amlibsused), - "\n\n"; - - print $makefile_extra{'am'} || ""; - select STDOUT; close OUT; -} - -if (defined $makefiles{'mpw'}) { - $mftyp = 'mpw'; - ##-- MPW Makefile - open OUT, ">$makefiles{'mpw'}"; select OUT; - print - "# Makefile for $project_name under MPW.\n#\n". - "# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - # MPW command line option is -d not /D - ($_ = $help) =~ s/=\/D/=-d /gs; - print $_; - print "\n\n". - "ROptions = `Echo \"{VER}\" | StreamEdit -e \"1,\$ replace /=(\xc5)\xa81\xb0/ 'STR=\xb6\xb6\xb6\xb6\xb6\"' \xa81 '\xb6\xb6\xb6\xb6\xb6\"'\"`". - "\n". - "C_68K = {C}\n". - "C_CFM68K = {C}\n". - "C_PPC = {PPCC}\n". - "C_Carbon = {PPCC}\n". - "\n". - "# -w 35 disables \"unused parameter\" warnings\n". - "COptions = -i : -i :: -i ::charset -w 35 -w err -proto strict -ansi on \xb6\n". - " -notOnce\n". - "COptions_68K = {COptions} -model far -opt time\n". - "# Enabling \"-opt space\" for CFM-68K gives me undefined references to\n". - "# _\$LDIVT and _\$LMODT.\n". - "COptions_CFM68K = {COptions} -model cfmSeg -opt time\n". - "COptions_PPC = {COptions} -opt size -traceback\n". - "COptions_Carbon = {COptions} -opt size -traceback -d TARGET_API_MAC_CARBON\n". - "\n". - "Link_68K = ILink\n". - "Link_CFM68K = ILink\n". - "Link_PPC = PPCLink\n". - "Link_Carbon = PPCLink\n". - "\n". - "LinkOptions = -c 'pTTY'\n". - "LinkOptions_68K = {LinkOptions} -br 68k -model far -compact\n". - "LinkOptions_CFM68K = {LinkOptions} -br 020 -model cfmseg -compact\n". - "LinkOptions_PPC = {LinkOptions}\n". - "LinkOptions_Carbon = -m __appstart -w {LinkOptions}\n". - "\n". - "Libs_68K = \"{CLibraries}StdCLib.far.o\" \xb6\n". - " \"{Libraries}MacRuntime.o\" \xb6\n". - " \"{Libraries}MathLib.far.o\" \xb6\n". - " \"{Libraries}IntEnv.far.o\" \xb6\n". - " \"{Libraries}Interface.o\" \xb6\n". - " \"{Libraries}Navigation.far.o\" \xb6\n". - " \"{Libraries}OpenTransport.o\" \xb6\n". - " \"{Libraries}OpenTransportApp.o\" \xb6\n". - " \"{Libraries}OpenTptInet.o\" \xb6\n". - " \"{Libraries}UnicodeConverterLib.far.o\"\n". - "\n". - "Libs_CFM = \"{SharedLibraries}InterfaceLib\" \xb6\n". - " \"{SharedLibraries}StdCLib\" \xb6\n". - " \"{SharedLibraries}AppearanceLib\" \xb6\n". - " -weaklib AppearanceLib \xb6\n". - " \"{SharedLibraries}NavigationLib\" \xb6\n". - " -weaklib NavigationLib \xb6\n". - " \"{SharedLibraries}TextCommon\" \xb6\n". - " -weaklib TextCommon \xb6\n". - " \"{SharedLibraries}UnicodeConverter\" \xb6\n". - " -weaklib UnicodeConverter\n". - "\n". - "Libs_CFM68K = {Libs_CFM} \xb6\n". - " \"{CFM68KLibraries}NuMacRuntime.o\"\n". - "\n". - "Libs_PPC = {Libs_CFM} \xb6\n". - " \"{SharedLibraries}ControlsLib\" \xb6\n". - " -weaklib ControlsLib \xb6\n". - " \"{SharedLibraries}WindowsLib\" \xb6\n". - " -weaklib WindowsLib \xb6\n". - " \"{SharedLibraries}OpenTransportLib\" \xb6\n". - " -weaklib OTClientLib \xb6\n". - " -weaklib OTClientUtilLib \xb6\n". - " \"{SharedLibraries}OpenTptInternetLib\" \xb6\n". - " -weaklib OTInetClientLib \xb6\n". - " \"{PPCLibraries}StdCRuntime.o\" \xb6\n". - " \"{PPCLibraries}PPCCRuntime.o\" \xb6\n". - " \"{PPCLibraries}CarbonAccessors.o\" \xb6\n". - " \"{PPCLibraries}OpenTransportAppPPC.o\" \xb6\n". - " \"{PPCLibraries}OpenTptInetPPC.o\"\n". - "\n". - "Libs_Carbon = \"{PPCLibraries}CarbonStdCLib.o\" \xb6\n". - " \"{PPCLibraries}StdCRuntime.o\" \xb6\n". - " \"{PPCLibraries}PPCCRuntime.o\" \xb6\n". - " \"{SharedLibraries}CarbonLib\" \xb6\n". - " \"{SharedLibraries}StdCLib\"\n". - "\n"; - print &splitline("all \xc4 " . join(" ", &progrealnames("M")), undef, "\xb6"); - print "\n\n"; - foreach $p (&prognames("M")) { - ($prog, $type) = split ",", $p; - - print &splitline("$prog \xc4 $prog.68k $prog.ppc $prog.carbon", - undef, "\xb6"), "\n\n"; - - $rsrc = &objects($p, "", "X.rsrc", undef); - - foreach $arch (qw(68K CFM68K PPC Carbon)) { - $objstr = &objects($p, "X.\L$arch\E.o", "", undef); - print &splitline("$prog.\L$arch\E \xc4 $objstr $rsrc", undef, "\xb6"); - print "\n"; - print &splitline("\tDuplicate -y $rsrc {Targ}", 69, "\xb6"), "\n"; - print &splitline("\t{Link_$arch} -o {Targ} -fragname $prog " . - "{LinkOptions_$arch} " . - $objstr . " {Libs_$arch}", 69, "\xb6"), "\n"; - print &splitline("\tSetFile -a BMi {Targ}", 69, "\xb6"), "\n\n"; - } - - } - foreach $d (&deps("", "X.rsrc", "::", ":")) { - next unless $d->{obj}; - print &splitline(sprintf("%s \xc4 %s", $d->{obj}, join " ", @{$d->{deps}}), - undef, "\xb6"), "\n"; - print "\tRez ", $d->{deps}->[0], " -o {Targ} {ROptions}\n\n"; - } - foreach $arch (qw(68K CFM68K)) { - foreach $d (&deps("X.\L$arch\E.o", "", "::", ":")) { - next unless $d->{obj}; - print &splitline(sprintf("%s \xc4 %s", $d->{obj}, - join " ", @{$d->{deps}}), - undef, "\xb6"), "\n"; - print "\t{C_$arch} ", $d->{deps}->[0], - " -o {Targ} {COptions_$arch}\n\n"; - } - } - foreach $arch (qw(PPC Carbon)) { - foreach $d (&deps("X.\L$arch\E.o", "", "::", ":")) { - next unless $d->{obj}; - print &splitline(sprintf("%s \xc4 %s", $d->{obj}, - join " ", @{$d->{deps}}), - undef, "\xb6"), "\n"; - # The odd stuff here seems to stop afpd getting confused. - print "\techo -n > {Targ}\n"; - print "\tsetfile -t XCOF {Targ}\n"; - print "\t{C_$arch} ", $d->{deps}->[0], - " -o {Targ} {COptions_$arch}\n\n"; - } - } - select STDOUT; close OUT; -} - -if (defined $makefiles{'lcc'}) { - $mftyp = 'lcc'; - $dirpfx = &dirpfx($makefiles{'lcc'}, "\\"); - - ##-- lcc makefile - open OUT, ">$makefiles{'lcc'}"; select OUT; - print - "# Makefile for $project_name under lcc.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - # lcc command line option is -D not /D - ($_ = $help) =~ s/=\/D/=-D/gs; - print $_; - print - "\n". - "# If you rename this file to `Makefile', you should change this line,\n". - "# so that the .rsp files still depend on the correct makefile.\n". - "MAKEFILE = Makefile.lcc\n". - "\n". - "# C compilation flags\n". - "CFLAGS = -D_WINDOWS " . - (join " ", map {"-I$dirpfx$_"} @srcdirs) . - "\n". - "\n". - "# Get include directory for resource compiler\n". - "\n"; - print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C")); - print "\n\n"; - foreach $p (&prognames("G:C")) { - ($prog, $type) = split ",", $p; - $objstr = &objects($p, "X.obj", "X.res", undef); - print &splitline("$prog.exe: " . $objstr ), "\n"; - $subsystemtype = undef; - if ($type eq "G") { $subsystemtype = "-subsystem windows"; } - my $libss = "shell32.lib wsock32.lib ws2_32.lib winspool.lib winmm.lib imm32.lib"; - print &splitline("\tlcclnk $subsystemtype -o $prog.exe $objstr $libss"); - print "\n\n"; - } - - foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\")) { - print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})), - "\n"; - if ($d->{obj} =~ /\.res$/) { - print &splitline("\tlrc \$(FWHACK) \$(RCFL) -r \$*.rc",69)."\n"; - } else { - $deflist = join "", map { " -D$_" } @{$d->{defs}}; - print &splitline("\tlcc -O -p6 \$(COMPAT) \$(FWHACK) \$(CFLAGS)". - " \$(XFLAGS)$deflist ".$d->{deps}->[0]." -o \$\@",69)."\n"; - } - } - print "\n"; - print $makefile_extra{'lcc'} || ""; - print "\nclean:\n". - "\t-del *.obj\n". - "\t-del *.exe\n". - "\t-del *.res\n"; - - select STDOUT; close OUT; -} - -if (defined $makefiles{'nestedvm'}) { - $mftyp = 'nestedvm'; - $dirpfx = &dirpfx($makefiles{'nestedvm'}, "/"); - - ##-- NestedVM makefile - open OUT, ">$makefiles{'nestedvm'}"; select OUT; - print - "# Makefile for $project_name under NestedVM.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - # gcc command line option is -D not /D - ($_ = $help) =~ s/=\/D/=-D/gs; - print $_; - print - "\n". - "# This path points at the nestedvm root directory\n". - "NESTEDVM = /opt/nestedvm\n". - "# You can define this path to point at your tools if you need to\n". - "TOOLPATH = \$(NESTEDVM)/upstream/install/bin\n". - "CC = \$(TOOLPATH)/mips-unknown-elf-gcc\n". - "\n". - &splitline("CFLAGS = -O2 -Wall -Werror -DSLOW_SYSTEM -g " . - (join " ", map {"-I$dirpfx$_"} @srcdirs))."\n". - "\n"; - print &splitline("all:" . join "", map { " $_.jar" } &progrealnames("X")); - print "\n\n"; - foreach $p (&prognames("X")) { - ($prog, $type) = split ",", $p; - $objstr = &objects($p, "X.o", undef, undef); - $objstr =~ s/gtk\.o/nestedvm\.o/g; - print &splitline($prog . ".mips: " . $objstr), "\n"; - $libstr = &objects($p, undef, undef, "-lX"); - print &splitline("\t\$(CC) \$(${type}LDFLAGS) -o \$@ " . - $objstr . " $libstr -lm", 69), "\n\n"; - } - foreach $d (&deps("X.o", undef, $dirpfx, "/")) { - $oobjs = $d->{obj}; - $ddeps= join " ", @{$d->{deps}}; - $oobjs =~ s/gtk/nestedvm/g; - $ddeps =~ s/gtk/nestedvm/g; - print &splitline(sprintf("%s: %s", $oobjs, $ddeps)), - "\n"; - $deflist = join "", map { " -D$_" } @{$d->{defs}}; - print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS)$deflist" . - " -c \$< -o \$\@\n"; - } - print "\n"; - print $makefile_extra{'nestedvm'} || ""; - print "\nclean:\n". - "\trm -rf *.o *.mips *.class *.html *.jar org applet.manifest\n"; - select STDOUT; close OUT; -} - -if (defined $makefiles{'osx'}) { - $mftyp = 'osx'; - $dirpfx = &dirpfx($makefiles{'osx'}, "/"); - @osxarchs = ('x86_64'); - my $osxminver = "10.6"; - - ##-- Mac OS X makefile - open OUT, ">$makefiles{'osx'}"; select OUT; - print - "# Makefile for $project_name under Mac OS X.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - # gcc command line option is -D not /D - ($_ = $help) =~ s/=\/D/=-D/gs; - print $_; - print - "CC = \$(TOOLPATH)gcc\n". - "LIPO = \$(TOOLPATH)lipo\n". - "\n". - &splitline("CFLAGS = -O2 -Wall -Werror -g " . - (join " ", map {"-I$dirpfx$_"} @srcdirs))."\n". - "LDFLAGS = -framework Cocoa\n". - &splitline("all:" . join "", map { " $_" } &progrealnames("MX:U")) . - "\n"; - print $makefile_extra{'osx'} || ""; - print "\n". - ".SUFFIXES: .o .c .m\n". - "\n"; - print "\n\n"; - foreach $p (&prognames("MX")) { - ($prog, $type) = split ",", $p; - $icon = &special($p, ".icns"); - $infoplist = &special($p, "info.plist"); - print "${prog}.app:\n\tmkdir -p \$\@\n"; - print "${prog}.app/Contents: ${prog}.app\n\tmkdir -p \$\@\n"; - print "${prog}.app/Contents/MacOS: ${prog}.app/Contents\n\tmkdir -p \$\@\n"; - $targets = "${prog}.app/Contents/MacOS/$prog"; - if (defined $icon) { - print "${prog}.app/Contents/Resources: ${prog}.app/Contents\n\tmkdir -p \$\@\n"; - print "${prog}.app/Contents/Resources/${prog}.icns: ${prog}.app/Contents/Resources $icon\n\tcp $icon \$\@\n"; - $targets .= " ${prog}.app/Contents/Resources/${prog}.icns"; - } - if (defined $infoplist) { - print "${prog}.app/Contents/Info.plist: ${prog}.app/Contents/Resources $infoplist\n\tcp $infoplist \$\@\n"; - $targets .= " ${prog}.app/Contents/Info.plist"; - } - $targets .= " \$(${prog}_extra)"; - print &splitline("${prog}: $targets", 69) . "\n\n"; - $libstr = &objects($p, undef, undef, "-lX"); - $archbins = ""; - foreach $arch (@osxarchs) { - $objstr = &objects($p, "X.${arch}.o", undef, undef); - print &splitline("${prog}.${arch}.bin: " . $objstr), "\n"; - print &splitline("\t\$(CC) -arch ${arch} -mmacosx-version-min=${osxminver} \$(LDFLAGS) -o \$@ " . - $objstr . " $libstr", 69), "\n\n"; - $archbins .= " ${prog}.${arch}.bin"; - } - print &splitline("${prog}.app/Contents/MacOS/$prog: ". - "${prog}.app/Contents/MacOS" . $archbins), "\n"; - print &splitline("\t\$(LIPO) -create $archbins -output \$@", 69), "\n\n"; - } - foreach $p (&prognames("U")) { - ($prog, $type) = split ",", $p; - $libstr = &objects($p, undef, undef, "-lX"); - $archbins = ""; - foreach $arch (@osxarchs) { - $objstr = &objects($p, "X.${arch}.o", undef, undef); - print &splitline("${prog}.${arch}: " . $objstr), "\n"; - print &splitline("\t\$(CC) -arch ${arch} -mmacosx-version-min=${osxminver} \$(ULDFLAGS) -o \$@ " . - $objstr . " $libstr", 69), "\n\n"; - $archbins .= " ${prog}.${arch}"; - } - print &splitline("${prog}:" . $archbins), "\n"; - print &splitline("\t\$(LIPO) -create $archbins -output \$@", 69), "\n\n"; - } - foreach $arch (@osxarchs) { - foreach $d (&deps("X.${arch}.o", undef, $dirpfx, "/")) { - print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})), - "\n"; - $deflist = join "", map { " -D$_" } @{$d->{defs}}; - if ($d->{deps}->[0] =~ /\.m$/) { - print "\t\$(CC) -arch $arch -mmacosx-version-min=${osxminver} -x objective-c \$(COMPAT) \$(FWHACK) \$(CFLAGS)". - " \$(XFLAGS)$deflist -c \$< -o \$\@\n"; - } else { - print "\t\$(CC) -arch $arch -mmacosx-version-min=${osxminver} \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS)$deflist" . - " -c \$< -o \$\@\n"; - } - } - } - print "\nclean:\n". - "\trm -f *.o *.dmg". (join "", map { my $a=$_; (" $a", map { " ${a}.$_" } @osxarchs) } &progrealnames("U")) . "\n". - "\trm -rf *.app\n"; - select STDOUT; close OUT; -} - -if (defined $makefiles{'gnustep'}) { - $mftyp = 'gnustep'; - $dirpfx = &dirpfx($makefiles{'gnustep'}, "/"); - - ##-- GNUstep makefile (use with 'gs_make -f Makefile.gnustep') - - # This is a pretty evil way to do things. In an ideal world, I'd - # use the approved GNUstep makefile mechanism which just defines a - # variable or two saying what source files go into what binary and - # then includes application.make. Unfortunately, that has the - # automake-ish limitation that it doesn't let you choose different - # command lines for each object, so I can't arrange for all those - # files with -DTHIS and -DTHAT to Just Work. - # - # A simple if ugly fix would be to have mkfiles.pl construct a - # directory full of stub C files of the form '#define thing', - # '#include "real_source_file"', and then reference those in this - # makefile. That would also make it easy to build a proper - # automake makefile. - open OUT, ">$makefiles{'gnustep'}"; select OUT; - print - "# Makefile for $project_name under GNUstep.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - # gcc command line option is -D not /D - ($_ = $help) =~ s/=\/D/=-D/gs; - print $_; - print - "NEEDS_GUI=yes\n". - "include \$(GNUSTEP_MAKEFILES)/common.make\n". - "include \$(GNUSTEP_MAKEFILES)/rules.make\n". - "include \$(GNUSTEP_MAKEFILES)/Instance/rules.make\n". - "\n". - &splitline("all::" . join "", map { " $_" } &progrealnames("MX:U")) . - "\n"; - print $makefile_extra{'gnustep'} || ""; - print "\n". - ".SUFFIXES: .o .c .m\n". - "\n"; - print "\n\n"; - foreach $p (&prognames("MX")) { - ($prog, $type) = split ",", $p; - $icon = &special($p, ".icns"); - $infoplist = &special($p, "info.plist"); - print "${prog}.app:\n\tmkdir -p \$\@\n"; - $targets = "${prog}.app ${prog}.app/$prog"; - if (defined $icon) { - print "${prog}.app/Resources: ${prog}.app\n\tmkdir -p \$\@\n"; - print "${prog}.app/Resources/${prog}.icns: ${prog}.app/Resources $icon\n\tcp $icon \$\@\n"; - $targets .= " ${prog}.app/Resources/${prog}.icns"; - } - if (defined $infoplist) { - print "${prog}.app/Info.plist: ${prog}.app $infoplist\n\tcp $infoplist \$\@\n"; - $targets .= " ${prog}.app/Info.plist"; - } - $targets .= " \$(${prog}_extra)"; - print &splitline("${prog}: $targets", 69) . "\n\n"; - $libstr = &objects($p, undef, undef, "-lX"); - $objstr = &objects($p, "X.o", undef, undef); - print &splitline("${prog}.app/$prog: " . $objstr), "\n"; - print &splitline("\t\$(CC) \$(ALL_LDFLAGS) -o \$@ " . $objstr . " \$(ALL_LIB_DIRS) $libstr \$(ALL_LIBS)", 69), "\n\n"; - } - foreach $p (&prognames("U")) { - ($prog, $type) = split ",", $p; - $libstr = &objects($p, undef, undef, "-lX"); - $objstr = &objects($p, "X.o", undef, undef); - print &splitline("${prog}: " . $objstr), "\n"; - print &splitline("\t\$(CC) \$(ULDFLAGS) -o \$@ " . $objstr . " $libstr", 69), "\n\n"; - } - foreach $d (&deps("X.o", undef, $dirpfx, "/")) { - print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})), - "\n"; - $deflist = join "", map { " -D$_" } @{$d->{defs}}; - if ($d->{deps}->[0] =~ /\.m$/) { - print "\t\$(CC) -DGNUSTEP \$(ALL_OBJCFLAGS) \$(COMPAT) \$(FWHACK) \$(OBJCFLAGS)". - " \$(XFLAGS)$deflist -c \$< -o \$\@\n"; - } else { - print "\t\$(CC) \$(ALL_CFLAGS) \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS)$deflist" . - " -c \$< -o \$\@\n"; - } - } - print "\nclean::\n". - "\trm -f *.o ". (join " ", &progrealnames("U")) . "\n". - "\trm -rf *.app\n"; - select STDOUT; close OUT; -} - -if (defined $makefiles{'emcc'}) { - $mftyp = 'emcc'; - $dirpfx = &dirpfx($makefiles{'emcc'}, "/"); - - ##-- Makefile for building Javascript puzzles via Emscripten - - open OUT, ">$makefiles{'emcc'}"; select OUT; - print - "# Makefile for $project_name using Emscripten. Requires GNU make.\n". - "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n". - "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n"; - # emcc command line option is -D not /D - ($_ = $help) =~ s/=\/D/=-D/gs; - print $_; - print - "\n". - "# This can be set on the command line to point at the emcc command,\n". - "# if it is not on your PATH.\n". - "EMCC = emcc\n". - "\n". - &splitline("CFLAGS = -DSLOW_SYSTEM " . - (join " ", map {"-I$dirpfx$_"} @srcdirs))."\n". - "\n"; - $output_js_files = join "", map { " \$(OUTPREFIX)$_.js" } &progrealnames("X"); - print &splitline("all:" . $output_js_files); - print "\n\n"; - foreach $p (&prognames("X")) { - ($prog, $type) = split ",", $p; - $objstr = &objects($p, "X.o", undef, undef); - $objstr =~ s/gtk\.o/emcc\.o/g; - print &splitline("\$(OUTPREFIX)" . $prog . ".js: " . $objstr . " emccpre.js emcclib.js emccx.json"), "\n"; - print "\t\$(EMCC) -o \$(OUTPREFIX)".$prog.".js ". - "-O2 ". - "-s ASM_JS=1 ". - "--pre-js emccpre.js ". - "--js-library emcclib.js ". - "-s EXPORTED_FUNCTIONS=\"`sed 's://.*::' emccx.json | tr -d ' \\n'`\" " . $objstr . "\n\n"; - } - foreach $d (&deps("X.o", undef, $dirpfx, "/")) { - $oobjs = $d->{obj}; - $ddeps= join " ", @{$d->{deps}}; - $oobjs =~ s/gtk/emcc/g; - $ddeps =~ s/gtk/emcc/g; - print &splitline(sprintf("%s: %s", $oobjs, $ddeps)), - "\n"; - $deflist = join "", map { " -D$_" } @{$d->{defs}}; - print "\t\$(EMCC) \$(CFLAGS) \$(XFLAGS)$deflist" . - " -c \$< -o \$\@\n"; - } - print "\n"; - print $makefile_extra{'emcc'} || ""; - print "\nclean:\n". - "\trm -rf *.o $output_js_files\n"; - select STDOUT; close OUT; -} - -# All done, so do the Unix postprocessing if asked to. - -if ($do_unix) { - chdir $orig_dir; - system "./mkauto.sh"; - die "mkfiles.pl: mkauto.sh returned $?\n" if $? > 0; - system "./configure", @confargs; - die "mkfiles.pl: configure returned $?\n" if $? > 0; -} diff --git a/net.R b/net.R deleted file mode 100644 index 8e98216..0000000 --- a/net.R +++ /dev/null @@ -1,23 +0,0 @@ -# -*- makefile -*- - -NET_EXTRA = tree234 dsf findloop - -net : [X] GTK COMMON net NET_EXTRA net-icon|no-icon - -# The Windows Net shouldn't be called `net.exe' since Windows -# already has a reasonably important utility program by that name! -netgame : [G] WINDOWS COMMON net NET_EXTRA net.res|noicon.res - -ALL += net[COMBINED] NET_EXTRA - -!begin am gtk -GAMES += net -!end - -!begin >list.c - A(net) \ -!end - -!begin >gamedesc.txt -net:netgame.exe:Net:Network jigsaw puzzle:Rotate each tile to reassemble the network. -!end diff --git a/netslide.R b/netslide.R deleted file mode 100644 index ecfe7c3..0000000 --- a/netslide.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -NETSLIDE_EXTRA = tree234 - -netslide : [X] GTK COMMON netslide NETSLIDE_EXTRA netslide-icon|no-icon - -netslide : [G] WINDOWS COMMON netslide NETSLIDE_EXTRA netslide.res|noicon.res - -ALL += netslide[COMBINED] NETSLIDE_EXTRA - -!begin am gtk -GAMES += netslide -!end - -!begin >list.c - A(netslide) \ -!end - -!begin >gamedesc.txt -netslide:netslide.exe:Netslide:Toroidal sliding network puzzle:Slide a row at a time to reassemble the network. -!end diff --git a/noicon.rc b/noicon.rc deleted file mode 100644 index 1de605d..0000000 --- a/noicon.rc +++ /dev/null @@ -1,11 +0,0 @@ -/* Puzzle resource file without an icon, used in the absence of icons/foo.rc */ - -#include "puzzles.rc2" - -/* XXX this probably isn't the right test, but it'll do. */ -#ifdef MINGW32_FIX -/* XXX The MinGW toolchain (specifically, windres) doesn't like a resource - * file with no resources. Give it a dummy one. - * This can go if/when VERSIONINFO resources are added. */ -200 RCDATA { 0 } -#endif diff --git a/nullgame.R b/nullgame.R deleted file mode 100644 index 41bdb85..0000000 --- a/nullgame.R +++ /dev/null @@ -1,12 +0,0 @@ -# -*- makefile -*- - -# The `nullgame' source file is a largely blank one, which contains -# all the correct function definitions to compile and link, but -# which defines the null game in which nothing is ever drawn and -# there are no valid moves. Its main purpose is to act as a -# template for writing new game definition source files. I include -# it in the Makefile because it will be worse than useless if it -# ever fails to compile, so it's important that it should actually -# be built on a regular basis. -nullgame : [X] GTK COMMON nullgame nullgame-icon|no-icon -nullgame : [G] WINDOWS COMMON nullgame nullgame.res|noicon.res diff --git a/osx.m b/osx.m index 0793817..ee9161f 100644 --- a/osx.m +++ b/osx.m @@ -77,7 +77,9 @@ * recreate it. */ -#define COMBINED /* we put all the puzzles in one binary in this port */ +#ifndef COMBINED +#error Expected -DCOMBINED to come from the makefile +#endif #include #include diff --git a/osx-info.plist b/osx/Info.plist similarity index 100% rename from osx-info.plist rename to osx/Info.plist diff --git a/osx.icns b/osx/Puzzles.icns similarity index 100% rename from osx.icns rename to osx/Puzzles.icns diff --git a/palisade.R b/palisade.R deleted file mode 100644 index de4bd83..0000000 --- a/palisade.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -PALISADE_EXTRA = divvy dsf - -palisade : [X] GTK COMMON palisade PALISADE_EXTRA palisade-icon|no-icon - -palisade : [G] WINDOWS COMMON palisade PALISADE_EXTRA palisade.res|noicon.res - -ALL += palisade[COMBINED] PALISADE_EXTRA - -!begin am gtk -GAMES += palisade -!end - -!begin >list.c - A(palisade) \ -!end - -!begin >gamedesc.txt -palisade:palisade.exe:Palisade:Grid-division puzzle:Divide the grid into equal-sized areas in accordance with the clues. -!end diff --git a/pattern.R b/pattern.R deleted file mode 100644 index d669571..0000000 --- a/pattern.R +++ /dev/null @@ -1,25 +0,0 @@ -# -*- makefile -*- - -pattern : [X] GTK COMMON pattern pattern-icon|no-icon - -pattern : [G] WINDOWS COMMON pattern pattern.res|noicon.res - -patternsolver : [U] pattern[STANDALONE_SOLVER] STANDALONE -patternsolver : [C] pattern[STANDALONE_SOLVER] STANDALONE - -patternpicture : [U] pattern[STANDALONE_PICTURE_GENERATOR] STANDALONE -patternpicture : [C] pattern[STANDALONE_PICTURE_GENERATOR] STANDALONE - -ALL += pattern[COMBINED] - -!begin am gtk -GAMES += pattern -!end - -!begin >list.c - A(pattern) \ -!end - -!begin >gamedesc.txt -pattern:pattern.exe:Pattern:Pattern puzzle:Fill in the pattern in the grid, given only the lengths of runs of black squares. -!end diff --git a/pearl.R b/pearl.R deleted file mode 100644 index 79bc732..0000000 --- a/pearl.R +++ /dev/null @@ -1,23 +0,0 @@ -# -*- makefile -*- - -PEARL_EXTRA = dsf tree234 grid penrose loopgen tdq - -pearl : [X] GTK COMMON pearl PEARL_EXTRA pearl-icon|no-icon -pearl : [G] WINDOWS COMMON pearl PEARL_EXTRA pearl.res? - -pearlbench : [U] pearl[STANDALONE_SOLVER] PEARL_EXTRA STANDALONE m.lib -pearlbench : [C] pearl[STANDALONE_SOLVER] PEARL_EXTRA STANDALONE - -ALL += pearl[COMBINED] PEARL_EXTRA - -!begin am gtk -GAMES += pearl -!end - -!begin >list.c - A(pearl) \ -!end - -!begin >gamedesc.txt -pearl:pearl.exe:Pearl:Loop-drawing puzzle:Draw a single closed loop, given clues about corner and straight squares. -!end diff --git a/pegs.R b/pegs.R deleted file mode 100644 index 1e79e99..0000000 --- a/pegs.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -PEGS_EXTRA = tree234 - -pegs : [X] GTK COMMON pegs PEGS_EXTRA pegs-icon|no-icon - -pegs : [G] WINDOWS COMMON pegs PEGS_EXTRA pegs.res|noicon.res - -ALL += pegs[COMBINED] PEGS_EXTRA - -!begin am gtk -GAMES += pegs -!end - -!begin >list.c - A(pegs) \ -!end - -!begin >gamedesc.txt -pegs:pegs.exe:Pegs:Peg solitaire puzzle:Jump pegs over each other to remove all but one. -!end diff --git a/puzzles.rc2 b/puzzles.rc similarity index 82% rename from puzzles.rc2 rename to puzzles.rc index 4442a9b..4574f52 100644 --- a/puzzles.rc2 +++ b/puzzles.rc @@ -1,4 +1,15 @@ -/* Standard stuff that goes into the Windows resources for all puzzles. */ +/* Windows resource file for all puzzles. */ + +#if defined ICON_FILE +200 ICON ICON_FILE +#else +#ifdef MINGW32_FIX +/* XXX The MinGW toolchain (specifically, windres) doesn't like a resource + * file with no resources. Give it a dummy one. + * This can go if/when VERSIONINFO resources are added. */ +200 RCDATA { 0 } +#endif +#endif #ifdef _WIN32_WCE diff --git a/range.R b/range.R deleted file mode 100644 index f1256ef..0000000 --- a/range.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -RANGE_EXTRA = dsf - -range : [X] GTK COMMON range RANGE_EXTRA range-icon|no-icon - -range : [G] WINDOWS COMMON range RANGE_EXTRA range.res|noicon.res - -ALL += range[COMBINED] RANGE_EXTRA - -!begin am gtk -GAMES += range -!end - -!begin >list.c - A(range) \ -!end - -!begin >gamedesc.txt -range:range.exe:Range:Visible-distance puzzle:Place black squares to limit the visible distance from each numbered cell. -!end diff --git a/rect.R b/rect.R deleted file mode 100644 index 1448c0f..0000000 --- a/rect.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -rect : [X] GTK COMMON rect rect-icon|no-icon - -rect : [G] WINDOWS COMMON rect rect.res|noicon.res - -ALL += rect[COMBINED] - -!begin am gtk -GAMES += rect -!end - -!begin >list.c - A(rect) \ -!end - -!begin >gamedesc.txt -rect:rect.exe:Rectangles:Rectangles puzzle:Divide the grid into rectangles with areas equal to the numbers. -!end diff --git a/samegame.R b/samegame.R deleted file mode 100644 index cc0d350..0000000 --- a/samegame.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -samegame : [X] GTK COMMON samegame samegame-icon|no-icon - -samegame : [G] WINDOWS COMMON samegame samegame.res|noicon.res - -ALL += samegame[COMBINED] - -!begin am gtk -GAMES += samegame -!end - -!begin >list.c - A(samegame) \ -!end - -!begin >gamedesc.txt -samegame:samegame.exe:Same Game:Block-clearing puzzle:Clear the grid by removing touching groups of the same colour squares. -!end diff --git a/signpost.R b/signpost.R deleted file mode 100644 index 09ea367..0000000 --- a/signpost.R +++ /dev/null @@ -1,23 +0,0 @@ -# -*- makefile -*- - -SIGNPOST_EXTRA = dsf - -signpost : [X] GTK COMMON signpost SIGNPOST_EXTRA signpost-icon|no-icon -signpost : [G] WINDOWS COMMON signpost SIGNPOST_EXTRA signpost.res|noicon.res - -signpostsolver : [U] signpost[STANDALONE_SOLVER] SIGNPOST_EXTRA STANDALONE m.lib -signpostsolver : [C] signpost[STANDALONE_SOLVER] SIGNPOST_EXTRA STANDALONE - -ALL += signpost[COMBINED] SIGNPOST_EXTRA - -!begin am gtk -GAMES += signpost -!end - -!begin >list.c - A(signpost) \ -!end - -!begin >gamedesc.txt -signpost:signpost.exe:Signpost:Square-connecting puzzle:Connect the squares into a path following the arrows. -!end diff --git a/singles.R b/singles.R deleted file mode 100644 index a67aed2..0000000 --- a/singles.R +++ /dev/null @@ -1,23 +0,0 @@ -# -*- makefile -*- - -SINGLES_EXTRA = dsf LATIN - -singles : [X] GTK COMMON singles SINGLES_EXTRA singles-icon|no-icon -singles : [G] WINDOWS COMMON singles SINGLES_EXTRA singles.res|noicon.res - -ALL += singles[COMBINED] SINGLES_EXTRA - -singlessolver : [U] singles[STANDALONE_SOLVER] SINGLES_EXTRA STANDALONE -singlessolver : [C] singles[STANDALONE_SOLVER] SINGLES_EXTRA STANDALONE - -!begin am gtk -GAMES += singles -!end - -!begin >list.c - A(singles) \ -!end - -!begin >gamedesc.txt -singles:singles.exe:Singles:Number-removing puzzle:Black out the right set of duplicate numbers. -!end diff --git a/sixteen.R b/sixteen.R deleted file mode 100644 index c63a27c..0000000 --- a/sixteen.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -sixteen : [X] GTK COMMON sixteen sixteen-icon|no-icon - -sixteen : [G] WINDOWS COMMON sixteen sixteen.res|noicon.res - -ALL += sixteen[COMBINED] - -!begin am gtk -GAMES += sixteen -!end - -!begin >list.c - A(sixteen) \ -!end - -!begin >gamedesc.txt -sixteen:sixteen.exe:Sixteen:Toroidal sliding block puzzle:Slide a row at a time to arrange the tiles into order. -!end diff --git a/slant.R b/slant.R deleted file mode 100644 index ff0d21f..0000000 --- a/slant.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -SLANT_EXTRA = dsf findloop - -slant : [X] GTK COMMON slant SLANT_EXTRA slant-icon|no-icon - -slant : [G] WINDOWS COMMON slant SLANT_EXTRA slant.res|noicon.res - -slantsolver : [U] slant[STANDALONE_SOLVER] SLANT_EXTRA STANDALONE -slantsolver : [C] slant[STANDALONE_SOLVER] SLANT_EXTRA STANDALONE - -ALL += slant[COMBINED] SLANT_EXTRA - -!begin am gtk -GAMES += slant -!end - -!begin >list.c - A(slant) \ -!end - -!begin >gamedesc.txt -slant:slant.exe:Slant:Maze-drawing puzzle:Draw a maze of slanting lines that matches the clues. -!end diff --git a/solo.R b/solo.R deleted file mode 100644 index 081a761..0000000 --- a/solo.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -SOLO_EXTRA = divvy dsf - -solo : [X] GTK COMMON solo SOLO_EXTRA solo-icon|no-icon - -solo : [G] WINDOWS COMMON solo SOLO_EXTRA solo.res|noicon.res - -solosolver : [U] solo[STANDALONE_SOLVER] SOLO_EXTRA STANDALONE -solosolver : [C] solo[STANDALONE_SOLVER] SOLO_EXTRA STANDALONE - -ALL += solo[COMBINED] SOLO_EXTRA - -!begin am gtk -GAMES += solo -!end - -!begin >list.c - A(solo) \ -!end - -!begin >gamedesc.txt -solo:solo.exe:Solo:Number placement puzzle:Fill in the grid so that each row, column and square block contains one of every digit. -!end diff --git a/tents.R b/tents.R deleted file mode 100644 index 925661c..0000000 --- a/tents.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -TENTS_EXTRA = matching dsf - -tents : [X] GTK COMMON tents TENTS_EXTRA tents-icon|no-icon - -tents : [G] WINDOWS COMMON tents TENTS_EXTRA tents.res|noicon.res - -ALL += tents[COMBINED] TENTS_EXTRA - -tentssolver : [U] tents[STANDALONE_SOLVER] TENTS_EXTRA STANDALONE -tentssolver : [C] tents[STANDALONE_SOLVER] TENTS_EXTRA STANDALONE - -!begin am gtk -GAMES += tents -!end - -!begin >list.c - A(tents) \ -!end - -!begin >gamedesc.txt -tents:tents.exe:Tents:Tent-placing puzzle:Place a tent next to each tree. -!end diff --git a/towers.R b/towers.R deleted file mode 100644 index c2bb78a..0000000 --- a/towers.R +++ /dev/null @@ -1,25 +0,0 @@ -# -*- makefile -*- - -TOWERS_EXTRA = LATIN -TOWERS_EXTRA_SOLVER = LATIN_SOLVER - -towers : [X] GTK COMMON towers TOWERS_EXTRA towers-icon|no-icon - -towers : [G] WINDOWS COMMON towers TOWERS_EXTRA towers.res|noicon.res - -towerssolver : [U] towers[STANDALONE_SOLVER] TOWERS_EXTRA_SOLVER STANDALONE -towerssolver : [C] towers[STANDALONE_SOLVER] TOWERS_EXTRA_SOLVER STANDALONE - -ALL += towers[COMBINED] TOWERS_EXTRA - -!begin am gtk -GAMES += towers -!end - -!begin >list.c - A(towers) \ -!end - -!begin >gamedesc.txt -towers:towers.exe:Towers:Tower-placing Latin square puzzle:Complete the latin square of towers in accordance with the clues. -!end diff --git a/tracks.R b/tracks.R deleted file mode 100644 index 8b0ac97..0000000 --- a/tracks.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -TRACKS_EXTRA = dsf findloop - -tracks : [X] GTK COMMON tracks TRACKS_EXTRA tracks-icon|no-icon - -tracks : [G] WINDOWS COMMON tracks TRACKS_EXTRA tracks.res|noicon.res - -ALL += tracks[COMBINED] TRACKS_EXTRA - -trackssolver : [U] tracks[STANDALONE_SOLVER] TRACKS_EXTRA STANDALONE -trackssolver : [C] tracks[STANDALONE_SOLVER] TRACKS_EXTRA STANDALONE - -!begin am gtk -GAMES += tracks -!end - -!begin >list.c - A(tracks) \ -!end - -!begin >gamedesc.txt -tracks:tracks.exe:Tracks:Path-finding railway track puzzle:Fill in the railway track according to the clues. -!end diff --git a/twiddle.R b/twiddle.R deleted file mode 100644 index 1495c33..0000000 --- a/twiddle.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -twiddle : [X] GTK COMMON twiddle twiddle-icon|no-icon - -twiddle : [G] WINDOWS COMMON twiddle twiddle.res|noicon.res - -ALL += twiddle[COMBINED] - -!begin am gtk -GAMES += twiddle -!end - -!begin >list.c - A(twiddle) \ -!end - -!begin >gamedesc.txt -twiddle:twiddle.exe:Twiddle:Rotational sliding block puzzle:Rotate the tiles around themselves to arrange them into order. -!end diff --git a/undead.R b/undead.R deleted file mode 100644 index 5907ed6..0000000 --- a/undead.R +++ /dev/null @@ -1,18 +0,0 @@ -# -*- makefile -*- - -undead : [X] GTK COMMON undead undead-icon|no-icon -undead : [G] WINDOWS COMMON undead undead.res|noicon.res - -ALL += undead[COMBINED] - -!begin am gtk -GAMES += undead -!end - -!begin >list.c - A(undead) \ -!end - -!begin >gamedesc.txt -undead:undead.exe:Undead:Monster-placing puzzle:Place ghosts, vampires and zombies so that the right numbers of them can be seen in mirrors. -!end diff --git a/unequal.R b/unequal.R deleted file mode 100644 index 077407f..0000000 --- a/unequal.R +++ /dev/null @@ -1,25 +0,0 @@ -# -*- makefile -*- - -UNEQUAL_EXTRA = LATIN -UNEQUAL_EXTRA_SOLVER = LATIN_SOLVER - -unequal : [X] GTK COMMON unequal UNEQUAL_EXTRA unequal-icon|no-icon - -unequal : [G] WINDOWS COMMON unequal UNEQUAL_EXTRA unequal.res|noicon.res - -unequalsolver : [U] unequal[STANDALONE_SOLVER] UNEQUAL_EXTRA_SOLVER STANDALONE -unequalsolver : [C] unequal[STANDALONE_SOLVER] UNEQUAL_EXTRA_SOLVER STANDALONE - -ALL += unequal[COMBINED] UNEQUAL_EXTRA - -!begin am gtk -GAMES += unequal -!end - -!begin >list.c - A(unequal) \ -!end - -!begin >gamedesc.txt -unequal:unequal.exe:Unequal:Latin square puzzle:Complete the latin square in accordance with the > signs. -!end diff --git a/unfinished/CMakeLists.txt b/unfinished/CMakeLists.txt new file mode 100644 index 0000000..0c1e331 --- /dev/null +++ b/unfinished/CMakeLists.txt @@ -0,0 +1,31 @@ +puzzle(group + DISPLAYNAME "Group" + DESCRIPTION "Group theory puzzle" + OBJECTIVE "Complete the unfinished Cayley table of a group.") +solver(group ${CMAKE_SOURCE_DIR}/latin.c) + +puzzle(separate + DISPLAYNAME "Separate" + DESCRIPTION "Rectangle-dividing puzzle" + OBJECTIVE "Partition the grid into regions containing one of each letter.") + +puzzle(slide + DISPLAYNAME "Slide" + DESCRIPTION "Sliding block puzzle" + OBJECTIVE "Slide the blocks to let the key block out.") +solver(slide) + +puzzle(sokoban + DISPLAYNAME "Sokoban" + DESCRIPTION "Barrel-pushing puzzle" + OBJECTIVE "Push all the barrels into the target squares.") + +# These unfinished programs don't even have the structure of a puzzle +# game yet; they're just command-line programs containing test +# implementations of some of the needed functionality. + +cliprogram(numgame numgame.c) + +cliprogram(path path.c COMPILE_DEFINITIONS TEST_GEN) + +export_variables_to_parent_scope() diff --git a/unfinished/README b/unfinished/README index 0f8bb41..c96ccc9 100644 --- a/unfinished/README +++ b/unfinished/README @@ -2,8 +2,13 @@ This subdirectory contains puzzle implementations which are half-written, fundamentally flawed, or in other ways unready to be shipped as part of the polished Puzzles collection. -Those puzzles which have .R files can be built as part of the -Puzzles collection by symlinking their source files into the parent -directory and re-running mkfiles.pl. Anything without a .R file -isn't even finished enough to do that, and you should read the -source file itself to find out the status. +The CMake build system will _build_ all of the source in this +directory (to ensure it hasn't become unbuildable), but they won't be +included in all-in-one puzzle binaries or installed by 'make install' +targets. If you want to temporarily change that, you can reconfigure +your build by defining the CMake variable PUZZLES_ENABLE_UNFINISHED. +For example, + + cmake . -DPUZZLES_ENABLE_UNFINISHED="group;slide" + +will build as if both Group and Slide were fully official puzzles. diff --git a/unfinished/group.R b/unfinished/group.R deleted file mode 100644 index 394e364..0000000 --- a/unfinished/group.R +++ /dev/null @@ -1,25 +0,0 @@ -# -*- makefile -*- - -GROUP_EXTRA = LATIN -GROUP_EXTRA_SOLVER = LATIN_SOLVER - -group : [X] GTK COMMON group GROUP_EXTRA group-icon|no-icon - -group : [G] WINDOWS COMMON group GROUP_EXTRA group.res|noicon.res - -groupsolver : [U] group[STANDALONE_SOLVER] GROUP_EXTRA_SOLVER STANDALONE -groupsolver : [C] group[STANDALONE_SOLVER] GROUP_EXTRA_SOLVER STANDALONE - -ALL += group[COMBINED] GROUP_EXTRA - -!begin am gtk -GAMES += group -!end - -!begin >list.c - A(group) \ -!end - -!begin >gamedesc.txt -group:group.exe:Group:Group theory puzzle:Complete the unfinished Cayley table of a group. -!end diff --git a/unfinished/separate.R b/unfinished/separate.R deleted file mode 100644 index f861c8f..0000000 --- a/unfinished/separate.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -SEPARATE_EXTRA = divvy dsf - -separate : [X] GTK COMMON separate SEPARATE_EXTRA separate-icon|no-icon - -separate : [G] WINDOWS COMMON separate SEPARATE_EXTRA separate.res|noicon.res - -ALL += separate[COMBINED] SEPARATE_EXTRA - -!begin am gtk -GAMES += separate -!end - -!begin >list.c - A(separate) \ -!end - -!begin >gamedesc.txt -separate:separate.exe:Separate:Rectangle-dividing puzzle:Partition the grid into regions containing one of each letter. -!end diff --git a/unfinished/slide.R b/unfinished/slide.R deleted file mode 100644 index 189ed65..0000000 --- a/unfinished/slide.R +++ /dev/null @@ -1,24 +0,0 @@ -# -*- makefile -*- - -SLIDE_EXTRA = dsf tree234 - -slide : [X] GTK COMMON slide SLIDE_EXTRA slide-icon|no-icon - -slide : [G] WINDOWS COMMON slide SLIDE_EXTRA slide.res|noicon.res - -slidesolver : [U] slide[STANDALONE_SOLVER] SLIDE_EXTRA STANDALONE -slidesolver : [C] slide[STANDALONE_SOLVER] SLIDE_EXTRA STANDALONE - -ALL += slide[COMBINED] SLIDE_EXTRA - -!begin am gtk -GAMES += slide -!end - -!begin >list.c - A(slide) \ -!end - -!begin >gamedesc.txt -slide:slide.exe:Slide:Sliding block puzzle:Slide the blocks to let the key block out. -!end diff --git a/unfinished/sokoban.R b/unfinished/sokoban.R deleted file mode 100644 index 3b6dab5..0000000 --- a/unfinished/sokoban.R +++ /dev/null @@ -1,19 +0,0 @@ -# -*- makefile -*- - -sokoban : [X] GTK COMMON sokoban sokoban-icon|no-icon - -sokoban : [G] WINDOWS COMMON sokoban sokoban.res? - -ALL += sokoban[COMBINED] - -!begin am gtk -GAMES += sokoban -!end - -!begin >list.c - A(sokoban) \ -!end - -!begin >gamedesc.txt -sokoban:sokoban.exe:Sokoban:Barrel-pushing puzzle:Push all the barrels into the target squares. -!end diff --git a/unruly.R b/unruly.R deleted file mode 100644 index 064ccc3..0000000 --- a/unruly.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -unruly : [X] GTK COMMON unruly unruly-icon|no-icon -unruly : [G] WINDOWS COMMON unruly unruly.res|noicon.res - -unrulysolver : [U] unruly[STANDALONE_SOLVER] STANDALONE -unrulysolver : [C] unruly[STANDALONE_SOLVER] STANDALONE - -ALL += unruly[COMBINED] - -!begin am gtk -GAMES += unruly -!end - -!begin >list.c - A(unruly) \ -!end - -!begin >gamedesc.txt -unruly:unruly.exe:Unruly:Black and white grid puzzle:Fill in the black and white grid to avoid runs of three. -!end diff --git a/untangle.R b/untangle.R deleted file mode 100644 index a57f1e5..0000000 --- a/untangle.R +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- - -UNTANGLE_EXTRA = tree234 - -untangle : [X] GTK COMMON untangle UNTANGLE_EXTRA untangle-icon|no-icon - -untangle : [G] WINDOWS COMMON untangle UNTANGLE_EXTRA untangle.res|noicon.res - -ALL += untangle[COMBINED] UNTANGLE_EXTRA - -!begin am gtk -GAMES += untangle -!end - -!begin >list.c - A(untangle) \ -!end - -!begin >gamedesc.txt -untangle:untangle.exe:Untangle:Planar graph layout puzzle:Reposition the points so that the lines do not cross. -!end diff --git a/webpage.pl b/webpage.pl index c6144bb..c70b0b2 100755 --- a/webpage.pl +++ b/webpage.pl @@ -9,8 +9,10 @@ use strict; use warnings; use HTML::Entities; -open my $desc, "<", "gamedesc.txt" - or die "gamedesc.txt: open: $!\n"; +my $gamedesc = shift @ARGV; + +open my $desc, "<", $gamedesc + or die "$gamedesc: open: $!\n"; open my $spans, ">", "wwwspans.html" or die "wwwspans.html: open: $!\n";