Currently, the system module files needed when compiling a Fortran source in /flang/module are built when compiling flang itself. The instructions for this are in /flang/tools/f18[1]. This has some issues:
-
Some of the .f90 files are target-dependent. While AFAIU .mod files are in principle target-triple-independent, some contain #ifdefs for specific targets. This includes:
iso_c_binding.f90
(C ABI is obviously target-dependent),__fortran_ieee_exceptions.f90
, andieee_arithmetic.f90
(floating point support varies between targets). -
__ppc_intrinsics.f90
andmma.f90
are only compiled if the LLVM PowerPC backend is enabled, since otherwise Flang will reject it. -
Module dependency resolution is done manually in the CMakeLists.txt using a
if
-elseif
cascade. -
Does not work when cross-compiling.
-
For building
omp_lib.mod
. requiresLLVM_ENABLE_PROJECTS=openmp
. This is because it looks foromp_var.F90
in openmp’s build directory because it is the output of openmp’s configure phase. WithLLVM_ENABLE_RUNTIMES=openmp
, openmp’s build dir is somewhere else, and might not even be present if building openmp standalone (in contrast to a bootstrapping build).LLVM_ENABLE_PROJECTS=openmp
will eventually be deprecated and we currently have no other way to buildomp_lib.mod
. Also note thatomp_var.F90
importsiso_c_binding
.
Require LLVM_RUNTIME_TARGETS=default
Low effort solution where we can assume to find omp_lib.F90
at ${CMAKE_BUILD_DIR}/runtimes/runtimes-bins/openmp/runtime/src
.
Solves 5: Can deprecate LLVM_ENABLE_PROJECTS=openmp
Solves only 5.
Only works with bootstrapping-builds, not standalone-runtime builds.
Must build runtime default target, even if only interested in cross-compilation
What’s currently upstream in main
There are additional sets of build instructions at
openmp/runtime/src/CMakeLists.txt#L378-L383
and
openmp/runtime/src/CMakeLists.txt#L400-L406
The first is activated with custom code in llvm/runtimes/CMakeLists.txt. With LLVM_RUNTIMES_TARGETS=default
, the omp_lib.mod
is emitted to runtimes/runtimes-bins/openmp/runtime/src/omp_lib.mod
. Because the flang-driver needs to find omp_lib.mod
when running tests, that path is added using -J
. The actual path is hardcoded.
This wasn’t working for me because check-flang
does not depend on building the runtimes. So just running ninja check-flang
in a newly configured build directory would fail a lot of OpenMP tests. The CMake output is also “Not building omp_lib.mod, no OpenMP runtime in LLVM_ENABLED_PROJECTS”.
Solves 5: Can deprecate LLVM_ENABLE_PROJECTS=openmp
Solves only 5.
Only works with bootstrapping-builds, not standalone-runtime builds.
Must build runtime default target, even if only interested in cross-compilation
When building another
LLVM_RUNTIME_TARGETS
, onninja install
theomp_lib.mod
files for each target will overwrite each other.
Remove the configure-time dependency to openmp
Some placeholders in the file omp_lib.F90.var
are replaced with values from the build configuration:
- Version of the OpenMP runtime library (
libomp.so
):kmp_version_major
,kmp_version_minor
,kmp_version_build
,kmp_build_date
. - Version of the OpenMP standard supported:
openmp_version
I think what version libomp.so
is does not even belong into the header file. Its version may be different from when an OpenMP program is compiled and when it is executed. For instance, an OS update may update libomp.so
but the application will not notice since it the header value is fixed. Should be replaced by a reference to a global variable defined in libomp.so
using e.g. bind(C)
.
According to the OpenMP spec, openmp_version
is the equivalent to the macro _OPENMP
in C, i.e. it is defined by version of OpenMP the compiler supports, not the runtime library or its header. It still might be regarded acceptable since both of them together are the OpenMP implementation. However, to avoid the configure-dependency, could be replaced by a built-in like __builtin_openmp_version
that the compiler replaces when compiling to the .mod file.
With these changes, flang could instead compile openmp/runtime/include/omp_lib.F90
from the source tree directly.
Solves 5: Can deprecate LLVM_ENABLE_PROJECTS=openmp
“more correct” than current approach
Solves only 5.
Build the .mod files in the runtimes, not by LLVM_ENABLE_PROJECTS=flang
Instead of the flang build looking for the .f90
files, make the runtimes look for the flang compiler to build their .mod
files. That is, LLVM_ENABLE_RUNTIMES=openmp
would build omp_lib.mod
, and LLVM_ENABLE_RUNTIMES=flang-rt
builds the .mod files from flang/module
. It already builds the .o
file from iso_fortran_env_impl.f90
. Therefore I would move the files from /flang/module
to Flang-RT.
The target-dependent modules also need to be install into target-triple-dependent paths or they would overwrite each other. That is, the driver needs to be changed to look for modules files in per-target directory. For gfortran, this is already the case. On my Ubuntu system, gfortran’s .mod
files are located at /usr/lib/gcc/x86_64-linux-gnu/13/finclude/
.
The necessary infrastructure is largely already created in #110217. That is, openmp and flang-rt can instruct the LLVM_ENABLE_RUNTIMES system to make flang available as Fortran compiler.
Solves 1: Different module files for each target
Solves 2: PowerPC module files only included on PowerPC target
Solves 3: Dependency resolution done by CMake
Solves 4: Cross-compilation done by LLVM_ENABLE_RUNTIMES bootstrapping build
Solves 5: Can deprecate LLVM_ENABLE_PROJECTS=openmp
Redundant non-target dependent module files
Modules only become available when compiling openmp/flang-rt
Does not yet work without changes to Flang
This is what I already tried in the first drafts of #110217, but removed this part because I encountered some problems:
-
CMake by default passes pre-processed sources (which are already available because CMake uses it for its dependency analysis), but Flang cannot always compile its own preprocessor output [sic!]. Fortunately, CMake has a workaround, or just adding some line breaks into will solve this issue.
-
Compiling modules requires builtin modules, even if those are the builtin modules themselves. Fortunately, CMake already has a solution: Fortran_BUILDING_INSTRINSIC_MODULES. This option was actually added for Classic Flang.
-
CMake assumes that the output of the compilation step is a
.o
file, but with-fsyntax-only
[2] no object file is being emitted. Unmitigated, CMake/ninja will rebuild the module files every time. We could just emit an empty object files for module-only sources, but unfortunately crashes on one some of the builtin modules, e.g.iso_fortran_env.f90
because the value of__builtin_numeric_storage_size()
cannot be emitted into an object file (it is not a constant but depends on compiler switches passed to Flang). This is also the reason whyiso_fortran_env_impl.f90
exists. -
Flang crashes while compiling
__fortran_builtins.mod
with the error
error: loc(".../flang/module/__fortran_builtins.f90":203:5): runtime derived type info descriptor was not generated
There is already is a flag that allows emit the object file: -mllvm -ignore-missing-type-desc