How to prevent double inclusion of a .lib when inheriting dependencies? - c++

I'm working to a Visual C++ 2008 project which needs two libraries (A and B), both of them are compiled using a a particular .lib (C). When I compile my project I'm asked for C again, and thus I specify it in the additional libraries. Then everything goes ok until the linking phase, where I get errors for external symbols which are defined more than once. Is there a way to exclude them from the linking?
Thank you
Tommaso

This sounds like you're adding two different versions of this library (Debug/Release, MT/ST etc.). Otherwise the linker would just ignore the second one.

I resolved the problem by specifying /NODEFAULTLIB:library in the linker options. I don't know what this should mean ... Visual Studio suggested it.

Related

Why do we reference C++ projects in Visual Studio 2013?

Why must we reference projects, for C++, in Visual Studio 2013 when we intend to use a method from a referenced project? I'm confused because we use the #include preprocessor directive, which is copying & pasting the code we intend to use into the same header file which is still above/before the method that is actually using it.
Basically, even if I have all the projects in the same solution file, and the header files are correctly finding each other (intellisense doesn't complain/ proper linting occurs), I still get linker errors. But even if referencing projects is purely about resolving linker errors, if intellisense can peek/show definition to the code I am importing from a separate project, doesn't that mean Visual Studio also knows which project I'm linking against?
There must be a reason why, we both #include and reference the included projects even now in VS 2013. Could someone help explain why?
"There must be a reason why, we both #include and reference the included projects even now in VS 2013. Could someone help explain why?"
Including header files allows to use the declarations (of functions, classes or structs) from there. But to get a completely executable program there's more necessary:
The compiler needs to know where to get the #include'd header files from
The compiled source code from a different project needs to be linked to the final artifact
The linker needs to know where to get the linked libraries from
If you have header only libraries, the least 2 points won't be relevant, but Visual Studio would still need the project reference for resolving the header file pathes.
For Visual Studio in particular there's also the #import directive available, that makes it easier to link against shared libraries (and keep those as standalone projects, instaead of referenced ones from the same solution).
No, it is computationally infeasible for a linker to magically guess which definitions you want to link into your project at any given time. It's a good thing that it does not attempt to do so.
The C/C++ compiling process has two steps:
compile (.c/.cpp) source code into a lib (requires external .h files)
link all necessary lib files into an executable (requires both the own compiled lib files and external lib files. After all, the external .h file only contains the definition)

MT / MD mismatch when compiling cryptopp despite no library dependencies

I'm currently trying to compile a static 64 bit version of cryptopp (more precisely, the cryptlib VS project) using MS Visual Studio 2013 on a Windows 8.1 machine. Since it is a static release build, I've set the Runtime Library to Multithreaded (/MT).
However the linker throws several of the following errors:
error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease' in adhoc.obj
In most of the similar cases I've found here and on google, this was caused by one library setting /MT and another one setting /MD. The weird thing about this case is that the linker does not include any libraries (except maybe some Visual-Studio-internal magic) and there are no additional include directories. The linker command line assembles as:
/OUT:"build\x64\static_release\cryptlib64.lib" /LTCG /MACHINE:X64 /NOLOGO
In the project file, I couldn't find any other <RuntimeLibrary> settings except for those on project level so I'd assume there is no .cpp file which has a /MD switch.
To sum it up, this means my library defines /MT, but something which is used by crytlib internally seems having /MD defined. Is there a way to find out what object/cpp/define/library/whatever has that switch defined?
This linker diagnostic is a 100% accurate hint that you are in fact linking .obj or .lib files that were built wrong. Almost always .lib files that you don't know about because you didn't have to explicitly list them as Additional Dependencies. MSVC++ makes it pretty easy to specify link dependencies without having to use the setting, like using Add Reference or #pragma comment(lib, "yadayada.lib") in a source code file. Very convenient of course, but not so visible when you are trying to troubleshoot linker errors like this.
It is easily diagnosable however, the linker has an option to show you what it is actually linking. Use Project + Properties, Linker, Command Line and add the /VERBOSE option. The linker now gets very chatty to the Output window, showing you every .lib file it loads and what symbols it uses from the .lib file.
The .lib name should be enough of a hint to know where to start looking, you ought to know the #include from there. Whether you can really build with /MT is still up in the air, if it is an import library of a DLL then the odds dwindle rapidly. Avoid forcing it, having more than one copy of the CRT in a process is fraught with trouble.
Cleaning the solution and then rebuilding might help. It seems the linker is still trying to use the old object files (before you applied /MT).
The weird thing about this case is that the linker does not include any libraries (except maybe some Visual-Studio-internal magic)
There is a good chance that is where its coming from if you are certian its not something in your gear.
If Dynamic C++ Runtime Linking is an option for you, then you might consider using it for Crypto++. To ease the troubles of converting Crypto++ to Visual Studio 2010 (and above) and converting to /MD and /MDd, you can use vs2010-dynamic.zip. Just unpack it over top of the existing Crypto++ sources.
Also see Mismatch Detected for 'RuntimeLibrary' and Crypto++ on Stack Overflow.

Visual Studio "object file does not define any previously undefined symbols"

While using C++ in Visual Studio 2013, I've come across a really weird warning/bug thing.
I have a static library and a console application.
Static library imports 4 3rd party .lib files, and their headers.
Console application imports the static library and the headers of the original 4 .lib files, so that I can use the code from the original 4 .libs and my .lib.
(I think this is the right setup in this situation, if there is a better way, do tell!)
However, when I build the static library, I get a warning: "LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library" for each .lib imported.
But where is it getting the code if not from the libraries? If I remove the .libs from being imported, the build fails stating that it needs them! I don't know what to do in a situation like this. I would be happy enough to just leave the .libs being imported as is and ignore the warnings, but when I try to disable them (Under disable specific warning, "4221", in the compiler options), the warnings are not disabled!
Edit: The 4 3rd party .libs are standalone - they do not use each other's code so I do need to import all of them.
I am truly at a loss - any advice would be much appreciated.
I found a way of disabling the warnings using /ignore: on the linker command line, but I'm still confused as to why the linker gave the warnings in the first place, when removing the library as input caused multiple "unresolved external symbol" errors.
Oh well, problem (sorta) solved.

VS2010 static linking issue

my company has recently upgraded from VS2005 to VS2010. We have a huge project which uses a lot of modules which are being linked statically into the exe. But there seem to be some issues with linking in VS2010.
To explain our problem, we've built a minimal example project which is composed as shown on this graphic:
There is an application using one function from library A. Library A calls one function of each library B and library C. Those two libraries call a function provided by library D.
For Exe 1 under Framework and References we set everything to false except for Link Library Dependencies which is set to true. The only reference added is linking to library A. For each of the libraries all the settings are set to false. Library A gets references to only B and C, as well as those two getting references to D only. Library D has no references.
When building the application it works without problems. The application notices that library A is using library B and C which are using library D, so it knows it has to link those libraries, too. The libs are linked into the exe without problems.
Now we change something in, let's say, library D. Just a little difference, only one letter. Now we try to build the application again, it notices the change and re-compiles library D, but: It doesn't link to it anymore. The result are linking errors in library B and C, because they use library D. We have to run Rebuild first, in order to force the complete building and then everything is linked again.
This happens for both the minimal example as well as for our main project. Of course, we can add each of the libraries as additional dependency for the exe but it would be nice if it would work just like it does when building the project for the first time and continue to work after changes in the code. We noticed that when setting Use Library Dependency Inputs to true, that it works again, but then it doesn't link the *.lib files but the *.obj files which is not what we want of course.
Has anyone made similar experiences or has anyone a solution for this issue? Is this a buggy behavior of VS2010?
TIA.
p.s.: All libraries and executables are native C++.
Edit: (Workaround taken from this site)
In the file %ProgramsFile%\MSBuild\Microsoft.cpp\v4.0\Microsoft.CPPBuild.Targets there is a line
<Target Name="GetResolvedLinkLibs" Returns="#(LibFullPath)" DependsOnTargets="$(CommonBuildOnlyTargets)">
If you change that line to
<Target Name="GetResolvedLinkLibs" Returns="#(LibFullPath)" DependsOnTargets="$(CommonBuildOnlyTargets);ResolvedLinkLib">
the linking works properly and all needed libs are linked to implicitly. The linker output not only shows lib_a.lib but also all other chained libs, lib_b, lib_c, lib_d without having them added manually as dependencies to the exe.
This seems to be more a workaround then a solution, maybe there is a proper way to achieve implicit linking.
Have a look at following links:
Visual Studio 2010 not autolinking static libraries from projects that are dependencies as it should be supposed to
Behavior of Link Library Dependencies in 2010
Unresolved Externals When Build a VC++ Project with Chained Static Lib Dependencies
Flexible Project-to-Project References
I only know that I had such similar situations because of wrong using of Libraries with same name but with different architecture. lets say, I have an Dll (lets call it mydll.dll) for x86 and will import it into my project it will work. If I will do the same with x64 dll (same name mydll.dll) it will work.
But if I want to include both libraries it is not allowed to only rename it into mydllx86.dll / mydllx64.dll. I CAN include now both libraries into Visual Studio. But when compiling it or restarting visual studio, one of both libraries will be unaccessable anymore.
In this case I perhaps it helps to have a look into library architecture and used namespaces / Api names.
Regards
You are pretty lost in that dialog if you are tinkering with Framework and References, those are settings that only apply to managed code. The term "reference" only applies to .NET assemblies. The linker doesn't support storing compiled managed code in a .lib. I'll work from the assumption that you actually are changing linker settings. If you make a change in library D then you also have to change its header file. Which in itself will be enough to get B and C rebuilt since one or more of their source code files should #include that header.
The only thing that Link Library Dependencies does is automatically make a .lib a dependency, same thing as Linker + Input, Additional Dependency setting. That however requires you to explicitly set the project dependencies. Right-click the B project, click Project Dependencies and tick D. Repeat for C. Repeat for A and tick B and C. Repeat for EXE and tick A.
This is rarely what you want, it makes the D library embedded into the B and C libraries. And B and C get embedded in A. The EXE now only has a dependency on A. It works, but it makes the .lib files unnecessarily beefy. And you have the problem you describe if you don't set the project dependencies properly, a rebuild of D doesn't cause it B and C to be relinked.
What you should do is not set dependencies between the .libs, they don't have any. Each can be built without the other .libs being present. A .lib is nothing but a bag of .obj files. All that's required is that you make all 4 .lib projects dependencies of the EXE project. That makes sure that they are built before the linker tries to link the EXE.
We starting seeing this issue again after moving to Visual Studio 2015 (and also in VS2017). The problem only seems to exist in the following configuration:
Project (EXE)
--> Static Library A (Reference)
--> Static Library B (Specified in Linker->Additional Dependencies)
--> Static Library C (Not in solution, specified in Linker->Additional Dependencies)
There are several other projects in the solution that use A and B. When something in project B or C changes, many of these projects give LNK4099 warnings.
In our case, the solution is to use the following:
Code Generation > Output Files > Program Database File Name: $(TargetDir)$(TargetName).pdb
Librarian > General > Output File: $(TargetDir)$(TargetName)$(TargetExt)
$(TargetDir) uses an absolute path versus the default $(OutDir) which in our case was relative. It seems that the correct path gets lost with multiple levels of indirection.
One interesting thing is if you switch the number of compile threads to 1, it doesn't appear to happen (maybe some kind of race condition within Visual Studio?).

Linking static libraries in visual studio with composite dependencies

Suppose you have two static libraries A and B such that A references methods from B. Is it possible to statically link an executable to A and B such that there are not unresolved symbols in B referenced by A?
Here is my situation:
When I try to link everything up that way in Visual Studio 2010, there are unresolved symbols between A and B.. but not between the application and A. The symbols it complains about have the __imp prefix (which do not, and should not, exist in B's DUMPBIN). Why is it looking for symbols with the __imp prefix even though none of the libs are built as DLL's and I have included all of the required "Additional Library Dependencies/Directories" in all of the projects? Also, everything is built with the exact same compiler.
EDIT: It may be helpful to know that if library B is built as a DLL with an import library instead of a static library, everything will link up correctly.
EDIT: I am almost certain it is not a preprocessor condition causing a declspec() or something, because there are no linker errors when the App uses B.. just when A uses B.
ANSWER: Both Edwin and JimR are correct, there was actually a macro being used in a header causing a declspec, but I was too stubborn to notice it when they first mentioned that possibility. Thanks guys for your patience.
the dependecies should not matter ! they may even be circular ,like A refs B and B refs A. It sounds to me (since you get linker errors) that either you don't have headerfiles for those libs (do you declare funcs from A in B by hand or funcs from B in A) or the headerfiles compile differently in your program and in your libs (due to some #define or compiler option). Do you use the same calling conventions in both prog and libs ?
I do not have MSVS 2010 to look at, so take this with a grain of salt.
If the symbols have imp in the name, that means either there's a declspec(dllimport) floating around somewhere, a (possibly embedded in the code) compiler switch forcing A to see B as a DLL or you're linking old stuff and not what's currently being produced by the build process.
Was the project you're using imported from an older version of MSVS? I had a similar problem with a poorly managed project that was imported into MSVS 2008 a few years ago...
Either way, check A's build environment carefully and make sure you look for pragmas that embed compiler/linker switches.
Since your used lib B as a DLL before is it possible that when you build lib A your lib B was still a DLL and when you changed lib to library you forgot to rebuild A.