This is an archive of the discontinued LLVM Phabricator instance.

Support LLVM_BUILD_USER_FORTRAN_LIBS=[shared|static|all] cmake option
Needs ReviewPublic

Authored by pscoro on Jun 21 2023, 7:37 AM.

Details

Summary

The goal of this patch is to enable the user to have more control over the linkage type of the fortran libraries used by user executables. We want to be able to, for example, have all the LLVM libs build and link statically in flang-new, but at the same time retain the ability to have the Fortran user libs (FortranDecimal, FortranRuntime) also be built and linked dynamically for executables made using flang-new.

In order to do this, a new CMake option LLVM_BUILD_USER_FORTRAN_LIBS=[shared|static|all] can be passed. This option works on top of the decisions made by BUILD_SHARED_LIBS/BUILD_STATIC_LIBS by appending additional linkage types for just the user fortran libs. For the example above, this could be done by passing BUILD_SHARED_LIBS and also LLVM_BUILD_USER_FORTRAN_LIBS=shared. The BUILD_SHARED_LIBS will guarantee that all the LLVM libs get built and linked into flang-new statically. But on top of this, the new optoin thats passed will cause cmake to also build FortranDecimal and FortranRuntime as shared. By default, flang-new tried to dynamically link these 2 libraries into user executables. A future patch will introduce a flang-new driver option to allow the end user to choose between static and shared linking of these user fortran libs.

In the case that both linkage types are built by cmake, duplicate names are avoided by appending "_static" to the lib name. This is a feature that already existed in LLVM's cmake. There are some code changes in this patch that are needed to support/expect these "_static" named libs.

Diff Detail

Event Timeline

pscoro created this revision.Jun 21 2023, 7:37 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald Transcript
pscoro requested review of this revision.Jun 21 2023, 7:37 AM
pscoro edited the summary of this revision. (Show Details)Jun 21 2023, 7:50 AM

Hi, thanks for the patch! I wonder if you could help me understand what's happening here as I'm not sure I fully get it.

Am I right in thinking that currently whether e.g. libFortranRuntime gets built as a shared or static library is solely dependent on BUILD_SHARED_LIBS? i.e. if you have BUILD_SHARED_LIBS set for all of LLVM you get a shared runtime library for flang, and no static one?
And so this patch is trying to allow you to control whether you get a fortran RTL as static or shared independently of the BUILD_SHARED_LIBS used for all of LLVM.

Is my understanding above correct?

Am I right in thinking that currently whether e.g. libFortranRuntime gets built as a shared or static library is solely dependent on BUILD_SHARED_LIBS? i.e. if you have BUILD_SHARED_LIBS set for all of LLVM you get a shared runtime library for flang, and no static one?

So the thing that complicates the process here is that a different linkage type may be wanted for flang-new than for user executables. For example in our downstream build of flang, we are trying to have flang-new statically link all the llvm libs, including fortran libs like FortranDecimal. But at the same time, we want user fortran libs to get built as shared as well, so that the shared versions can be linked into user executables built by flang-new. To answer your question, BUILD_SHARED_LIBS=true will guarantee that e.g. libFortranRuntime gets built as shared, so if you have BUILD_SHARED_LIBS set you will get a shared runtime lib. However, additional linkage types for the user fortran libs can be also built with the new LLVM_USER_FORTRAN_LIBS flag. Lets say you did have BUILD_SHARED_LIBS set but you want the fortran libs also built statically (lets say that the flang-new driver option to specify --static libs exists), then you can additionally specify LLVM_BUILD_USER_FORTRAN_LIBS=static (or all) and this will build the lib statically in addition. The catch is that when both linkage types get built, the static version gets named e.g. FortranRuntime_static instead.

And so this patch is trying to allow you to control whether you get a fortran RTL as static or shared independently of the BUILD_SHARED_LIBS used for all of LLVM.

Not independently, but in addition to. I dont think this applies to FortranRuntime (I dont think it gets linked into flang-new?), but FortranDecimal needs to be linked in both flang-new and user executables, and we want to have the option to have the linkage types be different.

This entire patch is very open to design changes.. We had a specific goal of making it possible to build flang-new with static linkage while retaining shared linkage of user fortran libs in user executables (or more broadly, make it possible to choose static/shared linking for both flang-new/user executables). We wanted to achieve this in 2 steps:

  1. by offering a cmake option that gives us more control over which linkage types are built for the user fortran libs (talking about libFortranRuntime and libFortranDecimal specifically) separately from the other LLVM libs, while retaining the current behavior of using BUILD_SHARED_LIBS to determine which link type actually gets linked into flang-new.
  2. (next patch) by offering a new flang-new driver option to allow user to choose between static and shared fortran libs linkage into user executables. But in order for a user to, for example, specify --static libs for their executables, those fortran libs need to be built statically. In the scenario that flang-new is being built with shared linking, this patch provides the ability for those user fortran libs to also be built statically so that they can be provided as static libs for the end user.

@DavidTruby

Also in case there is still some confusion, note the distinction between choosing which linkage types get built vs choosing which linkage types actually get linked into what. This patch aims to not change how cmake chooses which link type gets linked into flang-new (behaviour determined by BUILD_SHARED_LIBS). This patch enables someone to change which link types get built for certain libs. The next patch will enable someone to change which link types get linked into user executables, but in order for that to be possible, you first need to be able to control which link types get built for those libs, as provided by this patch.

Not independently, but in addition to. I dont think this applies to FortranRuntime (I dont think it gets linked into flang-new?), but FortranDecimal needs to be linked in both flang-new and user executables, and we want to have the option to have the linkage types be different.

That's right. The same binary<->decimal conversion routines in FortranDecimal are used by both the compiler and the runtime. The runtime support library FortranRuntime is not linked to the compiler, although several of its headers are included by lowering source files.

Thanks for working on this. Once the design is set, could you please document this new build functionality? A good place to do so might be https://github.com/llvm/llvm-project/blob/main/flang/docs/GettingStarted.md.

Thanks for working on this. Once the design is set, could you please document this new build functionality?

Sure thing. I will wait for a couple days as I expect that major design changes could be suggested by the community (since this touches some fundamental cmake code).

Thanks for working on this!

Thanks for working on this. Once the design is set, could you please document this new build functionality?

Sure thing. I will wait for a couple days as I expect that major design changes could be suggested by the community (since this touches some fundamental cmake code).

It would be good to advertise this on Discourse for better visibility. I imagine that this will have a pretty large impact on folks creating LLVM packages.

I would also appreciate an overview of what the end goal is (you mentioned e.g. -static). And, for example, the interaction between:

  • BUILD_SHARED_LIBS, and
  • LLVM_BUILD_USER_FORTRAN_LIBS

Perhaps you could add a table in the summary that would show what happens when toggling these flags? And the impact on the runtime libs? (i.e. what libs are built)

I have a couple of minor comments on the cmake here but I also agree we might want to discuss this in an RFC as well to hammer out exactly the behaviour we want. Thanks!

flang/CMakeLists.txt
9

Do we need to have _static added to the name? I think they can continue to have the same name as the file extensions will be different

12

This variable should be called FLANG_<something> as it is specific to the flang subproject. I also find this name a bit confusing as to me it suggests whether you're going to build the libraries or not, but the libraries will always need to be built. I also think RUNTIME would be clearer than USER as a term here.
I'd propose something like FLANG_RUNTIME_LIB_TYPES but am open to other suggestions.

flang/cmake/modules/AddFlang.cmake
112–132

can you split all this out into a function and call it in both places, rather than duplicating all the code?

pscoro added inline comments.Jun 26 2023, 7:29 AM
flang/CMakeLists.txt
9

I am doing some further investigating and am preparing a more detailed discourse post at the moment where this can be discussed more thoroughly but iirc the code that adds "_static" is actually in AddLLVM.cmake and is not added by this patch. The file extension is not enough to distinguish the libs in CMake. If there are 2 add_library calls with the same name, then later when that lib name is used in CMake code (eg, when its added as a dependency for a target) it is unclear which lib (static or shared) is being linked.

In actuality I think this behavior is already not very clear. I've been looking into the possibility of another variable (something like LLVM_LINK_TYPE or FLANG_LINK_TYPE, haven't decided on the scope). The issue is that when libs are built as both static AND shared, by default flang-new was linking the shared libs because they are the ones with the unmodified lib name (without _static). Currently, this patch reverses this for the fortran runtime libraries (FortranRuntime, FortranDecimal), but I'm not sure if this is the best way to handle this. My thinking is that if a variable like FLANG_LINK_TYPE=shared is passed when *all* lib types are being built (ignored if lib type != all), then the person building the compiler can choose whether the static or shared libs get linked into flang.

12

I also find this name a bit confusing as to me it suggests whether you're going to build the libraries or not, but the libraries will always need to be built

I understand that the libs always need to be built but the reason I added the word build in here is because im trying to make the distinction between which lib types are built and which ones are actually linked into flang-new. I like the name FLANG_RUNTIME_LIB_TYPES except for that the distinction is no longer made, if I say BUILD_SHARED_LIBS and FLANG_RUNTIME_LIB_TYPES=static, what this patch is arguing should happen is that *all* libs get built as shared and linked as shared into flang-new, but then in addition, the runtime libs get built as static (and thats it, they do not get linked into anything during the compiler building stage, they are just used by the user later). Because of this, I think if we just use FLANG_RUNTIME_LIB_TYPES I'm not sure its obvious that we are just building additional linkage types.

Based on this, what do you think of the name FLANG_BUILD_RUNTIME_LIBS=shared|static|all?

flang/cmake/modules/AddFlang.cmake
112–132

Will do

The discourse thread for this patch is now open here: https://discourse.llvm.org/t/rfc-support-cmake-option-to-control-link-type-built-for-flang-runtime-libraries/71602

I want to note that while doing some further investigating and writing up that post, I began to doubt the need for a BUILD_STATIC_LIBS variable (this variable was being introduced in this patch and never used elsewhere). I will likely remove any reference to this variable.

DavidTruby added inline comments.Jun 27 2023, 10:07 AM
flang/CMakeLists.txt
9

Right, I actually hit something on Windows today that made me realise why we need to do this anyway; on Windows .lib files are generated for both static and dynamic builds of libraries, so they do need to have different names. That's why AddLLVM.cmake uses _static

12

Based on this, what do you think of the name FLANG_BUILD_RUNTIME_LIBS=shared|static|all?

Works for me :)