Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

fpp preprocessor in Visual studio

Windyman
Beginner
2,947 Views
Dear all,
I am experiencing a problem whilst compiling myexecutable application using ifort 12.0 in Microsoft Visual Studio 2008. I have a preprocessor line in the source code to define the interface to an externalsubroutine that is available through alinked DLL (windows) or shared object (linux). This interface depends on the platform and looks like this:

INTERFACE

SUBROUTINE initialise()

#if _WIN32

!dec$ ATTRIBUTES ALIAS: '_DLL_mp_INITIALISE' :: initialise

#else

!dec$ ATTRIBUTES ALIAS: 'dll_mp_initialise_' :: initialise

#endif

END SUBROUTINE

END INTERFACE

This all goes well on linux when invoking: ifort -fpp -p
When adding /fpp /P in Visual studio I get the following error message:
error LNK2019: unresolved external symbol _INITIALISE referenced in function _MAIN__
A closer look at the intermediate output file (*.i) shows that the fpp does the right job but puts the output (# line number)after the preprocessor commandas well,which results in the !dec$ ATTRIBUTES command not being properly compiled. This although the /P flag is given..It appears to me that the fpp output (# line number) generally is not a problem, but in the INTERFACE statement it is. I have not been able to resolve this issue and hope anybody can help.
Kind regards,
Koen

0 Kudos
15 Replies
mecej4
Honored Contributor III
2,947 Views
I have a suspicion that one of your subprograms has a call to INITIALIZE without an interface being provided. Therefore, the missing external will be flagged by the linker regardless of what the preprocessor does to the other sources.
0 Kudos
Windyman
Beginner
2,947 Views

The interface is being provided as shown in the original post. When I comment the preprocessor part of the interface for linuxthe interface looks like this:

INTERFACE

SUBROUTINE initialise()

!dec$ ATTRIBUTES ALIAS: '_DLL_mp_INITIALISE' :: initialise

END SUBROUTINE

END INTERFACE

When I compilethis on windows with VS and donot use the preprocessorit works fine this way..

0 Kudos
IanH
Honored Contributor III
2,947 Views
"Compiling" with /P isn't going to get you very far as it means "preprocess only" - so the compiler doesn't actually... compile!

I suspect the object file that is actually being linked in is an old one.

By the alias name it looks like you are trying to pretend that something that was originally compiled as a module procedure should now be treated as an external procedure? Why?
0 Kudos
Windyman
Beginner
2,947 Views
I read online that the /P option stops the fpp output:

http://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/fortran/win/index.htm#bldaps_for/common/bldaps_use_fpp.htm


But apparantly this option is not available through MVS?

Anyway the LNK2019 error also occurs if I just use /fpp and I do get an object file.

The alias name is to recognise the "initialise" subroutine that is present in a DLL module indeed. Hence I have a console project in MVS that is callling this subroutine which is located in the DLL module. The interface statement is to link this external routine. However this alias statement is different for a linux platform. See also the posted code above. This is why I am using the fpp to get the right alias statement for the right platform automatically. But since the fpp call adds an output line with a hash key # followed by the original line number, the linking process is corrupted somehow. I am sorry if I am confusing you too much here, but I hope somebody can help me out...
0 Kudos
IanH
Honored Contributor III
2,947 Views
In the main program, why don't you just USE the module that provides the code in the DLL? Let the compiler worry about the linker names for its module procedures. Saves the need to maintain the interface block and you get the DLLIMPORT attribute for free too.

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,947 Views
Koen,

I suggest you follow IanH's suggestion about USE-ing a module to sort things out. However, if you want to continue along with using FPP try:

#if _WIN32
INTERFACE
SUBROUTINE initialise()
!dec$ ATTRIBUTES ALIAS: '_DLL_mp_INITIALISE' :: initialise
END SUBROUTINE
END INTERFACE
#else
INTERFACE
SUBROUTINE initialise()
!dec$ ATTRIBUTES ALIAS: 'dll_mp_initialise_' :: initialise
END SUBROUTINE
END INTERFACE
#endif

If that fails, then use the FPP option to omit the line numbers from the file that has the above code.
Note, if this is a FORTRAN include file this would require your fortran code to omit the FPP line numbers, which may not be what you want. However to fix this, create a FORTRAN souce file containing your interfaces as a module file (like IanH's suggestion) which is compiled without the FPP line numbers, and then use USE thisModuleNameHere in your FORTRAN programs compiled without FPP.

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
2,947 Views
Koen,

Would you please attach a ZIP with your source file and other information that leads you to believe that the preprocessor is not doing the right thing? We have many customers using this and have not seen a similar issue.
0 Kudos
Windyman
Beginner
2,947 Views

Dear all,

First of all thank you very much for your help on this matter. I found that the workaround as proposed by Jim was effective, but not very elegant with the bulky text. Linking through a USE statement is not an option I think since I need the shared object/DLL and the executable to remain separate at all times. Anyways I found out thatan ALIASstatementin the module would get rid of all my problems and does not necessitate me to use fpp anymore:

Subroutine initialise()

!dec$ ATTRIBUTES ALIAS: 'initialise' :: initialise

If I place this statement in the module where it is defined, this external routine always has the same name, independent of platform type. Hence if I put this statement also in the main program it will always recognise it. Problem solved!

For Steve's sake I have assembled the source files to recreate the problem. The only problem is that I have not succeeded in attaching the files here (although there is an Add Files button). An alternative suggestion to upload the files is welcome.

Once again many thanks for all your help!

Koen

0 Kudos
Steven_L_Intel1
Employee
2,947 Views
Please follow the instructions in the link below for attaching files. You can also send it to me by email at steve.lionel at intel dot com.
0 Kudos
IanH
Honored Contributor III
2,947 Views
I don't see how the USE statement stops you from keeping the executable and DLL separate.

If you want a module procedure to have a particular linker name (and calling convention) then consider using a BIND(C, NAME='xxx') suffix on the subroutine or function statement for the module procedure and inside the relevant interface block. That's a lot more portable than the compiler directive.
0 Kudos
Windyman
Beginner
2,947 Views
Ok I am not familiar with the BIND command. Since my program now works on both linux and windows without directive I will keep this in mind for future coupling problems.

I have uploaded two VS projects (CONSOLE and DLL) that recreate the problem. Note that the lib file which is created by the module must be included manually in the console project.
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,947 Views
Koen,

Here is another suggestion:

#if _WIN32
#define USE_initialize'_DLL_mp_INITIALISE'
#else
#define USE_initialize 'dll_mp_initialise_'
#endif

INTERFACE
SUBROUTINE initialise()
!dec$ ATTRIBUTES ALIAS: USE_initialize :: initialise
END SUBROUTINE
END INTERFACE

Jim Dempsey
0 Kudos
Steven_L_Intel1
Employee
2,947 Views
I can reproduce the problem, but it is very strange. Basically, the compiler is not properly parsing the directive in the preprocessed source when it is followed by the # 20 line number marker. But when I try a slightly different source that should otherwise show the same issue, it works. So I need to figure out what the difference is, and then send it on to the developers.

Suggestion 1: use the !DEC IF DEFINED(_WIN32) syntax rather than the # syntax.
Suggestion 2: Don't use directives at all: USE the module that declares INITIALISE and the correct name will then be automatically used. This would be my preference by far.
0 Kudos
Steven_L_Intel1
Employee
2,947 Views
The problem also seems to require putting a comment at the end of the ATTRIBUTES directive. If you take this off, it works. A comment here is allowed. Escalated as issue DPD200172584.
0 Kudos
Steven_L_Intel1
Employee
2,947 Views
This problem has been fixed in our sources for a future release.
0 Kudos
Reply