代码之家  ›  专栏  ›  技术社区  ›  Ton van den Heuvel

将cmake对象库与共享库结合

  •  8
  • Ton van den Heuvel  · 技术社区  · 7 年前

    下面的cmakelists.txt根据对象库定义了一个对象库和一个共享库,如下所示:

    add_library(foo OBJECT 
      foo.cpp
    )
    
    add_library(bar SHARED 
      bar.cpp
      $<TARGET_OBJECTS:foo>
    )
    
    add_executable(baz baz.cpp)
    target_link_libraries(baz
      PUBLIC bar
    )
    

    链接时出现以下链接器错误 baz :

    /usr/bin/ld: CMakeFiles/foo.dir/foo.cpp.o: relocation R_X86_64_PC32 against symbol `_ZSt4cout@@GLIBCXX_3.4' can not be used when making a shared object; recompile with -fPIC
    /usr/bin/ld: final link failed: Bad value
    

    这是因为 foo.cpp 不是用 -fPIC ( bar.cpp 是)。这可以通过添加以下内容来解决:

    set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE ON)
    

    这是解决这个问题的正确方法吗?我觉得应该有一个更干净的解决方案。我觉得cmake在这里更聪明,可以看到 foo 仅在以下上下文中使用 -FPIC 是必需的。我用的是cmake 3.11。

    一些上下文;在我们的项目中,我们需要从分散在不同目录中的许多源构建一个共享库。现在,我们为每个目录创建单独的共享库。这些库大多依赖于野牛源,而野牛源在幕后依赖于 add_custom_command 待建造。这会引入库之间的编译时依赖关系,严重限制了我们可以并行生成的数量(请参见: https://gitlab.kitware.com/cmake/cmake/issues/15555 )

    每个目录的对象库,然后用来构建共享库,似乎是解决这个问题的一个好方法。

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

    这是解决这个问题的正确方法吗?

    是的。

    自从 bar (共享)链接到 foo (静态),两个 酒吧 必须用位置无关代码编译。

    Cmake知道 酒吧 是共享库,并且 enables position independent code by default . 但是自从 是一个静态对象,即使它可以猜到它需要图片 ,默认情况下不启用pic .

    根据苏的问题 What is the idiomatic way in CMAKE to add the -fPIC compiler option?

    可以在所有目标上设置位置独立代码属性:

    set(CMAKE_POSITION_INDEPENDENT_CODE ON)
    

    或者在特定的库中:

    add_library(lib1 SHARED lib1.cpp)
    set_property(TARGET lib1 PROPERTY POSITION_INDEPENDENT_CODE ON)
    

    参考文献: CMAKE_POSITION_INDEPENDENT_CODE cmake build system


    1) 这可能是一个建议的功能,也许它已经是。