Installing Qlua

Building Qlua and the pieces of the USQCD software stack it needs, from one tarball and one make command.

Qlua is built by the build3 system: a single tarball holding a top-level Makefile, a description of every component, and nothing else. It carries no sources of its own. Given a target to build for, make fetches each component from this site, checks it against a recorded SHA-256 sum, and builds the stack in dependency order — Lua, the USQCD libraries (QMP, QLA, QIO, QDP), the solvers (clover, twisted, MDWF, QOPQDP, and QUDA where there is a GPU), and finally qlua itself.

There is no configure script. What a configure script would discover, you write down instead, in a target description under config/targets/. That file is the whole of the local configuration.

Get the tarball

The current build system is version 2026.10e. Earlier releases are on the downloads page; unless you have a reason to reproduce an older build, take the newest.

curl -O https://web.mit.edu/qlua/files/build3-2026.10e.tar.gz
tar xzf build3-2026.10e.tar.gz
cd build3-2026.10e

What you need first

build3 builds the lattice stack; it does not build a toolchain, an MPI, or CUDA. Those must already be on the machine, and on a cluster that usually means loading the right modules before you start. The build itself calls for:

ToolUsed for
GNU makethe build itself; -j with a number is worth using
curlfetching component tarballs
sha256sumverifying them against etc/parts.sums
pkg-configlocating libraries the components need
aclocal, automakecomponents that regenerate their build files (automake 1.16)
MPI C, C++ and Fortran compilersthe target build — mpicc, mpic++, mpif77 by default
a host C compilercode-generation tools that run on the build machine
CUDAGPU targets only, for QUDA

Each of these is a make variable with a default, so a machine that spells one of them differently is accommodated in the target file rather than in the environment.

Choose a target

A target names the components to build and the compilers and flags to build them with. The tarball ships four:

TargetWhat it builds
wombat-a100Wombat, NVIDIA A100 — the full stack including CUDA, QUDA and the GPU qlua
wombat-cpuWombat, CPU only — the same stack without CUDA and QUDA
perlmutter-cpuPerlmutter, CPU only, installing under a CFS project directory
haktora macOS laptop, checked on x86 — and the one target that takes the 2026 AFF

If none of them is your machine, copy the closest one and edit it — starting from an existing target is much less work than starting from common.mk. A target file is short: it lists parts, carries a default INSTALL_TOP, and includes config/targets/common.mk, which supplies every compiler and flag the parts expect.

Build it

make TARGET=wombat-a100 INSTALL_TOP=/opt/software/qlua-a100-2026.10e -j8

Both TARGET and INSTALL_TOP must be given. TARGET names the target description to build from; INSTALL_TOP is the directory everything is installed into, and it is where you will point PATH afterwards. The makefile stops with an error without a target, and that includes make clean, so every invocation on this page carries both.

Give -j a number. On its own it places no limit at all: make starts as many compilations as it finds work for, and a stack this size will start enough of them to exhaust the memory on the machine. The build then fails in ways that look like anything but too much parallelism — a compiler killed with no message, an assembler out of memory, a link that dies. If a build fails and the failure moves or changes between runs, suspect this first: build again with a smaller -j, or with no -j at all, before looking for a real error.

Expect hours, not minutes — on a CPU target as much as on a GPU one. The stack is large and much of it is slow to compile; QUDA is the largest single piece, so a GPU target is longer still. Build logs and per-step timestamps land in logs/, which is where to look while it runs.

The build also copies etc/ and config/ into $INSTALL_TOP/versions/ and writes the target name beside them, so an installation says exactly which component versions it was built from.

Changing a component

The files in config/parts/ are shared by every target, so it is better not to edit them. To build one component differently, copy its file and point your target at the copy. For HDF5, say:

cp config/parts/hdf5.mk config/parts/hdf5-my-target.mk
# edit config/parts/hdf5-my-target.mk
# then in config/targets/my-target.mk, replace hdf5 with hdf5-my-target
#   in the parts list

The aff-y26 part is this pattern already in use: haktor builds the 2026 AFF by naming aff-y26 where the other targets name aff.

Where things are

PathWhat it holds
Makefilethe top makefile
config/targets/one description per installation
config/parts/per-component variable definitions
parts/the makefile that builds each component
etc/parts.masterthe version — a git commit, or a release number — of every component
etc/parts.sumstheir SHA-256 checksums
downloads/created by make: component tarballs as fetched
build/created by make: where components are unpacked and built
logs/created by make: build logs and step timestamps

Fetching and cleaning

Component tarballs come from https://web.mit.edu/qlua/files — the same files this site serves. curl is run with -f, so a missing file is an error rather than a saved error page, and every tarball is checked against etc/parts.sums before it is used, which catches a bad download either way.

Four goals do the fetching and the clearing up. Each needs TARGET and INSTALL_TOP, like every other invocation.

make TARGET=wombat-cpu INSTALL_TOP=/opt/software/qlua-cpu-2026.10e download

Downloads every component the target calls for into downloads/, and stops there. Nothing is unpacked and nothing is built.

make TARGET=wombat-cpu INSTALL_TOP=/opt/software/qlua-cpu-2026.10e checksum

Verifies each downloaded tarball against etc/parts.sums, downloading first anything not yet fetched — so this one goal both fetches and checks, and running download beforehand is optional. This is the goal to use when you want everything in hand and verified without starting a build, and it is the first step of building a disconnected machine.

make TARGET=wombat-cpu INSTALL_TOP=/opt/software/qlua-cpu-2026.10e clean

Removes build/ and the step markers in logs/, leaving the downloaded tarballs where they are. The next build recompiles from the beginning but does not fetch anything again. This is what to use after changing a target or a part file.

make TARGET=wombat-cpu INSTALL_TOP=/opt/software/qlua-cpu-2026.10e realclean

The same, and removes the downloads as well, so the next build fetches every component over again. Use it when a download is suspect, or to get back to the tree as it came out of the tarball.

Building without a network

A machine that cannot reach this site can still be built on: fetch the components somewhere that can, and carry the tree across. Nothing after the fetch needs the network.

On a connected machine, unpack the tarball and run the checksum step with the target and prefix you intend to use on the final host:

make TARGET=haktor INSTALL_TOP=/opt/software/qlua-cpu-2026.10e checksum

That downloads every component the target calls for and verifies each one against etc/parts.sums. It builds nothing, so the connected machine need not be the same architecture as the one you are building for — and because the sums are checked here, a tarball that arrives corrupted is caught before it is carried anywhere.

Then pack the tree, downloads and all, and move it across:

cd ..
tar czf build3-2026.10e-with-downloads.tar.gz build3-2026.10e
# copy it to the disconnected machine and unpack it there

On the disconnected machine, continue the build as usual. The download and checksum steps are already recorded as done in logs/, so make goes straight to compiling:

make TARGET=haktor INSTALL_TOP=/opt/software/qlua-cpu-2026.10e -j8

Carry the tree whole, with logs/ in it. Those files are what record that the components have been fetched and checked; without them make will try to download again and stop when it cannot. Use the same TARGET on both machines — a different target may call for components the first one never fetched.