Why does -shared add -lFortran_main.a to the link line

I’m having trouble understanding why Flang, when used as linker with -shared, adds -lFortran_main.a to the link line for the shared object:

$ flang-new -### -shared -o libbla.so bla1.o bla2.o
"/usr/bin/ld" [...] "--whole-archive" "-lFortran_main" "--no-whole-archive" "-lFortranRuntime" "-lFortranDecimal" [...]

That does not seem to make much sense to me and before attempting to fix this, I wanted to quickly get some feedback about whether there was good reason to do that.

@banach-space has probably an answer for that.

Please double check this, as it’s been a while …

Flang injects calls to _QQmain in Fortran "program"s. So, when generating a shared object you will see a reference to an undefined symbol. Which is fine on Linux, but the linker on MacOS will complain. I think that you can use -undefined dynamic_lookup to override this behavior.

Sadly I don’t have a good reference to share - these things tend to be documented in man pages. Only. I also don’t build Flang on MacOS, so can’t verify. But I do know one user that does and I can ask them if that helps.

Btw, thanks for looking into this logic and improving Flang :pray:t2:

-Andrzej

Thanks! It turns out that also on Linux you get to see this complaints in codes that have a shared library and provide the main function via a C/C++ translation unit.

The problem is that you can get this fixed via the new fno-fortran-main and with CMake this is a viable workaround. But autotools-based build processes are too limited to inject the proper flag unless the project you compile already has it.

I’ll craft a fix for Flang. I should have a PR early next week and then we can see how many things I’m going to break with this change. :slight_smile:

1 Like

Where is _QQmain called from? Without knowing more details it sounds like it’s some startup code. Could it be delegated to something like crt0.o (but for Fortran)?

Apologies, I got that wrong. Fortran’s “program” becomes __QQmain:

$ cat file.f90
end program
$ flang-new  -S -emit-llvm file.f90 -o -
; Skipping stuff here

define void @_QQmain() {
  ret void
}

; Skipping stuff here

That’s what Fortran_main does:

That’s great. It does raise the question again though, whether we need to link this into a shared library…