Fortran library distribution and ABI stability

I have been thinking recently about the current state of Fortran library distribution, especially for modern Fortran libraries exposing module-based APIs (not based on bind(C)). As far as I understand, there are currently two main distribution models.

1. Source distribution + build system

The library author distributes: source code, and build system (fpm, CMake, Makefiles, etc.). The user then compiles the library locally using the same compiler and flags as the main project.

Advantages:

  • full use of modern Fortran semantics,
  • no .mod file/ABI mismatch.

Disadvantages:

  • users must integrate the build system,
  • all dependencies must use homogeneous compiler settings.

Although extended, this model feels cumbersome for reusable general-purpose libraries.

2. Binary library + .mod distribution

The library author distributes: .a / .so, and compiler-generated .mod files.

Advantages:

  • users can consume the library directly,
  • native Fortran APIs remain available.

Disadvantages:

  • .mod files are compiler(version)-specific,
  • users are effectively forced to use the same compiler.

This model scales poorly across compilers and distributions.

Main friction points

1. .mod files are compiler-specific

This issue is widely known already. However, submodules seem to offer an elegant partial solution. Instead of distributing compiler-generated .mod files, a library could distribute interface-only .F90 module source files together with a library archive. The user would compile only the interface modules locally, generating native .mod files compatible with their compiler. Submodules make this especially attractive because they cleanly separate interface from implementation. Making parallels between module files and C header files.

2. ABI instability

This seems to be the harder problem. Even if .mod incompatibility disappears, compilers still differ in symbol mangling, calling conventions…


This led me to wonder whether Fortran could eventually benefit from something similar to:

subroutine solve(A) bind(F)

bind(C) means ā€œinteroperable with C ABIā€. In this context, bind(F) would mean ā€œinteroperable with a standardized native Fortran ABIā€. This has been discussed before in other contexts.

The goal would not necessarily be to standardize all compiler internals, but perhaps:

  • symbol naming,
  • calling conventions,
  • descriptor layouts,
  • non-polymorphic derived type ABI,
  • allocatable conventions.

This could potentially allow for binary-distributed native Fortran libraries and compiler-independent linking.


I think this is worth discussing because Modern Fortran already has many of the right language features such as encapsulation, explicit interfaces, and rich array semantics. In many ways, the language itself is already better suited for large numerical libraries than, for example, C. However, C still has a much simpler and more stable binary ecosystem.

Still, I wonder whether at least a partially standardized native ABI could be feasible without sacrificing too much compiler freedom. Especially because:

  • ISO_Fortran_binding.h already standardizes descriptors for C interoperability,
  • submodules now provide clean interface/implementation separation.

Curious to hear thoughts from compiler developers and library authors here.

5 Likes

I know that NAG (Numerical Algorithms Group, a not for profit organisation) has been selling Fortran libraries since the 70s. It has also been selling a Fortran 90 compiler since the 90s. The chief developer has been editor of the Fortran Standard for many years (and a J3 member for even longer). One would think that if there was a real commercial need for this, a proposal might have appeared from NAG in the intervening 35 years (32 of which I was an employee there).

I suspect that the reasons nothing has changed are that the user demand is not overwhelming, that the committee work would be significant, the implementation work considerable, and the anticipated gain insufficient.

Fortran is not a systems programming language. But it supports interoperability with the leading systems programming language, C. NAG builds the core software with Fortran, and then wraps this so it is usable from C, Python, Java, MS Office, .NET, and MATLAB.

1 Like

Motivated by insights on how NAG libraries have been distributed over the years, I spent some time looking into the historical evolution of library distribution in the Fortran ecosystem. In summary, it evolved around wrappers and interoperability layers. NAG itself developed an automatic wrapper generation engine, where the numerical routines are implemented in Fortran and interfaces are generated automatically from structured documentation.

This suggests that, even before bind(C), portability was often achieved through stable interfaces to system-programming languages rather than through a compiler-independent native Fortran binary interface.

With the introduction of bind(C), Fortran gained something quite powerful: access to established platform ABIs via C. For the subset of features that can be expressed through C interoperability, users can create reusable libraries that can be consumed by Fortran and C compilers with quite a lot of generality.

For native Fortran libraries, the situation today is different. As detailed above, a practical distribution model already exists.


A hypothetical bind(F) facility could, in principle, reduce the binary compatibility requirements of this model from:

  • same platform + same compiler + same compiler version,

to something closer to:

  • same platform.

Whether such a capability would justify the standardization and implementation effort is, in my opinion, an open question. After this discussion, I am less convinced that the lack of a native standardized ABI is an oversight, and more inclined to view it as a consequence of the historical role Fortran has played within larger software ecosystems.