Hello,
I realized that there are many GDK users solving problems with linking C runtime without any idead what it is all about. The problem is that to some extent, you have to solve each problem individually, which is hardly possible if you don't know what it actually means. So I decided to summarize the problem for any followers to help them understand it and solve it on their own.
How does it look like? Well, in Visual Studio you try to compile your project and see lines like these in the Output window:
Case 1
Linking...
LIBCMT.lib(invarg.obj) : error LNK2005: __initp_misc_invarg already defined in LIBCMTD.lib(invarg.obj)
LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library
Debuggame.exe : fatal error LNK1169: one or more multiply defined symbols found
Case 2
Linking...
multiplayer.lib(CMultiplayerC.obj) : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)
system.lib(dxdiaginfo.obj) : error LNK2019: unresolved external symbol __vswprintf referenced in function "int __cdecl swprintf(wchar_t *,wchar_t const *,...)" (?swprintf@@YAHPA_WPB_WZZ)
Debuggame.exe : fatal error LNK1120: 127 unresolved externals
For an untrained eye, there is some unknown problem in a function you have never heard of, which is used in a file you have never heard of, which is part of a module you have never heard of
We will get into it, but we need some background first. Most beginners consider the error above to be a compiler problem. It's not! It's a
linker problem and most often you have caused it to happen. And you can shout out that the same code is working for some other guy and that it's crappy and bloody stupid, but it's not, actually it's pretty smart, just a bit more complex than you would think.
The problem is that nowadays with powerful IDE's like MS Visual Studio you might think that programming is just writing code in language specific syntax. But it's not and there are bits of knowledge you need to gather too. A
build process (a process of making an executable code out of your project/source files) have several steps and each step is simply performed by running some particular tool/program with particular arguments. Once you needed to know all the arguments and write them to so called
makefile which drives the build process. In advanced IDE like MSVS you don't need to know those tools and their arguments, but you should know where and how to configure them instead. That's where the project settings come in.
Two main parts of the build process are performed by a
compiler and
linker. While compiler translates pieces of your source code to pieces of machine specific code, the linker joins the pieces and links them together to one final output, which is the executable (od library) you are up to. Correct compiler errors is mostly very simple, you only need to know the language (C++ here) syntax. Persuade linker to do what you need can be sometimes bit more complex as you need more knowledge about the process.
However, the principle is quite similar to what compiler does. Where you need to tell compiler to read some declarations from some particular header file (using #include "header.h") so that compiler would know the identifier, you also need to tell the linker where it can find the appropriate symbol, i.e. the compiled code. You do this in "Project Settings | Linker | Input | Additional dependencies". There you add the name of the library (mylibrary.lib) which contains the code of a function you are going to use.
When someone builds a code as a
static (.lib) or
dynamic (.dll) library, you can reuse the code in your application by calling the routines stored in the library. The difference is that while the code from static library is linked to your executable by linker during build process, a dynamic library code is linked at runtime and your code only contains references (addresses) to the particular DLL (This is useful when more applications use the same code as you don't need to add the code to every application - they can share a single system version.). As a result, you always need to define static libraries only as an input for the linker. (Another thing is, that for each dynamic library there is always a static library which performs the dynamic linking in runtime. But don't do this too complex now.
)
"Smartass, we know these things!" Maybe you do, maybe someone not. Now we can return back to the original problem. Lets translate the Case 1 to some readable form:
StaticLibrary.lib(
ObjectFile.obj) : error LNK2005:
DuplicateSymbol already defined in
StaticLibrary2.lib(
ObjectFile2.obj)
The message says, that some symbol (e.g. a function) is already linked to your executable and you are trying to link it again. In our case it's a DuplicateSymbol defined in StaticLibrary, which has already been linked in from StaticLibrary2. It's because both static libraries contain a symbol of the same name. That's not allowed. We will see later why this can happen.
Case 2 says:
StaticLibrary.lib(
ObjectFile.obj) : error LNK2001: unresolved external symbol "
SymbolDeclaration" (
SymbolName)
This says that some symbol (e.g. a function) which is declared as 'SymbolDeclaration' in your language syntax and used by some function in StaticLibrary is not has not been found in any linker input file. (Ignore the SymbolName, it's a name mangling performed by the C++ linker. It will be complex enough without investigating this.
)
Whereas case 2 came up because you forget to add some static library to the list of dependencies (as mentioned before) and can be easily fixed, case 1 can occur because you linked incompatible libraries together. (Again, it can be more complex, but in most cases mentioned on these forums it's just the C runtime which makes troubles.)
Now, thing about the difference between debug and release code. In debug code you write unnecessary checks, error/debug outputs and so on. Simply you do a lot of stuff which is not needed, or even wanted in release code (makes it longer and slower). So, you write a library which someone can use and you need to decide - offer a debug version so that he can debug the code more easily, or release version so it is faster? The answer is straigtforward - offer both. If you offer both libraries, one can choose which one to use in each build (debug/release/whatever). But here's the problem, all the pairs of symbols in both libraries have the same name. How to solve it? Easily - you have separate project settings for debug and release build. Each build picks up its library.
"Where's the problem then?" The problem is that many programming beginners doesn't realize that while they are using standard functions like "printf", even these functions need to be defined somewhere. So in (almost) any program you need to add some static library to the linker dependencies list. You don't do that, do you? Still it's working, right. Why? Because these standrad functions are actually so common, that Visual C++ IDE is adding them automatically to the linker input.
"Case solved then?" Hardly. MSVS do this automatically, but only for the initial project setup if you create a project with a wizard (which you always do). If you change some project settings, it's possible that you need to change the linker input too. It's because there are several libraries implementing those standrad functions and they differ. You use one for debug build, another one for release build. You can link it statically or use dynamic libraries. In older versions of Visual C++ you were able to choose between single- and multi-threaded versions. In any case, you must assure that you use
only one of them, or else you get the error in case 1. Some people are smart enough to realize, that using
/NODEFAULTLIB linker option (does the same as "Proj.sets. | Linker | Input | Ignore All Default Libraries = Yes") prevents VC++ from adding these standard libraries to linker input. However, they are often not smart enough to realize, that when they does this, they must care about the linker input themself. That's when they obtain the error message in case 2.
Which runtime library you are actually using is defined in "Project sets. | C/C++ | Code Generation | Runtime Library" or by compiler switches /MT*, /MD* or deprecated /ML*. You should set the linker input according to this. However, with GDK it's more complex again, since they don't offer debug versions of their libraries. Therefore the code you are working with
is always using release version of runtime libraries. Since their libraries expect release version of standard libraries, you have to link against release version too. And since you have to link against one version only, you
can not use debug version of runtime libraries. A pitty, isn't it?
(Well, ok, we could make it more complex again and find our way out of this, but that would only spread fear and confusion
and practically help to nobody.
)
So, to summarize it:
1) you need to choose proper runtime usage (either DLL or static version, but release)
2) properly set the linker dependencies, or let the VC++ do it automatically and rather set the "exceptions" to the linker input, which are to be set in "Proj.sets. | Linker | Input | Ignore Specific Library"
As for myself, I enjoy the way of precise configuration, so I set the "/NODEFAULTLIB" and then set the input accordingly to my setting.
As a side note - don't forget that if you are working on more projects in one solution where one of these projects is dependent on others (the one is .exe and others are libraries), you should use the same Runtime libraries for all of them (for a particular build configuration).
I chose these links where you can find precise info of the setting I was slightly talking about (I was just explaining the background, you should read that after this!):
Choose appropriate runtime library:
http://msdn2.microsoft.com/en-us/library/aa278396(VS.60).aspx
Which libraries to ignore for particular setting:
http://msdn2.microsoft.com/en-us/library/aa267384(VS.60).aspx
What are those libraries (with samples):
http://support.microsoft.com/kb/154753
Finally, I would like to discuss the topic of
deploying your game. The easier way is when you choose the static version of runtime libraries. In that case the code of standard functions is linked into your executable file and it's not dependent on external DLLs installed (side-by-side) on the target machine. However, if you for some reason choose dynamic linkage of the runtime, you have to ensure those dynamic libraries are available on user's machine. There are several ways how to ensure this:
1) Install the C runtime redist during a setup process of your game. This is easy and efficient, especially if you have Pro version of Visual Studio where your Setup project can ensure this for you.
2) If you don't have an installer or you don't want it to be too big (small archive for download from web), you can link to this page:
http://www.microsoft.com/downloads/details.aspx?familyid=9b2da534-3e03-4391-8a4d-074b9f2bc1bf&displaylang=en, where anyone can download the installer for VC++ 2008 runtime redist (you can find similar download pages for VC++ 2005 and older). However, it becomes a bit more complex then because you need to provide a valid link depending on whether the user have x86 or x64 operating system installed.
3) Finally you can add those libraries to your archive
without installing the runtime redist. This is a valid way of linking and does not broke any license. You get a bigger installer than in case (2) and the user can end up with tens of these libraries on his machine if every application comes with this (it breaks the idea of dynamic linkage in some way). The advantage is that you don't have to create an installer and the user doesn't have a clue that such a thing is being copied to his machine (in contrast to (1) and (2) where the runtime redist installer asks the user for permission). Moreover it's more resistant to problems with user access rights. This way is pretty easy, but can sometimes bring some pain with inconsistent side-by-side (SxS) library linking and unresolved externals in runtime (not during build), which is much harder to solve as the code ran on machine to which you don't have access. In these cases it is most useful to use a tool like Dependency Walker (Depends.exe in your MSVS install dir) which tells you which libraries your application needs. However I'm not gonna talk about this as it could make a whole separate article
No matter which way you choose to use the runtime library, you always have to install the
DX9.0c redist (August 2007 version these days, but will probably change in the future) on the target machine. It should be noted, that
it's not the standard DirectX 9.0c package which is already installed on all XP SP2 and Vista platforms, and it
is not the DX SDK which you have to install on the development machine (though the runtime is a part of it). If you were curious what it is, it's a package of advanced useful functions (used by GDK) provided by Microsoft. Most of these functions are contained in dynamic library d3dx9_35.dll (for august version of DX SDK, other SDKs uses different number). Again there are several ways how to ensure this component is installed on the user's machine:
1) Use your setup program and add a custom step for installing the package you distribute with your game. If you chose "Redist" to be installed on your machine when you were running the DX SDK installer, the package is already on your computer and you can find it in [DX SDK]Redist folder. This setup package can be freely distributed with your game, however, in contrast with C runtime redist, you can't distribute the DLLs directly. You
must distribute only the setup package which contains EULA etc. Doing this other way you are breaking the license. The package has about 70 MB and will likely grow in the future, but it's possible to distribute just a portion of the package you actually use in your project. (I won't go into details now; ask if you are interested.
)
2) Offer a link to the redist on the MS's web:
http://www.microsoft.com/downloads/details.aspx?FamilyID=cb7397f3-0949-487b-9247-8fee451bf952&displaylang=en. Fortunately, there are both versions included in the package - x86 and x64. Unfortunately, the package is rather big. Also don't forget that this applies to GDK version which uses August 2007 DX redist, this will probably change in the future and the link won't be valid. However, for a game which you make today with actual version of GDK, this is true and remain true forever (so you don't have to be afraid that it won't run later). This way is useful for users which don't have internet connection on the machine where they are gonna play your game.
3) Offer a link to redist web setup:
http://www.microsoft.com/downloads/details.aspx?FamilyId=2DA43D38-DB71-4C1B-BC6A-9B6652CD92A3&displaylang=en. The difference is that the web setup precisely discovers what your system needs and what is missing and download only the necessary parts, which means a lot faster download. Another difference is that this link always points to the
last version of DX redist. That's a good behavior though as the newer version contains all the older components too.
The topic is hardly depleted
, but a bit exhaustive to summarize
. I hope this will help someone and prevent posting the same questions on this topic over and over. My apologize to those who are more confused than before.
Have a nice day
//rem