Michael Kruse 34ca553d30
[Flang/Flang-RT] Fix OldUnit tests on Windows (#150734)
Flang and Flang-RT have two flavours of unittests: 
1. GTest unittests, using lit's `lit.formats.GoogleTest` format ending
with `Tests${CMAKE_EXECUTABLE_SUFFIX}`
2. "non-GTest" or "OldUnit" unittests, a plain executable ending with
`.test${CMAKE_EXECUTABLE_SUFFIX}`

Both executables are emitted into the same unittests/ subdirectory. When
running ...
1. `tests/Unit/lit.cfg.py`, only considers executable ending with
`Tests` (or `Tests.exe` on Windows), hence skips the non-GTest tests.
2. `tests/NonGtestUnit/lit.cfg.py` considers all tests ending with
`.test` or `.exe`. On Windows, The GTest unitests also end with `.exe`.

In Flang-RT, `.exe` is considered an extension for non-GTest unitests
which causes tests such as Flang's `RuntimeTests.exe` to be executed for
both on Windows. This particular test includes a file write test, using
a hard-coded filename `ucsfile`. If the two instances are executed
concurrently, they might interfere with each other reading/writing
`ucsfile` which results in a flaky test.

This patch avoids the redundant execution by requiring the suffix
`.test.exe` on Windows. lit has to be modified because it uses
`os.path.splitext` the extract the extension, which would only recognize
the last component. It was changed from the orginal `endswith` in
c865abe747aa72192f02ebfdcabe730f2553e42f
for unknown reasons.

In Flang, `.exe` is not considered a suffix for non-GTest unittests and
hence they are not run at all. Fixing by also added `.test.exe` as valid
suffix, like with Flang-RT.

Unfortunately, the ` Evaluate/real.test.exe` test was failing on
Windows:
```
FAIL: flang-OldUnit :: Evaluate/real.test.exe (3592 of 3592)
******************** TEST 'flang-OldUnit :: Evaluate/real.test.exe' FAILED ********************
..\_src\flang\unittests\Evaluate\real.cpp:511: FAIL: FlagsToBits(prod.flags) == 0x18, not 0x10
        0 0x800001 * 0xbf7ffffe
..\_src\flang\unittests\Evaluate\real.cpp:511: FAIL: FlagsToBits(prod.flags) == 0x18, not 0x10
        0 0x800001 * 0x3f7ffffe
..\_src\flang\unittests\Evaluate\real.cpp:511: FAIL: FlagsToBits(prod.flags) == 0x18, not 0x10
        0 0x80800001 * 0xbf7ffffe
..\_src\flang\unittests\Evaluate\real.cpp:511: FAIL: FlagsToBits(prod.flags) == 0x18, not 0x10
        0 0x80800001 * 0x3f7ffffe
...
```
This is due to the `__x86_64__` macro not being set by Microsoft's
cl.exe and hence floating point status flags not being read out. The
equivalent macro for Microsofts compiler is `_M_X64` (or `_M_X64`).
2025-07-26 23:47:36 +02:00
..

Fortran Runtime (Flang-RT)

Flang-RT is the runtime library for code emitted by the Flang compiler (https://flang.llvm.org).

Getting Started

There are two build modes for the Flang-RT. The bootstrap build, also called the in-tree build, and the runtime-only build, also called the out-of-tree build. Not to be confused with the terms in-source and out-of-source builds as defined by CMake. In an in-source build, the source directory and the build directory are identical, whereas with an out-of-source build the build artifacts are stored somewhere else, possibly in a subdirectory of the source directory. LLVM does not support in-source builds.

Requirements

Requirements:

Bootstrapping Runtimes Build

The bootstrapping build will first build Clang and Flang, then use these compilers to compile Flang-RT. CMake will create a secondary build tree configured to use these just-built compilers. The secondary build will reuse the same build options (Flags, Debug/Release, ...) as the primary build. It will also ensure that once built, Flang-RT is found by Flang from either the build- or install-prefix. To enable, add flang-rt to LLVM_ENABLE_RUNTIMES:

cmake -S <path-to-llvm-project-source>/llvm \
  -GNinja                                   \
  -DLLVM_ENABLE_PROJECTS="clang;flang"      \
  -DLLVM_ENABLE_RUNTIMES=flang-rt           \
  ...

It is recommended to enable building OpenMP alongside Flang and Flang-RT as well. This will build omp_lib.mod required to use OpenMP from Fortran. Building Compiler-RT may also be required, particularly on platforms that do not provide all C-ABI functionality (such as Windows).

cmake -S <path-to-llvm-project-source>/llvm     \
  -GNinja                                       \
  -DCMAKE_BUILD_TYPE=Release                    \
  -DLLVM_ENABLE_PROJECTS="clang;flang;openmp"   \
  -DLLVM_ENABLE_RUNTIMES="compiler-rt;flang-rt" \
  ...

By default, the enabled runtimes will only be built for the host platform (-DLLVM_RUNTIME_TARGETS=default). To add additional targets to support cross-compilation via flang --target=<target-triple>, add more triples to LLVM_RUNTIME_TARGETS, such as -DLLVM_RUNTIME_TARGETS="default;aarch64-linux-gnu".

After configuration, build, test, and install the runtime(s) via

$ ninja flang-rt
$ ninja check-flang-rt
$ ninja install

Standalone Runtimes Build

Instead of building Clang and Flang from scratch, the standalone Runtime build uses CMake's environment introspection to find a C, C++, and Fortran compiler. The compiler to be used can be controlled using CMake's standard mechanisms such as CMAKE_CXX_COMPILER, CMAKE_CXX_COMPILER, and CMAKE_Fortran_COMPILER. CMAKE_Fortran_COMPILER must be flang built from the same Git commit as Flang-RT to ensure they are using the same ABI. The C and C++ compiler can be any compiler supporting the same ABI.

In addition to the compiler, the build must be able to find LLVM development tools such as lit and FileCheck that are not found in an LLVM's install directory. Use CMAKE_BINARY_DIR to point to directory where LLVM has been built. When building Flang as part of a bootstrapping build (LLVM_ENABLE_PROJECTS=flang), Flang-RT is automatically added unless configured with -DFLANG_ENABLE_FLANG_RT=OFF. Add that option to avoid having two conflicting versions of the same library.

A simple build configuration might look like the following:

cmake -S <path-to-llvm-project-source>/runtimes              \
  -GNinja                                                    \
  -DLLVM_BINARY_DIR=<path-to-llvm-builddir>                  \
  -DCMAKE_Fortran_COMPILER=<path-to-llvm-builddir>/bin/flang \
  -DCMAKE_Fortran_COMPILER_WORKS=yes                         \
  -DLLVM_ENABLE_RUNTIMES=flang-rt                            \
  ...

The CMAKE_Fortran_COMPILER_WORKS parameter must be set because otherwise CMake will test whether the Fortran compiler can compile and link programs which will obviously fail without a runtime library available yet.

Building Flang-RT for cross-compilation triple, the target triple can be selected using LLVM_DEFAULT_TARGET_TRIPLE AND LLVM_RUNTIMES_TARGET. Of course, Flang-RT can be built multiple times with different build configurations, but have to be located manually when using with the Flang driver using the -L option.

After configuration, build, test, and install the runtime via

$ ninja
$ ninja check-flang-rt
$ ninja install

Configuration Option Reference

Flang-RT has the followign configuration options. This is in addition to the build options the LLVM_ENABLE_RUNTIMES mechanism and CMake itself provide.

  • FLANG_RT_INCLUDE_TESTS (boolean; default: ON)

    When OFF, does not add any tests and unittests. The check-flang-rt build target will do nothing.

  • FLANG_RUNTIME_F128_MATH_LIB (default: "")

    Determines the implementation of REAL(16) math functions. If set to libquadmath, uses quadmath.h and -lquadmath typically distributed with gcc. If empty, disables REAL(16) support. For any other value, introspects the compiler for __float128 or 128-bit long double support. More details.

  • FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT (values: "CUDA","OpenMP", "" default: "")

    When set to CUDA, builds Flang-RT with experimental support for GPU accelerators using CUDA. CMAKE_CUDA_COMPILER must be set if not automatically detected by CMake. nvcc as well as clang are supported.

    When set to OpenMP, builds Flang-RT with experimental support for GPU accelerators using OpenMP offloading. Only Clang is supported for CMAKE_C_COMPILER and CMAKE_CXX_COMPILER.

  • FLANG_RT_INCLUDE_CUF (bool, default: OFF)

    Compiles the libflang_rt.cuda_<CUDA-version>.a/.so library. This is independent of FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT=CUDA and only requires a CUDA Toolkit installation (no CMAKE_CUDA_COMPILER).

Experimental CUDA Support

With -DFLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT=CUDA, the following additional configuration options become available.

  • FLANG_RT_LIBCUDACXX_PATH (path, default: "")

    Path to libcu++ package installation.

  • FLANG_RT_CUDA_RUNTIME_PTX_WITHOUT_GLOBAL_VARS (boolean, default: OFF)

    Do not compile global variables' definitions when producing PTX library. Default is OFF, meaning global variable definitions are compiled by default.

Experimental OpenMP Offload Support

With -DFLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT=OpenMP, the following additional configuration options become available.

  • FLANG_RT_DEVICE_ARCHITECTURES (default: "all")

    A list of device architectures that Flang-RT is going to support. If "all" uses a pre-defined list of architectures. Same purpose as LIBOMPTARGET_DEVICE_ARCHITECTURES from liboffload.