views:

32

answers:

1

Our project is a VS2008 based project using Boost and Qt heavily. However, today we have a new linking problem that doesn't make any sense.

What is happening is that during the link

  • For program A, our static library Foobar is finding links to 5 of the 8 member functions.
  • For program FoobarUnitTest, everything from Foobar links and runs fine.
  • For program B, our library Foobar2 is a DLL. During the link, it finds all of the member functions except for the constructor and destructor.

When I say the linker finds some of the member functions, what I did was link with /VERBOSE option on. I then went and examined the resulting buildlog.htm file and I could see where the linker was finding some of the functions from the libraries. Linker error is `"error LNK2019: unresolved external"

Also, the same thing happens in 32bit or 64bit - debug or release mode.

Any suggestions as to where to look?

A: 

Hard to give any meaningful advice for such a nebulous question but here are a couple things to check out. The linker reports "unresolved externals" when the header says there's a function named "x::y()" but it can't find that function in the lib file. Keep in mind that this assumes you have in fact implemented the functions in question. Ultimately however, whatever the problem ends up being, it will be some morphing of "you told me there's a function named x::y(), but then you didn't implement a functon named x::y()."

So, step zero is make sure you actually have implemented these functions. OK, lets assume you have.

Step 1 is make sure you are declspec(__dllexport)ing the functions in the library's implementation, and declspec(__dllimport)ing the functions on the client side. I use macros for this:

MyFancyLib.h:

#ifndef MYLIB_API
#  define MYLIB_API (declspec(__dllimport))
#endif

MYLIB_API void DoIt();

MyFancyLib.CPP:

// this should be moved to stdafx.h or something sufficiently low-level
#define MYLIB_API (declspec(__dllexport))

MYLIB_API void DoIt()
{
  // magic happens
}

Step 2: Make sure you've really named things properly in the implementation. One of my most common mistakes is to declare a member function of a class or namespace, say namespace Foo { void DoIt(); };, and then forget to fully-qualify the class or namespace in the implementation. If you never call the function in your implementation, the linker may never look for it.

MyLib.h:

namespace lib
{
  MILIB_API void DoIt();
};

MyLib.cpp:

MYLIB_API void DoIt()
{
  // magic happens
};

This will generate an unresolved external. The CPP should look like this:

MyLibCorrect.cpp:

MYLIB_API void mylib::DoIt()
{
  // magic
}

Step 3: Make sure you're linking to everything you need to link to. This might seem more like step-0 or step-1, but assuming you've linked to everything you think you need, this step can be hard. Look through the names the linker is complaing about, do some undecoration of them and search your library's code for the implementation of those functions. You may find they are exported from a project other than the one you think they're exported from.

John Dibling
Thanks for excellent comments. As I noted in my question, Program B (actually a full unit test for the class) that links just fine against the library and the production exe doesn't. One point I didn't make is that the production software was working fine. Now it isn't. The only real change has been to implement pre-compiled headers for Qt and Boost. But I've disabled the pre-compiled headers and still have the same problem.
photo_tom
Update - After spending several hours working through mis-leading error messages, your answer proved to be the write one. We had one base library project that had a class exclude for some reason. Thanks for help.
photo_tom
@photo_tom: Glad you found it. This kind of error can be very hard to solve. You're actually lucky it only took a couple hours!
John Dibling