【问题标题】:c++ shared library fPIC or undefined library ubuntu 16.04c++共享库fPIC或未定义库ubuntu 16.04
【发布时间】:2018-07-05 11:58:32
【问题描述】:

我正在尝试将代码编译为共享库(它在 windows 上编译得很好,但我无法让它在 ubuntu 16.04 上编译)。

如果我尝试“在 windows 上”编译,我会收到错误:

relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC

所以为了编译链接到我的代码的静态库,我添加了 -fPIC 选项(它似乎在 windows 上是默认的,但在 linux 上不是,但我不确定):

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")

在我使用 qmake 编译的代码中,我添加了:

QMAKE_CXXFLAGS += -fPIC

现在我得到了这些错误:

itkGDCMImageIO.cxx:(.text+0xf9e) : undefined reference to « typeinfo for itk::MetaDataObjectBase »
itkGDCMImageIO.cxx:(.text+0xfb5) : undefined reference to « itk::MetaDataObject<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::GetMetaDataObjectValue() const »

等等……

如果我只为我的代码添加 -fPIC 选项,而不是为编译它使用的静态库,我仍然会收到错误:

relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC

即使添加了 qmake_cxxflags -fPIC。

我做错了什么?* (我把 Make 文件放在这里以防万一:https://github.com/pdeman/mevislabFetalMRI/blob/master/Makefile.CHUVTools.Release

【问题讨论】:

  • 你必须用-fPIC编译itk;否则不能用它来构建.so;但听起来您图书馆的链接中缺少-lITKCommon
  • no -lITKCommon 存在于 LIBS 变量的 make 文件中。我使用 -fPIC 重新编译了 ITK,但仍然出现相同的错误
  • 会不会是链接库的顺序有问题?
  • 查看我的答案 - 问题出在链接库的顺序上,我有一个关于如何在这种情况下以最少的工作解决它的建议。

标签: c++ shared-libraries ubuntu-16.04 fpic


【解决方案1】:

有了 Makefile,我就有机会调试问题。

ITKCommon-4.13 中的 LIBS 链接,这是正确的;需要解析typeinfo for itk::MetaDataObjectBaselibITKIOGDCM-4.13 正在请求。

LIBS 行包含:

-lITKIOSiemens-4.13 -lITKBiasCorrection-4.13 -lITKIOSpatialObjects-4.13 -lITKBioCell-4.13 -lITKIOStimulate-4.13 -lITKCommon-4.13 -lITKIOTIFF-4.13 -lITKDICOMParser-4.13 -lITKIOTransformBase-4.13 -litkdouble-conversion-4.13 -lITKIOTransformHDF5-4.13 -lITKEXPAT-4.13 -lITKIOTransformInsightLegacy-4.13 -lITKFEM-4.13 -lITKIOTransformMatlab-4.13 -litkgdcmcharls-4.13 -lITKIOVTK-4.13 -litkgdcmCommon-4.13 -lITKIOXML-4.13 -litkgdcmDICT-4.13 -litkjpeg-4.13 -litkgdcmDSED-4.13 -lITKKLMRegionGrowing-4.13 -litkgdcmIOD-4.13 -lITKLabelMap-4.13 -litkgdcmjpeg12-4.13 -litklbfgs-4.13 -litkgdcmjpeg16-4.13 -lITKMesh-4.13 -litkgdcmjpeg8-4.13 -lITKMetaIO-4.13 -litkgdcmMEXD-4.13 -litkminc2-4.13 -litkgdcmMSFF-4.13 -litknetlib-4.13 -litkgdcmopenjp2-4.13 -litkNetlibSlatec-4.13 -litkgdcmsocketxx-4.13 -lITKniftiio-4.13 -litkgdcmuuid-4.13 -lITKNrrdIO-4.13 -lITKgiftiio-4.13 -lITKOptimizers-4.13 -litkgtest-4.13 -lITKOptimizersv4-4.13 -litkgtest_main-4.13 -lITKPath-4.13 -litkhdf5 -litkpng-4.13 -litkhdf5_cpp -lITKPolynomials-4.13 -lITKIOBioRad-4.13 -lITKQuadEdgeMesh-4.13 -lITKIOBMP-4.13 -lITKSpatialObjects-4.13 -lITKIOBruker-4.13 -lITKStatistics-4.13 -lITKIOCSV-4.13 -litksys-4.13 -lITKIOGDCM-4.13 -litktestlib-4.13 -lITKIOGE-4.13 -litktiff-4.13 -lITKIOGIPL-4.13 -lITKTransform-4.13 -lITKIOHDF5-4.13 -lITKTransformFactory-4.13 -lITKIOImageBase-4.13 -litkv3p_netlib-4.13 -lITKIOIPL-4.13 -litkvcl-4.13 -lITKIOJPEG-4.13 -lITKVideoCore-4.13 -lITKIOLSM-4.13 -lITKVideoIO-4.13 -lITKIOMesh-4.13 -litkvnl-4.13 -lITKIOMeta-4.13 -litkvnl_algo-4.13 -lITKIOMINC-4.13 -lITKVNLInstantiation-4.13 -lITKIOMRC-4.13 -lITKVTK-4.13 -lITKIONIFTI-4.13 -lITKWatersheds-4.13 -lITKIONRRD-4.13 -litkzlib-4.13 -lITKIOPNG-4.13 -lITKznz-4.13

链接解析将默认从左到右进行,这意味着因为对 ITKCommon-4.13 的引用发生在对 ITKIOGDCM-4.13 的引用之前,所以 typeinfo 不会得到解析。

对此有两种解决方案——第一种是确定所有库的链接依赖顺序,并以相反的顺序对它们进行排序。考虑到此处引用的库的数量,我对库中的依赖关系了解得不够多,甚至无法提出可能有效的命令 - 它具有链接厨房水槽的所有特征。

第二种解决方案是将所有链接选项包装在链接器标志中,该标志表示将所有这些文件一起处理以用于链接目的。它可能会减慢链接速度,但它保证将解决无序或交叉依赖关系。

在 ITK 库的 -l 项目列表的开头,添加选项:-

-Wl,--start-group

在 ITK 库的 -l 项目列表的末尾,添加选项:-

--Wl,--end-group

所以,缩写LIBS 行,它看起来有点像(省略号表示缺少文本):

-Wl,--start-group -lITKIOSiemens-4.13 … -lITKznz-4.13 -Wl,--end-group

【讨论】:

  • 谢谢,它解决了很多问题,我现在有这个错误: gdcm::System::GetCurrentModuleFileName() » : gdcmSystem.cxx:(.text+0xc90) : undefined reference to « dladdr »,我想我必须在链接中添加一个库
  • 我添加了 -ldl ,它似乎工作。多谢。我有最后一个问题,是否可以更改我的 qmake 文件 .pri 和 .pro,以便之后不必修改我的 make 文件。是否有任何 qmake 选项来设置 -Wl,--start-group, -Wl,--stop-group ?
  • 由于您在问题中引用的项目中的.pri 文件在unix:LIBS 部分中包含明确的-l… 项目,我怀疑您只需要将它添加到开头和结尾该选项列表以使它们正确链接。
  • 完美!非常感谢!
猜你喜欢
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
  • 2011-02-28
  • 2014-12-20
  • 1970-01-01
  • 2013-04-15
  • 2023-04-09
  • 1970-01-01
相关资源
最近更新 更多