The Fortran Ecosystem

The "Fortran is dead, so its ecosystem is dead" story inverts the truth: 65 years of validation produced BLAS, LAPACK, netCDF and MPI — libraries science is built on — and the last five years added fpm, stdlib and a modern registry. This lesson surveys what is production-grade and what to use for building, testing and data I/O.

fpm: the package manager and build tool

The setup lesson ran the hello-world cycle; here is the real workflow. An fpm.toml manifest names the package, its source layout and its dependencies (fetched from git or the fpm registry). Recent releases added profiles — named build configurations, the standard way to switch compiler flags between debug and release:

name = "mysolver"
version = "0.1.0"
license = "MIT"

[build]
auto-executables = true
auto-tests = true

[dependencies]
stdlib = { git = "https://github.com/fortran-lang/stdlib", tag = "v0.8.1" }
hdf5  = { git = "https://github.com/fortran-lang/hdf5-fortran" }

The commands are the loop of your day: fpm build, fpm run, fpm test, fpm install. Dependencies land in a local cache and their modules become importable automatically. For institutional builds, CMake's Fortran support remains the heavy-duty alternative, but new projects start with fpm.

stdlib: the community standard library

The ISO standard ships no standard library by design; fortran-lang/stdlib is the de-facto one. Current scope: string utilities (strip, slice, ends_with, to_upper), sorting and searching (sort, arg_sort), math (linspace, is_close, random distributions), statistics, IO helpers, and the full BLAS/LAPACK interfaces (stdlib_linalg). Reading stdlib is also how you learn canonical modern Fortran — add it with one fpm.toml line.

program stdlib_quick
  use stdlib_strings, only: strip, to_upper, ends_with
  use stdlib_sorting, only: sort
  implicit none
  character(len=32) :: msg = "  run done  "
  integer :: v(5) = [5, 2, 4, 1, 3]
  print '(a)', strip(to_upper(msg))   ! "RUN DONE"
  call sort(v)                        ! stdlib sorting, in place
  print '(5i2)', v                    ! 1 2 3 4 5
  print *, ends_with("report_v2.dat", ".dat")   ! T
end program stdlib_quick

Linear algebra: BLAS, LAPACK, MKL

The dense linear algebra stack is Fortran's most famous export. BLAS — the Basic Linear Algebra Subroutines — is the kernel layer (dgemm for matrix multiply, daxpy, norms and dots); LAPACK builds solvers and decompositions on top (linear solves, eigenvalues, SVD, QR). Every vendor ships tuned builds: Intel MKL (on Xeon, often the fastest), OpenBLAS, and the reference netlib codes. Call them directly through external dgemm plus explicit interfaces — or through stdlib's typed wrappers, which handle kinds automatically. The performance story is physical, not architectural: a good BLAS dgemm uses cache-blocking and SIMD that your hand loops will not match — for any problem that is a matrix problem, call the library.

program matmul_check
  use, intrinsic :: iso_fortran_env, only: real64
  implicit none
  real(real64) :: a(2,2), b(2,2), c(2,2)
  a = reshape([1.0_real64, 2.0_real64, 3.0_real64, 4.0_real64], [2,2])
  b = reshape([5.0_real64, 6.0_real64, 7.0_real64, 8.0_real64], [2,2])
  c = matmul(a, b)                ! intrinsic path — fine here
  print *, c
  ! For large sizes the BLAS call dgemm('n','n',n,n,n,1.0,a,n,b,n,0.0,c,n)
  ! is the production choice; stdlib_linalg wraps it type-safely.
end program matmul_check

Data formats: netCDF and HDF5

Scientific data outlives the program that wrote it; netCDF and HDF5 are the portable, self-describing container formats the Earth-science world standardized on — arrays with named dimensions, units attached to variables, and chunked compression. Both ship Fortran APIs used by every weather and climate codebase; gfortran users reach them through the netcdf-fortran and hdf5-fortran packages (both have fpm metapackages). The shapes lesson transfers directly: netCDF variables are just arrays with metadata, so a solver's output step is nf90_put_var over the same array the physics just advanced.

Testing and continuous integration

Three layers keep Fortran code honest. test-drive is the fpm-native test framework — unittest style blocks that compile with fpm test. Fruit and Funit add JUnit-style fixtures for large suites. On top, CI is the same GitHub Actions/Azure Pipelines you already know, with the twist that matrixes across gfortran versions cheaply enforce the portability that -std=f2018 promised — a matrix of {gfortran-12, gfortran-13, ifx} catches 90% of platform bugs before users do. The errors lesson's assert pattern plus -fcheck=bounds in the debug profile is the smallest viable test harness.

Debugging and profiling tooling

The professional toolchain, all free: gdb for interactive breakpoints and minimal Fortran awareness (set language fortran at the prompt); gfortran's -fbacktrace -fcheck=bounds for instant crash location; valgrind memcheck for leaks and invalid access in release builds; gprof/perf (performance lesson) for hot spots; and OpenMPI's mpiexec plus TAU/Scalasca on clusters for parallel profiling. A modern IDE adds the same features with less typing — VS Code's Modern Fortran extension gives hover types, go-to-definition, and its debugger binds gdb beneath the hood.

Next: with the ecosystem surveyed, the comparison lesson answers the question every newcomer asks — how Fortran positions itself against Rust, Zig and C++ — and whether it deserves the "systems language" label.