Edited: ODR violation fixed.
Edited: I found that reordering the link directories (-L) fixed the problem but I don't know why.
The original order in the g++ command that was causing the problem was this:
-L/usr/local/lib
-L/usr/local/lib64
-L/usr/lib
-L/usr/lib/64
-L../../bin/Release
Moving -L../../bin/Release
which contains the VampEngine.so fixed the problem, but why?
Edited Ends Here
I have two projects. VampEngine (A shared lib) and Application (the client). When I compile both of them on Windows (visual c++), VampEngine links just fine with the Application but on Linux I get undefined errors (g++).
I checked if the correct flags and paths are passed in the compiler's arguments and it seem right. Also I'm pretty positive that I use extern "C" in both the dll implementation and in the client's decelerations.
Here is analytically the g++ makefile execution:
-------------- Clean: Debug|x64 in VampEngine (compiler: GNU GCC Compiler)---------------
Cleaned "VampEngine - Debug|x64"
-------------- Clean: Debug|x64 in Application (compiler: GNU GCC Compiler)---------------
Cleaned "Application - Debug|x64"
-------------- Build: Debug|x64 in VampEngine (compiler: GNU GCC Compiler)---------------
g++ -m64 -fPIC -I../../Depedencies/Cross-Plat/glm-0.9.9.5 -I/usr/include -I/usr/local/include -c /home/babaliaris/Deve/cpp/VampEngine/VampEngine/src/core.cpp -o ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/core.o
g++ -m64 -fPIC -I../../Depedencies/Cross-Plat/glm-0.9.9.5 -I/usr/include -I/usr/local/include -c /home/babaliaris/Deve/cpp/VampEngine/VampEngine/src/stb_image/stb_image.cpp -o ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/stb_image/stb_image.o
g++ -m64 -fPIC -I../../Depedencies/Cross-Plat/glm-0.9.9.5 -I/usr/include -I/usr/local/include -c /home/babaliaris/Deve/cpp/VampEngine/VampEngine/src/window.cpp -o ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/window.o
g++ -shared -L/usr/lib -L/usr/lib64 -L/usr/local/lib -L/usr/local/lib64 ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/core.o ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/stb_image/stb_image.o ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/window.o -o ../../bin/Debug/libVampEngine.so -s -shared -m64 -L/usr/lib64 -lGL -lGLEW -lglfw
Output file is ../../bin/Debug/libVampEngine.so with size 138.57 KB
-------------- Build: Debug|x64 in Application (compiler: GNU GCC Compiler)---------------
g++ -m64 -I../../Depedencies/Cross-Plat/glm-0.9.9.5 -I../../VampEngine/src -I/usr/include -I/usr/local/include -c /home/babaliaris/Deve/cpp/VampEngine/Application/src/main.cpp -o ../../bin-int/Debug/VampEngine/x64/Debug/Application/Application/src/main.o
g++ -L/usr/lib -L/usr/lib64 -L/usr/local/lib -L/usr/local/lib64 -L../../bin/Debug -o ../../bin/Debug/Application ../../bin-int/Debug/VampEngine/x64/Debug/Application/Application/src/main.o -s -m64 -L/usr/lib64 -lVampEngine
/usr/bin/ld: ../../bin-int/Debug/VampEngine/x64/Debug/Application/Application/src/main.o: in function `VampEngine::Core::Core(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, unsigned int)':
main.cpp:(.text._ZN10VampEngine4CoreC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjj[_ZN10VampEngine4CoreC5ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjj]+0x31): undefined reference to `Vamp_Core_Constructor'
/usr/bin/ld: ../../bin-int/Debug/VampEngine/x64/Debug/Application/Application/src/main.o: in function `VampEngine::Core::~Core()':
main.cpp:(.text._ZN10VampEngine4CoreD2Ev[_ZN10VampEngine4CoreD5Ev]+0x17): undefined reference to `Vamp_Core_Deconstructor'
/usr/bin/ld: ../../bin-int/Debug/VampEngine/x64/Debug/Application/Application/src/main.o: in function `VampEngine::Core::MainLoop()':
main.cpp:(.text._ZN10VampEngine4Core8MainLoopEv[_ZN10VampEngine4Core8MainLoopEv]+0x17): undefined reference to `Vamp_Core_MainLoop'
collect2: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 1 second(s))
4 error(s), 0 warning(s) (0 minute(s), 1 second(s))
Here is the core.cpp file which contains the implementation of the extern functions in the shared library:
#include "core.h"
#include "window.h"
#include <GLFW/glfw3.h>
#include "Engine/API.h"
namespace VampEngine
{
CoreImpl::CoreImpl(std::string title, unsigned int width, unsigned int height)
: window( new WindowImpl(title, width, height) )
{
}
CoreImpl::~CoreImpl()
{
delete window;
}
void CoreImpl::MainLoop()
{
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window->m_window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window->m_window);
/* Poll for and process events */
glfwPollEvents();
}
}
}
extern "C" VAMP_API void* Vamp_Core_Constructor(const char* title, unsigned int width, unsigned int height)
{
return new VampEngine::CoreImpl(title, width, height);
}
extern "C" VAMP_API void Vamp_Core_Deconstructor(void* obj)
{
VampEngine::CoreImpl *object = (VampEngine::CoreImpl*)obj;
delete object;
}
extern "C" VAMP_API void Vamp_Core_MainLoop(void* obj)
{
VampEngine::CoreImpl* object = (VampEngine::CoreImpl*)obj;
object->MainLoop();
}
And this is the core.hpp which the client includes and compiles in his main.cpp file:
#ifndef VAMP_ENGINE_CORE_HPP
#define VAMP_ENGINE_CORE_HPP
#include <Engine/API.h>
#include <iostream>
extern "C"
{
VAMP_API void* Vamp_Core_Constructor(const char* title, unsigned int width, unsigned int height);
VAMP_API void Vamp_Core_Deconstructor(void* obj);
VAMP_API void Vamp_Core_MainLoop(void* obj);
}
namespace VampEngine
{
class Core
{
private:
void* m_core;
public:
Core(std::string title, unsigned int width, unsigned int height)
: m_core(Vamp_Core_Constructor(title.c_str(), width, height))
{
}
~Core()
{
Vamp_Core_Deconstructor(m_core);
}
void MainLoop()
{
Vamp_Core_MainLoop(m_core);
}
};
}
#endif
The VAMP_API macro is empty when compiled on Linux.
#ifndef VAMP_ENGINE_API_H
#define VAMP_ENGINE_API_H
//On Windows Platforms.
#ifdef VAMP_PLATFORM_WINDOWS
#ifdef VAMP_BUILD_DLL
#define VAMP_API _declspec(dllexport)
#else
#define VAMP_API _declspec(dllimport)
#endif
//Unix-Based Systems (GCC).
#else
#define VAMP_API
#endif
#endif
As you can see I use exactly the same names.
So what else can cause an undefined error?
I use arch linux x64, with gcc version:
$gcc --version
gcc (GCC) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.