# PETSc's GitHub mirror ships five makefiles and a setup.py that still imports distutils

> The GitHub copy of PETSc is a mirror, so its README is five sections of links and every issue goes to GitLab. The interesting file is setup.py, which documents the install paths, forbids four configure flags and imports a module newer Python versions no longer ship.

**petsc/petsc** — Mirror of https://gitlab.com/petsc/petsc

- Repository: https://github.com/petsc/petsc
- Website: https://petsc.org
- Stars: 543 · Forks: 219
- Language: C
- License: NOASSERTION
- Published: 2026-08-26 · Updated: 2026-08-26 · Language: en
- Canonical page: https://hysenlabs.com/projects/petsc-petsc

## The README is five sections of links and says nothing about PETSc

The entire GitHub README runs to five short sections. The first asks what the repository is for and answers in one line: it hosts the PETSc numerical library package. The second, on getting set up, contains two links, one to a download page and one to an installation page, both on the project site. The third points at a contributing file, the fourth lists a GitLab issue tracker, a maintenance email address and a mailing list page, and the fifth points at a code of conduct file. Nowhere in it is a definition of what PETSc is, what it solves, or how to build it. That omission is consistent with the repository's stated purpose, since the summary describes this as a mirror of the same project on GitLab, and a mirror does not owe its readers documentation.

## Issues go to GitLab, and so does the development install

The mirror relationship is not decorative, and the packaging makes it visible. The contributing and code of conduct links are relative paths to files in this tree, but the place to raise an issue is a GitLab tracker, and the maintenance contact is an email address rather than a GitHub one. Then there is the development install path, which fetches a source archive from the canonical host rather than from the mirror:

```bash
python -m pip install cython numpy
python -m pip install --no-deps https://gitlab.com/petsc/petsc/-/archive/main/petsc-main.tar.gz
```

So even when you install from a checkout like this one, the in-development path goes to GitLab. The stable path is shorter, since the released packages come from the index:

```bash
python -m pip install numpy
python -m pip install petsc petsc4py
```

The dependency flag is not a detail: that is why Cython and NumPy are installed first, because the archive install pulls nothing with the no-deps flag and the compile step needs them present.

## setup.py is the only file that explains anything

Since the README is links, the definition of the project lives in the docstring at the top of the packaging script. PETSc is named out as the Portable, Extensible Toolkit for Scientific Computation, and described as a suite of data structures and routines for the scalable and parallel solution of scientific applications modelled by partial differential equations, using the Message Passing Interface for all message-passing communication. Two things follow from that description. The parallel claim is not optional, since every message-passing call goes through the interface, which means an MPI implementation is part of the toolchain rather than an alternative to it. And the scope is deliberately narrow, a toolkit rather than an application, which is why the installation instructions point at a configuration step instead of at a set of examples.

## Four configure flags are refused, and the toolchain is detected instead

The packaging carries an explicit prohibition, and it is unusual enough to quote. You are told not to use the configure options for the C, C++ and Fortran compilers or for the MPI directory. Instead, compilers are detected in a fixed order: first from the environment variables for the MPI C, C++ and Fortran wrappers, then by running the shell to locate those wrappers on the path. Everything else you would want to pass to configure still works, through the environment variable that carries configure options. The reason for the restriction is implicit but clear, since passing a compiler flag and letting the build probe for MPI are two sources of truth for the same decision, and the detection order exists so that the MPI wrapper wins. If you have a toolchain that configure cannot find, override the wrapper variables rather than reaching for the flags.

## pyproject.toml carries build requirements and no project metadata

The Python packaging is split across two files in an unusual proportion. The pyproject file has a build system section and nothing else: it requires setuptools and wheel, adds patchelf when the platform is Linux, and names the setuptools backend. There is no project table, no name, no version and no metadata, because all of that still lives in setup.py, which is where the long description, the version detection and the install command live. The Linux-only build requirement is the interesting one, since patchelf is what rewrites the runtime library paths inside a wheel, and a library that links against several MPI implementations needs those paths to be right on the platform where it ships. The rest of the tree is traditional autotools-shaped: a committed configure script, a config directory, makefiles and source directories.

## Five makefiles sit at the repository root

The root of this tree contains GNUmakefile, gmakefile, gmakefile.test, makefile and petscdir.mk, which is five build files before you reach configure or the Python scripts. A GNUmakefile and a plain makefile together usually mean two entry points for the same build, one for the GNU make that developers use and one as a fallback for other make implementations. gmakefile.test is a third, scoped to the test suite. petscdir.mk is not an entry point at all but an included fragment, the kind of file that holds shared directory and installation paths so the other makefiles do not each define them. A library that has shipped for decades accumulates build files the way a build system accumulates compatibility, and the cost is that a newcomer has four candidate commands to try before knowing which one the project means.

## The metadata records no licence while the tree contains a LICENSE file

The repository's recorded license field is empty, in the form GitHub uses when its detector cannot classify the file, and the root of the tree does contain a file named LICENSE. Those two facts are in tension and the page does not resolve it, because the README says nothing about terms. For a scientific library distributed through a package index, that matters more than it would for a small tool, since downstream code inherits whatever obligations the license carries and nobody should guess on your behalf. Read the LICENSE file in a checkout, or ask the maintainers at the address the README gives, and treat the metadata field as unreliable rather than as an absence of licensing. The same caution applies to the container and CI files: this repository keeps two GitLab CI configurations, one of them for a national laboratory computing facility, which suggests the build matrix is more varied than the two-file root suggests.

## The packaging script still reaches for distutils

The setup script imports its logger from distutils, with a fallback that tries setuptools' wheel command first and the standalone wheel package second. Both of those patterns are older than the packaging standard they now sit inside: the wheel fallback exists for setuptools versions that did not yet ship that command, and distutils is a module that newer Python versions no longer ship in the standard library. The file also opens with a shebang and is written to be executed directly, and it reads version information from the source tree rather than from a single hard-coded constant. None of this stops the documented pip install from working on a supported interpreter, but it does mean the oldest file in the tree carries the most version sensitivity, which is worth knowing before you debug an install failure on a recent Python.

## Conclusion

Use the GitHub copy as a mirror and nothing more. Documentation, downloads and installation instructions live at petsc.org, and anything you want to change belongs in a GitLab issue, so treating this repository as the project's home will send your work nowhere. If you are reading the packaging rather than the library, setup.py is the only file here that explains anything, and it is worth remembering that it is the oldest part of the tree: the build requirements live in a pyproject file that carries no project metadata at all, and the compiler detection rules were written when configure flags were the normal way to select a toolchain.

## FAQ

### How do I install PETSc?

From the package index, install NumPy first and then the two packages with `python -m pip install petsc petsc4py`. For an in-development build, install Cython and NumPy, then install the main archive from the GitLab host with the no-deps flag, and pass any configure options through the PETSC_CONFIGURE_OPTIONS environment variable.

### What is PETSc?

The Portable, Extensible Toolkit for Scientific Computation: a suite of data structures and routines for the scalable, parallel solution of scientific applications modelled by partial differential equations, using the Message Passing Interface for all message-passing communication.

### Does the GitHub petsc/petsc repository take issues and pull requests?

It is a mirror. The README directs issues to the project's GitLab tracker, gives a maintenance email address and points at the mailing list pages, and the contributing and code of conduct documents live in this tree as relative links. Work belongs in the canonical repository, not here.

### What license is PETSc released under?

The repository's recorded license field is empty while the tree contains a LICENSE file at its root, and the README states no terms. Read the LICENSE file in a checkout or ask the maintainers, and do not treat the empty metadata field as meaning the library is unlicensed.

### Why does the PETSc repository contain five makefiles?

The root holds GNUmakefile, gmakefile, gmakefile.test, makefile and petscdir.mk, alongside a committed configure script and a config directory. The first two are duplicate entry points, the third is scoped to tests and the last is an included fragment holding shared paths rather than an entry point.

### How does PETSc choose which compilers to build with?

It is documented not to use the configure flags for the C, C++ and Fortran compilers or for the MPI directory. Compilers are detected from the MPI C, C++ and Fortran wrapper environment variables first, and otherwise by locating those wrappers on the path. Other configure options go through PETSC_CONFIGURE_OPTIONS.

## Sources

- [Official documentation](https://petsc.org)
- [Official README](https://github.com/petsc/petsc#readme)
- [Project repository](https://github.com/petsc/petsc)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/petsc-petsc
