我正在为某些fpga API编写适配器(共享库)。我有libsomelib.a
及其API - somelibAPI.h
。这是我的适配器的最小示例:
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找到libsomelib.a
,但在我尝试nm libuntitled1.so | c++filt
时,它不包含somelibAPI_call
的符号位置。更重要的是,我测试它的可执行文件存在undefined reference
错误。可能有什么问题?
编辑:libsomelib.a
使用-fPIC
EDIT2:我看到我误解了一些例子。现在我得到target_link_libraries(untitled1 -Wl,--whole-archive ${SOMELIB_LIBRARIES} -Wl,--no-whole-archive some_other_shared_lib_used_by_somelib)
但还有另一个问题:/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
答案 0 :(得分:1)
通常,这是不可能的,除非您重新编译静态库。
这里的问题是必须使用position independent code生成动态库,以便可以将它们动态加载到现有进程的地址空间中。也就是说,编译器必须以特定方式生成代码,以便它适合从共享库执行。
由于我们对静态库没有这个要求,编译器可以自由地在那里创建与位置相关的代码(这正是你的情况所发生的),这禁止它以后被链接到共享库。因此,为了使其工作,您需要更改静态库的编译,以使其知道稍后将链接到共享库。只有通过使用正确的选项重新编译静态库,才能使其工作。
设置正确构建选项的确切方法当然取决于用于构建静态库的构建系统。例如,对于使用CMake构建的静态库,您可以更改其构建脚本,以便在静态库目标上设置POSITION_INDEPENDENT_CODE
目标属性。