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

building and linking against a Fortran dynamic library on Linux

DataScientist
Valued Contributor I
2,053 Views

I have a subroutine inside a Fortran module which I compile and generate a dynamic library from it via -fpic -shared flags. When I "objdump" the shared library to see the contents of it, among the symbols, I see my subroutine of interest,

quadpackdpr_MP_dqawoe_

Then I have a test function that uses the module containing this subroutine and I compile it. However, at the time of linking, I get the following error,

main.f90:(.text+0x49): undefined reference to `quadpackdpr_mp_dqawoe_'

I have been spending hours on this to find the cause. In the end, I noticed that the two names quadpackdpr_mp_dqawoe_ and quadpackdpr_MP_dqawoe_ are not exactly the same. Is this the source of the error message?

If not maybe I am not linking against this dynamic library properly. Does Intel have any page that includes instructions on how to perform the linking? All my search so far has been dead-end. So your help is greatly appreciated.

0 Kudos
1 Solution
mecej4
Honored Contributor III
2,053 Views

The section "Fortran Module Naming Conventions" of the Intel Fortran documentation states:

_mp_ is the separator between the module and entity names and is always lowercase (except when the assume std_mod_proc_name compiler option or standard-semantics compiler option is used).

Please check the commands (generated by Cmake and Make) used to compile and link. If either or both of the options mentioned above were included in some of the commands and not in the other commands, one could encounter the problem that you reported.

The simplest fix would be to add -standard-semantics to the command used for building the a.out (your main.exe).

BIND(C) overrides default name generation and can be used to suppress inconsistencies in name decoration. It should not be needed when both the shared library and the a.out are compiled from all-Fortran sources using a single Fortran compiler.

View solution in original post

0 Kudos
7 Replies
mecej4
Honored Contributor III
2,053 Views

Please show all the command lines used. Document the compiler and OS versions as well.

0 Kudos
DataScientist
Valued Contributor I
2,053 Views

The SO library is built by cmake, but these are the compiler linker options used,

 -fpp -module ../mod -fPIC -nologo -standard-semantics -threads -O3 -ip -ipo -unroll -unroll-aggressive -finline-functions -diag-disable=10346 -qopt-report=2 -heap-arrays=10 -fpic -shared -c

and to build the executable, I do,

ifort  main.f90 libmylib.so -o main.exe

The important thing is that the library build is done by cmake and executable build is done on the Bash command line. I just compiled the same routine by giving it a global name via bind(c) attribute, and the executable was successfully built and run.

So the problem does seem to be due to name-mangling, and the case-sensitivity of MP vs mp in the global names generated by ifort, once via CMAKE and later on the Bash command line. But then this raises another question as to why the same intel ifort behaves differently under CMAKE and Bash command line for name-mangling. I even tried to check the compiler options passed by CMAKE to ifort via compiler_options() and those are the given flags above. None appear to cause such behavior in my eyes. Thanks for your help in advance!

Obviously, the bind() attribute is an option, but I need to keep that solution as the last resort, since the problem is actually significantly more complex than what I described here (In reality, I need to USE a class/type definition from inside the shared library module, which has ~tens of type-bound procedures and object components)

0 Kudos
mecej4
Honored Contributor III
2,054 Views

The section "Fortran Module Naming Conventions" of the Intel Fortran documentation states:

_mp_ is the separator between the module and entity names and is always lowercase (except when the assume std_mod_proc_name compiler option or standard-semantics compiler option is used).

Please check the commands (generated by Cmake and Make) used to compile and link. If either or both of the options mentioned above were included in some of the commands and not in the other commands, one could encounter the problem that you reported.

The simplest fix would be to add -standard-semantics to the command used for building the a.out (your main.exe).

BIND(C) overrides default name generation and can be used to suppress inconsistencies in name decoration. It should not be needed when both the shared library and the a.out are compiled from all-Fortran sources using a single Fortran compiler.

0 Kudos
DataScientist
Valued Contributor I
2,053 Views

mecej4 wrote:

The simplest fix would be to add -standard-semantics to the linking command for building the a.out (your main.exe).

I cannot thank you enough. This error has kept me awake all night. (I never fully understood what this flag does in ifort).

0 Kudos
Steve_Lionel
Honored Contributor III
2,053 Views

-standard-semantics changes certain defaults that conflict with earlier compiler versions' defaults but are needed to fully comply with the Fortran standard's semantics. You can see a full list at https://software.intel.com/en-us/articles/intel-fortran-compiler-support-for-fortran-language-standards/

What's happening here is that the compiler's default module procedure name decoration on Linux and MacOS potentially conflicted with a user routine in an otherwise standard-conforming program. Intel couldn't just make a blanket change as that would break existing applications that linked to libraries, etc., so an -assume option was added and included under -standard-semantics.

0 Kudos
DataScientist
Valued Contributor I
2,053 Views

Thanks, Steve, that helped a lot. So does std_mod_proc_name always lead to quadpackdpr_MP_dqawoe_ type of names where MP is uppercase?

0 Kudos
Steve_Lionel
Honored Contributor III
2,053 Views

On Linux, yes. On Windows, it's the opposite - module and procedure names are uppercase and the _mp_ is lowercase, so this option doesn't do anything there since a user can't create a module procedure with a conflicting global name (without straying outside the standard.) Yes, you could do something with BIND(C,NAME=) and end up with a conflict, but the standard has a rule forbidding you doing that.

0 Kudos
Reply