JNEXT
Skip to content

5.1 Make targets

The place to start is make with no arguments, which prints every target together with its description:

$ make

Available targets:

  sdl-debug        Configure and build the SDL-only frontend in Debug mode ...
  ...

There are 69 documented targets at the time of writing. The sections below group them into families rather than listing them one by one, because make is the authority here and the exact number changes.

The self-documenting convention

The convention is a single rule: a # comment line immediately above a target is that target's description. The default target is a small awk program over $(MAKEFILE_LIST) that pairs each such comment with the target underneath it. Nothing else is maintained — there is no second list of targets to keep in sync — so a target that exists is a target make shows.

There is one sharp edge. The awk keeps only the last # line before a target, so a second comment line silently replaces the description rather than extending it. That is not a hypothetical: eight targets, unit-test and regression among them, advertised a sentence fragment for as long as nobody happened to re-read the listing. The rule is therefore enforced rather than remembered. make lint-makefile-help fails if any target's description would be discarded, and it is a prerequisite of both make unit-test and make regression; it costs about 8 ms of awk over one file, so it fails long before anything expensive has started.

That gives you the rule to follow when you add a target: one # line above it, and every word of rationale inside the recipe as @# comment lines. The Makefile is full of those, and they are where the reasoning actually lives.

Build

sdl-* builds the SDL-only frontend and gui-* builds the Qt6 GUI, each in a -debug and a -release flavour. Every build variant also has a -run target, which builds and then runs, and a -clean target; make clean removes all of them along with build/.

gui-release is the binary JNEXT ships and tests, and it is a PGO build: it depends on gui-release-pgo-gen, the instrumented twin, runs the training and then compiles build/gui-release with the profile — see 5.5. gui-release-non-pgo is the same Release build without PGO, in its own tree; it is the one to measure code changes with.

The win-* family cross-compiles Windows executables with the MinGW toolchain. win-release is the x64 Qt6 build; win-qt5-release and win32-qt5-release are the legacy Qt5 legs, 64- and 32-bit, which keep a lower Windows floor than the Qt6 build can offer; and win-sdl-release / win32-sdl-release are SDL-only legs used to validate the cross-build rather than to publish anything. The three published legs are PGO builds trained under wine; WIN_PGO=0 builds any of them without, and win-release-non-pgo does that for the x64 one. Separately, qt5-guard-build compiles the GUI against native Linux Qt5, purely to keep that combination building.

Test

make unit-test builds build/ and runs every declared subsystem suite, and make regression runs the screenshot and functional suite headless. Between them they pull in a set of structural gates as prerequisites — lint-assertions, lint-makefile-help, lint-thread-detach, lint-ascii-text, cli-check, docs-check (which includes docs-devguide-cites-check), traceability-check and friends — which is deliberate: it puts those checks in your inner loop instead of leaving them for CI to discover. make regression also runs make fuse-pgo, the FUSE Z80 opcode suite built against the PGO tree's CPU core, because build/ — where make unit-test runs it — is neither the shipped build nor a Release one. Alongside them, make harness-selftest proves that the test harness itself fails loudly when faults are injected into it, make build-matrix builds every combination of the frontend options, make unit-test-sdl runs the declared suites a second time in the SDL-only configuration (its own build/sdl-unit-test tree, so build/ stays the Qt one), and make unit-test-dashboard runs the unit tests and refreshes the committed per-subsystem status table.

Two more targets run the SDL-only suites on other operating systems. make unit-test-sdl also works on macOS, where the test harness needs Homebrew's bash, coreutils and grep (brew install bash coreutils grep; the target puts them first on PATH for its own recipe only, and the harness refuses with that install line when they are missing). make unit-test-win cross-builds the same suites for Windows with the Fedora MinGW toolchain into build/win-sdl-unit-test (dnf install mingw64-gcc mingw64-gcc-c++ mingw64-SDL3 mingw64-zlib mingw64-libpng mingw64-winpthreads wine-core wine-common) and runs them under wine through test/wine-run.sh, with no display variable set so no window can open on your desktop, under a UTF-8 locale (a non-ASCII file name cannot exist under LC_ALL=C), and, when run as root (the CI container), with CAP_DAC_OVERRIDE and CAP_DAC_READ_SEARCH dropped for wine and wineserver: wine emulates the Windows read-only attribute with a permission bit that root ignores, where real Windows refuses even an administrator. The test executables link with an 8 MB stack (their fixtures hold emulators on the stack; Linux gives a main thread 8 MB, MinGW 2 MB), while jnext.exe keeps the default and its frame gate. Both need the SD image, which make sdcard-image provisions through jnext's own download if it is missing. make unit-test-win is two steps, unit-test-win-build (cross-build the tree) and unit-test-win-run (run it under wine, no compiler needed), so the run step could later be taken over by a real Windows host; it is part of the merge gate for every code change.

make regression-win runs the regression suite's screenshots and the functional rows Windows can run against MinGW-built exes under wine: the Qt exe as shipped minus PGO (win-release-non-pgo, with qoffscreen.dll bundled into that test tree only), the SDL-only exe, and the native helpers from the SDL unit-test tree. make regression-macos is its macOS twin (CI macos-regression). ROWS="..." names rows. Neither is stamped; see the regression suite.

The built tree is not yet a relocatable directory, so there is no recipe for running it by hand on a real Windows machine, and none has been tried. What stands in the way, in order of effort: JNEXT_BINARY (the CLI suite) and the ffmpeg stub's path are compiled in as absolute paths; the suites run with the source checkout as their working directory and read fixtures from it; the unit harness itself needs bash 4, GNU timeout/grep -P and perl, and checks every reported row ID against the suite's source files; the SD image is reached by absolute path through JNEXT_TEST_SD_IMAGE. A bundle (executables, the MinGW DLLs packaging/windows/bundle-dlls.sh copies, the manifest, the harness and the sources it reads) is feasible, but it is its own piece of work.

Chapter 4. Testing covers what each of these actually proves.

Documentation

Each documentation source generates a committed output, and each output has a staleness check guarding it:

Target Renders Guard
docs-man doc/man/jnext.1 + USAGE.md from doc/man/jnext.1.md docs-man-check
docs-userguide doc/user-guide from src/doc/user-guide docs-userguide-check
docs-devguide doc/developer-guide from src/doc/developer-guide docs-devguide-check
docs-devguide-diagrams the guide's committed SVGs from Graphviz .dot sources (same check)
(none) the guide's file and line cites, checked against the code docs-devguide-cites-check
docs-screenshots the user guide's Qt screenshots (img/debugger-*.png, the main window, Preferences) from the running debugger none — see below

make docs-check runs the first three guards and the cite check and aggregates their results, so one stale document never hides another behind it. It is a prerequisite of both test targets. For reading rather than checking, make read-userguide and make read-devguide serve the rendered sites on localhost.

docs-screenshots is the odd one out: it regenerates pictures rather than text, it needs a Qt build, an offscreen QPA platform and an SD image to boot, and it has no staleness guard — a byte comparison would fail on any Qt or font update rather than on a stale image. 1.3 explains what it covers, what it does not, and why the gate was declined.

Packaging and version

package-src, package-rpm, package-deb, package-flatpak, package-macos and the five package-win* variants each build one distributable. package-test builds them all except macOS and Flatpak (the flatpak CI job builds that) and then asserts their contents, while package-contract-test runs only the hermetic script contract suites. version prints the current version, and bump-patch / bump-minor / bump-major bump it, commit, and tag. 5.3 covers what those actually do.