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.
Related
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.
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.
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.
trying to compile some code i downloaded, i get link error LNK1104: cannot open file 'LIBCD.lib'. i cant find this file anywhere on my computer. what is it, and can i download it from somewhere? is there another way to get the code to work?
In my case, I only wrote "LIBCD.lib" in Configuration Properties -> Linker -> Input -> Ignore Specific Library
The first hit on Google for libcd says:
This file is the static library for the debug single threaded version
of the C runtime. Visual Studio 2005 no longer supports this version
of the C runtime: instead you need to use the multi-threaded version
(libcmtd.lib) or the dynamically linked (DLL) version (msvcrtd.lib).
To fix this problem you will need to change the makefile that comes
with GLUI to get it to use a different version of the library.
and some other things that might help you.
You can fix this from the project settings. You need to add the /NODEFAULTLIB to the linker settings:
core.2f.nodefaultlib.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/core.2f.nodefaultlib.asp
This option will make the linker ignore all the /DEFAULTLIB directives - this will remove the dependency on libcd.lib. Unfortunately it will remove all the other dependencies as well so you will need to explicitly add the libraries you do need (like glut32.lib etc.) as inputs to the linker.
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)