I recently updated my Visual Studio version to the latest (mostly because of an automatic update rather than me willingly doing so). This proceeded to break my compiler when linking in third party libraries that were built using 15.2 instead of the current version of 15.3. The error I'm seeing is:
"Library_Name_here.lib" was created with an older compiler than other objects; rebuild old objects and libraries
I am looking for either ideas for solutions to avoid a re-compile of these libraries, but if one does not exist, I am looking for a way to compile the libraries to be version agnostic to not have to keep recompiling every time that vs updates.
It is not a good idea to mix and match code (object files or static libraries) compiled by different versions of the compiler in the same binary.
To quote MSDN on that:
To avoid run-time errors that are difficult to detect and diagnose, we
recommend that you never statically link to binaries that were
compiled by using different versions of the compiler. Also, when you
upgrade an EXE or DLL project, make sure to upgrade the libraries that
it links to. If you're using CRT (C Runtime) or STL (Standard Template
Library) types, don't pass them between binaries (including DLLs) that
were compiled by using different versions of the compiler. For more
information, see Potential Errors Passing CRT Objects Across DLL
Boundaries.
The solution is therefore to recompile all third-party static libraries with the new compiler.
I also had issues few months ago when i upgraded VS2015 to VS2017 and one of my big project that i was running on visual studio 2015 stopped working. That project had several class libraries and external DLLs added.
So what I did was, Uninstalled the upgraded version of visual studio 2017 and re-installed the complete visual studio 2017 from MSDN website (selecting the default selection of features). And then i loaded my Project in VS2017 fresh copy and added the reference of all external libraries and it worked.
I suggest you to try the same
This is a shot in the dark, based on this other SO answer: Error C1047: Object file created with an older compiler than other objects
Recompile the other library without link time code generation enabled (/GL and /LTCG). With it enabled the library expects the linker to do most of the compiling, and you cannot expect one version of the compiler to finish the compiling another version started.
Do not disable it in your active project, as it improves performance significantly. Just in the library.
Major compiler versions may still require rebuilding the 3rd party library, but not minor.
You can do this from within VS2017. It allows you to use tool sets going all the way back to VS2008
See this for details!
https://blogs.msdn.microsoft.com/vcblog/2016/02/24/stuck-on-an-older-toolset-version-move-to-visual-studio-2015-without-upgrading-your-toolset/
Hope that helps!
Related
So, I know that Microsoft enhanced their toolsets such that there is compatibility between applications and libraries built with VS2015, VS2017 and VS2019.
However, I thought that this combination would fail:
C++ application (.exe) built with the toolset from VS2012 (VC11), linking at runtime with
shared library (.dll) containing C++ built with the toolset from VS2019
However, we have seen that this combination "seems" to work.
I am expecting that combination to fail, but cannot explain its success.
Anyone have any ideas on this?
The 'binary compatibility' covered on Microsoft Docs between VS 2015 Update 3, VS 2017, and VS 2019 is specifically around the Standard C++ Library and static library linkage. Historically different generations of toolsets would fail to link or would crash at runtime. To avoid the crash, VS added these symbols so you'd get an error at link time instead:
error LNK2038: mismatch detected for '_MSC_VER': value '1600' doesn't match value '1700' in CppFile1.obj
VS 2015 Update 3, VS 2017, and VS 2019 all use '1900' as the link stamp because they are designed and tested to work when mixed. Of course, it's important to note that the final link is expected to be against the newer CRT libs and linker (i.e. it's forward compatibility only). The link stamp is only pulled in when using C++ headers, not C headers or Win32 system headers.
For example, if you had a C++ library that had inline functions that worked on a std::vector in the class implementation, and the rest of the class was hosted in a DLL, historically this would fail if you built with different toolsets because the implementation of std::vector would use different binary layouts, etc. This was the key value of having this 'binary compatibility' policy between toolsets so it would be easier to use the newest toolset and keep the majority of your existing 3rd party libraries and tools.
C ABIs via import libraries has always worked across compiler versions. That is in large part why Win32 APIs and COM APIs are hosted in DLLs and use C ABIs. Otherwise, every release of the compiler toolset would require a new set of OS libraries. In theory you could successfully link a program with VS 2019 using the libraries shipped in one of the ancient Platform SDKs.
So it really depends on exactly what your exe is using. If it's just using C APIs, extern "C" linkage, and/or Win32 APIs it would work pretty much no matter what combination you used.
TL;DR: Dynamic Link Libraries that use C ABIs work across toolsets. Static libraries or libraries with C++ ABIs only work across toolsets in specific scenarios.
One more caveat here: Whole Program Optimization / Link-Time Code Generation static libraries are not compatible between toolsets.
Compiled couple of .dll's using visual studio 2015, and tried to deploy on some older windows 7 / 64 bit. Tried also to guess which dll's are needed for application to start and copied MSVCP140.DLL & VCRUNTIME140.DLL - but application could not load vs2015 dll. Started to analyze what is wrong - and dependency walker showed dependencies from following dll's:
API-MS-WIN-CRT-MATH-L1-1-0.DLL
API-MS-WIN-CRT-HEAP-L1-1-0.DLL
API-MS-WIN-CRT-CONVERT-L1-1-0.DLL
API-MS-WIN-CRT-STRING-L1-1-0.DLL
API-MS-WIN-CRT-STDIO-L1-1-0.DLL
API-MS-WIN-CRT-RUNTIME-L1-1-0.DLL
API-MS-WIN-CRT-FILESYSTEM-L1-1-0.DLL
API-MS-WIN-CRT-TIME-L1-1-0.DLL
This was especially surprising since to my best understanding CRT is responsible for starting dll/exe, it does not provide any higher level services.
Ok, tried to figure out how to get rid of them or at least to minimize.
Found one article:
https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/
It mentions about release static libraries - so I thought that I could link against them and get rid from *L1-1-0.DLL* dependency hell, but no matter what I have tried - I had no success. I've tried to link against libvcruntime.lib, libucrt.lib, libcmt.lib, tried to disable using linker option "/nodefaultlib:vcruntime.lib", and even tried to add include directory $(UniversalCRT_IncludePath), and also overriding some of define's as I have tried to guess they works - none of my attempts helped.
As an intermediate solution I've fall back to using Visual studio 2013, where CRT dll's are only two: msvcp120.dll, msvcr120.dll.
Of course you will probably recommend to install Visual studio 2015 run-times, but one of our requirement is to support standalone executable - which works without any installation - so additional installation is out of question for now.
Can you recommend me anything else than to wait Visual studio 2017 to arrive ?
No, you can't get rid of them, but I was able to statically-link to them by setting the
C/C++ > Code Generation > Runtime Library compiler option
For Debug: from /MDd to /MTd
For Release: from /MD to /MT
This removed all the API-MS-WIN-CRT-* and runtime dll references and caused all the CRT code to be statically linked.
Details on the new VS2015 Universal CRT (dynamic and static) are here:
https://msdn.microsoft.com/en-us/library/abx4dbyh.aspx
Note that the only other option is to compile with an older-compiler (like virus developers),
not newer, because Microsoft promises same UCRT-requirements for any newer compiler-version as well.
I too was fighting with statically linking a solution with multiple components/project library dependencies importing functions from various parts of the MSVCRT, UCRT and Kernel. The hope was the resulting EXE could be just copied around where it was needed (it was no product which would justify a full MSI installation).
After almost giving-up I found the best solution was the follow the guidelines hidden in the Universal C Runtime announcement, specifically:
We strongly recommend against static linking of the Visual C++
libraries, for both performance and serviceability reasons
Just remove all the "special" linker options you tried, drop-back to /MT|/MD (Multi-Threaded CRT DLL Release|Debug) runtime library choice and it works everywhere, e.g. newer Windows 10 workstations, 2012 R2 servers and Windows 7). Just install/redistribute MSVCRT (VC_Redist*.exe) and KB2999226 (UCRT via Windows Update) as Microsoft tell us to do, because as they also say:
The Universal CRT is a component of the Windows operating system. It
is included as a part of Windows 10, starting with the January
Technical Preview, and it is available for older versions of the
operating system via Windows Update.
So logically the only additional deployment dependency our C++ solutions add for the customer is the MSVCRT, because the UCRT should already be there on up-to-date/well maintained machines. Of course it adds a bit of uncertainty; you can't just copy the EXE and run on any machine, good or bad.
If you produce a decent deployment package like an MSI then it's straightforward to include when you have tools like WIX. Also to note is since the recent SDK you can include the 40-odd DLLs locally, but that doesn't satisfy the security update principle so I wouldn't do that.
This is really the only supported way to do it, see another example here. This article also suggests we link against "mincore_downlevel.lib" which is an important tip, crucial to whether you get these "api-ms-win*" missing DLL errors. For example:
Project SDK version set to 10, link with mincore.lib = Runs only on Windows 10, but not 8.1/2012 R2 or Windows 7/2008 R2 server.
Project SDK version set to 8.1, link with mincore.lib = Runs on both Windows 10 and 8.1/2012 R2 server, but not Windows 7/2008 R2 server.
Project SDK version set to 10, link with mincore_downlevel.lib = Runs on all!
In summary:
Do not link statically, leave the default DLL C runtimes selected in the project settings.
You don't need the old SDKs, can develop with the latest Windows 10 SDK, but you must link with "mincore_downlevel.lib" not "mincore.lib" if you want to support older Windows versions.
For ease of use, add this to your targetver.h or stdafx.h which also documents your choice (remove the other line):
// Libraries
#pragma comment(lib, "mincore.lib") // Lowest OS support is same as SDK
#pragma comment(lib, "mincore_downlevel.lib") // Support OS older than SDK
(Updated 11.10.2016).
It's possible to get rid of universal CRT by linking it statically, I'll get to it later on, but let's take
a look if you continue to use universal CRT as such.
According to article https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/ -
it's possible to launch your application using universal crt dll distributables from following folder:
C:\Program Files (x86)\Windows Kits\10\Redist\ucrt
There are 41 files totally in list with 1.8 Mb size in total. (example for 64-bit platform)
Of course it's not enough, you will need additionally vcruntime140.dll & msvcp140.dll coming from following folder:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.CRT
So after that you will ship totally 43 additional dll's besides your application.
It's also possible to statically compile ucrt library inside your application after which you will not need 43 dll's -
but whether static link will for after linking or not - depends on your application - how many dll's and which api's are in use.
Generally after ucrt gets linked into two different dll's they don't necessarily share same globals with each other - which can results in errors.
You need to link against vcruntime.lib / msvcrt.lib, but it's not sufficient - there are extra _VCRTIMP= and _ACRTIMP=
defines which needs to be disabled from pulling functions from ucrt.
If you're using premake5 you can configure your project like this:
defines { "_VCRTIMP="}
linkoptions { "/nodefaultlib:vcruntime.lib" }
links { "libvcruntime.lib" }
followed by:
defines { "_ACRTIMP="}
linkoptions { "/nodefaultlib:msvcrt.lib" }
links { "libcmt.lib" }
Defines are not documented by Microsoft - so it's possible that it's subject to change in future.
Besides your own projects, you will need to re-compile all static libraries which are in use in your projects.
As for boost libraries - I've managed to compile boost as well, using b2.exe boostrapper
boost>call b2 threading=multi toolset=msvc-14.0 address-model=64 --stagedir=release_64bit --build-dir=intermediate_64but release link=static,shared --with-atomic --with-thread --with-date_time --with-filesystem define=_VCRTIMP= define=_ACRTIMP=
When troubleshooting linking problems - notice that unresolved __imp* function names from because of dllimport keyword usage -
and if you link against libvcruntime.lib, you should not have any __imp* references.
I was too struggled a lot finding out the run time DLLs required to run an application which was built in Visual Studio 2015.
Here I found the following things which allow VS-2015 built application to run.
Download the redistributable from https://www.microsoft.com/en-us/download/details.aspx?id=52685
Place the msvcp140d.dll, vccorlib140d.dll, vcruntime140d.dll & ucrtbased.dll.
Note : Place the dlls versions according to your system processor's architecture(x86, x64..).
Setting: Configuration Properties - Advanced - Use of MFC - "Use MFC in a Static Library" worked for me (with a console application - not a MFC/ATL application per-se).
If you're not trying to replace the Runtime with your own then it doesn't matter whether
You have Runtime Typing enabled/disabled
You have C++ Exceptions enabled/disabled
Whether you have the Runtime Library set to Multithreaded DLL or not (setting it to non-DLL is still building it into your binary)
The only thing you need to ensure is that you don't use any of its capabilities and Visual Studio automatically doesn't link to it. Ie. No asserts, no calls to anything in string.h or stdio.h, nothing. Anything the compiler can replace with its own intrinsics tho is ok, as are compiler checks like static_assert.
I have made a small game which I need to take in to a school to carry out some testing.
Unfortunately, being a school system, I will need to package all DLLs not already installed so that it will run. Installing anything on the computers is out of the question. When I went down a few days ago I noticed that the application would not start up due to a missing d3dx9_43.dll file.
I have statically linked the libraries I have used and am confused as to why this wasn't included. I referenced all the Direct3D 9 libraries I used (or so I thought).
Can anyone help me out?
I am using Visual Studio C++ 2010 and used Direct3D 9.
The only option that abides by the license is to install the redistributable package.
Earlier versions of D3DX did support static linking, but for reasons of security MS changed the rules to ban static linking. They wanted to be able to service these DLLs through WIndows Update and that's only possible if they are installed using the official redistributable package.
One possible option for you is to see if you can avoid linking to D3DX. It may be that you use a small enough footprint of that library that you can bypass it.
It's supposed to be done by including the DirectX 9.0 Redistributable package inside the application installer, but since you can't install anything you either have to ship all the dll with your executable (which is against the SDK license) or statically link against the DirectX runtime (which is also probably not allowed).
Statically link against the DirectX runtime is not a good idea and is not as trivial as it seems, I'm not even sure it's possibe but you must have to have the actual static libraries (not the one that are actually linked by themselves against the dll).
So the easiest solution would be to keep all the needed DLL with the exe, if you're worried about missing one dependency you can use the Dependency Walker. Note that this solution is not allowed by the SDK license and cannot be used to actually distribute an application to the final users.
I know that if I link my c++ program to a dynamic library (DLL) that was built with a different version of Visual Studio, it won't work because of the binary compatibility issue.
(I have experienced this with Boost library and VS 2005 and 2008)
But my question is: is this true for all versions of MSVS? Does this apply to static libraries(LIB) as well? Is this an issue with GCC & Linux as well? and finally how about linking in VS to a DLL built with MinGW?
By the way aside from cross-platform or cross-compiler, why can't two version of the same compiler(VS) be compatibile?
Hi. I know that if I link my c++ program to a dynamic library (DLL) that was built with a different version of Visual Studio, it won't work because of the binary compatibility issue. (I have experienced this with Boost library and VS 2005 and 2008)
I do not remember ever seeing MS changing the ABI, so technically different versions of the compiler will produce the same output (given the same flags (see below)).
Therefore I don't think this is not incompatibilities in Dev Studio but changes in Boost.
Different versions of boost are not backwards compatible (in binary, source they are backward compatible).
But my question is: is this true for all versions of MSVS?
I don't believe there is a problem. Now if you use different flags you can make the object files incompatible. This is why debug/release binaries are built into separate directories and linked against different versions of the standard run-time.
Does this apply to static libraries(LIB) as well?
You must link against the correct static library. But once the static library is in your code it is stuck there all resolved names will not be re-resolved at a later date.
Is this an issue with GCC & Linux as well?
Yes. GCC has broken backwards compatability in the ABI a couple of times (several on purpose (some by mistake)). This is not a real issue as on Linux code is usually distributed as source and you compile it on your platform and it will work.
and finally how about linking in VS to a DLL built with MinGW?
Sorry I don't know.
By the way aside from cross-platform or cross-compiler, why can't two version of the same compiler(VS) be compatibile?
Well fully optimized code objects may be compressed more thus alignment is different. Other compiler flags may affect the way code is generated that is incompatible with other binary objects (changing the way functions are called (all parameters on the stack or some parameters in registers)). Technically only objects compiled with exactly the same flags should be linked together (technically it is a bit looser than that as a lot of flags don't affect the binary compatibility).
Note some libraries are released with multiple versions of the same library that are compiled in different ways. You usually distinguish the library by the extension on the end. At my last job we used the following convention.
libASR.dll // A Sincgle threaded Relase version lib
libASD.dll // A Single threaded Debug version
libAMR.dll // A Multi threaded Release version
libAMD.dll // A Multi threaded Debug version
If properly built, DLLs should be programming-language and version neutral. You can link to DLLs built with VB, C, C++, etc.
You can use dependency walker to examine the exported functions in the dll.
To answer part of your question, GCC/Linux does not have this problem. At least, not as often. libstdc++ and glibc are the standard C++/C libraries on GNU systems, and the authors of those libraries go to efforts to avoid breaking compatibility. glibc is pretty much always backward compatible, but libstdc++ has broken ABI several times in the past and probably will again in the future.
It is very difficult to write stable ABIs in C++ compared to C, because the automatic features in C++ take away some of the control you need to maintain an ABI. Especially once you get into templates and inline functions, where some of the code gets embedded in your application rather than staying contained in the shared library. That means that the object's structure can't ever change without requiring a recompilation of the application.
In practice, it isn't a huge deal on Windows. It would be fantastic if Microsoft just made the MSI installer know how to grab Microsoft-provided DLLs from Windows Update when an app is installed that needs them, but simply adding the redistributable to an InnoSetup-generated installer works well enough.
it's been a long while since I've used VS 2010 and C++, and as I'm getting back to using it, I'm running into the same problems that plagued me last year: the exe's that I compile do not run well on older machines that do not have the correct C++ runtimes. I do not even know what link to give them, and I told them to install this after they had an error that said "The program can't start because MSVCR100.dll is missing from your computer. Try Reinstalling the program to fix this problem. Click OK to close the application."). So I went in and set the code generation to /MT and disabled quite a few options, and tried messing around with lots of options, but still the same result.
My question is: Is there a list of complete VS 2010 C++ distributables that I can just give and tell them to install so all of the C++ programs I compile on my VS 2010 will work on Windows XP, or even better, a way to general a standalone exe that contains all it needs to work, and does not rely on DLLs? I'm thinking like linking to a library that has everything the exe references. If it helps, I'm building for both x64 and x86.
P.S. What's up with the manifest file, should I include it or not?
The easiest thing to do is to just install the VC++ Redistributable Package. It has both x86 and x64 versions.
Firstly, before I actually give you the detail:
Warning
If you do this, things will be bad for two reasons:
If there are security or other bugs in the MSVC runtimes, and you take this approach, they're baked into your app which means you need to re-distribute. DLLs are preferred because theoretically people use system update which means any errors get fixed.
Everything else you compile into your exe also needs to do this. If you don't, you end up with two versions of the code and whatever you're using won't link.
One possible solution is to bake the MSVC runtime into your application, by using the cl.exe option (C/C++ compiler settings) /MT which means multi-threaded version of the C/C++ runtime linked statically. As I said, if you try to link against something that is linked itself dynamically to the runtime, you're going to end up in a mess. Also, as I said, this represents an additional security risk factor, so bear that in mind.
The other options are to write an installer that can either download the appropriate runtime, or include the DLL needed.
If you're using some feature of the runtime that exceeds a certain version of Windows (generic statement, but it does happen) then you should be able to use the Windows SDK to target various versions of Windows using appropriate C runtimes.
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=a7b7a05e-6de6-4d3a-a423-37bf0912db84
google text: visual studio c++ redist
Do not statically link to the runtime; specifically don't do so if you're using any kind of dll for other purposes. It introduces all kinds of bogus problems wrt heap management that you probably don't want to mess with.
Open the properties dialog for your project and select Configuration Properties | C/C++ | Code Generation. The default setting is Multi-threaded DLL. Change that to Multi-threaded and you'll be building and .EXE with the run-time statically linked in. Don't forget to do the same for the debug version.
If you're using MFC or ATL, you will need to navigate to Configuration Properties | General and set "Use of MFC" or "Use of ATL" to link statically as well.
NB: If you link the runtime statically, you must make sure that any other library you're linking in also links it in statically. Otherwise you'll wind up with two copies of the runtime in memory, each with its own heap and bad things will happen when code using one runtime tries to free an object allocated by the other runtime.
This previous answer should hold true for VS2010. I still build with VS2005, but all my apps use the static CRT for the sole reason of being able to run across old and newer machines alike.