我正在使用通常的AutoTools生成的configure && make && make install
程序附带的库。该库包含一个主(共享)库和一些工具,主要用C语言编写。
现在我遇到了一个问题,其中一个工具的构建之一在使用一个指导者时失败了(Score-P包装了编译器调用以实现它的魔力)。
我将其缩小到以下事实:
libMain使用C文件和1个C ++文件,C文件使用gcc进行编译,使用g ++进行C ++文件编译。该库与g ++作为共享库链接 binTool仅使用C文件,但链接到libMain。
这可以在没有指导者的情况下工作。但是,在使用时,它会在使用C ++功能的g ++链接时添加额外的库。将binTool与gcc链接然后给出undefined reference to 'operator delete[](void*)'
(以及一些类似的)
第一:有人可以向我解释,为什么在链接共享库时要小心(即使二进制文件只使用C代码,也要使用g ++)?我的印象是,共享二进制文件的链接已经完成,因此链接不应该引入任何新的依赖项或者依赖项已经解决(在这种情况下libMain
会知道它需要libc++
并且具有它已经引用/存储/无论是什么 - 正在做什么)
第二:通过阅读AutoTools文档,我发现程序的链接器是根据其源文件选择的。由于libMain
使用C ++文件,因此它与g ++链接。 binTool
仅使用C文件,因此它与gcc链接。但binTool
链接libMain
也是C ++链接的,似乎需要与g ++链接。
罪魁祸首在哪里?是否AutoTools为binTool
发出了错误的链接器命令?或者,在链接libMain
?
供参考:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)
ldd libMain
:
Linux的vdso.so.1
librt.so.1
libpthread.so.0
下的libm.so.6 libc.so.6的
libgcc_s.so.1
libdl.so.2
libnuma.so.1
libltdl.so.7
答案 0 :(得分:1)
正如我评论的那样,您可以将共享库(当构建该库时)与另一个库链接。有关详细信息,请参阅this答案。阅读Drepper的How To Write Shared Libraries论文。
您可能应该重新配置并重新编译并重新构建libMain
。您希望将显式与-lstdc++
链接。
将某些LDFLAGS=-lstdc++
或LIBES=-lstdc++
传递给configure
的{{1}}可能有所帮助。请参阅this。
libgccjit
),它们与libMain
链接
答案 1 :(得分:0)
实现您的问题的想法是编写一个包装器库,其标头位于C
中,并且主体内部使用C++
编译器进行编译,以便它可以调用您的C++
库功能
稍后,您可以将C++
库与其C
标题链接到您的应用
答案 2 :(得分:0)
我找到了解决方案(TL& DR跳到脂肪解决方案):
情况比我想象的要困难得多。会发生什么:
binTool
链接到共享库libMain
,链接到共享库libExtraCxx
。
binTool
是一个C程序,因此与gcc libMain
包含一个C ++文件,因此与g ++链接。但它不使用任何C ++库功能,因此链接器会忽略libstdc++
链接过程中的libMain
。libExtraCxx
是一个C库,旨在通过自动包装脚本链接到C程序。由于libMain
使用g ++,它会链接到libExtraCxx
。此库应该拦截C ++ new
/ delete
调用,并使用GNU -wrap
来执行此操作链接器命令并在内部定义(手动)以new
为前缀的delete
/ __wrap_
的受损版本,并声明以__real_
为前缀的受损版本。通常这是有效的,因为当binTool
使用C ++链接器时,包装器将发出-wrap
命令,libstdc++
提供__real_
函数。
然而,错误是,libstdc++
永远不会被链接:libExtraCxx
是一个C库,它只是挂钩到C ++函数。 libMain
不使用任何C ++库函数,binTool
也是一个C程序,并且没有链接到它的共享库与libstdc++
相关联。
所以可以指出2个问题:
libExtraCxx
应该是一个C ++库并且链接libstdc++
但是我想这个“技巧”是为了明确地避免对C ++库的依赖所以它可以被GNU,Intel或Clang C ++编译器可能有不同的标准库。libMain
应该省略libstdc++
而不是。这通常可以通过将-Wl,--no-as-needed
传递给编译器/链接器来完成,如here所述。由于所涉及的工作量,我无法更改libExtraCxx
,但我可以将参数传递给编译器,所以我选择了2。
然而,简单地执行configure <...> LDFLAGS=-Wl,--no-as-needed
不起作用。使用了该标志,但libstdc++
不存在。
我发现罪魁祸首是由libMain
使用的libtool:libtool 2.4.2 does not pass the flag at the right position AFAIK这个错误#12880尚未修复,所以我正在寻找更多。
<强>解强>
我找到了hack here:只需使用CXX="$CXX -Wl,--no-as-needed"
即可。这基本上使得libtool认为,该标志是编译器命令的一部分,它不会重新排序,而是将其保留在开头。
供参考:我使用的是starPU,因此libMain
实际上是libstarpu-1.2.so
。失败的二进制文件(binTool
)是starpu_perfmodel_display
。 “假”-C ++ - 库来自Score-P libscorep_adapter_memory_event_cxx.so.5
我只是更改了名称以简化它们。
对于SCORE-P,解决方案有点复杂,因为人们不能简单地改变CXX。因此,使用ScoreP编译starPU的完整解决方案是:
SCOREP_WRAPPER=off ~/Downloads/starpu-1.2.3/configure --prefix /usr/local CC=scorep-gcc CXX=scorep-g++ FC=scorep-gfortran --with-mpicc=scorep-mpicc --with-mpifort=scorep-mpif77
和
make SCOREP_WRAPPER_INSTRUMENTER_FLAGS="--opencl --thread=pthread" SCOREP_WRAPPER_COMPILER_FLAGS="-Wl,--no-as-needed"
说明:SCOREP_WRAPPER_COMPILER_FLAGS
将导致包装器将标志传递给编译器。由于libTool使用的是scorep包装器,因此它甚至看不到这些标志,因此它们会被透明地添加。