Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating DLL with gfortran on Windows

I would like to create DLLs on windows for a Fortran project (in fact Fortran+C). I get a trouble I do not meet on Linux when a dll depends on another one.

Here is a short example :

file dll1.f90

module dll1
   implicit none
   contains
   subroutine test1
      write(*,*) "test1 ok"
   end subroutine
end module

file dll2.f90

module dll2
   use dll1,only : test1
   implicit none
   contains
   subroutine test2
      call test1
   end subroutine
end module

File main.f90

program main
   use dll2, only : test2
   implicit none
   call test2
end program

Linux commands (file run.bash)

gfortran -shared -fPIC -o libdll1.so dll1.f90
gfortran -shared -fPIC -o libdll2.so dll2.f90
gfortran -o main.exe main.f90 -I. -L. -ldll2 -ldll1
export LD_LIBRARY_PATH="./"
./main.exe

Windows commands (file run.bat)

gfortran -shared -fPIC -o dll1.dll dll1.f90
gfortran -shared -fPIC -o dll2.dll dll2.f90
gfortran -o main.exe main.f90 -I. -L. -ldll2 -ldll1
.\main.exe

On Windows, I get the first error message at the second instruction :

undefined reference to __dll1_MOD_test1 (ld message)

I can solve this trouble in modifying the second instruction as follows :

gfortran -shared -fPIC -o dll2.dll dll2.f90 -L . -ldll1

But this modification is not convenient for several reasons :

  • if a dll depends on many dlls, then its size becomes very large (it seems to contain all the sub dlls)

  • the size of the executable program is large as well

  • I get a much more reasonable result using classical libraries instead of dlls

Linux file sizes :

[coul@localhost dll]$ ls -al
total 68
drwxrwxr-x  2 coul coul 4096 29 déc.  12:09 .
drwxrwxr-x. 7 coul coul 4096 29 déc.  11:46 ..
-rw-rw-r--  1 coul coul  118 29 déc.  11:25 dll1.f90
-rw-rw-r--  1 coul coul  204 29 déc.  12:09 dll1.mod
-rw-rw-r--  1 coul coul  132 29 déc.  11:29 dll2.f90
-rw-rw-r--  1 coul coul  237 29 déc.  12:09 dll2.mod
-rwxrwxr-x  1 coul coul 8184 29 déc.  12:09 libdll1.so
-rwxrwxr-x  1 coul coul 7920 29 déc.  12:09 libdll2.so
-rwxrwxr-x  1 coul coul 8712 29 déc.  12:09 main.exe
-rw-rw-r--  1 coul coul   82 29 déc.  11:27 main.f90
-rwxrwxr-x  1 coul coul  183 29 déc.  11:38 run.bash
-rw-rw-r--  1 coul coul  151 29 déc.  11:55 run.bat

Windows file sizes

29/12/2017  11:53    <DIR>          .
29/12/2017  11:53    <DIR>          ..
29/12/2017  11:53         2 264 764 dll1.dll
29/12/2017  11:25               118 dll1.f90
29/12/2017  11:50               204 dll1.mod
29/12/2017  11:53            51 814 dll2.dll
29/12/2017  11:29               132 dll2.f90
29/12/2017  11:50               237 dll2.mod
29/12/2017  11:53         2 264 671 main.exe
29/12/2017  11:27                82 main.f90
29/12/2017  11:38               183 run.bash
29/12/2017  11:53               162 run.bat

So my question is : how to solve these drawbacks ?

like image 620
Francois Jacq Avatar asked Dec 29 '17 11:12

Francois Jacq


1 Answers

There is a difference in philosophy between the two operating systems in terms of how symbols are resolved for load time dynamic linking. In linux, the resolution of the name of the library that provides a particular symbol can be deferred till load time, while in Windows the name of the library that will provide a symbol must be resolved at link time.

Consequently, under linux you can link the libdll2.so shared library without providing any information to the linker about the location of the object code for the test1 procedure, while linking dll2 on Windows requires something akin to the -ldll1 command option. When linking the final executable on Windows, you then do not need to repeat the -ldll1 specification.

I cannot reproduce your observations with the modified link process on Windows with the Msys2 mingw-64 x86_64 toolchain.

$ gfortran -shared -fPIC -o dll1.dll dll1.f90
$ gfortran -shared -fPIC -o dll2.dll dll2.f90 -L. -ldll1
$ gfortran -o main main.f90 -L. -ldll2
$ ./main.exe
 test1 ok

$ du -b *
330013  dll1.dll
125     dll1.f90
204     dll1.mod
329573  dll2.dll
140     dll2.f90
237     dll2.mod
398054  main.exe
87      main.f90

Inspection of the dll and exe executable modules show the expected symbol imports and exports, and runtime debugging shows that execution is being transferred between executable modules.

Note that stripping debugging symbols will spectacularly reduce EXE and DLL file size.

like image 196
IanH Avatar answered Sep 21 '22 20:09

IanH