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

error LNK2019: unresolved external symbol using module

Frederic_A_
Beginner
6,172 Views

Hi!

I face a problem which I did not succeed to solve despite several trials based on clues found here and elsewhere on the internet…

I gathered several functions and procedures in a module ‘mymod.f90'. Some of these procedures are calling other functions or procedures within the same module. I also have a program ‘myprog’ using the module. These files are in attachment.

I compiled the module without error with ifort –c  mymod.f90 and get files ‘mymod.obj’ and ‘mymod.mod’ created

Then, when I try to compile with ifort mymod.obj myprog.f I have the following errors:

c:\Users>ifort mymod.obj myprog.f

Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.3.202 Build 20140422

Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

 

Microsoft (R) Incremental Linker Version 10.00.40219.01

Copyright (C) Microsoft Corporation.  All rights reserved.

 

-out:mymod.exe

-subsystem:console

mymod.obj

myprog.obj

mymod.obj : error LNK2019: unresolved external symbol I1MACH referenced in function MYMOD_mp_INTEXJX

mymod.obj : error LNK2019: unresolved external symbol ZABS referenced in function MYMOD_mp_INTEXJX

myprog.obj : error LNK2019: unresolved external symbol DQAG referenced in function MAIN__

mymod.exe : fatal error LNK1120: 3 unresolved externals

 

I could solve such errors by removing declarations of variables corresponding to call of functions defined within the module (e.g., variable D1MACH in lines 51,361, 1664,… and variable DGAMLN in lines 3261, 4459 and 4162 of module mymod), as recommended somewhere on this forum. Yet, this did not work for I1MACH and ZABS, for which I get type definition errors. For instance, when removing declaration of variable I1MACH at line 1067 of mymod, I get the following:

 

c:\Users>ifort –c mymod.f90

Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.3.202 Build 20140422

Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

 

mymod.f90(1094): error #6404: This name does not have a type, and must have an explicit type.   [I1MACH]

      K1 = I1MACH(15)

-----------^

mymod.f90(1116): error #6362: The data types of the argument(s) are invalid.   [FLOAT]

      BB=DBLE(FLOAT(I1MACH(9)))*0.5D0

--------------------^

compilation aborted for mymod.f90 (code 1)

 

Besides, I do not know how to solve the error for procedure DQAG called in myprog.

 

For further information, the code works when compiling it with functions and procedures in separate files. Yet, I decided to use a module as I got problem when attempting to parallelize the code with OpenMP (i.e. the ‘do loop’ at line 51 in myprog), apparently because of threads interacting on some variables (though these were declared as private and subroutines as recursive, according to recommendations found on the web in this regard). I read that working with module might solve it.

 

Hope someone can help. Thank you very much in advance!

Fred

 

 

0 Kudos
1 Solution
mecej4
Honored Contributor III
6,172 Views

You have three problems to fix in your code.

  • Do not apply PRIVATE to subprogram names inside a module that you plan to call from outside the module.
  • Do not declare EXTERNAL those subprogram names that are accessible through a USE statement or are contained in the same module.
  • Provide missing function subprogram I1MACH(); perhaps the one at www.netlib.org/slatec/src/i1mach.f will do.

There are several source lines that are longer than 132 characters, and these may give you trouble with other compilers. The source code in the module is in need of clean-up; in particular, many specific names of Fortran intrinsics are given EXTERNAL declarations. You will have to fix these declarations, and possibly replace specific names with generic names.

I removed the lines from "MODULE..." to "CONTAINS" and the last line, "END MODULE", and the program could be built when I used the I1MACH from Netlib. It needs a data file to be run.

From what I have seen, the objective of your program is to calculate an integral using numerical quadrature routines from QUADPACK. A clean solution would be possible if you used the F90 interface available provided in IMSL to QUADPACK.

View solution in original post

0 Kudos
6 Replies
mecej4
Honored Contributor III
6,173 Views

You have three problems to fix in your code.

  • Do not apply PRIVATE to subprogram names inside a module that you plan to call from outside the module.
  • Do not declare EXTERNAL those subprogram names that are accessible through a USE statement or are contained in the same module.
  • Provide missing function subprogram I1MACH(); perhaps the one at www.netlib.org/slatec/src/i1mach.f will do.

There are several source lines that are longer than 132 characters, and these may give you trouble with other compilers. The source code in the module is in need of clean-up; in particular, many specific names of Fortran intrinsics are given EXTERNAL declarations. You will have to fix these declarations, and possibly replace specific names with generic names.

I removed the lines from "MODULE..." to "CONTAINS" and the last line, "END MODULE", and the program could be built when I used the I1MACH from Netlib. It needs a data file to be run.

From what I have seen, the objective of your program is to calculate an integral using numerical quadrature routines from QUADPACK. A clean solution would be possible if you used the F90 interface available provided in IMSL to QUADPACK.

0 Kudos
Frederic_A_
Beginner
6,172 Views

Thank you very much for your prompt reply!

I have applied your recommendations could successfully built the program and make it run. So I am now ready for the next step: parallelization...

I indeed inadvertently did not include i1mach.

Regarding the PRIVATE statement, I used it to ensure that all variables and procedures/functions declared in the module have a separate copy for each thread of this (future) parallel section. But this statement indeed generated the error for DQAG. To work around this problem, I used PUBLIC :: DQAG. Is there any other way to ensure independent copies amongst threads of all involved variables, i.e., to avoid threads interaction on variables as I apparently had before?

0 Kudos
Steven_L_Intel1
Employee
6,172 Views

PUBLIC and PRIVATE are not storage-related. They affect the visibility of symbols inherited from a module. You're looking for the PRIVATE clause on an OpenMP directive.

0 Kudos
Frederic_A_
Beginner
6,172 Views

OK, great! Thanks for the clarification!

0 Kudos
mecej4
Honored Contributor III
6,172 Views

You have resolved the issue of the visibility of DQAG correctly.

Regarding the thread safety question: do you have any variables that are passed through COMMON or module variables accessed by USE? If so, you would have to ensure that only one thread modifies those variables and that the modifications are completed before you pass control to the other threads in which those variables are referenced.

There are tools such as the Intel Inspector XE for debugging threading problems.

0 Kudos
Frederic_A_
Beginner
6,172 Views

     

0 Kudos
Reply