Linking a shared library with unresolved characters in linux

I have the following three projects:

  • Host: executable file that exports a global variable (declared extern)
  • Plugin: runtime library loaded Hostand referencing a global variable
  • Tool: An executable file that references Pluginand uses some functions. It does not refer to a global variable in any way.

Now, if I build it on the windows, everything will be fine. Toolwill only reference the export library Pluginand will not attempt to resolve the global variable.

On Linux, I ran into a problem. Tooltries to link to the Plugin.so library (because there is no export library) and will find a link to the global variable in Hostwhich it cannot solve.

How to solve this problem?


Edit:

The following is a compiled example of a problem using CMake.

CMakeLists.txt

SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/bin")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/bin")

SET(CMAKE_POSITION_INDEPENDENT_CODE ON)

ADD_SUBDIRECTORY(Host)
ADD_SUBDIRECTORY(Plugin)
ADD_SUBDIRECTORY(Tool)

Host / host.h

#ifndef HOST_H
#define HOST_H

#ifdef _MSC_VER

#ifdef COMPILE_HOST
#define HOST_EXPORT __declspec(dllexport)
#else
#define HOST_EXPORT __declspec(dllimport)
#endif

#else
#define HOST_EXPORT
#endif


class HOST_EXPORT Host
{
public:
    int getAnswer();

};


extern HOST_EXPORT Host g_host;


#endif

Host / Host.cpp

#include "Host.h"
#include "../Plugin/Plugin.h"
#include <iostream>


Host g_host;


int Host::getAnswer()
{
    return 42;
}


int main()
{
    std::cout << g_host.getAnswer() << std::endl;

    // load plugin and use it
}

Host / CMakeLists.txt

PROJECT(Host)

ADD_EXECUTABLE(Host Host.cpp Host.h)

ADD_DEFINITIONS(-DCOMPILE_HOST)

SET_TARGET_PROPERTIES(Host PROPERTIES ENABLE_EXPORTS ON)

Plugin / plugin.h

#ifndef PLUGIN_H
#define PLUGIN_H


class Plugin
{
public:
    Plugin();

};

#endif

Plugin / plugin.cpp

#include "Plugin.h"
#include "../Host/Host.h"
#include <iostream>


Plugin::Plugin()
{
    std::cout << g_host.getAnswer() << std::endl;
}

Plugin / PluginFunc.h

#ifndef PLUGINFUNC_H
#define PLUGINFUNC_H

#ifdef _MSC_VER
#define PLUGIN_EXPORT __declspec(dllexport)
#else
#define PLUGIN_EXPORT
#endif


namespace plug
{
    int PLUGIN_EXPORT getRandomNumber();
}

#endif

Plugin / PluginFunc.cpp

#include "PluginFunc.h"


int plug::getRandomNumber()
{
    return 4;
}

Plugin / CMakeLists.txt

PROJECT(Plugin)

ADD_LIBRARY(Plugin SHARED Plugin.cpp Plugin.h PluginFunc.cpp PluginFunc.h)

TARGET_LINK_LIBRARIES(Plugin Host)

Tool / Tool.cpp

#include "../Plugin/PluginFunc.h"
#include <iostream>


int main()
{
    std::cout << plug::getRandomNumber() << std::endl;
}

Tool / CMakeLists.txt

PROJECT(Tool)

ADD_EXECUTABLE(Tool Tool.cpp)

TARGET_LINK_LIBRARIES(Tool Plugin)

On Windows, it builds and runs. Host.exe displays "42" and Tool.exe displays "4".

On Linux, I get the following binding error:

usr@debian64:~/vbox/testlink/build$ make
Scanning dependencies of target Host
[ 25%] Building CXX object Host/CMakeFiles/Host.dir/Host.o
Linking CXX executable Host
[ 25%] Built target Host
Scanning dependencies of target Plugin
[ 50%] Building CXX object Plugin/CMakeFiles/Plugin.dir/Plugin.o
[ 75%] Building CXX object Plugin/CMakeFiles/Plugin.dir/PluginFunc.o
Linking CXX shared library libPlugin.so
[ 75%] Built target Plugin
Scanning dependencies of target Tool
[100%] Building CXX object Tool/CMakeFiles/Tool.dir/Tool.o
Linking CXX executable Tool
../Plugin/libPlugin.so: undefined reference to `Host::getAnswer()'
../Plugin/libPlugin.so: undefined reference to `g_host'
collect2: error: ld returned 1 exit status
make[2]: *** [Tool/Tool] Error 1
make[1]: *** [Tool/CMakeFiles/Tool.dir/all] Error 2
make: *** [all] Error 2
+4
source share
2

:

  • . , , .
  • . GCC GNU ld - gcc -Wl,--defsym=GlobalSymbol=0
+1

:

  • DLL, Host, Plugin.
  • Plugin , Tool , Host ( ).

.

, Tool DLL Plugin, , . , , Tool , undefined.

+1

Source: https://habr.com/ru/post/1525943/


All Articles