fortran-lang / fpm

Fortran Package Manager (fpm)
https://fpm.fortran-lang.org
MIT License
867 stars 97 forks source link

Consider adding -static for ifort compiler so -traceback works properly #323

Open urbanjost opened 3 years ago

urbanjost commented 3 years ago

An original reading of the Intel documentation missed this:

NOTE: If you want to use traceback, you must also link to the static version of the libgcc library. This library enables printing of backtrace information.

So -static has to be added to the default for this to work, as referred to in a discussion about fman from @certik.

This would limit what external libraries can be linked to on quiet a few platforms, so perhaps -static-libgcc (L*X only) conditionally on ULS platforms (?).

I prefer -static as a default but the platform suppliers do not, and it makes using a lot of parallel programming interfaces impossible or near to it.

awvwgk commented 3 years ago

Static linking is a difficult topic, I'm not on a particular side here, but rather on both sides at once...

As a project maintainer on the one hand, I'm usually distributing statically linked binaries and my build files also default to this behaviour at least with ifort. Yet it had let to frequent discussions and request to remove static linking. Usually this requests are originating from the OSX community were static linking is not possible at all (-static-intel might still work on OSX) or the Red Hat Linux Distributions where certain libraries are not available for static linking. Over the last year I got more than a dozen request on this topic and had to implement various workarounds for the particularities of certain distributions or platforms.

As a packager for conda-forge on the other hand, I'm always trying to go for shared libraries even for Fortran projects where this is a bit tricky due to ABI compatibility issues, but the conda-forge pinning mechanism allows for stricter version constraints to ensure ABI compatibility between dependencies and therefore minimizes the required package rebuilds.

We are currently distributing statically linked binaries for fpm itself, the CI setup from this repository is something you could adapt for your fman project.

LKedward commented 3 years ago

Hi @urbanjost, are you able to elaborate further on why static linking is needed for the traceback? The traceback should work for non-library code with dynamic linking. This appears to be the case in Ondrej's second output dump where I can see the frame for testit at app/fpm_intrinsics.f90:80 and I assume the preceding frames are from a dynamically linked library.

Am I right in thinking you want traceback information for the full stack including linked libraries? My experience is that traceback information from the linked libraries isn't usually helpful — it is sufficient for me to know where in my code the error occurs.

For the reasons already mentioned I am wary of making static linking the default, even just to libgcc. EDIT: Though I agree that having the option to enable static linking is certainly beneficial.

urbanjost commented 3 years ago

At least on my RedHat8 machine the traceback is just a backtrace of addresses without using the static libgcc with the ifort compiler; and the manpage for ifort says it is required on Lnx machines in one place in the document; although it does not mention it in several other places -- it only mentioned it when discussing the switch for static libgcc. So maybe it is not a problem on all platforms. I will look at the actual Intel documentation site and maybe try the Intel forum for some clarification.

Definitely need to revisit an equivalent of the --flags option on h-fpm for f-fpm.

LKedward commented 3 years ago

Simple example traceback with ifort on my machine:

/tmp/a$ cat src/a.f90 
module a
  implicit none
  private

  public :: say_hello
contains
  subroutine say_hello
    print *, "Hello, a!",1/0
  end subroutine say_hello
end module a
/tmp/a$ ffpm run --compiler ifort
 + build/ifort_debug/app/a 
forrtl: severe (71): integer divide by zero
Image              PC                Routine            Line        Source             
a                  0000000000403A3B  Unknown               Unknown  Unknown
libpthread-2.27.s  00007FF0FA1CE8A0  Unknown               Unknown  Unknown
a                  0000000000402B58  a_mp_say_hello_             8  a.f90
a                  0000000000402AD6  MAIN__                      5  main.f90
a                  0000000000402AA2  Unknown               Unknown  Unknown
libc-2.27.so       00007FF0F9BE8B97  __libc_start_main     Unknown  Unknown
a                  00000000004029AA  Unknown               Unknown  Unknown
 Command failed
ERROR STOP 

Error termination. Backtrace:
#0  0x7f33ebad3aed in ???
#1  0x7f33ebad4605 in ???
#2  0x7f33ebad5c93 in ???
#3  0x55a39474ecd4 in __fpm_environment_MOD_run
    at src/fpm_environment.f90:127
#4  0x55a394720049 in __fpm_MOD_cmd_run
    at src/fpm.f90:346
#5  0x55a39471c63d in MAIN__
    at app/main.f90:37
#6  0x55a39471c703 in main
    at app/main.f90:9
/tmp/a$ ifort --version
ifort (IFORT) 19.1.0.166 20191121
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

lk12325@ljk-laptop:/tmp/a$ uname -a
Linux laptop 5.4.0-58-generic #64~18.04.1-Ubuntu SMP Wed Dec 9 17:11:11 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

As expected in the Intel backtrace I can see the two relevant frames for my code: a_mp_say_hello_ (a.f90:8) and MAIN__ (main.f90:5).

certik commented 3 years ago

I firmly believe fpm needs to support static linking of Fortran binaries. That is a frequent and common use case.

In addition, we should also support dynamic linking for things like conda-forge or Debian.

That means for example the cmake backend that I plan to write should support both.

So the only question is how to specify this from the fpm point of view: it seems a command line switch like fpm build --static or something like that should work? We can argue about which way should be the default, I am fine either way.