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 ?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With