billyquith / ponder

C++ reflection library with Lua binding, and JSON and XML serialisation.
http://billyquith.github.io/ponder/
Other
640 stars 93 forks source link

Multiple Defined Symbols #67

Closed NickCullen closed 7 years ago

NickCullen commented 7 years ago

Hi,

I am getting multiple defined symbol errors like so

obj/Debug/Sandbox/Mathf.conf.o: In function ponder::runtime::ObjectFactory::construct(ponder::Args const&, void*) const: Mathf.conf.cpp:(.text+0x168): multiple definition of ponder::runtime::ObjectFactory::construct(ponder::Args const&, void*) const obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x1a2): first defined here

I can successfully compile and run when I use ponder to build one of these classes (say Mathf) but as soon as I introduce another class (Vector2f) I get the above error. I understand why the error would be caused after quite a lot of digging about but I can't figure out why it is happening in this case.

My set up is as follows:

Mathf.h

#pragma once

class Mathf
{
public:
    static void Initialize();

    void MyFunction();
};

Mathf.cpp

#include "Mathf.h"

void Mathf::MyFunction()
{
    int i = 0;
}

Mathf.conf.cpp

#include "Mathf.h"

#include "Core/LuaState.h"
#include <ponder/classbuilder.hpp>
#include <ponder/uses/lua.hpp>  

PONDER_TYPE(Mathf);

void Mathf::Initialize()
{
    ponder::Class::declare<Mathf>()
        .function("MyFunction", &Mathf::MyFunction)
        ;

    ponder::lua::expose<Mathf>(LuaState::L, "Mathf");
}

Vector2f.h, Vector2f.cpp & Vector2f.conf.cpp uses the exact same set up as described above so I won't write out that code as well...

I have tried linking to ponder both statically and dynamically and tested on Windows, Mac and Linux (Ubuntu) but I am still getting the same error.

Any ideas why this is happening? I've been trying to overcome this issue for 3 days now but have had no luck :(

Here is the full output from the compiler error:

obj/Debug/Sandbox/Mathf.conf.o: In function `ponder::runtime::ObjectFactory::construct(ponder::Args const&, void*) const':
Mathf.conf.cpp:(.text+0x168): multiple definition of `ponder::runtime::ObjectFactory::construct(ponder::Args const&, void*) const'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x1a2): first defined here
obj/Debug/Sandbox/Mathf.conf.o: In function `ponder::runtime::ObjectFactory::destroy(ponder::UserObject const&) const':
Mathf.conf.cpp:(.text+0x24a): multiple definition of `ponder::runtime::ObjectFactory::destroy(ponder::UserObject const&) const'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x284): first defined here
obj/Debug/Sandbox/Mathf.conf.o: In function `ponder::runtime::ObjectFactory::destruct(ponder::UserObject const&) const':
Mathf.conf.cpp:(.text+0x28e): multiple definition of `ponder::runtime::ObjectFactory::destruct(ponder::UserObject const&) const'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x2c8): first defined here
obj/Debug/Sandbox/Mathf.conf.o: In function `ponder::runtime::ObjectCaller::ObjectCaller(ponder::Function const&)':
Mathf.conf.cpp:(.text+0x2d2): multiple definition of `ponder::runtime::ObjectCaller::ObjectCaller(ponder::Function const&)'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x30c): first defined here
obj/Debug/Sandbox/Mathf.conf.o: In function `ponder::runtime::ObjectCaller::ObjectCaller(ponder::Function const&)':
Mathf.conf.cpp:(.text+0x2d2): multiple definition of `ponder::runtime::ObjectCaller::ObjectCaller(ponder::Function const&)'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x30c): first defined here
obj/Debug/Sandbox/Mathf.conf.o: In function `ponder::runtime::FunctionCaller::FunctionCaller(ponder::Function const&)':
Mathf.conf.cpp:(.text+0x312): multiple definition of `ponder::runtime::FunctionCaller::FunctionCaller(ponder::Function const&)'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x34c): first defined here
obj/Debug/Sandbox/Mathf.conf.o: In function `ponder::runtime::FunctionCaller::FunctionCaller(ponder::Function const&)':
Mathf.conf.cpp:(.text+0x312): multiple definition of `ponder::runtime::FunctionCaller::FunctionCaller(ponder::Function const&)'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x34c): first defined here
obj/Debug/Sandbox/Mathf.conf.o: In function `ponder_ext::pushUserObject(lua_State*, ponder::UserObject const&)':
Mathf.conf.cpp:(.text+0x352): multiple definition of `ponder_ext::pushUserObject(lua_State*, ponder::UserObject const&)'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x38c): first defined here
obj/Debug/Sandbox/Mathf.conf.o: In function `ponder::lua::expose(lua_State*, ponder::Class const&, ponder::detail::basic_string_view<char, std::char_traits<char> >)':
Mathf.conf.cpp:(.text+0x1423): multiple definition of `ponder::lua::expose(lua_State*, ponder::Class const&, ponder::detail::basic_string_view<char, std::char_traits<char> >)'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x145d): first defined here
obj/Debug/Sandbox/Mathf.conf.o: In function `ponder::lua::expose(lua_State*, ponder::Enum const&, ponder::detail::basic_string_view<char, std::char_traits<char> >)':
Mathf.conf.cpp:(.text+0x168c): multiple definition of `ponder::lua::expose(lua_State*, ponder::Enum const&, ponder::detail::basic_string_view<char, std::char_traits<char> >)'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x16c6): first defined here
obj/Debug/Sandbox/Mathf.conf.o: In function `ponder::lua::runString(lua_State*, char const*)':
Mathf.conf.cpp:(.text+0x17f0): multiple definition of `ponder::lua::runString(lua_State*, char const*)'
obj/Debug/Sandbox/Vector2.conf.o:Vector2.conf.cpp:(.text+0x182a): first defined here
collect2: error: ld returned 1 exit status
Sandbox.make:98: recipe for target '../Bin/Debug/libSandbox.so' failed
make[1]: *** [../Bin/Debug/libSandbox.so] Error 1
Makefile:28: recipe for target 'Sandbox' failed
make: *** [Sandbox] Error 2
billyquith commented 7 years ago

Hi. Did you define PONDER_USES_RUNTIME_IMPL in a header? It should be in one implementation file before ponder headers.

billyquith commented 7 years ago

For an example, see the Lua test.

I.e. in *.cpp file:

#define PONDER_USES_LUA_IMPL
#define PONDER_USES_RUNTIME_IMPL
#include <ponder/class.hpp>
#include <ponder/detail/format.hpp>
#include <ponder/classbuilder.hpp>
#include <ponder/uses/lua.hpp>
#include <list>

If you put these defines in the project settings, or a header that is multiply included then you'll get these symbols multiply defined. See header that defines them.

NickCullen commented 7 years ago

Hey thanks for the reply, sorry I am late coming back - I had to come away from the computer for a few days!

I had both PONDER_USES_LUA/RUNTIME_IMPL defined as a project-wise definition - would this cause that issue?

As I knew what the compiler was complaining about (duplicate definition across more than one object file) I looked at using a unity build solution for compiling all my .conf.cpp files into one object. This forced the symbols to be built into a single (hence only having 1 definition) object file ReflectableClasses.o

billyquith commented 7 years ago

Working too hard?!

Yes that would cause a problem. Don't put the defines in project settings, put before includes in one implementation. For unity build undefine them after the headers.

billyquith commented 7 years ago

Need to document this better.

billyquith commented 7 years ago

I'll close this as I think this should work for you now. Re-open if now.