Scenario: I have 2 Visual C++ programs which independently compile and
link perfectly. My task is to integrate one into the other. As usual,
the compiling went smoothly.
The linking phase is the troublesome one.
- I get a lot of "unresolved external symbols" - This should be fixed
by _adding_ libraries.
- At the same time, I get a lot of "already defined" - This should be
fixed by _removing_ libraries.
Therein lies my quandary: Damn if I do, damn if I don't.
Question 1: Which should I attack first: finding the libraries needed
for the missing symbols, or removing libraries in which the redundant
ones are contained?
Question 2: Let's say that I know symbol _xyz is unresolved. How the
heck do I search through all the libraries at my disposal? I don't
think grep is an option here.
I guess I need a better way to look inside libraries, and find what
symbols are repeated in two of them.
This is a very long-standing problem. Your expert help is most
appreciated.
TIA,
-Ramon
Remove the redundancies first. They shouldn't be there if you have
studied the two source programs dependencies first. In other words,
you should have made a plan instead of waiting to see what linking
errors you get. Most often, this amounts to deciding whether you want
static linking or DLLs for the various Microsoft libraries. The
linker cannot decide that for you.
> Question 2: Let's say that I know symbol _xyz is unresolved. How the
> heck do I search through all the libraries at my disposal? I don't
> think grep is an option here.
>
In your particular case, where you already have two working programs,
finding out which lib a function comes from should be trivial. In the
original working project, right click on the function name and select
Go To Definition. In the more general case, you can look up any
Windows function and check the Information section of the help page.
It (almost always) lists the .h file and the .lib file.
Thanks for your expert and kind assistance, Scott.
The problem turned out to be that two libraries were in conflict.
Furthermore, the IDE itself suggested the following solution:
LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of
other libs; use /NODEFAULTLIB:library
So, I guessed that 2 libraries (msvcrt.lib and libcmt.lib) don't like
each other.
My first attempt was to try this:
/NODEFAULTLIB:msvcrt.lib
But alas, it didn't work.
However, the good news it that the following worked:
/NODEFAULTLIB:libcmt.lib
And now the program compiles and links.
Like I said, I am looking for conceptual answers, not for a quick tip.
Need to know the semantics, not the syntax.
Therefore, the question remains: exactly what is it that I did?
TIA,
- Ramon
-----------------
[many lines similar to the ones below:]
MSVCRT.lib(MSVCR80.dll) : error LNK2005: _strtoul already defined in
LIBCMT.lib(strtol.obj)
MSVCRT.lib(MSVCR80.dll) : error LNK2005: _sprintf_s already defined in
LIBCMT.lib(sprintf.obj)
MSVCRT.lib(MSVCR80.dll) : error LNK2005: _strcat_s already defined in
LIBCMT.lib(strcat_s.obj)
MSVCRT.lib(MSVCR80.dll) : error LNK2005: _printf already defined in
LIBCMT.lib(printf.obj)
MSVCRT.lib(MSVCR80.dll) : error LNK2005: _fwrite already defined in
LIBCMT.lib(fwrite.obj)
MSVCRT.lib(MSVCR80.dll) : error LNK2005: _atoi already defined in
LIBCMT.lib(atox.obj)
LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of
other libs; use /NODEFAULTLIB:library
You learnt that there are alternatives to a requirement, and those two
projects needed a different solution.
http://support.microsoft.com/kb/94248
You are letting the linker error messages decide something that you
should be deciding based on requirements. The "semantics" are if you
statically link then you have multiple copies of the runtime library
in your program+DLLs, and this restricts what will work at the program/
DLL interfaces. If you dynamically link then all modules will be
using the same copy of the runtime library (smaller runtime footprint)
and program/DLL interfaces have fewer restrictions. This is a rather
fundamental design decision, and can cause issues in running and
deployment.
You don't seem aware that MSVCRT and LIBCMT are the same library,
packaged in a different way. It's not that they don't like each
other, it's that using both of them gives you the disadvantages of
each! But that's the default decision that you, unknowingly, made :(
If your program consists of a single exe then static linking will make
an exe that can run on just about any machine, without needing an
installer. If your program has lots of DLLs then dynamic linking
saves memory and avoids some interface restrictions/errors, but you
then have a dependency on the runtime DLL version and so you will need
to build an installer for your program because it needs a DLL that
might not be present on a user's PC.
> You don't seem aware that MSVCRT and LIBCMT
> are the same library, packaged in a different way.
Well, after I saw all those "already defined" error messages, I
obviously suspected that the two libraries had to have a high degree
of overlap.
Could you blame me about not knowing about those two libraries? I
never included either one in my project. I have no idea by what
mechanism they sneaked into my project. When I look at the project
properties, this is what I see:
[Added by Ramon:]
psapi.lib
ws2_32.lib
crypt32.lib
ChilkatDbgDll.lib
[Inherited somehow:]
kernel32.lib
user32.lib
gdi32.lib
winspool.lib
comdlg32.lib
advapi32.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
odbc32.lib
odbccp32.lib
So the question is: How the hack [sic] did MSVCRT and LIBCMT manage to
subreptitiously land themselves in my project?
-Ramon
The C runtime libraries (or more precisely, one of the 4 variants
of the CRT) are in your project because you're compiling C/C++ code.
The compiler needs to know where to find the definitions of the
standard C/C++ functions, e.g. where 'printf' is, etc.
All Visual Studio projects that are built together into an exe
(including DLLs you build linked by that exe) MUST have the same C
runtime library choice. You can find it under project properties ->
C/C++ -> Code Generation -> Runtime Library. If you don't fully
understand *what* the 4 choices are, then perhaps you need to take a
step back and not try and bolt together multiple projects. Google
is your friend. Links to Microsoft KB articles have been posted in
this thread. Go read them.
Nathan Mates
--
<*> Nathan Mates - personal webpage http://www.visi.com/~nathan/
# Programmer at Pandemic Studios -- http://www.pandemicstudios.com/
# NOT speaking for Pandemic Studios. "Care not what the neighbors
# think. What are the facts, and to how many decimal places?" -R.A. Heinlein
The runtime library is part of the C/C++ language, containing the
language's built in functions (like printf). In the Visual Studio
menu select Project, Properties, C/C++, Code Generation, Runtime
Library. That setting lets you select static linking or dynamic
linking for the runtime library, with debug and release versions of
each available. Whatever you pick it shows up on the C/C++ compler
Command Line as /MTd or /MT (static) or /MDd or /MD (dynamic). To
read all about it in the help look up /MD.
All those other inherited libs let you call Windows APIs and are
specified in the Linker command line. The Visual Studio new project
wizard sets all these things up when you first create the project.
That helps you get started with a typical set of settings, but then
you can change some settings as you learn more about what they do.