I'm trying to build a C/C++ static library using visual studio 2005. Since the selection of the runtime library is a compile option, I am forced to build four variations of my library, one for each variation of the runtime library:
- /MT - static runtime library
- /MD - DLL runtime library
- /MTd - debug static runtime library
- /MDd - debug DLL runtime library
These are compiler options, not linker options. Coming from a Linux background, this seems strange. Do the different runtime libraries have different calling conventions or something? Why can't the different runtime libraries be resolved at link time, i.e. when I link the application which uses my static library?
One side effect of the C preprocessor definitions like _DLL
and _DEBUG
that zdan mentioned:
Some data structures (such as STL containers and iterators) may be sized differently in the debug runtime, possibly due to features such as _HAS_ITERATOR_DEBUGGING
and _SECURE_SCL
. You must compile your code with structure definitions that are binary-compatible with the library you're linking to.
If you mix and match object files that were compiled against different runtime libraries, you will get linker warnings such as the following:
warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs
These options may add defines (__DLL and __DEBUG for example) that are used in the runtime library header files. One common thing to do is to add __declspec(dllimport) to function declarations when linked dynamically.
The compiler also seems to use these to assist the linker in linking to the correct libraries. This is explained in the MSDN.
The compiler needs to know if you are generating single threaded or multi-threaded code. By default the compiler generates thread safe code (multi-threaded). You have to tell it if you want single thread code.If you change the default the compiler changes the default run-time library (you can always override this in the linker command options, just be sure that the library you pick has the same code structure as your object files: single-threaded static, multi-threaded static or multi-threaded DLL). Note that there is no single-threaded DLL option (by definition the run-time library DLL will have been built as thread safe as it is shared by multiple apps).
If you ignore the static runtime then you get the same options as Linux.
I know static runtime can be usful but I have never actually needed it. Also it leads to potential problems dealing with allocation/deallocation of memory and as a result I find it easier to just to use the DLL runtime.
Having Release/Debug version is the same as Linux/Unix though.
Though for effeciency I reasons I alos build a single thread and multi thread versions of libraries.
I believe the reason behind this is that SEH (structured exception handler) code will be generated differently depending on which runtime library you link against.
There is different machine code generated for DLL's and static libraries.
And on Linux you have to do the same, the compiler flag is called -fPIC if you want to build a shared library. Otherwise on AMD64 and SPARC (and maybe others) it will crash. On i386 architecture the linker is clever enough and does not share the library in memory so it won't crash.