fpm: a Cargo-shaped build system and package manager for Fortran
Fortran Package Manager (fpm)
At a glance
- What is it?
- fpm is the Fortran Package Manager, a build system and dependency manager whose interface is deliberately modeled on Rust's Cargo. It builds libraries, executables, tests and examples from a fpm.toml manifest, and it can consume packages from the fpm registry. The project still describes itself as an early prototype.
- Who is it for?
- fpm suits a Fortran team that wants one manifest, one build command, and one dependency mechanism across its libraries, executables, and tests, especially a team coming from Cargo and willing to accept an early-stage tool. It is the wrong choice for a project that needs a stable, frozen dependency graph or for a team that already has working Makefile or CMake infrastructure and no appetite for a migration.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Fortran, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The interface is Cargo on purpose
Fortran Package Manager, fpm for short, is a package manager and build system for Fortran. Its stated key goal is to improve the user experience of Fortran programmers, and it does so by making it easier to build a Fortran program or library, run the executables, tests, and examples, and distribute it as a dependency to other Fortran projects.
The design decision that shapes everything else is stated plainly: fpm's user interface is modeled after Rust's Cargo, so if you are familiar with that tool, you will feel at home. That is a deliberate choice about who the tool is for. Fortran has a long history of build systems assembled per project, with Makefiles that differ from repository to repository and CMake configurations that are hard to share. A tool that copies the ergonomics of the most polished language build system is making a claim that the shape of the interface matters as much as the functionality.
The long term vision is stated just as directly: to nurture and grow the ecosystem of modern Fortran applications and libraries. The unit of that ecosystem is a package, and the fpm registry is where existing packages are found for use as dependencies.
The caveat is important and the project does not bury it. Fpm is an early prototype and is evolving rapidly, and its behaviour and user interface may change as it evolves. The stated commitment is that as fpm matures and the project enters production, they will aim to stay backwards compatible. The current tag, which is updated automatically to always provide the current git version from the default branch, is the mechanism that lets you track that development, and the last push to the repository was on 2026-09-03.
A new project is one command and six files
The getting-started section is worth reading because it shows what the tool considers the minimum viable project, and how little ceremony there is.
Creating a new fpm project is as simple as running `fpm new project_name`. That creates a new folder in the current directory with a fixed set of contents and initializes it as a git repository. The files are `fpm.toml` with the project's name and some default standard meta-data, a `README.md` with the project's name, a `.gitignore`, and `src/project_name.f90` with a simple hello world subroutine. Two more are conditional: `app/main.f90`, a program that calls the subroutine, if the `--app` flag is used, and `test/main.f90`, an empty test program, if the `--test` flag is used.
Three things stand out. The project is a git repository from the start, which means version control is not an afterthought you add later. The source and program directories are separate by default, so the library code and the executable that consumes it are distinct from the start. And the test file is generated empty rather than with a sample test, so the structure exists but the content is yours.
The manifest itself is `fpm.toml`, and it is the single place the project is described. There is a manifest reference document in the documentation site and a `manifest-reference.md` file at the repository root, plus a separate `PACKAGING.md` for the packaging guide, which covers what happens when your project is consumed as a dependency by someone else rather than built on its own.
The example_packages directory at the root is there for the same reason. It gives you working manifests to read rather than making you infer the format from one generated file.
Four commands cover the whole inner loop
The build commands are the part that mirrors Cargo most directly, and the list is short enough to remember.
`fpm build` builds your library, executables and tests. `fpm run` runs executables. `fpm test` runs tests. `fpm install` installs the executables locally.
The refinement is in how you target a specific thing. The command `fpm run` can optionally accept the name of the specific executable to run, as can `fpm test`, so `fpm run specific_executable` runs one binary out of several. Command line arguments can also be passed to the executable or the test with the option `-- some arguments`, which is the part that matters when your program takes input, since it is the difference between a tool that can be scripted and one that cannot.
The one-word design is deliberate, and it has a consequence worth naming. Because the same command builds libraries, executables, and tests, a project that has several executables will build all of them every time, and the test suite runs as part of the same unit. For a small library that is exactly what you want. For a project with a slow test suite, knowing that `fpm test` and `fpm build` share a build step tells you where the time goes.
The project also ships a `ChangeLog.md` at the root, and the repository has `app/` for the fpm executable itself, `src/` for the library code, `test/` for the test suite, `ci/` for the continuous integration configuration, and `doc/` alongside a `docs.md` file.
Compilers, flags, and the archiver are all overridable
The environment variable table is the part of the documentation that a Fortran user will actually need, because toolchain configuration is where a build system earns its keep.
The table lists the environment variables that control fpm's choice of compilers, compiler flags, archiver locations, and link flags, each of which can be overridden by passing fpm flags that are also shown in the table. The pairs are direct: `FPM_FC` for the Fortran compiler path is overridden by `--compiler`, `FPM_CC` for the C compiler path by `--c-compiler`, `FPM_CXX` for the C++ compiler path by `--cxx-compiler`, `FPM_FFLAGS` for Fortran compiler flags by `--flag`, `FPM_CFLAGS` by `--c-flag`, `FPM_CXXFLAGS` by `--cxx-flag`, `FPM_AR` for the archiver path by `--archiver`, and `FPM_LDFLAGS` for link flags by `--link-flag`.
The structure is sensible: the environment variable is for the machine, the flag is for the one-off invocation, and the flag wins. That lets you set a default in your shell profile and still override it on a specific build.
The C and C++ compiler entries deserve a note. A Fortran project with a modern dependency often has a C or C++ component, and a build system that only knew about gfortran would not survive its first real dependency. The archiver entry matters for the same reason: static libraries are archived with `ar`, and a toolchain that hardcodes a path breaks on the first machine where it is elsewhere.
The repository includes an `install.sh` at the root and there is a bootstrapping route through a single-source distribution that can be compiled with gfortran directly, for building fpm on a platform for the first time. That bootstrapping path is the one to use if you are installing on a system fpm does not ship binaries for.
Installation covers binaries, conda, and a Homebrew tap
Fpm is available on many platforms and through multiple package managers, and the documentation site has a page listing all supported installations. The three easiest routes follow.
The first is the binary. Binaries for the latest stable release are available to download for Windows, MacOS, and Linux. There is one platform gotcha: on Linux and MacOS you will need to enable executable permission before you can use the binary, with the example given as `chmod u+x fpm-0.6.0-linux-x86_64`. That is the kind of detail that catches people out when a downloaded file refuses to run.
The second is conda-forge. Adding the channel is done with `conda config --add channels conda-forge`, and then fpm is installed into its own environment with `conda create -n fpm fpm` followed by `conda activate fpm`. Conda itself can be installed from miniforge or miniconda.
The third is Homebrew, which requires an additional tap:
brew tap fortran-lang/fortran
brew install fpmThe Homebrew route has a platform limit stated in the same paragraph. Binary distributions are available for MacOS 11 (Catalina) and 12 (Big Sur) for x86_64 architectures, and for other platforms fpm will be built locally from source automatically. So the tap works everywhere, but only on a narrow set of Mac configurations do you get a prebuilt binary instead of a local compile.
There is also a `current` tag that is updated automatically to always provide the current git version from the default branch, which is how you track the leading edge without tracking the default branch itself.
Where fpm is the wrong tool, and where it is a prototype
The limits of fpm are the limits of the Fortran ecosystem it is trying to bootstrap, and the project is candid about both.
The first is the prototype status. Behaviour and user interface may change as it evolves, and the compatibility promise is an aim for the future rather than a current guarantee. For a team that pins a toolchain in CI, that is a real operational cost, and it is the reason to check the ChangeLog and the issues rather than assuming a version bump is safe.
The second is the registry. The fpm registry is where existing packages are found and used as dependencies, and a young registry is a young supply chain. A dependency you pull from it may have one maintainer, may be unmaintained, and may have a manifest that fpm itself would no longer accept after a breaking change. A Cargo-like model brings Cargo-like expectations, and the ecosystem is not yet at that scale.
The third is the missing pieces. The documented command set is short: `fpm new`, `fpm build`, `fpm run`, `fpm test` and `fpm install`. Beyond that, fpm covers the build and the dependency graph and leaves the rest to the wider toolchain.
The fourth is that Fortran itself carries legacy constraints that a package manager cannot solve. An fpm manifest is TOML and a project layout is conventional, but a Fortran library with a legacy build script and a C binding and a pre-generated module file does not become a package just because there is a manifest. The documentation's own mention of a Packaging guide for the case where your project is consumed as a dependency by someone else is where those details surface.
And the fifth is a naming trap the project itself flags. Fortran Package Manager is not to be confused with Jordan Sissel's fpm, a more general, non-Fortran related package manager. If you are searching for tooling, that name collision is real, and the project links both.
Editorial conclusion
fpm suits a Fortran team that wants one manifest, one build command, and one dependency mechanism across its libraries, executables, and tests, especially a team coming from Cargo and willing to accept an early-stage tool. It is the wrong choice for a project that needs a stable, frozen dependency graph or for a team that already has working Makefile or CMake infrastructure and no appetite for a migration. Check three things before adopting it: that the compiler and archiver paths are set for your machine, whether through the FPM_FC, FPM_CC, FPM_CXX, FPM_AR variables or the matching command line flags, that you read the manifest reference for the features you need rather than assuming Cargo semantics carry over exactly, and that the tools your dependencies expect, such as a test runner, are present, because the ecosystem is still young.
Frequently asked questions
How do I install the Fortran Package Manager?
Binaries for the latest stable release are available for Windows, MacOS, and Linux, and on Linux and MacOS you need to enable executable permission first, for example `chmod u+x fpm-0.6.0-linux-x86_64`. It is also on conda-forge via `conda create -n fpm fpm`, and through a Homebrew tap with `brew tap fortran-lang/fortran` then `brew install fpm`.
How do I create a new fpm project and build it?
Run `fpm new project_name`, which creates a folder with `fpm.toml`, a `README.md`, a `.gitignore`, `src/project_name.f90`, and optionally `app/main.f90` and `test/main.f90`, and initializes a git repository. Then `fpm build` builds the library, executables and tests, `fpm run` runs executables, `fpm test` runs tests, and `fpm install` installs the executables locally.
How do I tell fpm which compilers to use?
Through environment variables or the matching command line flags, where the flag wins. `FPM_FC` sets the Fortran compiler path and is overridden by `--compiler`, `FPM_CC` the C compiler path by `--c-compiler`, `FPM_CXX` the C++ compiler path by `--cxx-compiler`, `FPM_FFLAGS` the Fortran flags by `--flag`, `FPM_AR` the archiver path by `--archiver`, and `FPM_LDFLAGS` the link flags by `--link-flag`.
Is fpm stable enough for production use?
The project describes fpm as an early prototype that is evolving rapidly, and states that its behaviour and user interface may change as it evolves, with a stated aim to stay backwards compatible as it matures. The newest tagged release is v0.13.0 from 2026-02-17 and the last push was on 2026-09-03.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/fortran-lang-fpm)Was this useful?