3

I'm experiencing a linking error that I can't understand, and that only happens to some developers (maybe because we are using some different library or compiler versions):

undefined reference to `CodeAttributes::AddCodeAttribute(boost::variant<boost::blank, A, B, C > const&)'

The whole problematic class and function are kind of simple, but I can't make a self contained example because of the dependencies on other classes.

This is the declaration of the class:

class CodeAttributes : public SomeMixinClass<CodeAttributes>
{
public:
   CodeAttributes();
   CodeAttributes(const CodeAttribute& codeAttribute);
   void AddCodeAttribute(const CodeAttribute& codeAttribute);
   CodeAttribute GetCodeAttribute() const;
   // other stuff

Then the CodeAttribute type is a typedef like this:

typedef boost::variant<boost::blank, A, B, C> CodeAttribute;

And the implementation is again pretty simple:

void CodeAttributes::AddCodeAttribute(const CodeAttribute& codeAttribute)
{
   m_CodeAttribute = codeAttribute;
}
CodeAttribute CodeAttributes::GetCodeAttribute() const
{
   return m_CodeAttribute;
}
CodeAttributes::CodeAttributes(const CodeAttribute& codeAttribute)
   : m_CodeAttribute(codeAttribute)
{}
CodeAttributes::CodeAttributes()
   : m_CodeAttribute(boost::blank())
{}

The class gets compiled as a static library, and I get the above linking error when using the function from the unit tests of the project, which is using the static library to build an executable program. The function call is like this:

CodeAttributesPtr x(new CodeAttributes);
x->AddCodeAttribute(A());

I don't know which the problem could be, but I've tried the following:

  • If I comment out the call to the setter function, it links correctly, so there seems to be only one problematic function: the setter. The getter is fine.
  • Since I'm a bit lost, I tried calling the function some other way, like x->AddCodeAttribute(x->GetCodeAttribute()); or passing boost::blank() or CodeAtrribute(boost::blank()). It still fails linking the same way.
  • I know little about libraries or object code, but I tried running objdump on the object code and the static library. I've found that the function exists, but the CodeAttribute argument is a boost::variant with the template arguments of the definition (as expected), but followed by many boost::detail::variant::void_ arguments which are not in the typedef. I don't know if this is just an implementation detail of boost::variant, but it seems to be the same type as the getter function, so is probably fine?

I don't know what else I could look at to find out which and where is the problem.

  • Please do provide a [mcve]. It will require a bit more effort, I understand, but it is definitely possible. You just need to "mock" enough of the dependencies. How about `struct A{}; struct B{}; struct C{};` for start? – Angew is no longer proud of SO May 21 '18 at 12:08
  • I know, I know. This is what I normally do, so you are right. Ideally I would just do that, and then I would probably be able to figure out the problem myself by reducing the complexity. But this is code that just got merged in recently and I'm too unfamiliar with to deal with it quickly, as its part of a very large application, and reducing it could be a lot of work if the mixin class is relevant. What I was hoping is that maybe somebody could give a clue of where to look. But I will try to make the simple test case without the mixin to see if it gives any hints. Thank you. – Alejandro Exojo May 21 '18 at 13:59
  • Which toolchain do you use and how do you link to the lib? Did you check that there are no differences in compiler/linker options between lib and app? – D Drmmr May 21 '18 at 14:12
  • I'm using GCC 5.4, and I've tried with both GNU LD and ld. I don't see any difference in the flags used, but I'll look again, thank you. – Alejandro Exojo May 22 '18 at 09:13
  • Gosh, I meant GNU LD and gold. (facepalms) – Alejandro Exojo May 22 '18 at 09:55

0 Answers0