To repeat: I'm looking for ABI compatibility between libraries of the same Visual-C++ version!
We want to mix and match some internal C++ DLLs from different teams - built at different times with different project files. Because of long build times, we exactly want to avoid large monolithic builds where each team re-compiles the source code of another team's library.
When consuming C++ DLLs with C++ interfaces it is rather clear that you only can do this if all DLLs are compiled with the same compiler / Visual Studio version.
What is not readily apparent to me is what, exactly needs to be the same to get ABI compatibility.
- Obviously debug (
_DEBUG
) and release (NDEBUG
) cannot be mixed -- but that's also apparent from the fact that these link to different versions of the shared runtime.
- Do you need the exact same compiler version, or is it sufficient that the resulting DLL links to the same shared C++ runtime -- that is, basically to the same redistributable? (I think static doesn't fly when passing full C++ objects around)
- Is there a documented list of compiler (and linker) options that need to be the same for two C++ DLLs of the same vc++ version to be compatible?
- For example, is the same
/O
switch necessary - does the optimization level affect ABI compatibility´? (I'm pretty sure not.)
- Or do both version have to use the same
/EH
switch?
- Or
/volatile:ms|iso
... ?
Essentially, I'd like to come up with a set of (meta-)data to associate with a Visual-C++ DLL that describes it's ABI compatibility.
If differences exist, my focus is on VS2015 only at the moment.
Have been thinking this through the last days, and what I did do was to try to see if some use-cases exists where devs have already needed to categorize their C++ build to make sure binaries are compatible.
One such place is the Native Packages from nuget. So I looked at one package there, specifically the cpprestsdk:
The binaries in the downloadable package as split like this:
native\v120\windesktop\msvcstl\dyn\rt-dyn\x64\Release\
^ ^ ^ ^ ^
VS version | not sure | uses cpp-runtime dynamically
| lib itself dynamic (as opposed to static)
or WinXP or WinApp(WinRT?)
I pulled this out from this example, because I couldn't find any other docs. I also know that the boost binaries build directory is separated in a similar way.
So, to get to a list of meta data to identify the ABI compatibility, I can preliminarily list the following:
- VC version (that is, the version of the C and CPP runtime libraries used)
- one point here is that e.g.
vc140
should be enough nowadays - given how the CRT is linked in, all possible bugfixes to the versioned CRT components must be ABI compatible anyway, so it shouldn't matter which version a given precompiled library was built with.
- pure native | managed (/CLI) | WinRT
- how the CRT is consumed (statically / dynamically)
- bitness / platform (Win32, x64, ARM, etc.)
- Release or Debug version (i.e. which version of the CRT we link to)
- plus:
_ITERATOR_DEBUG_LEVEL
... if everyone goes with the defaults, fine, if a project does not, it must declare so
Additionally my best guess as to the following items:
/O
must not matter - we constantly mix&match binaries with different optimization settings - specifically, this is even working for object files within the same binary
/volatile
- since this is a code-gen thing, I have a hard time imagining how this could break an ABI
/EH
- except for the option to disable all exception, in which case you obviously can't call anything that throws, I'm pretty confident this is save from an ABI perspective: There are possible pitfalls here, but I think they can't really be categorized into ABI compat. (Maybe some complex callback chains could be said to be ABI incompatible, not sure)
Others:
- Default calling convention (
/G..
) : I think this would break at link time, when mangled export symbols and header declarations don't match up.
/Zc:wchar_t
- will break at link time (It's actually ABI compatible, but the symbols won't macth.)
- Enable RTTI (
/GR
) - not too sure 'bout this one - I never have worked with this disabled.