Building GRASS with CMake
This guide covers developer workflows for building GRASS with CMake: configuring and compiling, running GRASS directly from the build directory, recompiling only modified code, and compiling addons. For dependencies and general installation instructions, see INSTALL.md. If you are coming from the Autotools build, see the comparison table at the end.
Configuring
Create and configure a build directory with:
cmake -B build
The build is fully out-of-source: all generated files go into the build
directory (here build), the source tree stays clean, and you can keep
several independently configured build directories side by side
(e.g. build-debug, build-clang).
Optional dependencies are controlled with WITH_* options:
cmake -B build -DWITH_MYSQL=ON -DWITH_FFTW=OFF
See the option(WITH_...) calls in the top-level CMakeLists.txt for
the full list. Note that options enabled by default (PDAL, GEOS, FFTW,
etc.) are treated as required: on a system missing one, configure fails
with a "Could not find ..." error. Either install the dependency or
disable the option explicitly.
Other frequently used settings:
# Custom compiler flags
cmake -B build -DCMAKE_C_FLAGS="-g -Wall"
# Optimization/debug presets (Debug, Release, RelWithDebInfo)
cmake -B build -DCMAKE_BUILD_TYPE=Debug
# Installation directory (default /usr/local)
cmake -B build -DCMAKE_INSTALL_PREFIX=/opt/grass
The install prefix is recorded in the build at configure time, so set it
with -DCMAKE_INSTALL_PREFIX here rather than at install time.
Settings are sticky: they are cached in the build directory, so a later
plain cmake -B build or rebuild keeps using them. To change a setting,
pass the new -D... value; to reset everything, delete the build
directory.
By default the build is driven by make. If Ninja
is installed, you can select it instead with -G Ninja; it is faster on
incremental builds and compiles in parallel by default. The build tool
is chosen at configure time and cannot be changed in an existing build
directory.
If ccache is installed, the build uses it automatically to cache
compiler output, so recompiling files that have not changed (e.g. after
deleting the build directory or in a second build directory) is nearly
instant. Pass -DUSE_CCACHE=OFF to opt out.
Compiling
cmake --build build -j$(nproc)
cmake --build is a thin wrapper that runs the actual build tool
selected at configure time: make by default, or ninja if configured
with -G Ninja. With make it compiles serially unless you pass -j;
Ninja parallelizes by default.
There is no separate reconfigure step after pulling changes: the build
re-runs CMake automatically when any CMakeLists.txt changed.
Running GRASS from the build directory
The runnable tree is staged under build/output, so GRASS can be run
without installing:
./build/output/bin/grass
For running tests against the build tree, put build/output/bin on
PATH:
export PATH="$(pwd)/build/output/bin:${PATH}"
Recompiling only what you modified
Every tool is a CMake target named exactly like the tool, and building a
target also rebuilds any libraries it depends on and re-links the result
into build/output. So after editing, e.g., raster/r.slope.aspect/main.c
or a library it uses:
cmake --build build --target r.slope.aspect
and the updated tool is immediately runnable from build/output.
Targets are always built this way from the top level; there is no
per-directory build.
Other useful target names:
- C libraries:
grass_<name>(e.g.grass_gis,grass_raster,grass_vector) - Python packages, staged into
build/output:python_<name>(e.g.python_script,python_tools,python_temporal,python_pygrass); an edited file underpython/grass/is not visible inbuild/outputuntil its target is rebuilt - Python script tools: the tool name, same as C tools (e.g.
r.mask)
To list all available targets (with the default Makefile generator):
cmake --build build --target help
Installing
For everyday development, installing is optional: GRASS runs directly
from build/output. To install, run:
cmake --install build
This installs into the prefix recorded at configure time (default
/usr/local, which typically requires sudo). To install without
root, configure with -DCMAKE_INSTALL_PREFIX set to a writable
directory, e.g. $HOME/grass-install.
Compiling addons
Addons are installed with g.extension, which downloads the addon source code, compiles it, and installs it into your user addon directory. With a CMake-built GRASS, g.extension compiles the addon using CMake automatically; you do not run any CMake commands yourself.
The requirement is that the GRASS you run g.extension from is an
installed one (cmake --install build), not the build/output tree,
which lacks the addon build machinery. No root is needed: install to a
prefix in your home directory. In the GRASS source directory:
cmake -B build -DCMAKE_INSTALL_PREFIX=$HOME/grass-install
cmake --build build -j$(nproc)
cmake --install build
Then run g.extension from the installed GRASS as usual, in a GRASS
session or on the command line with --exec:
$HOME/grass-install/bin/grass --tmp-project XY --exec \
g.extension extension=r.example
Comparison with Autotools
For developers used to the Autotools build (./configure && make):
| Task | Autotools | CMake |
|---|---|---|
| Configure | ./configure [options] |
cmake -B build [options] |
| Configure with debug flags | CFLAGS="-g -Wall" ./configure |
cmake -B build -DCMAKE_C_FLAGS="-g -Wall" |
| Set install directory | ./configure --prefix=... |
cmake -B build -DCMAKE_INSTALL_PREFIX=... |
| Compile everything | make -j$(nproc) |
cmake --build build -j$(nproc) |
| Install | make install |
cmake --install build |
| Run without installing | bin.$ARCH/grass |
build/output/bin/grass |
| Recompile one tool | cd raster/r.slope.aspect && make |
cmake --build build --target r.slope.aspect |
| Clean compiled files | make clean |
cmake --build build --target clean |
| Clean everything incl. configuration | make distclean |
rm -rf build |
| Use ccache | CC="ccache gcc" ./configure |
automatic if installed |
SOURCE CODE
Available at: building_with_cmake source code
(history)
Latest change: Wednesday Aug 19 05:37:26 2026 in commit 4677089