Options for linking Fortran on a Mac

Over the weekend I’ve been playing with Fortran on a Mac M1 to see if there’s any future-proof ways Fortran code can be used and tied to modern UIs (only been trying free/open-source options so far).
Here’s what I found:

  • most GNU software and libraries can be very easily used through homebrew (great effort!), including gfortran, openmpi, …: I can build and run large codes easily.
  • However, linking doesn’t play well with macOS’s system libraries. It seems this is related to the GNU toolchain relying on a c++ standard library that’s different than the system’s one, ultimately leading to non-ABI-compatible / non-linkable code. For example, I was unable to link against the system’s OpenCL framework or the wxWidgets library, which is otherwise usually very easy to build against. This is also true for some of the libraries that are shipped with homebrew: maybe they just build them with clang/clang++ whenever there’s no other options. This seems different than what happens on Windows with the MSYS2 toolchain, for example.

So the bitter conclusion of the weekend has been that Fortran on Mac will have no other options than being confined to its fenced GNU playground unless tremendous efforts are undertaken to attempt gluing libraries and make them talking to each other. Unfortunately I don’t have experience with flang/LFortran but I would be glad to learn from the community if there are viable options for large Fortran codebases.

Next weekend I plan on trying to link some code via a DLL, but I’m not sure if that’s going to be viable ( I think the safest thing will be to expose a C API anyways). Glad to hear any opinions from the community!

Federico

2 Likes

Was this a Mac M1 or the older Intel Macs ?

It’s an M1 Mac. I suspect things aren’t going to be any simpler on Intel chips, as Apple system headers make usage of C++ block which AFAICT won’t be supported by GNU compilers any time soon

1 Like

I use fortran on a M1 Mac. I use CMake for all linking and managing dependencies. Works like a charm with all combinations of compilers I have tried.

You have to make sure to use iso_c_binding to communicate between C and Fortran.

Thank you, that’s very interesting. Does that include binding GNU binary objects to clang/clang++ binaries?

Ya. You can use find_package command in CMake. Typically big binaries will be findable with this command. Some libraries have special commands for finding them, like “FindOpenMP”.

@awvwgk is a CMake expert.

Uh, when did I get this qualification? Tries to hide inconspicuously.


More seriously, I didn’t observe problems with the homebrew (GCC/GFortran) and conda-forge (clang/GFortran) tool chains on both x86_64 and Arm64 so far.

With the default compiler, Apple’s system clang, it can be tricky because some things are missing in its standard library (OpenMP for example), which means you need to be careful with the ABI (newer C++ standards in particular, like the filesystem support). However, this is mostly relevant for C++ projects were conflicting standard libraries with different ABIs can cause havoc.

For Fortran you are lucky because you bring your Fortran runtime libraries and there is no conflicting version which might be provided by the system. The best example is the conda-forge tool chain which provides a freestanding GFortran.

Regarding CMake, if you are not using it already, best stay away from it. It is not worth the time to overcome the initial steep learning curve to become a CMake expert. There are much better alternatives available, like meson.

Yeah I’m specifically trying to link to Apple’s OpenCL and system UI libraries, which is what breaks the homebrew-gcc ABI. Is what you’re saying that libgfortran has essentially no dependencies on the system c++ library?

One option I was thinking about was to build a dynamic library with the Fortran code (maybe it only depends on libgfortran), and then link to it from Apple’s clang++ compiled C++ code, but I’m not sure it’s going to work.

You might want to try the conda-forge tool chain (use a mambaforge installer from Releases · conda-forge/miniforge · GitHub), which provides a rather clear separation between Fortran and C++ compiler, install either the gfortran or fortran-compiler package.

My guess is that the choice of linker or compiler wrapper used for linking can be rather important. Figuring this out by hand can be difficult. A minimal build file with meson should make it easier to clearly select the language for linking using the link_language option when creating a library or executable target.

project(
  'abc',
  'fortran', 'cpp',
)

executable(
  meson.project_name(),
  sources: files(
    'src/a.f90',
    'src/b.cpp',
  ),
  dependencies: [
    dependency('wxwidgets', modules: ['std', 'stc']),
    dependency('opencl'),
  ],
  link_language: 'cpp',
  install: true,
)

CMake and Meson seem about the same to me. The biggest difference is that most projects have CMake support, while far fewer have Meson support. I’m a little annoyed that Meson is a thing because it would be much more convenient if everyone just one or the other.

That’s a somewhat fallible argument, since it extends to any pair of build system, like autotools and CMake or fpm and CMake+CPM as well as package managers, e.g. pip and conda. The motivation for having yet another build system or package manager is mostly that things are difficult to do or support in the existing ones. User and developer friendliness is one of CMake’s weak points, which leaves room for other build systems to provide a better alternative.