Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28602 Discussions

Common blocks in dynamic shared libraries still not linked correctly

mmalson
Beginner
1,845 Views
I am opening a new thread rather than glomming on to older threads. Is there a fix or a workaround for this problem yet? I would really make my life easier if I could use FORTRAN on a Mac, but at present I cannot because of this bug.
Here is a shell script that writes two very simple source files (stolen from another thread), compiles them, and links them together, or via static library, or via dynamic library. When linked together or via library, the program works (the output is 3). When linked dynamically, the program fails (the output is 0). This works just fine under Linux.
------------------
cat >lib.f90 <
SUBROUTINE LIB
COMMON /MYCOMMON/ I
I = 3
RETURN
END
EOT
cat >prog.f90 <
PROGRAM MAIN
COMMON /MYCOMMON/ I
CALL LIB
PRINT *, I
END
EOT
ifort -dynamiclib -o lib.dylib lib.f90 -Wl,-single_module
ifort -c -o lib.o lib.f90
ar rc lib.a lib.o
ifort -c -o prog.o prog.f90
ifort -o together prog.f90 lib.f90
ifort -o static prog.f90 lib.a
ifort -o dylib prog.o lib.dylib
./static
./together
./dylib
------------------
The output is:
3
3
0
where it should be 3 in all cases.
I have tried tons of different compiler and linker options suggested in other threads, all to no avail.
0 Kudos
1 Solution
Kevin_D_Intel
Employee
1,845 Views

Thank you for the details on your build environment.

I found a simple change to the ifort command line to build the dynamic lib. Use -Wl,-flat_namespace instead of -Wl,-single_module

$ ifort -dynamiclib -o lib.dylib lib.f90 -Wl,-flat_namespace
$ ifort -c -o lib.o lib.f90
$ ar rc lib.a lib.o
$ ifort -c -o prog.o prog.f90
$ ifort -o together prog.f90 lib.f90
$ ifort -o static prog.f90 lib.a
$ ifort -o dylib prog.o lib.dylib
$ ./together
3
$ ./static
3
$ ./dylib
3

I verified on:
- Lion 10.7+Xcode 4.1+ ifort 12.0.5.209 Build 20110719
- Snow Leopard 10.6 + Xcode 3.2 + ifort 12.0.3.167 Build 20110309
- Leopard 10.5 + Xcode 3.1.4 + ifort Version 11.1.088 Build 20100401

View solution in original post

0 Kudos
5 Replies
Kevin_D_Intel
Employee
1,845 Views
It would help knowing your versions of: Mac OS, Xcode, Linker (ld -v), and ifort (ifort -V)

This seems related to the earlier issues with COMMON discussedhere. I will try your test case and update soon.
0 Kudos
mmalson
Beginner
1,845 Views
Yes, I stole some of this code from that thread, but his problem seemed more related to locating symbols in static libraries. My problem is that symbols are not resolved correctly in dynamic libraries.


I'm using Lion, XCode 4.2.

Here is the output from ld -v:
@(#)PROGRAM:ld PROJECT:ld64-123.4.1
llvm version 3.0svn, from Apple Clang 3.0 (build 209.9.2)
@(#)PROGRAM:ld PROJECT:ld64-123.4.1llvm version 3.0svn, from Apple Clang 3.0 (build 209.9.2)


Here is the output from gcc -v (FWIW):
Using built-in specs.
Target: i686-apple-darwin10
Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2335.15~13/src/configure --disable-checking --enable-werror --prefix=/Developer/usr/llvm-gcc-4.2 --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-prefix=llvm- --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2335.15~13/dst-llvmCore/Developer/usr/local --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/usr/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)
0 Kudos
Kevin_D_Intel
Employee
1,846 Views

Thank you for the details on your build environment.

I found a simple change to the ifort command line to build the dynamic lib. Use -Wl,-flat_namespace instead of -Wl,-single_module

$ ifort -dynamiclib -o lib.dylib lib.f90 -Wl,-flat_namespace
$ ifort -c -o lib.o lib.f90
$ ar rc lib.a lib.o
$ ifort -c -o prog.o prog.f90
$ ifort -o together prog.f90 lib.f90
$ ifort -o static prog.f90 lib.a
$ ifort -o dylib prog.o lib.dylib
$ ./together
3
$ ./static
3
$ ./dylib
3

I verified on:
- Lion 10.7+Xcode 4.1+ ifort 12.0.5.209 Build 20110719
- Snow Leopard 10.6 + Xcode 3.2 + ifort 12.0.3.167 Build 20110309
- Leopard 10.5 + Xcode 3.1.4 + ifort Version 11.1.088 Build 20100401

0 Kudos
Kevin_D_Intel
Employee
1,845 Views

There's a better solution than that. Just use -Wl,-commons,use_dylibs for the final link and no need to use -Wl,flat_namespace.

$ ifort -c -o lib.o lib.f90
$ ar rc lib.a lib.o
$ ifort -c -o prog.o prog.f90
$ ifort -o together prog.f90 lib.f90
$ ifort -o static prog.f90 lib.a
$ ifort -o dylib prog.o lib.dylib -Wl,-commons,use_dylibs
$ ./together
3
$ ./static
3
$ ./dylib
3

0 Kudos
mmalson
Beginner
1,845 Views

The flat_namespace argument (which I had never tried before) seems to work better. When using the -Wl,-commons,use_dylibs, it seems to matter whether or not there is a DATA statement to initialize the common block.

Here is a revised script that shows what I mean:
#!/bin/sh
rm -f libwith.f90 libwithout.f90 progwith.f90 progwithout.f90 *.o *.dylib app
cat >libwith.f90 <
SUBROUTINE LIB
COMMON/MYCOMMON/I
DATA I/20/
I=3
RETURN
END
EOT
cat >libwithout.f90 <
SUBROUTINE LIB
COMMON/MYCOMMON/I
I=3
RETURN
END
EOT
cat >progwith.f90 <
PROGRAM MAIN
COMMON/MYCOMMON/I
INTEGER I
DATA I/10/
CALL LIB
PRINT *,I
STOP
END
EOT
cat >progwithout.f90 <
PROGRAM MAIN
COMMON/MYCOMMON/I
INTEGER I
CALL LIB
PRINT *,I
STOP
END
EOT
ifort -dynamiclib -o libwith.dylib lib.f90 -Wl,-flat_namespace
ifort -dynamiclib -o libwithout.dylib lib.f90 -Wl,-flat_namespace
ifort -c -o progwith.o progwith.f90
ifort -c -o progwithout.o progwithout.f90
ifort -o app progwith.o libwithout.dylib ; ./app
ifort -o app progwithout.o libwith.dylib ; ./app
ifort -o app progwithout.o libwithout.dylib ; ./app
ifort -dynamiclib -o libwith.dylib lib.f90
ifort -dynamiclib -o libwithout.dylib lib.f90
ifort -c -o progwith.o progwith.f90
ifort -c -o progwithout.o progwithout.f90
ifort -o app progwith.o libwithout.dylib -Wl,-commons,use_dylibs; ./app
ifort -o app progwithout.o libwith.dylib -Wl,-commons,use_dylibs; ./app
ifort -o app progwithout.o libwithout.dylib -Wl,-commons,use_dylibs; ./app
----------
Output:
3
3
3
10
3
3
----------
I would expect the results to be 3 in each case, but in the case where the common is initialized by data in the main program, the flat_namespace produces the desired result whereas the commons use_dylibs does not.
I'm going to try rebuilding my project adding the flat_namespaces on the dylib generation everywhere and see how it goes.

0 Kudos
Reply