Hi, unfortunately you may need to be a little more specific. But I’ll try anyway.
Preferably the objects bundled into a static lib should not have been built in a way that requires any default lib, but some get added implicitly based on compiler flags.
Each (well most) of those object (COFF) files contains a .drectve
section which in turn contains hardcoded linker switches. These come in implicitly¹ or via something like #pragma comment(lib, ...)
. An example where this is useful is when OpenSSL requires certain DLLs and so the authors placed the names of the corresponding import libs so you don’t have to remember to do that on your linker line!
Now there are cases where /nodefaultlib
with the library name won’t work. For example if you have a Debug configuration and certain features turned on, your object files will proclaim to want certain symbol names which only exist in the debug runtime. So whatever you do an object file or static lib containing an object file requesting such a symbol cannot be linked with the Release runtime.
However, if we’re talking ordinary C runtime functions, they’re largely interchangeable. It’s just symbol names after all! Once you step into C++ territory you should diligently pair the correct configuration for all object files with the correct runtime. But even for the C case there could reasonably be differences between Release/Debug, e.g. in the layout for structs that get passed into functions.
So by saying in your final linker invocation that you want the list of /nodefaultlib:...
you gave, you’re telling the linker to ignore respective/defaultlib:...
from the .drectve
section and just look out for the symbols.
To get this done in CMake, I think you’d do:
target_link_options(my_target PRIVATE "/nodefaultlib…")
Not sure how to do it from the command line.
This still may fail, but then quite frankly you’ll need to build your older OpenSSL in the respective configuration. Reasons why this fails includes something like the following inside the .drectve
section:
/FAILIFMISMATCH:"_ITERATOR_DEBUG_LEVEL=0"
This particular item gets inserted through #pragma detect_mismatch(...)
. The example from the explanation also clearly shows the purpose: #pragma detect_mismatch("myLib_version", "9")
. In fact such a mismatch can cause the LNK2038
you’re seeing. So you better be sure about what you’re doing if you opt for /nodefaultlib
.
Hah, the Possible causes and solutions section for LNK2038 even mentions:
Visual Studio defines the following symbols to prevent the linking of incompatible code, which can cause run-time errors or other unexpected behavior.
_MSC_VER
Indicates the major and minor version numbers of the Microsoft C++ compiler (MSVC) used to build an app or library. […]
_ITERATOR_DEBUG_LEVEL
Indicates the level of security and debugging features that are enabled in the C++ Standard Library. […]
RuntimeLibrary
Indicates the version of the C++ Standard Library and C runtime used by an app or library. […]
[…]
Ensure that the values of these symbols are consistent throughout the projects in your Visual Studio solution, and also that they’re consistent with code and libraries that your app links to.
¹ /nodefaultlib
(without any name) can be used to sidestep the implicit ones for the generated object files