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

visual studio, 64 bit building question

Brian_Murphy
New Contributor II
568 Views

I am using visual studio 2019.  I can build a project for 32 bits, but not 64 because linking says unresolved externals for routines in a dependent LIB project.  How do I figure out how the 32 bit build is finding the LIB's routines?  The 32 bit linking command line doesn't show the LIB, but it evidently does find it somehow during linking.  The LIB file is not in the source file list, but it is in the Project/Project Dependencies list and is checked for inclusion.  After much fiddling I managed to get past this problem, although I'm not sure what fixed it.  Revisiting the intel-mkl-link-line-advisor might have been the key, but maybe not.

In a related visual studio question, my main program is calling routines in a DLL provided by a 3rd party vendor.  I have LIB and DLL files (separate pair of files for 32 and 64 bits, but the vendor uses the same file names for 32 and 64), and I have successfully made my 32 bit build by adding the 32 bit LIB file to the source file list.  I don't know if that is the recommended way to add a LIB file, but it works.  When I try to build for 64 bits, how do I tell visual studio to use a different LIB file?  I renamed the vendor's 64 bit LIB file to end with _x64.LIB, and added this file the project's source file list (both 32 and 64 LIB files are now in the list) and I can now build both 32 and 64 bit exe's,  However, the 64 bit exe needs the vendor's DLL file having the same file name as the 32 bit DLL.  Is there a way to get the 64 bit exe to look for a renamed version of the 64 bit DLL file?

0 Kudos
9 Replies
Steve_Lionel
Honored Contributor III
568 Views

What I would recommend in this case is - remove the .lib from your source files (this is a perfectly fine way to do it if you are not multiplatform building). Now go to the Linker> Input property page. At the top of the page select Configuration: All Configurations and Platform: All Platforms. In the Additional Dependencies property, put the name (only!) of the vendor .LIB, for example, "vendorlib.lib". Click Apply.

Now go to the Linker > General page. Change Platform to "Win32". Under "Additional Library Directories" enter the path to the folder containing the 32-bit vendor library. Click Apply. Change Platform to "x64", enter the path to the 64-bit library, click OK.

0 Kudos
Brian_Murphy
New Contributor II
568 Views

Thanks, Steve.  I think I understand that, and it is working for me.  A 32 or 64 bit build will pull the LIB files having the same name, but from different directories.  I think that means the 32 and 64 bit exe's cannot be executed in the same folder because they each will need a DLL file having the same name.  Is that right?

When I have LIB and DLL files, how do I get visual studio to link in the DLL file statically so the exe doesn't need that file present to run.  I thought /libs:static would do this, but it's not.

0 Kudos
Brian_Murphy
New Contributor II
568 Views

When I do a Debug build with /libs:dll /threads /dbglibs that goes ok. 

But with /libs:static I get hundreds of linker errors.  What am I missing?

I've got to get away from my computer for a while before I go nuts.

0 Kudos
Steve_Lionel
Honored Contributor III
568 Views

Brian Murphy wrote:

Thanks, Steve.  I think I understand that, and it is working for me.  A 32 or 64 bit build will pull the LIB files having the same name, but from different directories.  I think that means the 32 and 64 bit exe's cannot be executed in the same folder because they each will need a DLL file having the same name.  Is that right?

Not if you're running on 64-bit Windows, as it is smart enough to ignore "wrong architecture" DLLs in its search. You would need to have PATH set to include both, though, if that was the case.

When I have LIB and DLL files, how do I get visual studio to link in the DLL file statically so the exe doesn't need that file present to run.  I thought /libs:static would do this, but it's not.

No such thing as linking in a DLL statically. /libs:static says to use the static library form of the language libraries (Fortran and C++ here), but has no effect on user libraries. The LIB you get that accompanies a DLL is the "import library". It has no code, it serves only as a connection to the DLL when linking.

When I do a Debug build with /libs:dll /threads /dbglibs that goes ok. 

But with /libs:static I get hundreds of linker errors.  What am I missing?

If you are linking in any libraries built with C/C++, they are sensitive to the choice of run-time library made when the source was compiled: debug vs. release, static vs. DLL. Intel Fortran compiled sources are not sensitive to that, but by default the objects include linker directives that pull in specific libraries.

Without seeing a sample of the errors, I can't say more. But one often can't just blithely change the run-time library type when using third-party libraries.

0 Kudos
Brian_Murphy
New Contributor II
568 Views

Thanks, Steve.  I guess DLL means dynamic link library for good reason.

About linking failing for Debug with /libs:static.  I discovered that the Debug build setting for Linker/Input/Ignore Specific Library was set to Libc;Libcmtd, but was not set for Release.  I don't know why this was set, but removing this got the program to build Debug with or without /libs:static.

In what circumstances would Linker/Input/Ignore Specific Library be set to Libc;Libcmtd ?

0 Kudos
Steve_Lionel
Honored Contributor III
568 Views

I'm generally not a fan of "Ignore specific library", at least as a first try. The issue it is trying to address (at least here) is "Mixed C Library Syndrome".

By default, when a Fortran or C source is compiled, the compiler adds to the object "linker directives" that name the language support libraries the compiler thinks should be included. You can see these with a "dumpbin -directives" command on the object file. For example:

D:\Projects>dumpbin -directives main.obj
Microsoft (R) COFF/PE Dumper Version 14.24.28319.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file main.obj

File Type: COFF OBJECT

   Linker Directives
   -----------------
   -defaultlib:ifconsol
   -defaultlib:libifcoremt
   -defaultlib:libifport
   -defaultlib:libmmt
   -defaultlib:LIBCMT
   -defaultlib:libirc
   -defaultlib:svml_dispmt
   -defaultlib:OLDNAMES

This was a Fortran source. Note that it names both Intel Fortran libraries (ifconsol, etc.) and MSVC libraries (LIBCMT). The set of libraries will change as you use different options. In this example, the compile was done specifying static libraries, so that's why libifcoremt and libcmt were named. Now let's try it with a /libs:dll:

   Linker Directives
   -----------------
   -defaultlib:ifconsol
   -defaultlib:libifcoremd
   -defaultlib:libifportmd
   -defaultlib:libmmd
   -defaultlib:MSVCRT
   -defaultlib:libirc
   -defaultlib:svml_dispmd
   -defaultlib:OLDNAMES

Now we have the DLL forms of the libraries referenced. So, what happens if we link one object built for static libraries together with one built for dynamic libraries? In most cases, the global symbols have the same names between the two sets, so what can happen is that the linker sees the same name declared in two different places (where it has been asked to pull in the object module defining one or more) and it complains.

When the linker does complain, it gives a message suggesting that you tell it to ignore a specific library, so people tend to try this. Sometimes it works, but sometimes it causes hidden problems. In the case of MSVC-compiled sources, the choice of run-time library affects compiled code, changing names of some symbols it references. Intel Fortran doesn't do this, but both languages have issues if there are multiple versions of the library code loaded in the application. In Fortran, this is most likely to bite you if both your main program and the vendor library you linked to do I/O or do anything with allocatable variables.

The preferable way of dealing with this, at least for Fortran libraries, is to build the library with the option to not generate these directives at all. In VS, that's Fortran > Libraries > Disable default library search rules (/libdir:noauto). This allows the executable to specify the run-time library set. This works less well for C code due to the generated code differences.

0 Kudos
Steve_Lionel
Honored Contributor III
568 Views

Oh, I should talk about libc. This is the non-thread-safe MSVC static library. Microsoft dropped this entirely around the VS2015 timeframe, but there are objects around compiled with old compilers that specify this. If you're linking with one of these, you may be able to get away with ignoring libc. Maybe. 

0 Kudos
Brian_Murphy
New Contributor II
568 Views

Dr. Fortran delivers again.  Thanks, Steve. 

The use of the Ignore Specific Libraries option setting must have been a holdover from old versions of code linking to C code which probably is no longer part of the project.  Now, however, my fortran console program is linking to 3rd party C DLL's which are very recent builds from this vendor.

0 Kudos
JohnNichols
Valued Contributor III
567 Views

I have a theory that Dr Fortran is Dr Fortran for 364 days a year and Santa for one day a year.  

Or as my 13 year old daughter said the other day -- Dad you look like Evil Santa with your black/white beard.

 

0 Kudos
Reply