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

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?

Related

Visual Studio (C++) is automatically linking against an unwanted version of lib file

I am trying to create a C++ project in Visual Studio 2013 that has CGAL and Boost (and a couple of other libraries) as dependencies. I preferably like to link to these libraries dynamically. Also, I'd like to link to the "Release" versions of these libraries for performance reasons (not the "Debug" versions).
Starting from an empty C++ project, I added the path to header files of the aforementioned libraries as shown in the image below:
Inside the linker options, I then added the directories that contain the DLL and lib files of the external libraries. (CGAL directory contains CGAL's compiled DLL files along with lib files).
At this point, I have not added a single "lib" file "Additional Dependencies" dialog:
Now something weird is going on and I cannot explain why. If I try to build the project as-is (under the "Debug" configuration), I get a LNK1104 error about the linker not being able to find CGAL-vc120-mt-gd-4.7.lib. I know that the error means I should add the lib file in "Additional Dependencies" dialog...
But wait... WHAT...?!!
How does Visual Studio know how to automatically link against this lib file?! Worse yet, how does it know it needs the "debug" version of the library? (With the gd suffix). Also, how does it know I compiled CGAL with VS2013!!??
At first, I though the project was inheriting properties from some preset property sheets somewhere in my system. But I am certain that's not the case as this behavior shows even with a project created from scratch.
My main question is, how would you force Visual Studio to link against the "Release" version of this library? (eg. CGAL-vc120-mt-4.7.lib)
Side question but related: Am I even linking against the DLL files? How can I be certain that I am in deed doing dynamic linking and not static linking?
This is probably happening due to the #pragma comment(lib) mechanism - eg see What does "#pragma comment" mean?
This is a way of the compiler emitting instructions for the linker so that it can decide between multiple versions of a library depending on the compiler version. In this case it means that it can automatically pick up the correct version of the library (debug vs release, vs2013 vs vs2015, MT vs MD, etc). When you added the explicit reference to the library in Additional Dependencies then it is now trying to look for two files.
So, to fix the problem, remove it from Additional Dependencies and let VS pick the right library. If you are getting the LNK1104 error then it suggests that either the link library path isn't set up correctly, or you don't have the CGAL library file it's looking for. You can increase the verbosity settings for the linker in the Project Options to get more detail about what's happening.

Visual Studio C++ - Check the reason of link a specific library

vs report a error such as:
can not find xxx.lib
How do I check out why vs need to link xxx.lib? Is there a trace log? My project have not use boost.regex, but vs report a error says can not find regex.lib. So I want to find out which part of code refer to regex
LNK error: LIBCMT.lib: xxx was already defined in LIBCMTD.lib
How do I check why vs also link yyy.lib even this is a debug build? I have 2 projects, they link to same libs, all libs and project itself was /MTd. But one of them will report above error, I think it shouldn't link LIBCMT.lib because it is a release version lib, and another project is OK so the lib file was build correctly
VS can show the link trace?
1) Let's start with how the linker actually knows what to link with. Basically there are 2 categories:
Libraries specified in the project settings in the linker options as additional inputs
Libraries added in code with precompiler directive #pragma comment (generally the same thing as above but people have different tastes)
Otherwise you just get information about missing symbols but not the actual library they are from. What you can do to help is under visual studio linker options set Show Progress to For Libraries Searched (or just /VERBOSE:LIB linker flag), that will actually show you what dependencies are added after each lib is loaded, this also helps with point 2) to see which library loads which run-time.
2) Already mentioned in 1) that you can make the linker show library load progress, otherwise if a dynamic C run-time is used in the external library you are linking against you could use Dependency Walker to examine the dependencies of the library and find if the C run-time dll that is needed is debug or release by 'd' suffix in the dll name. If the library is already linked with static run-time then I guess only the linker errors will warn you. But I think that most serious libraries are correctly packed and structured so that you will be able to tell which files contain the debug version and which the release. If the library has only release version, well than that's another story. But i mean still, you can reconfigure the Debug configuration of your project to actually link against the release run-time to satisfy the external library, of course this prevents some debugging features, debug heap, etc.
For the missing boost regex library problem, I think the cause is due to boost's default autolink behaviour. If you include one of the headers of some of the boost libraries (not all of them, but regex is one of them), then these will cause Visual Studio to automatically link against the library. It uses a special pragma of the form:
#pragma comment(lib, "regex")
This has the effect of automatically adding a flag to the linker command. However, it's only picked up during compilation and so you won't see it in the project properties. In the case of boost, the solution to this is quite simple - find boost/config/user.hpp and uncomment the line
#define BOOST_ALL_NO_LIB
This will turn off the autolink behaviour for all libraries. Alternatively you can use #define BOOST_REGEX_NO_LIB to change this just for the regex library.
To solve the second problem, you need to find out which library is linking against the release build. Try selecting all projects in the solution and open Properties -> C++ -> Code Generation. You will probably find that the Runtime Library setting will be blank (because the option is different for some of the libraries. Force it to the correct threaded/single-threaded Debug option and rebuild.

Identifying Needed Link Libraries

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.

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.

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.