I'm trying to link a c++ .o file into an application (also c++). Here is the build line:
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++
The problematic .o is the ../ev3/ev3dev.o file. After build, I get the Touch_publisher application, but nm reports:
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
If I do an nm on ev3dev.o, for the missing symbols, I get e.g.,
root@arundel:~/rti_510/Touch# nm ../ev3/ev3dev.o | grep _ZN6ev3dev12touch_sensorC1ESs
0000ee5c T _ZN6ev3dev12touch_sensorC1ESs
root@arundel:~/rti_510/Touch#
So a symbol is there. What from the above is the detail I'm unware of? The " T " means it is an external symbol...
Am I missing some esoteric flag on the command line? The ev3dev.o file is built using:
BUILD:
gcc -std=c++11 -shared -fpic -march=armv5t -mfloat-abi=soft -mlong-calls -o ev3dev.o ev3dev.cpp
Or maybe is there another step? I've tried '-Wl,-whole-archive,../ev3/ev3dev.o,-no-whole-archive' but still get those pesky U symbols.
I have no -O# optimizations enabled.
I have read 20 or so similar questions ("missing symbols from linked object")
Thank you
addendum: result of objdump rather than 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#
The ev3dev.o file is built using:
BUILD:
gcc -std=c++11 -shared ... -o ev3dev.o ev3dev.cpp
That's your problem, right there: you've built a shared library and mis-named it ev3dev.o
.
The rules for linking shared libraries is that they are not included into the main executable when you link against them, so no wonder ev3dev.o
is not included into the Touch_publisher
.
Solution: replace -shared
with -c
if you want ev3dev.o
to be a normal (relocatable) object file, suitable for linking into the main executable.