gcc没有将.o中的符号链接到应用程序中
Posted
技术标签:
【中文标题】gcc没有将.o中的符号链接到应用程序中【英文标题】:gcc not linking symbols from .o into application 【发布时间】:2014-10-25 11:12:35 【问题描述】:我正在尝试将 c++ .o 文件链接到应用程序(也是 c++)。这是构建行:
g++ -o ../objs/armv5sfLinux3.2gcc4.6.2.EV3/Touch_publisher ../objs/armv5sfLinux3.2gcc4.6.2.EV3/Touch_publisher.o ../objs/armv5sfLinux3.2gcc4.6.2.EV3/EV3_Touch .o ../objs/armv5sfLinux3.2gcc4.6.2.EV3/EV3_TouchPlugin.o ../objs/armv5sfLinux3.2gcc4.6.2.EV3/EV3_TouchSupport.o ../ev3/ev3dev.o -L/host-rootfs/home /rip/nfs/ev3dev/ndds.5.1.0/lib/armv5sfLinux3.2gcc4.6.2.EV3 -lnddscppz -lnddscz -lnddscorez -ldl -lnsl -lm -lpthread -lrt -lstdc++
有问题的 .o 是 ../ev3/ev3dev.o 文件。构建后,我得到了 Touch_publisher 应用程序,但 nm 报告:
root@arundel:~/rti_510/Touch# nm ../objs/armv5sfLinux3.2gcc4.6.2.EV3/Touch_publisher | grep ev3 | grep " U "
U _ZN6ev3dev12touch_sensorC1ESs
U _ZNK6ev3dev12touch_sensor7pressedEv
U _ZNK6ev3dev6sensor9type_nameEv
如果我在 ev3dev.o 上执行 nm,对于缺少的符号,我会得到例如,
root@arundel:~/rti_510/Touch# nm ../ev3/ev3dev.o | grep _ZN6ev3dev12touch_sensorC1ESs
0000ee5c T _ZN6ev3dev12touch_sensorC1ESs
root@arundel:~/rti_510/Touch#
所以有一个符号。从上面我不知道的细节是什么? “T”表示它是一个外部符号...
我是否在命令行上遗漏了一些深奥的标志? ev3dev.o 文件的构建使用:
BUILD:
gcc -std=c++11 -shared -fpic -march=armv5t -mfloat-abi=soft -mlong-calls -o ev3dev.o ev3dev.cpp
或者也许还有其他步骤?我试过 '-Wl,-whole-archive,../ev3/ev3dev.o,-no-whole-archive' 但仍然得到那些讨厌的 U 符号。
我没有启用 -O# 优化。
我已经阅读了 20 个左右类似的问题(“链接对象中缺少符号”)
谢谢
附录:objdump而不是nm的结果:
root@arundel:/host-rootfs/home/rip/nfs/ev3dev/rti_510/Touch# objdump -T Touch_publisher | grep \*UND\* | grep ev3dev
00000000 DF *UND* 00000000 _ZNK6ev3dev12touch_sensor7pressedEv
00000000 DF *UND* 00000000 _ZNK6ev3dev6sensor9type_nameEv
00000000 DF *UND* 00000000 _ZN6ev3dev12touch_sensorC1ESs
root@arundel:/host-rootfs/home/rip/nfs/ev3dev/rti_510/Touch# objdump -t ../ev3/ev3dev.o | grep ev3dev | grep _ZNK6ev3dev12touch
0000f040 g F .text 00000058 _ZNK6ev3dev12touch_sensor7pressedEv
root@arundel:/host-rootfs/home/rip/nfs/ev3dev/rti_510/Touch# objdump -t ../ev3/ev3dev.o | grep ev3dev | grep _ZNK6ev3dev6sensor9type
0000dd10 g F .text 00000690 _ZNK6ev3dev6sensor9type_nameEv
root@arundel:/host-rootfs/home/rip/nfs/ev3dev/rti_510/Touch# objdump -t ../ev3/ev3dev.o | grep ev3dev | grep _ZN6ev3dev12touch
0000ee5c g F .text 000001e4 _ZN6ev3dev12touch_sensorC1ESs
0000ee5c g F .text 000001e4 _ZN6ev3dev12touch_sensorC2ESs
root@arundel:/host-rootfs/home/rip/nfs/ev3dev/rti_510/Touch#
【问题讨论】:
它可能是特定于操作系统的。为什么需要将目标文件链接到现有应用程序?你想做什么还不清楚。你想要运行时dynamic linking吗?在 Posix 和 Linux 上,使用 dlopen(3)。也许您在链接时需要-rdynamic
标志。也许您缺少一些库!
我在 Ubuntu 上交叉编译,在 Qemu for Armv5sf 下。我将 ev3dev.o 文件与所有其他 .o 文件一次性链接到应用程序中(而不是“链接到 /existing/ 应用程序”)。我会尝试 -rdynamic... nop。仍然得到未解决的外部问题。
缺少一些库会很有趣,除了最终应用程序中缺少符号的库在命令行上。
检查file
和objdump
每个*.o
文件
这些符号是只出现一次还是出现多次(除了“U”之外的其他字母)?
【参考方案1】:
ev3dev.o 文件是使用以下方法构建的:
构建:
gcc -std=c++11 -shared ... -o ev3dev.o ev3dev.cpp
那是你的问题,就在那里:你构建了一个共享库并将其错误命名为ev3dev.o
。
链接共享库的规则是,当您链接它们时,它们不包含在主可执行文件中,所以难怪ev3dev.o
不包含在Touch_publisher
中。
解决方案:如果您希望ev3dev.o
成为普通(可重定位)对象文件,适合链接到主可执行文件,则将-shared
替换为-c
。
【讨论】:
非常出色——我认为这很简单,比如编译器标志。我没有意识到这种行为(不是针对共享库的静态链接)。谢谢!以上是关于gcc没有将.o中的符号链接到应用程序中的主要内容,如果未能解决你的问题,请参考以下文章