2

I'm writing adapter (shared library) to some fpga API. I've got libsomelib.a and its API - somelibAPI.h. Here is a minimal example of my adapter:

somelib_adapter.h:

#include <string> namespace details { #include "somelibAPI.h" } class somelib_adapter { public: std::string foo(); }; 

somelib_adapter.cpp:

#include "somelib_adapter.h" using namespace details; std::string somelib_adapter::foo() { char result[64]; somelibAPI_call(result); return std::string(result); } 

CMakeLists.txt:

cmake_minimum_required(VERSION 3.8) project(untitled1) set(CMAKE_CXX_STANDARD 11) set(SOURCE_FILES somelib_adapter.cpp somelib_adapter.h) FIND_LIBRARY(SOMELIB_LIBRARIES NAMES libsomelib.a PATHS "${SRC_CPP_DIRECTORY}") add_library(untitled1 SHARED ${SOURCE_FILES}) set(untitled1 -Wl,--whole-archive ${SOMELIB_LIBRARIES} -Wl,--no-whole-archive) target_link_libraries(untitled1 some_other_shared_lib_used_by_somelib) 

cmake finds libsomelib.a but when I'm trying to nm libuntitled1.so | c++filt it does not contain symbols location of somelibAPI_call. What's more, there is an undefined reference error with executable I made to test it. What may be wrong?

EDIT: libsomelib.a is compiled with -fPIC

EDIT2: I see I misunderstood some example. Now Ive got target_link_libraries(untitled1 -Wl,--whole-archive ${SOMELIB_LIBRARIES} -Wl,--no-whole-archive some_other_shared_lib_used_by_somelib) but there is another problem: /usr/bin/ld: ../libsomelib.a(somelibAPI.o): relocation R_X86_64_32 against .rodata.str1.1 can not be used when making a shared object; recompile with -fPIC

4
  • Your code sets variable untitled1, but never uses it. Just add needed linker flags directly to target_link_libraries call. Commented Nov 20, 2017 at 17:18
  • @Tsyvarev: see EDIT2 Commented Nov 20, 2017 at 17:33
  • According to the error message, your libsomelib.a has not actually built with -fPIC. BTW, with make VERBOSE=1 you may see actual compilation and linking commands used in build process. You may check these commands for containing required flags. Commented Nov 20, 2017 at 18:25
  • Following @Tsyvarev observations, you should see this question related to -fPIC or this Commented Nov 20, 2017 at 22:12

1 Answer 1

6

This is, in general, not possible, unless you recompile the static library.

The problem here is that dynamic libraries have to be generated with position independent code, so that they can be loaded dynamically into the address space of an existing process. That is, the compiler must generate the code in a specific way so that it is suitable for execution from a shared library.

Since we do not have this requirement for static libraries, a compiler is free to create position-dependent code there (which is exactly what happened in your case), which prohibits it from being linked into a shared library later. So for this to work, you need to change compilation of the static library to make it aware that it will be linked into a shared library later on. Only by recompiling the static library with the correct options can you make this work.

The exact way to set the correct build options of course depends on the build system used for building that static library. For example, for a static library built with CMake, you could change its build script so that it sets the POSITION_INDEPENDENT_CODE target property on the static library target.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.