MS Visual Studio 2019, C++, Librarian tool aka LIB.EXE
I have large "super" library combined from 20+ separate libraries and want to rebuild only one of them.
Tried to set super.lib as additional input library
/OUT:"super2.lib" /LTCG "super.lib" /MACHINE:X64 /NOLOGO
but LIB.EXE ignores second (new) definition of objects already defined in super.lib
warning LNK4006: "public: class NNN already defined in super.lib(className.obj); second definition ignored
Related
Synopsis:
Managed (/clr) C++ project (.dll) statically links native C++ library (which is compiled with /MD). Static library is big and references a lot of other libraries, but functionality used by managed C++ code is trivial and shouldn't pull in any additional dependencies.
Problems:
linking fails with LNK2001 and LNK2019 mentioning symbols that code definitely does not depend on
even if I add required dependencies, switching toolset (e.g. migrating from VS2017 to VS2019) causes errors to come back (this time mentioning other dependencies)
What happens:
Apparently, /clr switch causes compiler to treat inlined functions differently -- they are no longer get embedded into .obj files (as "weak symbols"), instead they get referenced in the table of imports. This means linker has to find things like:
"public: virtual char const * __cdecl std::exception::what(void)const " (?what#exception#std##UEBAPEBDXZ)
... which it does and (since CRT libraries are DEFAULTLIB and therefore are used last) typically it finds it in other library (namely, in aforementioned static native lib). So, it finds first .obj file in static lib that contains std::exception::what() and pulls it in -- meaning we now depend on everything said .obj depends. This explains problem #1 (bogus linker errors).
Now, if you compile your static lib with another toolset -- obj files can be stored in different order, causing problem #2.
To reproduce the issue you can use this code (make sure managed project links static lib):
//--------------------
// statlib.cpp
//
#include <exception>
void this_is_a_trap() { throw std::exception(); }
extern int bar();
int foo() { return bar(); }
//--------------------
// clrdll.cpp (managed code)
//
#include <exception>
__declspec(dllexport) void oops()
{
throw std::exception();
}
If you link with /VERBOSE flag you'll see smth like:
1> Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64\oleaut32.lib:
1> Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64\uuid.lib:
1> Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64\odbc32.lib:
1> Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64\odbccp32.lib:
1> Searching C:\tst\x64\Release\statlib.lib:
1> Found "public: virtual char const * __cdecl std::exception::what(void)const " (?what#exception#std##UEBAPEBDXZ)
1> Referenced in clrdll.obj
1> Loaded statlib.lib(statlib.obj) <-- Now we depend on `bar()`
Question
What is the best way to deal with this?
Notes:
adding msvcrt.lib to linker inputs (before other static libs) helps, but not always -- certain symbols (such as std::bad_weak_ptr::what() aren't present in msvcrt.lib)
this problem is the root cause for this SO post
In mixed (/clr and native) code std::exception::what() (and other similar symbols) do get inlined, but these definitions are managed (not native). Which normally is not an issue, but native code refers to native definition via std::exception's vtable. Normally, such reference (once it fails to resolve) gets redirected to managed definition (which is generated, as stated above), but in this case -- native definition is found in another object (random object from native static library) before "redirection" kicks in, causing that object to be referenced.
See details here. MS is figuring out a best way to deal with this.
I have the following projects in a Visual Studio 2012 solution:
Native (no /clr) static lib project, compiled with /ZI for Edit And Continue.
C++/CLI DLL project, which references the above static lib.
The C++/CLI project builds with the following warning:
warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/OPT:LBR' specification
If /OPT:NOLBR is added to the linker options of the C++/CLI project, the warning becomes:
warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/INCREMENTAL:NO' specification
Any attempt to change the incremental linkage setting of the C++/CLI project doesn't change the warning (C++/CLI projects never link incrementally anyway).
I understand that I won't be able to use Edit And Continue in the C++/CLI project, because this is not supported. Indeed, changing /ZI to /Zi (disabling Edit And Continue) in the static lib project eliminates the warning, but I can't do that - other non-CLR consumers of that lib need to use Edit And Continue.
How can I get rid of this warning without disabling Edit And Continue in the static lib (and hopefully without maintaining separate build configuration for native and CLR users of the static lib)? I mean, is there any way to ask the linker to ignore the /EDITANDCONTINUE directive that is embedded in the referenced static lib (much in the same way that /NODEFAULTLIB can ignore /DEFAULTLIB directives)?
I have created a minimal VS solution that reproduces the described issue.
due to '/OPT:LBR' specification
This is a nonsense error message, that linker option is only effective for ARM binaries. This is simply a bug, using /OPT:NOLBR takes the sting out of it and you get the real warning.
Which is accurate enough, although it doesn't win any prizes either, you asked for Edit+Continue support in your static lib project but that is not available for a mixed-mode .NET assembly. The undocumented /IGNORE linker option is available to suppress warning messages but this one is ranked as an "unignorable warning" by Chapell.
You'll have to live with this warning as long as you don't want to change your static lib project. It is completely benign. You won't get it when you recompile it with /Zi.
There is no other way than to
disable "Edit And Continue" in the library
create a separate build configuration for "Edit And Continue (/ZI)" and "Program Database (/Zi)"
Of course: I am not aware that there is a predefined macro to determine between /ZI and /Zi... so you need to define your own preprocessor directive to distinguish between these configurations...
I had the same problem and found the only solution is to delete the .vcxproj and .sln files of the project and create the project again.
But then in an old copy of the same project I found a better solution: I changed in the projectname.vcxproj file the line
Profile true
to
Profile false
and LNK4075 warnings disappeared.
It had been the Visual Studio Profiler who had caused the troubles.
I've got a 3d party static library built with some older version of MSVC, and I successfully link it to my application in MSVC10 (VisualStudio2010). Now I upgraded to MSVC11, and I'm unable to link it:
2>LINK : fatal error C1047: The object or library file 'MyLib.lib' was
created with an older compiler than other objects; rebuild old objects
and libraries
I guess this happens because the lib was compiled with /GL option, so the object files don't really contain COFF, but some intermediate format.
I don't have the library source-code to re-compile, and I don't want to make a dll out of it to link dynamically.
Is there a way - maybe some undocumented trick - to "re-compile" these obj's to COFF and eventually link them to MSVC11 application?
Even if this was possible, you don't want to do this: linking object files that are built against different versions of the CRT usually ends in tears. More specifically, if two such object files both use the C++ Standard Library, it is all but certain that you will violate the One Definition Rule (ODR).
If you cannot rebuild the module using Visual C++ 2012, then you should encapsulate it within a dynamic library, built with Visual C++ 2010, and avoid using any C++ Standard Library types in the interface of that DLL.
By default, Visual Studio compiles a project to use the Multi Threaded DLL, found in the Visual Studio runtime. I want to compile my program using only /MT instead of /MD. Granted, that most systems already have this installed, and it's also available as a re-distributable.
When I change /MD to /MT, I get an error:
MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _free already defined in LIBCMT.lib(free.obj)
And four or five similar errors.
To try and fix this I removed LIBCMT.LIB from the default libraries.
I then get the error:
libcpmt.lib(_tolower.obj) : error LNK2019: unresolved external symbol __calloc_crt referenced in function __Getctype
Removing MSVCRTD.lib from the default list leads to similar errors?
It should be noted that:
-This is an OpenGL project, using the glfw library.
-I am using the SOIL image library by lonesock for texture loading.
Without any further precise information, I would say your first problem is that you're somehow mixing release and debug versions of libraries. MSVCRTD.lib is the debug version of MSVCRT.lib.
Either you have some debug settings hanging around in your own projects, or you're linking against debug versions of libraries you're using.
Never ever mix debug and release versions. If you're lucky you get an error like this. In some rare situations all magically seems to work until it doesn't.
I have C++ source code (xyz.cpp) for static library called libxyz.lib, in this xyz.cpp I call some functions p, q, r which are part of other static library called libabc.lib.
Now when I compile code (xyz.cpp) i want that object code for libabc.lib gets included inside (libxyz.lib)
Is this possible?
Or do I have to ship both libxyz.lib & libabc.lib to user who wants to use them ?
I am using Visual Studio C++ 2005
Thank you in advance
AFAIK you can only achieve that by turning xyz into a DLL, but in that case you would still be shipping xyz.dll + a xyz.lib file + required headers. When you build a static lib, other static libraries are not linked in: the .lib file only contains the object code of xyz functions. See http://msdn.microsoft.com/en-us/library/ms235627(v=vs.80).aspx
If building from the command line, you must build the program in two steps. First, compile the code using Cl.exe with the /c compiler option (cl /c /EHsc MathFuncsLib.cpp). This will create an object file named MathFuncsLib.obj. For more information, see /c (Compile Without Linking). Second, link the code using the Library Manager Lib.exe (lib MathFuncsLib.obj). This will create the static library MathFuncsLib.lib. For more information on the Library Manager, see LIB Reference.