代码之家  ›  专栏  ›  技术社区  ›  pingwindyktator

cmake,无法将静态库链接到共享库

  •  2
  • pingwindyktator  · 技术社区  · 7 年前

    我正在为一些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。一 但是当我试图 nm libuntitled1.so | c++filt 它不包含位置符号 somelibAPI_call . 此外,还有一个 undefined reference 我测试它的可执行文件出错。可能出了什么问题?

    编辑: libsomelib。一 编译时使用 -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

    1 回复  |  直到 7 年前
        1
  •  6
  •   ComicSansMS    7 年前

    通常,这是不可能的,除非重新编译静态库。

    这里的问题是动态库必须用 position independent code ,以便可以将它们动态加载到现有进程的地址空间中。也就是说,编译器必须以特定的方式生成代码,以便适合从共享库执行。

    由于我们对静态库没有这个要求,编译器可以在那里自由创建位置相关的代码(这正是在您的案例中所发生的情况),这禁止它稍后链接到共享库中。因此,为了使其工作,您需要更改 静态库 使其知道稍后将链接到共享库。只有使用正确的选项重新编译静态库,您才能做到这一点。

    当然,设置正确构建选项的确切方法取决于用于构建静态库的构建系统。例如,对于使用CMake构建的静态库,可以更改其构建脚本,使其设置 POSITION_INDEPENDENT_CODE 静态库目标的target属性。