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

Linker does not recognize subroutine in new IFX project

spainchaud
Beginner
1,159 Views

I have a Fortran library project I created about 14 years ago. It was compiling under Fortran 2019 and as of this weekend I have it compiling with the 2024.0 compiler. I decided to start over with a new IFX project in VS2022 and copied all the code into the project. When I compile, I get an undefined symbol error from the linker. Four of my f90 files are failing to reference a subroutine in an older .for file. This code builds fine in the IFORT compiler, while giving me messages that the compiler is deprecated. This is why I am trying to get the IFX compiler working. Is there something special setting I need for the IFX compiler to work with mixed for and f90 files?

0 Kudos
12 Replies
Arjen_Markus
Honored Contributor I
1,145 Views

We have project with .f and .f90 projects and see no such problem using VS 2022 and ifx. Is the .for file compiled? As the errors come from the linker, could it be that there is a dependency missing for the object file related to the .for source?

0 Kudos
spainchaud
Beginner
1,107 Views

All the code seems to compile correctly. There are object files for every source file. I have done nothing with the setup of the project, other than to create it and add the source code.

 

Rebuild started at 11:01 AM...
1>------ Rebuild All started: Project: LibDipmag (IFX), Configuration: Debug x64 ------
Deleting intermediate files and output files for project 'LibDipmag', configuration 'Debug|x64'.
Compiling with Intel® Fortran Compiler 2024.0.2 [Intel(R) 64]...
dipmag_express.f90
errorCheck.f90
dipmag_express_tl.f90
dipmag_no_jacobian_mx.f90
dipmag_espress_win.f90
dipmag_mtc4_m.for
Linking...
lld-link: error: undefined symbol: DIPMAG_DML
>>> referenced by C:\Users\painste\source\repos\LibDipmag\LibDipmag\dipmag_express.f90:0
>>> x64\Debug\dipmag_express.obj:(DIPMAG_DML.t524p.t525p.t526p.t527p.t528p.t529p.t530p.t531p.t532p.t533p.t534p.t535p.t536p.t537p.t538p.t539p.t540p.t541p.t542p.t543p.t544p.t545p.t546p.t547p.t548p.t549p.t550p.t551p.t552p.t553p.t554p.t555p.t556p.t557p.t558p.t559p.t560p.t561p.t562p.t563p.t564p.t565p.t566p.t567p.t568p.t569p.t570p.t571p.t572p.t573p.t574p.t575p.t576p.t577p.t578p.t579p.t580p.t581p.t582p.t583p.t584p.t3v)
>>> referenced by C:\Users\painste\source\repos\LibDipmag\LibDipmag\dipmag_express_tl.f90:0
>>> x64\Debug\dipmag_express_tl.obj:(DIPMAG_DML.t714p.t715p.t716p.t717p.t718p.t719p.t720p.t721p.t722p.t723p.t724p.t725p.t726p.t727p.t728p.t729p.t730p.t731p.t732p.t733p.t734p.t735p.t736p.t737p.t738p.t739p.t740p.t741p.t742p.t743p.t744p.t745p.t746p.t747p.t748p.t749p.t750p.t751p.t752p.t753p.t754p.t755p.t756p.t757p.t758p.t759p.t760p.t761p.t762p.t763p.t764p.t765p.t766p.t767p.t768p.t769p.t770p.t771p.t772p.t773p.t774p.t3v)
>>> referenced by C:\Users\painste\source\repos\LibDipmag\LibDipmag\dipmag_no_jacobian_mx.f90:0
>>> x64\Debug\dipmag_no_jacobian_mx.obj:(DIPMAG_DML.t714p.t715p.t716p.t717p.t718p.t719p.t720p.t721p.t722p.t723p.t724p.t725p.t726p.t727p.t728p.t729p.t730p.t731p.t732p.t733p.t734p.t735p.t736p.t737p.t738p.t739p.t740p.t741p.t742p.t743p.t744p.t745p.t746p.t747p.t748p.t749p.t750p.t751p.t752p.t753p.t754p.t755p.t756p.t757p.t758p.t759p.t760p.t761p.t762p.t763p.t764p.t765p.t766p.t767p.t768p.t769p.t770p.t771p.t772p.t773p.t774p.t3v)
>>> referenced 1 more times

 

 

0 Kudos
spainchaud
Beginner
1,106 Views

I solved the problem by taking the DIPMAG_DML subroutine and placing it by itself in a f90 file. I had to reformat the comments and the line wrapping. I am surprised that this actually worked, because DIPAMG_DML is the entry point for all the other subroutines in the for file. I expected further problems referencing the subroutines left in the old file.

 

If anyone can explain what is going on, I would appreciate it. We have a lot more code written to the f77 standard, that will be moved to IFX. I would be good to understand what problems we might face.

0 Kudos
mecej4
Honored Contributor III
1,041 Views

There are several inconsistencies in your description and they make it difficult to give useful suggestions.

I suspect that there are errors in your newly created project. If it is a static library that you are trying to build, there should be no linking step at all. 

Static libraries are expected to have lots of unsatisfied external symbols. those symbols should be defined in other libraries (user-provided or the Fortran compiler's runtime libraries).

Does one of your Fortran source files contain CALL DIPMAG_DML(...), or the body of the subroutine itself? If not, the interface blocks that you showed serve no useful purpose.

If the old code had interface blocks that were required (by the Fortran Standard), removing them is a blunder that is sure to cause more problems despite giving a transient illusion of having fixed something.

0 Kudos
Arjen_Markus
Honored Contributor I
1,064 Views

Is it possible to publish a (small) reproducer? This really looks odd.

0 Kudos
spainchaud
Beginner
1,054 Views

I tried to create a small example, by gutting the .for file, leaving only the DIPMAG_DML subroutine. I was still getting the undefined symbol error up until I removed the other two subroutines that could be used as entry points (I never use them). These two subroutines had interface sections describing DIPMAG_DML. Here is one of those sections:

 

interface
subroutine DIPMAG_DML(FREQ,NTRN,XL_TRN,NREC,XL_REC,
     *                    NMED,R_OT,IDRT,IDT,R_ON,IDRN,IDN,Z_M,IDZI,IDZ,
     *                    NSTEP,PRFAZX,PRFAXY,PRFZ,tm,
     *                    ITF,INF,IZF,
     *                    HXX,DRTXX,DRNXX,DZXX,
     *                    HYY,DRTYY,DRNYY,DZYY,
     *                    HZZ,DRTZZ,DRNZZ,DZZZ,
     *                    HXY,DRTXY,DRNXY,DZXY,
     *                    HYX,DRTYX,DRNYX,DZYX,
     *                    HXZ,DRTXZ,DRNXZ,DZXZ,
     *                    HZX,DRTZX,DRNZX,DZZX,
     *                    HYZ,DRTYZ,DRNYZ,DZYZ,
     *                    HZY,DRTZY,DRNZY,DZZY,
     *                    IERR,iac)
INTEGER iac,NREC,NTRN
real*8  XL_TRN(NTRN),XM_SX(NTRN),XM_SY(NTRN),XM_SZ(NTRN)
real*8  XL_REC(NREC),XM_RX(NREC),XM_RY(NREC),XM_RZ(NREC)
INTEGER NMED,IDRT(0:NMED),IDRN(0:NMED),IDZI(NMED)
real*8  FREQ,Z_M(NMED)
complex*16 R_OT(0:NMED),R_ON(0:NMED)
INTEGER NSTEP
real*8  PRFAZX(NSTEP),PRFAXY(NSTEP),PRFZ(NSTEP)
INTEGER IDT,IDN,IDZ,ITF,INF,IZF,IERR
complex*16 HXX(NSTEP*NREC*NTRN),
     *                   DRTXX(ITF*NSTEP*NREC*NTRN,IDT),
     *                   DRNXX(INF*NSTEP*NREC*NTRN,IDN),
     *                   DZXX (IZF*NSTEP*NREC*NTRN,IDZ)
complex*16 HYY(NSTEP*NREC*NTRN),
     *                   DRTYY(ITF*NSTEP*NREC*NTRN,IDT),
     *                   DRNYY(INF*NSTEP*NREC*NTRN,IDN),
     *                   DZYY (IZF*NSTEP*NREC*NTRN,IDZ)
complex*16 HZZ(NSTEP*NREC*NTRN),
     *                   DRTZZ(ITF*NSTEP*NREC*NTRN,IDT),
     *                   DRNZZ(INF*NSTEP*NREC*NTRN,IDN),
     *                   DZZZ (IZF*NSTEP*NREC*NTRN,IDZ)
complex*16 HXY(NSTEP*NREC*NTRN),
     *                   DRTXY(ITF*NSTEP*NREC*NTRN,IDT),
     *                   DRNXY(INF*NSTEP*NREC*NTRN,IDN),
     *                   DZXY (IZF*NSTEP*NREC*NTRN,IDZ)
complex*16 HYX(NSTEP*NREC*NTRN),
     *                   DRTYX(ITF*NSTEP*NREC*NTRN,IDT),
     *                   DRNYX(INF*NSTEP*NREC*NTRN,IDN),
     *                   DZYX (IZF*NSTEP*NREC*NTRN,IDZ)
complex*16 HXZ(NSTEP*NREC*NTRN),
     *                   DRTXZ(ITF*NSTEP*NREC*NTRN,IDT),
     *                   DRNXZ(INF*NSTEP*NREC*NTRN,IDN),
     *                   DZXZ (IZF*NSTEP*NREC*NTRN,IDZ)
complex*16 HZX(NSTEP*NREC*NTRN),
     *                   DRTZX(ITF*NSTEP*NREC*NTRN,IDT),
     *                   DRNZX(INF*NSTEP*NREC*NTRN,IDN),
     *                   DZZX (IZF*NSTEP*NREC*NTRN,IDZ)
complex*16 HYZ(NSTEP*NREC*NTRN),
     *                   DRTYZ(ITF*NSTEP*NREC*NTRN,IDT),
     *                   DRNYZ(INF*NSTEP*NREC*NTRN,IDN),
     *                   DZYZ (IZF*NSTEP*NREC*NTRN,IDZ)
complex*16 HZY(NSTEP*NREC*NTRN),
     *                   DRTZY(ITF*NSTEP*NREC*NTRN,IDT),
     *                   DRNZY(INF*NSTEP*NREC*NTRN,IDN),
     *                   DZZY (IZF*NSTEP*NREC*NTRN,IDZ)
character*2 tm
C
! real*8  TX_,TY_,TZ_,RX_,RY_,RZ_,AZX_,AXY_
! complex*16 XX_,YY_,ZZ_,XZ_,ZX_,CZERO
! complex*16 HXX_,HYY_,HZZ_,HXY_,HYX_,HXZ_,HZX_,HYZ_,HZY_
! INTEGER I,J,JT,JN,JZ,ID,ITZ,K,INT,INC,III,IT,IN,IZ
! real*8  R
end subroutine DIPMAG_DML
end interface

 

 

I never use interface sections myself, so I am not familiar with them, or how they might be different in the IFORT and IFX compilers. I did further tests. First, I restarted with the full code, just deleting the interface sections. I still had the link error. Then I deleted the two subroutines that had contained the interfaces, and the link error went away. So at least I know the source of the problem, although I do not understand why it was happening.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,026 Views

Also, your interface declaration need only include the dummy (called) arguments declarations, not the local variables.

Jim

0 Kudos
Steve_Lionel
Honored Contributor III
1,048 Views

This is not a complete or even usable example - it's just the interface without a call of the procedure, and we don't know how the procedure itself was declared or which compile options were used. Also, when including examples, please either attach them as a file or use the code insertion tool in the forum (click on ... and then <>, select Fortran as the language), as, especially for fixed-form source, just pasting the text removes leading blanks.

0 Kudos
spainchaud
Beginner
999 Views

Here is a cut down version of the code that retains the link error. Use a standard IFX project with check routine interfaces set to no. This setting is necessary to compile the code that I had to remove to make this example. Without this setting the link error goes away in this example. 

0 Kudos
Steve_Lionel
Honored Contributor III
991 Views

OK, I can reproduce this, and indeed IFX is doing something wrong. Just the linker error message is bizarre. If I look at dipmag_express.obj's symbol table I see:

 

04F 00002860 SECT1  notype ()    Static       | DIPMAG_DML.t524p.t525p.t526p.t527p.t528p.t529p.t530p.t531p.t532p.t533p.t534p.t535p.t536p.t537p.t538p.t539p.t540p.t541p.t542p.t543p.t544p.t545p.t546p.t547p.t548p.t549p.t550p.t551p.t552p.t553p.t554p.t555p.t556p.t557p.t558p.t559p.t560p.t561p.t562p.t563p.t564p.t565p.t566p.t567p.t568p.t569p.t570p.t571p.t572p.t573p.t574p.t575p.t576p.t577p.t578p.t579p.t580p.t581p.t582p.t583p.t584p.t3v

Unless I miscount, those txxxp things correspond to actual arguments - some sort of C++-like name mangling?

But the other weird thing is that dipmag_express.f90 doesn't have an interface to DIPMAG_DML - that interface is in dipmag_mtc4_m.for

 

0 Kudos
spainchaud
Beginner
974 Views

It looks like two conditions are necessary for this link error to occur. The subroutine ATOOLC_DML must be in the code, with its interface statement, and the check interfaces must be turned off. I am not sure that the interface statement is part of the problem. Also separating DIPMAG_DML into a separate f90 file seems to eliminate the issue.

DIPMAG_DML is the original entry point to the code, probably developed on an old Compaq compiler with no interface checking. I wrote DIPMAG_EXPRESS as a wrapper to DIPMAG_DML to eliminate inputs and outputs that I never use. The subroutine ATOOLC_DML was added years later by someone other than me. I was never told what its purpose was, but it is a wrapper and should has been put in a separate file. Most of this code was developed in Rusia, and I am not in Russia, which should explain the inconsistent programming styles.

0 Kudos
Devorah_H_Intel
Moderator
768 Views

This issue has now escalated to Compiler Engineering. 

0 Kudos
Reply