Skip to content

Commit 6403287

Browse files
pscoromadanial0
authored andcommitted
[Flang] [FlangRT] Introduce FlangRT project as solution to Flang's runtime LLVM integration
See discourse thread https://discourse.llvm.org/t/rfc-support-cmake-option-to-control-link-type-built-for-flang-runtime-libraries/71602/18 for full details. Flang-rt is the new library target for the flang runtime libraries. It builds the Flang-rt library (which contains the sources of FortranRuntime and FortranDecimal) and the Fortran_main library. See documentation in this patch for detailed description (flang-rt/docs/GettingStarted.md). This patch aims to: - integrate Flang's runtime into existing llvm infrasturcture so that Flang's runtime can be built similarly to other runtimes via the runtimes target or via the llvm target as an enabled runtime - decouple the FortranDecimal library sources that were used by both compiler and runtime so that different build configurations can be applied for compiler vs runtime - add support for running flang-rt testsuites, which were created by migrating relevant tests from `flang/test` and `flang/unittest` to `flang-rt/test` and `flang-rt/unittest`, using a new `check-flang-rt` target. - provide documentation on how to build and use the new FlangRT runtime Reviewed By: DanielCChen Differential Revision: https://reviews.llvm.org/D154869
1 parent d222c5e commit 6403287

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1294
-245
lines changed

Diff for: clang/lib/Driver/ToolChains/CommonArgs.cpp

+26-14
Original file line numberDiff line numberDiff line change
@@ -969,29 +969,41 @@ void tools::addFortranRuntimeLibs(const ToolChain &TC,
969969
llvm::opt::ArgStringList &CmdArgs) {
970970
if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
971971
CmdArgs.push_back("Fortran_main.lib");
972-
CmdArgs.push_back("FortranRuntime.lib");
973-
CmdArgs.push_back("FortranDecimal.lib");
972+
CmdArgs.push_back("flang-rt.lib");
974973
} else {
975974
CmdArgs.push_back("-lFortran_main");
976-
CmdArgs.push_back("-lFortranRuntime");
977-
CmdArgs.push_back("-lFortranDecimal");
975+
CmdArgs.push_back("-lflang-rt");
978976
}
979977
}
980978

981979
void tools::addFortranRuntimeLibraryPath(const ToolChain &TC,
982980
const llvm::opt::ArgList &Args,
983981
ArgStringList &CmdArgs) {
984-
// Default to the <driver-path>/../lib directory. This works fine on the
985-
// platforms that we have tested so far. We will probably have to re-fine
986-
// this in the future. In particular, on some platforms, we may need to use
987-
// lib64 instead of lib.
988-
SmallString<256> DefaultLibPath =
982+
// Default to the <driver-path>/../lib, <driver-path>/../flang-rt/lib, and
983+
// <driver-path>/../runtimes/runtimes-bins/flang-rt/lib directories. This
984+
// works fine on the platforms that we have tested so far. We will probably
985+
// have to re-fine this in the future. In particular, on some platforms, we
986+
// may need to use lib64 instead of lib.
987+
SmallString<256> BuildLibPath =
988+
llvm::sys::path::parent_path(TC.getDriver().Dir);
989+
SmallString<256> FlangRTLibPath =
990+
llvm::sys::path::parent_path(TC.getDriver().Dir);
991+
SmallString<256> RuntimesLibPath =
989992
llvm::sys::path::parent_path(TC.getDriver().Dir);
990-
llvm::sys::path::append(DefaultLibPath, "lib");
991-
if (TC.getTriple().isKnownWindowsMSVCEnvironment())
992-
CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath));
993-
else
994-
CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
993+
// Search path for Fortran_main and Flang-rt libraries.
994+
llvm::sys::path::append(BuildLibPath, "lib");
995+
llvm::sys::path::append(FlangRTLibPath, "flang-rt/lib");
996+
llvm::sys::path::append(RuntimesLibPath,
997+
"runtimes/runtimes-bins/flang-rt/lib");
998+
if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
999+
CmdArgs.push_back(Args.MakeArgString("-libpath:" + BuildLibPath));
1000+
CmdArgs.push_back(Args.MakeArgString("-libpath:" + FlangRTLibPath));
1001+
CmdArgs.push_back(Args.MakeArgString("-libpath:" + RuntimesLibPath));
1002+
} else {
1003+
CmdArgs.push_back(Args.MakeArgString("-L" + BuildLibPath));
1004+
CmdArgs.push_back(Args.MakeArgString("-L" + FlangRTLibPath));
1005+
CmdArgs.push_back(Args.MakeArgString("-L" + RuntimesLibPath));
1006+
}
9951007
}
9961008

9971009
static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,

Diff for: flang-rt/CMakeLists.txt

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# CMake build for the Flang runtime libraries
2+
# The source for the flang runtime libraries (FortranDecimalRT, FortranRuntime)
3+
# exist in the flang top-level directory.
4+
# Flang-rt is only scaffolding and does not provide any additional source files.
5+
6+
cmake_minimum_required(VERSION 3.20.0)
7+
8+
#===============================================================================
9+
# Configure CMake
10+
#===============================================================================
11+
set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
12+
include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake
13+
NO_POLICY_SCOPE)
14+
15+
set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON)
16+
set(CMAKE_INCLUDE_CURRENT_DIR ON)
17+
18+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/flang-rt/bin)
19+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
20+
${CMAKE_BINARY_DIR}/flang-rt/lib)
21+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
22+
${CMAKE_BINARY_DIR}/flang-rt/lib)
23+
set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_BINARY_DIR}/flang-rt)
24+
25+
set(FLANG_RT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
26+
set(FLANG_RT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
27+
28+
#===============================================================================
29+
# Setup Options and Defaults
30+
#===============================================================================
31+
option(FLANG_RT_ENABLE_SHARED "Build flang-rt as a shared library." OFF)
32+
option(FLANG_RT_ENABLE_STATIC "Build flang-rt as a static library." OFF)
33+
34+
option(FLANG_RT_INCLUDE_TESTS
35+
"Generate build targets for the Flang-rt unit tests." ${LLVM_INCLUDE_TESTS})
36+
37+
# MLIR_DIR must be passed on invocation of flang-rt because it is needed for the Flang package.
38+
if(NOT DEFINED MLIR_DIR OR MLIR_DIR STREQUAL "")
39+
message(FATAL_ERROR "MLIR_DIR must be set to the directory of the MLIRConfig cmake file in order to find the MLIR package.")
40+
endif()
41+
# Flang-rt requires a pre-built/installed version of flang that requires MLIR.
42+
find_package(MLIR REQUIRED HINTS "${MLIR_DIR}")
43+
44+
# FLANG_DIR must be passed on invocation of flang-rt.
45+
if(NOT DEFINED FLANG_DIR OR FLANG_DIR STREQUAL "")
46+
message(FATAL_ERROR "FLANG_DIR must be set to the directory of the FlangConfig cmake file in order to find the Flang package.")
47+
endif()
48+
# Flang-rt requires a pre-built/installed version of flang.
49+
# Flang-rt uses flang/Common headers.
50+
# Finding this package exposes FLANG_SOURCE_DIR, FLANG_BINARY_DIR, and FLANG_INCLUDE_DIRS to Flang-rt
51+
find_package(Flang REQUIRED HINTS "${FLANG_DIR}")
52+
# If the user specifies a relative path to LLVM_DIR, the calls to include
53+
# LLVM modules fail. Append the absolute path to LLVM_DIR instead.
54+
get_filename_component(FLANG_DIR_ABSOLUTE ${FLANG_DIR} REALPATH)
55+
list(APPEND CMAKE_MODULE_PATH ${FLANG_DIR_ABSOLUTE})
56+
57+
set(LLVM_COMMON_CMAKE_UTILS "${FLANG_RT_SOURCE_DIR}/../cmake")
58+
set(LLVM_CMAKE_UTILS "${LLVM_BUILD_MAIN_SOURCE_DIR}/cmake")
59+
set(CLANG_CMAKE_UTILS "${FLANG_RT_SOURCE_DIR}/../clang/cmake")
60+
61+
if (FLANG_RT_INCLUDE_TESTS)
62+
# LLVM_DIR must be passed on invocation of flang-rt when tests are enabled.
63+
if(NOT DEFINED LLVM_DIR OR LLVM_DIR STREQUAL "")
64+
message(FATAL_ERROR "LLVM_DIR must be set to the directory of the LLVMConfig cmake file in order to find the LLVM package.")
65+
endif()
66+
# We need a pre-built/installed version of LLVM for gtest.
67+
find_package(LLVM REQUIRED HINTS "${LLVM_DIR}")
68+
# If the user specifies a relative path to LLVM_DIR, the calls to include
69+
# LLVM modules fail. Append the absolute path to LLVM_DIR instead.
70+
get_filename_component(LLVM_DIR_ABSOLUTE ${LLVM_DIR} REALPATH)
71+
list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR_ABSOLUTE})
72+
73+
add_compile_definitions(FLANG_RT_INCLUDE_TESTS=1)
74+
75+
if (DEFINED FLANG_BINARY_DIR)
76+
set(FLANG_BINARY_DIR ${FLANG_BINARY_DIR} CACHE PATH "Path to the Flang build directory" FORCE)
77+
else()
78+
message(FATAL_ERROR "FLANG_BINARY_DIR must be defined or passed by the user when building tests.")
79+
endif()
80+
set(FLANG_RT_TEST_COMPILER ${FLANG_BINARY_DIR}/bin/flang-new
81+
CACHE PATH "Compiler to use for testing")
82+
set(FLANG_RT_GTEST_AVAIL 1)
83+
endif()
84+
85+
# Add path for custom modules
86+
list(INSERT CMAKE_MODULE_PATH 0
87+
"${FLANG_SOURCE_DIR}/cmake"
88+
"${FLANG_SOURCE_DIR}/cmake/modules"
89+
"${CLANG_CMAKE_UTILS}/modules"
90+
"${LLVM_CMAKE_UTILS}/modules"
91+
)
92+
93+
include(AddClang)
94+
include(AddFlang)
95+
include(TestBigEndian)
96+
test_big_endian(IS_BIGENDIAN)
97+
if (IS_BIGENDIAN)
98+
add_compile_definitions(FLANG_BIG_ENDIAN=1)
99+
else ()
100+
add_compile_definitions(FLANG_LITTLE_ENDIAN=1)
101+
endif ()
102+
103+
# Flang's include directories are needed for flang/Common.
104+
include_directories(SYSTEM ${FLANG_INCLUDE_DIRS})
105+
106+
# LLVM's include directories are needed for gtest.
107+
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
108+
109+
#===============================================================================
110+
# Add Subdirectories
111+
#===============================================================================
112+
set(FORTRAN_DECIMAL_SRC "${FLANG_SOURCE_DIR}/lib/Decimal")
113+
set(FORTRAN_RUNTIME_SRC "${FLANG_SOURCE_DIR}/runtime")
114+
set(FORTRAN_MAIN_SRC "${FLANG_SOURCE_DIR}/runtime/FortranMain")
115+
116+
add_subdirectory(${FORTRAN_DECIMAL_SRC} FortranDecimalRT)
117+
add_subdirectory(${FORTRAN_RUNTIME_SRC} FortranRuntime)
118+
add_subdirectory(${FORTRAN_MAIN_SRC} FortranMain)
119+
120+
if (FLANG_RT_INCLUDE_TESTS)
121+
add_subdirectory(test)
122+
if (FLANG_RT_GTEST_AVAIL)
123+
add_subdirectory(unittests)
124+
endif()
125+
endif()
126+
127+
#===============================================================================
128+
# Create Flang-rt wrapper library
129+
#===============================================================================
130+
# Build as shared by default if no linkage type option set.
131+
if (NOT FLANG_RT_ENABLE_SHARED AND NOT FLANG_RT_ENABLE_STATIC)
132+
add_library(flang-rt SHARED $<TARGET_OBJECTS:obj.FortranDecimalRT>
133+
$<TARGET_OBJECTS:obj.FortranRuntime>)
134+
endif()
135+
if (FLANG_RT_ENABLE_SHARED)
136+
add_library(flang-rt SHARED $<TARGET_OBJECTS:obj.FortranDecimalRT>
137+
$<TARGET_OBJECTS:obj.FortranRuntime>)
138+
endif()
139+
if (FLANG_RT_ENABLE_STATIC AND NOT FLANG_RT_ENABLE_SHARED)
140+
add_library(flang-rt STATIC $<TARGET_OBJECTS:obj.FortranDecimalRT>
141+
$<TARGET_OBJECTS:obj.FortranRuntime>)
142+
endif()
143+
# When building both static and shared, we need to append _static to the name
144+
# to avoid naming conflicts.
145+
if (FLANG_RT_ENABLE_STATIC AND FLANG_RT_ENABLE_SHARED)
146+
add_library(flang-rt_static STATIC $<TARGET_OBJECTS:obj.FortranDecimalRT>
147+
$<TARGET_OBJECTS:obj.FortranRuntime>)
148+
endif()

Diff for: flang-rt/docs/GettingStarted.md

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<!--===- docs/GettingStarted.md
2+
3+
Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
See https://llvm.org/LICENSE.txt for license information.
5+
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
7+
-->
8+
9+
# Flang-rt Runtime Library
10+
11+
```eval_rst
12+
.. contents::
13+
:local:
14+
```
15+
## What is Flang-rt
16+
Flang-rt is the runtime library project for Flang. The Flang driver requires
17+
the Fortran_main and Flang-rt libraries at runtime in order to generate
18+
user executables. Building this Flang-rt project will build both Fortran_main
19+
and the Flang-rt library, which is comprised of the FortranRuntime and
20+
FortranDecimalRT libraries.
21+
22+
### Fortran_main
23+
Fortran_main is left out of the Flang-rt library because it is required to
24+
always be static unlike the link type of the Flang-rt library which can be
25+
configured. Fortran_main implements the main entry point into Fortran's
26+
`PROGRAM` in Flang by being the bridge between object files generated by Flang
27+
and the C runtime that takes care of program set-up at system-level. For
28+
every Fortran `PROGRAM`, Flang generates the `_QQmain` function.
29+
Fortran_main implements the C `main` function that simply calls
30+
`_QQmain`.
31+
32+
### FortranDecimalRT
33+
In order to decouple the common dependency between compiler and runtime,
34+
[FortranDecimal's sources](../../flang/lib/Decimal/CMakeLists.txt) are built
35+
separately for the compiler and the runtime. When the library is built for
36+
Flang-rt, the name FortranDecimalRT is used to avoid naming conflicts and
37+
confusion.
38+
39+
### FortranRuntime
40+
This is the core runtime library in Flang-rt. The sources for this library
41+
currently still exist in the
42+
[Flang source directory](../../flang/runtime/CMakeLists.txt). We hope to
43+
migrate the sources to the Flang-rt directory in the future in order to further
44+
decouple the runtime from the Flang compiler.
45+
46+
## Building Flang-rt
47+
Like other LLVM runtimes, Flang-rt can be built by targetting the
48+
[runtimes LLVM target](../../runtimes/CMakelists.txt). It can also be built
49+
when targetting the [llvm target](../../llvm/CMakeLists.txt) as an enabled
50+
runtime. Flang-rt will implicitly be added as an enabled runtime when Flang
51+
is an enabled project built by llvm. Flang-rt does not support standalone
52+
builds.
53+
54+
In the future, we may be interested in supporting in optionally building
55+
Flang-rt when doing a Flang standalone build.
56+
57+
### Building with the llvm target
58+
Assuming you are building Flang-rt to use with Flang, see
59+
[Flang's Getting Started guide](../../flang/docs/GettingStarted.md) for more
60+
information. To build Flang-rt when building the Flang compiler, once you have
61+
the llvm-project source ready, make a clean build directory. Let root be the
62+
root directory that you cloned llvm-project into.
63+
```bash
64+
cd root
65+
rm -rf build
66+
mkdir build
67+
cd build
68+
```
69+
Now invoke the cmake configuration command for llvm that would build Flang with
70+
Flang-rt.
71+
```bash
72+
cmake \
73+
-G Ninja \
74+
-DLLVM_ENABLE_RUNTIMES="compiler-rt;flang-rt" \
75+
-DCMAKE_CXX_STANDARD=17 \
76+
-DLLVM_INSTALL_UTILS=On \
77+
# New Flang-rt flags for enabled link types
78+
-DFLANG_RT_ENABLE_STATIC=On \
79+
-DFLANG_RT_ENABLE_SHARED=On \
80+
# We need to enable GTest if we want to run Flang-rt's testsuites
81+
-DLLVM_INSTALL_GTEST=On \
82+
-DFLANG_ENABLE_WERROR=On \
83+
-DLLVM_LIT_ARGS=-v \
84+
-DCMAKE_BUILD_TYPE=Release \
85+
-DLLVM_ENABLE_PROJECTS="clang;flang;lld;mlir;openmp" \
86+
../llvm-project/llvm
87+
```
88+
Flang requires other llvm projects (see LLVM_ENABLE_PROJECTS and the [Flang
89+
Getting Started Guide](../../flang/docs/GettingStarted.md) for more specifics
90+
on building Flang.
91+
92+
By targetting the LLVM project, we are letting LLVM infrastructure handle
93+
invoking the runtimes target that will build Flang-rt. This includes finding
94+
the cmake packages for Clang, LLVM, Flang and MLIR that Flang-rt depends on.
95+
96+
### Building with the runtimes target
97+
If you already have a pre-built/installed version of LLVM, Flang, Clang and
98+
MLIR, and would like to build Flang-rt without rebuilding the sources for these
99+
other projects. You can simply target the runtimes project directly and passing
100+
the paths to the directories of these files. If you built LLVM as we did above
101+
with default build directories, your runtimes invocation should look something
102+
like:
103+
```bash
104+
cd build
105+
BUILDDIR=`pwd`
106+
107+
cmake \
108+
-G Ninja \
109+
-DCMAKE_CXX_STANDARD=17 \
110+
# New Flang-rt flags for enabled link types
111+
-DFLANG_RT_ENABLE_SHARED=On \
112+
-DFLANG_RT_ENABLE_STATIC=On \
113+
-DLLVM_LIT_ARGS=-v \
114+
-DCMAKE_BUILD_TYPE=Release \
115+
-DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,$LD_LIBRARY_PATH" \
116+
-DLLVM_TARGETS_TO_BUILD=host \
117+
-DLLVM_EXTERNAL_LIT=$BUILD_DIR/bin/llvm-lit \
118+
# We need to specify the paths to the cmake packages of the dependencies
119+
-DLLVM_DIR=$BUILD_DIR/lib/cmake/llvm \
120+
-DMLIR_DIR=$BUILD_DIR/lib/cmake/mlir \
121+
-DFLANG_DIR=$BUILD_DIR/lib/cmake/flang \
122+
-DLLVM_ENABLE_RUNTIMES="flang-rt" \
123+
../llvm-project/runtimes/
124+
```
125+
126+
## Library locations
127+
When building the llvm target with flang as an enabled project, the Flang-rt
128+
library will be built to `$BUILDDIR/runtimes/runtimes-bins/flang-rt/lib`. When
129+
building the runtimes target with flang-rt as an enabled runtime, the libraries
130+
will be built to `$BUILDDIR/flang-rt/lib` by default. In either configuration,
131+
the Fortran_main library will be built to `$BUILDDIR/lib` by default.
132+
133+
## Using Flang-rt
134+
The two build paths mentioned above get implicitly added as library paths at the
135+
invocation of the driver. If Flang-rt is a shared library, you must make the
136+
dynamic linker aware of where to look. One method to do so is to set the
137+
environment variable `LD_LIBRARY_PATH` include the path to Flang-rt's directory.
138+
139+
## Options
140+
Flang-rt introduces 2 CMake options used to configure the library's link type:
141+
```
142+
option(FLANG_RT_ENABLE_SHARED "Build flang-rt as a shared library." OFF)
143+
option(FLANG_RT_ENABLE_STATIC "Build flang-rt as a static library." OFF)
144+
```
145+
Both can be specified if you want to build both shared and static versions of
146+
the Flang-rt runtime. If both are specified, the static library will be named
147+
Flang-rt_static.a to avoid naming conflicts, as per the LLVM standard.
148+
149+
## Usage Examples
150+
```bash
151+
# Example of using Flang with the shared Flang-rt runtime
152+
# First we need to explicitly tell the dynamic linker where to find Flang-rt
153+
# since it was built as shared.
154+
$ $ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$BUILDDIR/runtimes/runtimes-bins/flang-rt/lib"
155+
$ flang-new -ffree-form hello.f95 -o hello
156+
```

0 commit comments

Comments
 (0)