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

lnk2019 error from Main

drew14385
Beginner
1,232 Views
I am fairly new to Fortran and am in the middle of writing a code. I have a main file and I use the 'Use' statement to reference about 12 different modules that contain subroutines. Each module and subroutine compile fine seperately. When I use IVF to compile the main file it goes through all of the modules and then says "Linking...". I then get errors for nearly every variable I declared. Examples are:

main.obj : error LNK2019: unresolved external symbol _QRR referenced in function _MAIN__

main.obj : error LNK2019: unresolved external symbol _QET referenced in function _MAIN__

main.obj : error LNK2019: unresolved external symbol _QETT referenced in function _MAIN__

main.obj : error LNK2019: unresolved external symbol _QINFF referenced in function _MAIN__

......................

I have tried research this problem for quite some time and can not find the solution, although I have a feeling it may be a simple fix. I have tried adding each file to the include directory, but still get the errors. Does any have an idea what I am doing wrong? Thanks in advance!

0 Kudos
5 Replies
mecej4
Honored Contributor III
1,232 Views
When you compile source files (.f90) containing modules, corresponding module (.mod) and object (.obj) files are produced. During compilation of other sources that USE the modules requires that the .mod files be available. In the final link step (in your case, following the compilation of the main program) all the .obj files containing the codes for the modules need to be included.

If, for instance, you have .obj files called QRR.obj, QET.obj, QETT.obj and QINFF.obj, the final command would be

ifort main.f90 QRR.obj QET.obj QETT.obj QINFF.obj
0 Kudos
IanH
Honored Contributor III
1,232 Views
If the module obj's were missing in the link stage, the symbols that were unresolved would look a bit like _ModuleName_mp_VariableName. What the OP is seeing suggests that the compiler doesn't think that his variables are actually module variables. Maybe substitute "procedure" for "variable": convincing the compiler that a non-module-variable is an external of some sort is beyond me.

To the OP - are the unresolved symbols similar to your subroutine names or variable names? You say "each module and subroutine" - the subroutines would normally be part of the module, what exactly do you mean? If you are using modules it is unlikely that you want the files to be in the "include directory" (assuming you are talking about the folder in the VS project tree?). If the compiler can't find the modules while compiling your main program it will complain directly about that - in that case you might need to specify the directory that contains the module files to the compiler, but that means that you've got more than one project or similar on the go.

I suggest that you post the top bit of your PROGRAM (where the use statements are down to an example subroutine call or variable reference) and a part of one of your modules. Something ain't right...

0 Kudos
drew14385
Beginner
1,232 Views
To address your points:
- The unresolved symbols are variable names.
- Each module compiles correctly and the subroutines are included in the modules.

"If the compiler can't find the modules while compiling your main program it will complain directly about that - in that case you might need to specify the directory that contains the module files to the compiler, but that means that you've got more than one project or similar on the go."

This sentence is exactly what happens when I compile the main program...maybe I have a problem with my hierarchy.

Here is the top of the main program:

Program WETSAND

Use XRAINPETINF

Use XPETX

Use XINFILTRATION

Use XINPUTSX

Use XINTERACTION

Use XUPLANDIMP

Use XQUALITYDATA

Use XAXX

Use XNITROGEN

Use XPHOSPHORUS

Use XWETLANDIMP

Use XSTREAMIMP

Use XAXXX

Use XHEADARDIS

Use XSTORAGE

Use XLINTERP

Use XLATERALX

IMPLICIT NONE

!------------------------Inputs------------------------------------!

Common/name/dt,nt

Real::Li,md,ri,T,DH,qet,qett,qrr,qinff,P,F,delt,gwl,y_ubc, Q_ubc, ql, h, qr, qinf, qu, yu, uu, q, y, u, qall, yimpw, qimpw, uimpw, CLTP, CLON, CLAN, CLNN, CLTN, CTP_ubc, CON_ubc, CAN_ubc, CNN_ubc, CTN_ubc,yimpu, Ax, qdrchp, CONnn, CANnn, CNNnn, CTNnn, uimpu, CTPnn, qw, yw, uw, qdrch, kz, IMC, kx, S, tn, CgwTP, CgwON, CgwAN, CgwNN, CgwTN, JUAN, JUNN, JRON, ddx, KTP, KON, KAN, KNN, KTN, psi, CTP_ic, CON_ic, CAN_ic, CNN_ic, CTN_ic, LW,So,KK,W,m, delta, y_ic, u_ic, y_lbc, Q_ic, mn, z, glwet,EP, Qs, us, ys, qstream, ustream, ystream, head, area, Qdam, Qlake, ulake, ylake, Qinflow, ul, yl, qdrchpl

Integer::a, tc, nt, nnt, nn, dx,i, j, dt, Lt, wq

Call RAINPETINF(a,dt,Lt,wq,ri(3320),T(12),DH(12),kz,S,EP,IMC,kx,qrr(3320))

tc=1/dt !time constant

nt=tc*Lt+1 !number of time steps

Call PETX(T(12),DH(12),qet(12),qett(12)) !evapotranspiration

Call INFILTRATION(kz,S,EP,IMC,qrr(3320),qinff(1,nt),P(1,nt),F(1,nt)) !infiltration [qinff,P,F]




Here is the XRAINPETINF module, which contains the called subroutine 'rainpetinf':

MODULE XRAINPETINF

IMPLICIT NONE

CONTAINS

subroutine RAINPETINF(a,dt,Lt,wq,ri,xT,xDH,kz,S,EP,IMC,kx,qrr)

!a

!GENERAL INFORMATION:

Real::qrr(3320),ri(36),xT(12), xDH(12),KZ,KX,S,EP,IMC

Integer::a, dt,i, j, valri, Lt, wq

dt=1 !time step (hr)

Lt=3319 !365*24 - total time length of the simulation (hr)

wq=1 !if wq=1 then water quality calculated, if wq=0 then water qulaity is not calculated.

!RAINFALL DATA

ri=(/ 0.0, 0.0005, 0.0005, 0.0002, 0.0002, 0.0003, 0.0003, 0.0002, 0.0002, 0.0005, 0.0005, 0.0001, 0.0001, 0.0002, 0.0002, 0.0, 0.0, 0.0001, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 , 0.0, 0.0 ,0.0, 0.0 ,0.0, 0.0, 0.0 ,0.0 ,0.0 ,0.0 /); !september 26

valri = size(ri)

Do i = 1,valri

qrr(i)=ri(i)

Do j= (valri+1),3320

qrr(j) = 0

End do

END DO

!EVAPOTRANSPIRATION DATA

xT=(/ 4.4, 6.1, 10, 16.7, 18.3, 24.4, 26.1, 25, 21.7, 15.6 ,7.8, 3.9 /); !historical average monthly temperature (in celcius) (for Durham-2002)

xDH=(/ 0.87, 0.85, 1.03, 1.09, 1.21, 1.21, 1.23, 1.16, 1.03, 0.97, 0.86, 0.85 /); !mean possible hours in units of 30 days of 12 hours each (data for N35-lat)

!INFILTRATION DATA

!Choose silt loam type of soil:

kz=0.5*6.5*10**(-3) !6.5*10^(-3) - Hydraulic conductivity [m/hr] Ref:Rawls, Brakensiek, Miller (1983) !vertical hydraulic conductivity

kx=0.5*6.5*10**(-3)

S=166.8*10**(-3) !suction head

EP=0.486 !effective porosity

IMC=0.45 !initial moisture content

END SUBROUTINE RAINPETINF

END MODULE XRAINPETINF

Thank you for your help!

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,232 Views
Here lies the immediate culprit:

Real:: ...qrr...
Call RAINPETINF(a,dt,Lt,wq,ri(3320),T(12),DH(12),kz,S,EP,IMC,kx,qrr(3320))

You declared that QRR is REAL, but not that it is an array. Without the dimension, compiler thinks that QRR(3320) is a function call, and generates a call to it (_QRR) to be later resolved by linker. However, linker cannot find it.

However, it is not clear to me what was the intent. Did you mean:

[bash]REAL:: QRR(3320) !declares the dimension in the main program
CALL RainPetInf(...QRR)
...
MODULE XRAINPETINF
...
CONTAINS
...
SUBROUTINE RainPetInf(...QRR)
Real::qrr(3320)[/bash]
0 Kudos
mecej4
Honored Contributor III
1,232 Views
Ah, now that you have shown us some code, a better diagnosis can be made.

QRR, QET, QETT, QINFF are declared as REAL scalars in the main program, although the apparent intention is for them to be arrays. In the absence of an array declaration, the compiler sees a reference such as qrr(3320) in the call to RAINPETINF as a function reference, with integer argument 3320. At link time, the referenced function is not found.

The usage in your program of arrays such as QRR -- with the upper bound as subscript in the call, and a declaration with that upper bound in the subroutine or function called -- is a sign of misunderstanding as to how arrays are declared in the caller, passed to a subprogram as an argument, and declared as a dummy argument in the subprogram. Please consult the Fortran Ref. Manual.

Perhaps, what you need is something such as

(in the main program)

REAL :: QRR(3320)
...

Call RAINPETINF(a,dt,Lt,wq,ri,T,DH,kz,S,EP,IMC,kx,qrr)

...

If you call the subroutine with the last actual argument as QRR(3320), what you do is to ask the 3320-th element of the array to be passed (usually by reference), rather than the array with size 3320.


0 Kudos
Reply