Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 17 additions & 37 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,43 +76,23 @@ To contribute effectively, please familiarize yourself with our
If you use an AI assistant or agent, see [`AGENTS.md`](./AGENTS.md) for
project-specific instructions and conventions.

### Testing changes

Testing helps to ensure that the changes work well with the rest
of the project. While there are many different ways to test,
usually you will want to compile the source code (see below),
add test code (using _grass.gunittest_ or pytest), and run code
linters (automated code quality checks).

There is a series of automated checks which will run on your pull request
after you create one. You don't need to run all these
checks locally and, indeed, some of them may fail for your code. This is a part
of the standard iterative process of integrating changes into the main code,
so if that happens, just see the error messages, go back to your code
and try again. If you are not sure what to do, let others know in a pull
request comment.

Note that there are some steps you can do locally to improve your code.
For Python, run `ruff format` to apply standardized formatting. You can
also run linter tools such as `ruff check` or Pylint which will suggest
different improvements to your code.

## Compilation

More often than not, in order to test the changes, you need to create
a runnable binary program from the source code,
using the so-called "compilation step". While the
source code consists of thousands of C and Python files (plus HTML
documentation and other files), the included "makefiles" tell the build system to
generate binaries from the source code in the correct order, render the
manual pages, etc.

The way to install the compiler tools and Python depends on the operating
system. To make this easier, we have collected copy-paste instructions
to install dependencies and compile GRASS source code for most operating systems.
Please see our dedicated wiki:

[Compile and install instructions](https://grasswiki.osgeo.org/wiki/Compile_and_Install)
To test your changes, you may need to compile the source code.
For compilation, see [instructions for building with CMake](./doc/development/building_with_cmake.md)
or [instructions for GNU Autoools](./INSTALL.md).
Further notes for various platforms can be found on a dedicated
[wiki page](https://grasswiki.osgeo.org/wiki/Compile_and_Install).

Before creating a PR, please test your changes.
Refer to [testing README](./testsuite/README.md) for details.
Once you create a PR, a series of automated checks which will run on your pull request.
This is a part of the standard iterative process of integrating
changes into the main code, so if that happens,
just see the error messages, go back to your code and try again.
If you are not sure what to do, let others know in a pull request comment.

In addition to testing, please use
[pre-commit](doc/development/style_guide.md#using-pre-commit)
to apply standardized formatting.

## About source code

Expand Down
184 changes: 184 additions & 0 deletions doc/development/building_with_cmake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# 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](../../INSTALL.md). If you are coming from the Autotools
build, see the [comparison table](#comparison-with-autotools) at the
end.

## Configuring

Create and configure a build directory with:

```bash
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:

```bash
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:

```bash
# 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](https://ninja-build.org/)
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

```bash
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:

```bash
./build/output/bin/grass
```

For running tests against the build tree, put `build/output/bin` on
`PATH`:

```bash
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:

```bash
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 under `python/grass/` is not visible
in `build/output` until 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):

```bash
cmake --build build --target help
```

## Installing

For everyday development, installing is optional: GRASS runs directly
from `build/output`. To install, run:

```bash
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:

```bash
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`:

```bash
$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 |
1 change: 1 addition & 0 deletions man/mkdocs/docs/development_intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ and are a great way to extend the functionality of GRASS.

- [Style guide](style_guide.md)
- [GitHub guide](github_guide.md)
- [CMake guide](building_with_cmake.md)
- [Investigating code history](investigating_history.md)
- [CONTRIBUTING file on GitHub](https://github.com/OSGeo/grass/blob/main/CONTRIBUTING.md)
Loading