Identifying Needed Link Libraries - c++

I'm using C++ under Visual Studio 2010 (VS2010). I've pulled in a third-party library provided as headers and libs. The first call I added into this library produced a ton of unresolved symbol link errors. The problem is that there are a lot of .lib files in this library. I need to somehow identify the ones I need. I have already added the library directory to the VS2010 linker options. Now I just need to identify the individual libraries I need.
Best possible solution: After the link attempt, VS2010 would scan the library directory for the unresolved symbols and would tell me what .lib files contain them.
Barring this, I'd like to solicit ideas from the community on the most efficient way to solve this problem.
Thanks,
Dave

The documentation is supposed to tell you. If you don't have any then leave it up to the linker to sort it out. Add all the .libs as Additional Dependencies.
Then take a lazy Friday to sort out which ones you really need with the /VERBOSE linker option, it shows you which .lib is actually getting used in the trace to the Output window. Project + Properties, Linker, Command line to add the option.

Related

Visual Studio: which source file includes a particular library (with "pragma comment")?

EDIT:solved with James McNellis' suggestion, which led me to the offending library. It was one I hadn't checked with dumpbin.
I'm building a Visual Studio 2013 project that links against static libraries using "#pragma comment" instead of listing the libraries in the project properties. After replacing the libraries with new versions, I'm getting a link error because it's still trying to find some of the old libraries, e.g. it can't find "library_v9.lib" when it should be linking "library_v12.lib" instead. How can I find where the old libraries are being requested? Here's what I've tried:
Deleting all the objects, etc. and rebuilding from scratch.
Searching for "#pragma comment" doesn't work because it's built up into several layers of macros, and the version number is obtained from _MSC_VER so the "9" and "12" never actually appear anywhere in the source.
Running dumpbin /DIRECTIVES on all the libraries that get linked together into the executable. They all refer to the correct "12" library versions.
The linker has a /verbose switch that will cause it to print out a detailed log of what libraries it is opening, what symbols it is searching for, and why it is searching for those symbols.
Typically, the most straightforward way to debug this sort of issue is to add /verbose to the linker options, open the build log in a text editor, and search for the library name or symbol in which you're interested. In this case, search for "library_v9.lib". The linker will tell you what caused it to open that library.
Did you check Properties->Linker->Input section?

Linker Trouble: How to determine where a "/DEFAULTLIB" is coming from

I am trying to find a good way to determine what module at link time is causing a certain library to get processed as a "/DEFAULTLIB" as seen in the verbose linker output from Visual Studio.
Here is my situation, I have several static library pre-requisites and each has a release and a debug version (BlahD.lib and Blah.lib). For some reason at link time all of the *D.lib's are processed as default libraries even though I am building a release with the non-debug libs specified as "Additional Dependencies". If I never build the debug versions of the static libraries those *D files wouldn't exist and there would be a linker error (can't open file).
I can get my project to build successfully by specifying /NODEFAULTLIB for all of these offending .lib files. All the release libraries link up and everyone is happy. But I want to understand what is going on here. What is causing these *D.lib files to be processed by the linker? Is my only hope to write some kind of script that dumpbins everything in this massive project and its dependant projects (microsoft support)? Even then I don't understand what to look for in the dumpbin output, does this apply to the .lib files as well the .obj files?
I had a similar problem. I was only able to solve it by analyzing the *.obj files as you suggested. To do it, I ran the following command via the Visual Studio command prompt (in the temp folder of the project, where *.obj files are generated):
for /R %1 in (*.obj) do #dumpbin /directives /section:.drectve "%1" > "%1".directives.txt
Then I used Notepad++ to search for the name of the offending library in all of these *.directives.txt files. This revealed which project was referencing the wrong lib.
Note: you may want to modify this to include any 3rd-party *.lib files your project may use, and not just *.obj files. "/DEFAULTLIB" directives may also come from them.
Note: you may need to use *.o instead of *.obj
Look for #pragma comment(lib) in the source. See if it perhaps is dependent on a #define - This is a common way for a SDK to ensure that the right libs are linked, and you may need to define THESDK_DEBUG or THESDK_RELEASE for the logic to work out.
Additional information:
I discovered in Visual Studio 2008 that even commenting out the statement from the *.idl file does not work, as in:
//cpp_quote("#pragma comment( lib, \"MYLIB.lib\")")
The compiler still adds MYLIB.lib as a DEFAULTLIB, and it winds up in the *.obj file. Make sure you remove the line completely from the code!
Link with the /verbose option and search the output for the name of the library in question. This will tell you which object file dragged the library into the link.

ODBC refuses to statically link to libcmt.lib under VS2010

There is a short response from Microsoft regarding this issue:
https://connect.microsoft.com/VisualStudio/feedback/details/470376/odbc-application-linking-with-odbccp32-lib-gets-link-errors-in-vs2010-beta-1?wa=wsignin1.0#tabs
Basically, their response doesn't seem to address the problem.
Our application needs to statically link to the C libraries, but there is a linker error when attempting to do so. Microsoft's answer seems to be "dynamically link instead", but that's not an option. Their alternative is to "Use the version of odbccp32.lib that came with Vista SDK." However, I am unaware as to how to force VisualStudio 2010 to use a different version of the ODBC library?
I just spent the last hour trying every conceivable search through the .vcxproj and .sln files for any references to odbccp32.lib. None. I similarly looked for ODBC. None. Looking at all of the compiler & linker options for the project(s) in question: nothing refers to ODBC whatsoever. The only connection between our application and ODBC I can see is the #include <sql.h> and <sqlext.h>. However, even those files do not refer to odbccp32.lib (or any other .lib or linker option).
The only references to odbccp32.lib I can find at all are in .obj files. So it appears that VS2010 automagically knows which ODBC libraries to link against based on what functions are referenced in our software (SQLConnect(), for example).
So how might I:
1) "obtain Vista SDK version of odbccp32.lib"?
2) cause VS2010 to link against that version?
-OR-
Is there a better way to solve this?! Right now I am unable to proceed with a conversion of our software from VS2008 -> 2010 unless I can find a way to force this goofy software to compile.
NOTE: Apparently I could force the system to compile using 2008's tooling, which may "cure" this. But that means changing all of our projects up & down the chain to do this, which is rather backwards and contrary to the whole point of moving to 2010, no?
For the curious, the exact linker error:
odbccp32.lib(dllload.obj) : error LNK2019: unresolved external symbol __imp___vsnprintf referenced in function _StringVPrintfWorkerA#20
Reading through your link, it seems that Microsoft has verified that there is a problem, and they intend to fix it in the next version of the SDK. Doesn't help much, does it?
It's quite normal for the linker to daisy-chain through the objects, linking one object only to discover that it has dependencies on other objects. If you want to preemptively link to a specific library, add it to the "Additional Dependencies" in the Linker Input tab of the project properties.
If you aren't able to get the linker to prefer a specific version of a library, just seek out and replace the version of the library in the installation.
I think this is a link to the Vista SDK, but I can't verify it: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=ff6467e6-5bba-4bf5-b562-9199be864d29&displaylang=en
I see it. Ouch, my condolences. Their advice is about as best as it is going to get if you don't want to compile with /MD. I think I know the source of the problem, this isn't that easy to fix for them either. It's going to require them getting the VS2010 CRT header file fixed first, then recompile and issue an SDK update. That takes some major doing.
It is getting linked because it is listed in the "Core Windows Libraries" property sheet. View + Property Manager to see it. Not linking it is not an option, you are probably actually using it when you #include <sql.h>
The Vista version indeed doesn't have the same problem, it was probably built with an earlier version of VS. Project + Properties, Linker, Input, Additional Dependencies = "c:\program files\microsoft sdks\windows\v6.0a\lib\odbccp32.lib". This injects the vista version before the 7.0 version. You may have to live with this for a while, be sure to keep VS2008 installed on your build machines.
I just encountered the undefined __imp___vsnprintf symbol while converting an ODBC application to Visual Studio 2015. Figuring that there must be a workaround, I dumped all the symbols exported by the various libraries in the Visual Studio 2015 LIB directories with DUMPBIN and found that this library with a most obvious name, legacy_stdio_definitions.lib, defines these symbols.
Adding this to the LINK command line resolved the missing external referenced by odbccp32.lib.
Once one knows what to search for, some info is available here.
Don't know all the details, so shooting in the dark. When I had a situation when certain functions were available with one compiler and not the other, I created a simple DLL with the functions exported with C interface, using compiler version that supported those functions, and used that DLL with another compiler.
the solution is to link with just odbccp32.lib from v6.0 sdk all else from the default sdk.
1. download v6.0 sdk from: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=ff6467e6-5bba-4bf5-b562-9199be864d29&displaylang=en
(do not install documentation and samples/examples, the result is 75MB downlaod):
2. create a folder, some folder.
for example: lib_odbc_fromsdkv6.0 in your project's folder
3. copy the file odbccp32.lib from:
C:\Program Files\Microsoft SDKs\Windows\v6.0\Lib
to folder created above (only one file).
4. in each project's properties add that (lib_odbc_fromsdkv6.0) directory to Library directories:
VC++ Directories -> Library directories
the depended projects in myodbc are myodbc5S and myodbc-installer.
(from Mordachai)

Why is VisualStudio looking for this lib file? LNK1104 error

We have a large project using VS2008 and boost 1_42. I'm trying to upgrade to VS2010 and boost 1_44. I installed VS2010 and boost 1_44 and converted the project. Now I am trying to build, and everything compiles, but fails when linking:
LINK : fatal error LNK1104: cannot open file 'libboost_thread-vc90-mt-1_42.lib'
I have changed the include and lib directories to point to the new boost 1_44 files and I have renamed the old boost 1_42 directory.
Why is the linker still looking for a vc90-1_42 file, when it is only using 1_44 headers? Is there a way that I can determine WHY the linker wants this file? The linker obviously thinks it needs the file, but why?
I have cleaned the project and I am re-building to ensure any old build files are erased.
I've run into exactly this problem a couple of times too. It's usually been some old temporary files but like in your case cleaning didn't always do the trick straight away. Does your project include any static libs that might have been built with 1.42?
Something you can try which may or may not be helpful in tracking down your issue:
Rename the old boost directory back to it's original name
Clean the solution
Under C/C++->Command Line->Additional Options add "/showIncludes"
Under Linker->Command Line->Additional Options add "/verbose:lib"
Rebuild all
Then when you build you'll be able to see at which point 1.42 headers are included, etc. in the output window. Somehow doing this helped me in tracking down where the problem was.
Along with changing the lib directory, you need to change the name of the boost library. That's in the Linker | Input section of the project settings.
Your added comment makes it clear that the dependency on the Boost 1.42 library was being created indirectly by another library that hadn't been rebuilt.
For this you basically have two choices: either add that library as a project to your main solution, and make sure it has enough dependency information that it'll be re-built when you upgrade Boost, or use the /Zl compiler switch when you build your library. This tells the compiler you're building a library so you do not want to embed library dependencies like this.
Boost uses
#pragma comment(lib)
command to inform the linker of libraries it needs to link with. It is not an error. If Boost says you need it, it's likely you do.
On How can I find out why the linker wants this file?
There are programs which will go through your app and dlls/libs and report the content of manifests and what the binaries report they depend on. You could then scan the report for the unexpected libraries being included. We used this mainly to find libs including the previous version of the VC runtime.
Have not used the one we had in about 5 years though, now if only I could remember the name of the app!
DependancyWalker (depends.exe) will allow you to see dependancies of dll/exe but not static libs.
You could open each binary as a 'file' in MSVS and look at the manifest content by hand, but I imaging this would be a bit painful. I've not tried this with a static lib.

Visual Studio 2010 library linking order

How do you specify, in Visual Studio 2010, the order in which library files should be linked?
I have a project that links against libexpat and against another library. This library (not under my control) seems to also include libexpat. The problem is that 'we' use a different version of the library (XML_UNICODE vs not). In Visual Studio 2008 things seemed to work out okay (might have been a coincidence), but in Visual Studio 2010 the wrong instance of libexpat is linked. I was thinking that if I could specify the order in which these two libraries should be linked that then I could circumvent the problem.
A few years back I discovered a hack that allows you to force Visual C++ to link libraries with a specific precedence. This is not elegant, but it is functional.
It seems that the linker for Visual C++ generates link order on the fly based on symbol dependencies. By adding a symbol reference up-front, you can force the linker to include the first library specified in the linker input. Please note, I have only tested this with Visual C++ 6 and 8 (2005).
Let's say for example that you have two libraries with the symbol XML_ParserCreate:
libexpat.lib - XML_ParserCreate
someother.lib - OtherSymbolsYouNeed, XML_ParserCreate
First, order your library dependencies as you would expect, libexpat.lib and then someother.lib. Via command line these would be options to link.exe. In Visual Studio 2005, they would be options under the project's Configuration Properties -> Linker -> Input -> Additional Dependencies. I would imagine Visual C++ 2010 has a similar menu.
Next, add a command line option that defines a known repeated symbol up-front, by using the /INCLUDE linker option. In Visual Studio 2005, this can be added under the project's Configuration Properties -> Linker -> Command Line -> Additional options:
/out some.exe ... libexpat.lib someother.lib
/include:XML_ParserCreate
The definition of this symbol will cause the linker to immediately prefer the first library that terminates (realizes) it. In general Visual C++ will generate an error with repeated symbols; if you haven't already, make sure you are also specifying the /FORCE:MULTIPLE linker option.
My specific need for this was using the DUMA memory debugging library. It defines a variety of memory functions that are also defined in libcmtd.lib. The following would incorrectly link libcmtd's version of _malloc, despite a library order that seems to the contrary:
/out some.exe ... duma.lib libcmtd.lib
/FORCE:MULTIPLE
This was resolved by manually adding the symbol, and has worked reliably for years:
/out some.exe ... duma.lib libcmtd.lib
/INCLUDE:_malloc /FORCE:MULTIPLE
I have found 'a' solution: if you add the libraries through #pragma comment(lib... the order of linking is the same as the order in which you type those pragma's. I'm still keeping the question open for a solution when the libraries are added through the project file instead of through pragma statements.
You could create a DLL with the third party library and link it against the static version of expat that it needs and then link your code against the version of expat you need.
However, the fact that it worked before might mean that one library has all the functionality of the other plus some extra. I don't know the details of expat. If that is the case, you need to make sure that you only have the version you want to use in your library search path. A different search directory order in the other version of the compiler could explain the change in behaviour.
I think you can change the order in which library files are linked bij adding them in the project file in linker -> input -> additional dependencies. The library files will be linked in the order in which they are specified.