I have used the above flags to generate portable x86_64 libraries for several years and have not encountered problems. The nature of the libraries that I distribute does not require native optimizations because the heavy computations are supposed to happen somewhere else (in the user-supplied external functions). But if such optimizations are needed it is easy to add them to the build generators (like CMake).
I’d caution against the use of some of the flags listed above. For example,
-parallel
of Intel ifort compiler creates a runtime dependency on Intel OpenMP shared library if I remember correctly. That is not a big deal if you also share the Intel runtime libraries with the users, or simply ship the OMP library along with yours. This is what I frequently do with gofrtran runtime dependencies.
Another example is the -fwhole-program
option of gfortran which I think should be specified only for local main programs (and that is why I commented it out in the above).
Over the years, I realized the easiest way to handle different build scenarios with different compilers is to list them all along with the relevant compile flags in a build generator like CMake, something like,
if (intel_enabled AND release_enabled)
...
endif()
One such example is this file, although this file more is reflective of my learning history than a good CMake file design (a clean fully revamped version is currently under construction in a private branch).
Once the CMake (or meson, …) build generator files are set up, it truly becomes bliss to compile and run complex codebases for intricate build scenarios with any compiler, even for the end-users. For example, to build the ParaMonte library, the user would only need to type
install.sh --build release
in Bash, or
install.bat --build release
in Windows command line. The rest is all taken care of for the user, even the compiler installation (on Linux, for example). On Linux, the user does not even need to know if the codebase is in Fortran, C, or … . Then, one can add more build scenarios to the scripts like a --build fast
option to build for the native arch. Currently, I separate ifort’s -ipo
and gfortran -flto
from the rest of the flags and invoke them once all development is done via a separate build flag --build ipo
because specifying these two enables interprocedural optimizations and function inlines that can make the linking process too long. I specify these links only in the final production stage.
In sum, if portability is desired, the above optimizations flags should be good. But if that is not enough, having a build script that automates the process for the end-users is a great solution. It takes some time to write and fine-tune but once written, it is there forever, or for as long as Bash terminals are available on computers. The compiler options or bash scripting are unlikely to change for the foreseeable future, making such build scripts a good time investment.