0

I'm getting a linker error from the OpenCL 2.0 C++ bindings header file cl2.hpp. All my headers files come directly from the Khronos OpenCL registry and I build the OpenCL.lib file myself. I don't get an error using the OpenCL 1.2 C++ bindings header file.

I am using Qt 5.5.0 and Visual Studio C++ 2013 with Windows7 64-bit.

The error is related to multiply defined symbols in multiple source files.

mainwindow.cpp.obj:-1: error: LNK2005: "enum cl::QueueProperties __cdecl
 cl::operator|(enum cl::QueueProperties,enum cl::QueueProperties)"
 (??Ucl@@YA?AW4QueueProperties@0@W410@0@Z) already defined in main.cpp.obj

I don't understand why the compiler is saying this is already defined.

I have narrowed down the problem to this code in the cl2.hpp file

QueueProperties operator|(QueueProperties lhs, QueueProperties rhs)
{
    return static_cast<QueueProperties>(static_cast<cl_command_queue_properties>(lhs) | static_cast<cl_command_queue_properties>(rhs));
}

When I comment that code out my project compiles and runs fine. Do you have any clue to what this problem is? Is it a poor design in the cl2.hpp header file?

Community
  • 1
  • 1
Z boson
  • 32,619
  • 11
  • 123
  • 226
  • 1
    Could well be a bug in `cl2.hpp`. If you mark the offending function as `inline`, does it resolve the issue? – jprice Oct 19 '15 at 14:31
  • I do concur with @jprice , this looks like a case of missing `inline` here since if the header is included in two different compilation units, you'll have a multiple define for the function... – Gilles Oct 19 '15 at 15:04
  • @jprice, yes, `inline` fixes it. Feel free to write up an answer. Is there a better solution than inline? I usually use static inline. What about an anonymous namespace? My C++ skills are weak. I guess somebody should report a bug to Khronos? – Z boson Oct 19 '15 at 15:45
  • 1
    I think `inline` or `static inline` is fine, that's how many of the other functions in the header are handled, this one just slipped through the cracks. I can fix this within Khronos, so it will get pushed out with the next release. – jprice Oct 19 '15 at 15:50

1 Answers1

1

The issue is that the offending function is a non-inline member function. This means that when cl2.hpp is included from multiple source files, there will be multiple copies of the function definition that will clash when these object files are linked together.

The simple solution is to mark the offending function as inline (as many of the other functions in the header already are).

jprice
  • 9,755
  • 1
  • 28
  • 32
  • I only included the cl2.hpp file once explicitly. However, I think to to Qt's moc preprocessor it's implicitly included again. I see the duplicate in a file generated by Qt with an extension `_automoc.cpp`. – Z boson Oct 19 '15 at 15:59