Problems with build of static .EXE

I have a dilemma I need some of the team’s help with. I am trying to build a static, distributable EXE that has no external dependencies.

If I compile all my code using FPM then link it manually via:
gfortran -static app_opldrvb.f.o src_a.f.o src_b.f,o src_c.f.o ... -o opl.exe
My executable works as expected.

However, if I use FPM out of the box, it first builds a library libopl.a .
ar -t reports that src_a.f.o src_b.f,o src_c.f.o are included) in the library.

FPM then issues the command
gfortran -static build\gfortran_7AF256F622D5F2C8\opl\app_opldrvb.f.o build\gfortran_4052131EE03EE371\opl\libopl.a -o build\gfortran_A6B903709DDEB456\app\opl.exe

However, the exe produced is about 1 MB smaller in size then when I manually link. The EXE blows up due to a segmentation fault.

Am I missing something? My manifest is given below:
name = “opl”
version = “30.0.0”
license = “Apache 2.0”
author = “”
maintainer = “”
copyright = “”
[build]
auto-executables = true
auto-tests = false
auto-examples = false
module-naming = false
[install]
library = false
[fortran]
implicit-typing = true
implicit-external = true
source-form = “default”
[library]
include-dir = [“include/high”, “include/low”]
[[executable]]
name = “opl”
source-dir = “app”
main = “opldrvb.f”

1 Like

By default fpm uses the debug profile. This turns on a series of flags, including backtraces.

character(*), parameter :: &
    flag_gnu_coarray = " -fcoarray=single", &
    flag_gnu_backtrace = " -fbacktrace", &
    flag_gnu_opt = " -O3 -funroll-loops", &
    flag_gnu_debug = " -g", &
    flag_gnu_pic = " -fPIC", &
    flag_gnu_warn = " -Wall -Wextra", &
    flag_gnu_check = " -fcheck=bounds -fcheck=array-temps", &
    flag_gnu_limit = " -fmax-errors=1", &
    flag_gnu_external = " -Wimplicit-interface", &
    flag_gnu_openmp = " -fopenmp", &
    flag_gnu_no_implicit_typing = " -fimplicit-none", &
    flag_gnu_no_implicit_external = " -Werror=implicit-interface", &
    flag_gnu_free_form = " -ffree-form", &
    flag_gnu_fixed_form = " -ffixed-form"

Go ahead and create an issue at the fpm repository for this: the goal should be to have an option in fpm to create a static binary on all platforms. That is indeed very useful, as then you can just copy it to other machines on the same platform.

I thought by default fpm always builds a static library.
See [fpm] can fpm be used to build a dynamic link library? - Help / fpm - Fortran Discourse (fortran-lang.discourse.group)

@gwenning: a static library is just a collection of binary objects. No linking is performed among any of them.

In order to build a static executable with gfortran, you will need both gfortran’s runtime library and the quadruple-precision to be library statically built (no external dependencies), then linked into your executable.

If this is not the case (gfortran will emit no warnings), it means that you don’t have such libraries statically built on your system, and your executable will not run if you take it to another machine. (You may just be extremely lucky to find compatible libraries there too, but in general you won’t, neither I believe you’d want to rely on that).

The only way you can have them is to build GCC from source code yourself first, configured with flags -static-libgfortran and -static-libquadmath - it is usually never the case in pre-packaged GCC installations.

So, while I like the idea of having fpm enable some static build flags, it’s outside of fpm’s control whether that can be done at all.

PS: there are limitations associated with statically linking libquadmath due to its LGPL license

1 Like

@FedericoPerini good point, I didn’t realize this limitation of GFortran. I would say, fpm should still support it for compilers that support that, including GFortran (if compiled with this feature).

1 Like

I thought by default fpm always builds a static library.
See [fpm] can fpm be used to build a dynamic link library? - Help / fpm - Fortran Discourse (fortran-lang.discourse.group)

Here is my issue.

Fpm uses the archiver named ar and creates a file with .a extension. (I am on Windows but assume fpm’s use of .a versus .lib is okay )

Fpm appears to do this in order to bundle the numerous object files so that a shorter command can be issued to the linker (i.e. gfortran).

When the archive of object files is linked to the main program a smaller sized executable is created versus listing all the objects individually.

The executable linked with the archive also throws a seg fault.

So, there is an issue somewhere in the ar to gfortran interface. I plan on reinstalling using lkedward’s quuck atart because my gfortran version is from 2016.

This is much more discouraging than my experience indicates. Perhaps packaging has gotten better? I have been distributing statically linked binaries for Windows, Linux ,FreeBSD and OSX for several years with no pushbak. I only need special treatment for libquadmath on OSX. Of course, I am not using quad precision (or FPM) with the program.

I use:
gfortran -static-libgfortran -static-libgcc -o prog.exe prog.f
for the compile as few users will have those libraries and even fewer will know how to install them.On osx it is necessary to run
oTool -L prog.exe
to finish linking the file. I know that no special installation of gfortran was done on FreeBSD because I did that installation myself from the available package. As to the others - I didn’t ask for libquadmath and I doubt the sysadmin anticipated a need for it.

Got to the bottom of this issue.

Block data F 77 routines, while compiled and archived into a library by fpm, cannot be linked by gfortran into an executable. I have tried the workaround detailed here https://gcc.gnu.org/onlinedocs/gcc-3.4.1/g77/Block-Data-and-Libraries.html
, still no luck.

Impact of this is I have to migrate to another build system because fpm insists on building an archive/library in preparation for gfortran’s link phase.

I don’t know if this is a bug in gfortran or not.

I guess I will need to revisit fpm if / when I try to modernize this legacy code.

The linking problem is not related to the version of Fortran or the package manager used, if any. The Linux linker will not link in a symbol from a library if there is no reference to it in at least one of the other objects that are being linked with the library. There is a simple solution to the problem.

I believe the link you provided is similar to my attempted workaround. The latest gfortran compiler seems to ignore the EXTERNAL statement as no reference us created for the linker to resolve.

This is an old issue that dates back to f77 times with libraries. One workaround is to put all of the block data stuff in the same file as the main program. The *.o file that is created contains everything together, so when the main program is linked with the other files and libraries, the block data stuff gets swept along.