How do i solve this"... .so: undefined reference to '..." - makefile

I have gone through the internet for hours for similar cases to mine but I've tried all solutions and hasn't got my code working. I'm using a library called "vdo_slam" which has been built and can be found in /usr/local/include/vdo_slam. In my project's CMakeList.txt I can find_package(vdo_slam REQUIRED) with no error. The only problem I have is at the end of "catkin_build" I get several of these "undefined reference to ...." as shown below. I have tried several solutions as listed below. All these undefined references are declared and defined inside the "vdo_slam" package. Any help is appreciated.
Known solutions I have tried:
I looked for classes and functions mentioned in the errors and see if there are pure virtual destructors as mentioned in here but they are all defined solidly.
I have tried to debug with "readelf" command as shown below referring to this. But i don't have the "libvdo_slam.so" which actually includes these functions in the error. I suppose i need to have "libvdo_slam.so" when i run this "readelf" command right? How can i add that?
Error message from "catkin_build":
/home/tranks/testing_ws/devel/lib/libmy_realtime_vdo_slam.so: undefined reference to `typeinfo for VDO_SLAM::Visualizer2D'
/home/tranks/testing_ws/devel/lib/libmy_realtime_vdo_slam.so: undefined reference to `vtable for VDO_SLAM::Visualizer2D'
/home/tranks/testing_ws/devel/lib/libmy_realtime_vdo_slam.so: undefined referealtime_vdo_slam/CMakeFiles/ros_vdoslam_node.dir/all' failed
make[3]: *** [my_realtime_vdo_slam/CMakeFiles/ros_vdoslam_node.dir/all] Error 2
Makefile:140: recipe for target 'all' failed
make: *** [all] Error 2
Invoking "make -j12 -l12" failede/tranks/testing_ws/devel/lib/libmy_realtime_vdo_slam.so: undefined reference to `VDO_SLAM::BoundingBox::BoundingBox(double, double, double, double)'
/home/tranks/testing_ws/devel/lib/libmy_realtime_vdo_slam.so: undefined reference to `VDO_SLAM::Scene::Scene()'
/home/tranks/testing_ws/devel/lib/libmy_realtime_vdo_slam.so: undefined reference to `VDO_SLAM::Visualizer2D::spinOnce(std::shared_ptr<VDO_SLAM::Scene>&)'
/home/tranks/testing_ws/devel/lib/libmy_realtime_vdo_slam.so: undefined reference to `VDO_SLAM::Scene::add_scene_object(std::shared_ptr<VDO_SLAM::SceneObject>&)'
/home/tranks/testing_ws/devel/lib/libmy_realtime_vdo_slam.so: undefined reference to `VDO_SLAM::Visualizer2D::Visualizer2D(std::shared_ptr<VDO_SLAM::VisualizerParams>&)'
collect2: error: ld returned 1 exit status
my_realtime_vdo_slam/CMakeFiles/ros_vdoslam_node.dir/build.make:226: recipe for target '/home/tranks/testing_ws/devel/lib/my_realtime_vdo_slam/ros_vdoslam_node' failed
make[3]: *** [/home/tranks/testing_ws/devel/lib/my_realtime_vdo_slam/ros_vdoslam_node] Error 1
CMakeFiles/Makefile2:6593: recipe for target 'my_realtime_vdo_slam/CMakeFiles/ros_vdoslam_node.dir/all' failed
make[3]: *** [my_realtime_vdo_slam/CMakeFiles/ros_vdoslam_node.dir/all] Error 2
Makefile:140: recipe for target 'all' failed
make: *** [all] Error 2
Invoking "make -j12 -l12" failed
$ readelf --dynamic /home/tranks/testing_ws/devel/lib/libmy_realtime_vdo_slam.so
Dynamic section at offset 0x161608 contains 42 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libimage_transport.so]
0x0000000000000001 (NEEDED) Shared library: [libcv_bridge.so]
0x0000000000000001 (NEEDED) Shared library: [libopencv_core.so.3.2]
0x0000000000000001 (NEEDED) Shared library: [libtf2_ros.so]
0x0000000000000001 (NEEDED) Shared library: [libtf2.so]
0x0000000000000001 (NEEDED) Shared library: [libroscpp.so]
0x0000000000000001 (NEEDED) Shared library: [libroscpp_serialization.so]
0x0000000000000001 (NEEDED) Shared library: [librosconsole.so]
0x0000000000000001 (NEEDED) Shared library: [librostime.so]
0x0000000000000001 (NEEDED) Shared library: [libboost_system.so.1.65.1]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libopencv_highgui.so.3.4]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
0x000000000000000e (SONAME) Library soname: [libmy_realtime_vdo_slam.so]
0x000000000000001d (RUNPATH) Library runpath: [/home/tranks/testing_ws/devel/lib:/opt/ros/melodic/lib:/usr/local/lib]
0x000000000000000c (INIT) 0xd0bd0
0x000000000000000d (FINI) 0x129494
0x0000000000000019 (INIT_ARRAY) 0x35f580
0x000000000000001b (INIT_ARRAYSZ) 56 (bytes)
0x000000000000001a (FINI_ARRAY) 0x35f5b8
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x1f0
0x0000000000000005 (STRTAB) 0x2be68
0x0000000000000006 (SYMTAB) 0xa7d8
0x000000000000000a (STRSZ) 545696 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0x362000
0x0000000000000002 (PLTRELSZ) 90336 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0xbaaf0
0x0000000000000007 (RELA) 0xb4058
0x0000000000000008 (RELASZ) 27288 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0xb3e98
0x000000006fffffff (VERNEEDNUM) 6
0x000000006ffffff0 (VERSYM) 0xb1208
0x000000006ffffff9 (RELACOUNT) 9
0x0000000000000000 (NULL) 0x0
This is my CMakeList.txt:
cmake_minimum_required(VERSION 3.10)
project(my_realtime_vdo_slam)
find_package(catkin REQUIRED COMPONENTS
cv_bridge
flow_net
geometry_msgs
image_transport
mask_rcnn
message_generation
midas_ros
mono_depth_2
nav_msgs
python_service_starter
roscpp
sensor_msgs
std_msgs
tf
tf2
tf2_geometry_msgs
tf2_ros
tf2_sensor_msgs
vision_msgs
visualization_msgs
nodelet
message_filters
)
find_package(OpenCV)
find_package(vdo_slam REQUIRED)
## Generate messages in the 'msg' folder
add_message_files(
FILES
VdoSlamScene.msg
VdoSlamMap.msg
VdoSceneObject.msg
VdoInput.msg
)
generate_messages(
DEPENDENCIES
actionlib_msgs
geometry_msgs
std_msgs
sensor_msgs
mask_rcnn
vision_msgs
)
set(PROJECT_INCLUDE_DIRS
include
${catkin_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
${vdo_slam_INCLUDE_DIRS}
)
include_directories(
${PROJECT_INCLUDE_DIRS}
)
catkin_package(
INCLUDE_DIRS ${PROJECT_INCLUDE_DIRS}
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS
roscpp
image_transport
python_service_starter
std_msgs
tf
tf2
tf2_geometry_msgs
tf2_ros
tf2_sensor_msgs
nav_msgs
sensor_msgs
geometry_msgs
cv_bridge
flow_net
mask_rcnn
mono_depth_2
midas_ros
message_runtime
nodelet
message_filters
# DEPENDS system_lib
)
add_library(${PROJECT_NAME} SHARED
src/RosVdoSlam.cpp
src/utils/RosUtils.cpp
src/visualizer/RosVisualizer.cpp
src/visualizer/RosAsyncManager.cpp
src/tracking/HungarianSolver.cpp
src/tracking/SemanticTracker.cpp
)
target_link_libraries(${PROJECT_NAME} PUBLIC
${catkin_LIBRARIES}
${OpenCV_LIBS}
${vdo_slam_LIBRARIES}
)
#if(catkin_EXPORTED_LIBRARIES)
# add_dependencies(${PROJECT_NAME}
# ${catkin_EXPORTED_LIBRARIES}
# ${catkin_LIBRARIES}
# ${OpenCV_LIBS}
# ${vdo_slam_LIB_DIRS})
# endif()
# target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC
# ${catkin_INCLUDE_DIRS}
# ${OpenCV_INCLUDE_DIRS}
# ${vdo_slam_INCLUDE_DIRS}
# $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
# $<INSTALL_INTERFACE:include>
# )
add_executable(ros_vdoslam_node
src/ros_vdoslam_node.cpp
)
target_link_libraries(ros_vdoslam_node
${catkin_LIBRARIES}
${OpenCV_LIBS}
${vdo_slam_LIB_DIRS}
${PROJECT_NAME}
)
if(catkin_EXPORTED_LIBRARIES)
add_dependencies(ros_vdoslam_node
${catkin_EXPORTED_LIBRARIES}
${catkin_LIBRARIES}
${OpenCV_LIBS}
${vdo_slam_LIBRARIES})
endif()

Eureka!
I found a solution although it's not an ideal one. As mentioned in the question, I noticed that libvdo_slam.so was not listed as a shared library when running $ readelf <on_my_library.so>. So I manually added -lvdo_slam in the CMakeList.txt so it looks like:
target_link_libraries(ros_vdoslam_node
${catkin_LIBRARIES}
${OpenCV_LIBS}
${PROJECT_NAME}
-lvdo_slam
) `
Moreover, since "vdo_slam" also uses a modified "g2o" library, the same procedure had to be done in the VDO_SLAM library's CMakeList.txt(which is adding -lvdo_slam_g2o in a similar place).
Although it builds successfully now, I still wonder why this happened. From my understanding, -lvdo_slam is the same as ${vdo_slam_LIBS}, and the latter should be valid after using find_package(vdo_slam REQUIRED)

Related

Call exported functions of DLL in assembly without .lib file

So I'm currently trying to call the exported functions of a dll inside my assembly file.
The DLL is in the same directory as my asm program, I don't have the .lib file.
Here is my code:
EXTERN __imp__CreateCompressor#12:PROC
EXTERN __imp__Compress#24:PROC
EXTERN __imp__CloseCompressor#4:PROC
.code
START:
push 2 ;COMPRESS_ALGORITHM_MSZIP
push 0
push OFFSET hCompress
call __imp__CreateCompressor#12
push 0 ;CompressedDataSize
push DWORD ptr [DataSize] ;CompressedBufferSize
push eax ;CompressedBuffer
push DWORD ptr [DataSize]
push DWORD ptr [pBuf3]
push DWORD ptr [hCompress]
call __imp__Compress#24
push DWORD ptr [hCompress]
call __imp__CloseCompressor#4
END START
However I get the errors:
file.obj : error LNK2001: unresolved external symbol ___imp__CreateCompressor#12
file.obj : error LNK2001: unresolved external symbol ___imp__Compress#24
file.obj : error LNK2001: unresolved external symbol ___imp__CloseCompressor#4
file.exe : fatal error LNK1120: 3 unresolved externals
I'm assembling it like so:
ml file.asm /link /subsystem:console /entry:START
Any ideas?
You must use LoadLibrary() and GetProcAddress() functions to load the library and get the address from the function you want to call.
To enable Load-Time Dynamic Linking the linker needs an import library.
Without an import library you're going to have to use Run-Time Dynamic Linking.
Alternatively, you can generate an import library yourself. The easiest way to do so is to author an appropriate Module-Definition (.Def) File and have the Microsoft Librarian Manager (LIB.exe) generate an import library.

Undefined symbol error: the target library has been set in rpath but it still cannot be found

calving#norfolk:~/sandbox/stage/third_party/houdini16.5/lib$ ldd libgusd.so | grep boost
libboost_python.so.1.55.0 => /home/calveng/sandbox/stage/third_party/houdini16.5/lib/./../../../lib/libboost_python.so.1.55.0 (0x00007f735cb9c000)
libboost_regex.so.1.55.0 => /home/calveng/sandbox/stage/third_party/houdini16.5/lib/./../../../lib/./libboost_regex.so.1.55.0 (0x00007f735af6a000)
calving#norfolk:~/sandbox/stage/third_party/houdini16.5/lib$ readelf -s --wide libgusd.so | grep _ZN5boost6system16generic_categoryEv
1064: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _ZN5boost6system16generic_categoryEv
6632: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _ZN5boost6system16generic_categoryEv
Once I try to link this "libgusd.so" library, it will throw an error: "undefined symbol: _ZN5boost6system16generic_categoryEv"
But the point is the path which including boost has already been set by an embedded rpath, and some other boost file can be linked properly.
Does anybody ran into similar condition before? Any prompt would be really helpful.
TIPS: There isn't a LD_LIBRARY_PATH in my environment, so no overwritten.
Well, it solved by:
patchelf --add-needed libboost_system.so.1.55.0 libgusd.so
I guess I still a little confusing about the difference between linked-libraries and their paths... I thought all of the dynamic libraries will be linked automatically once the program needs them.

Understanding why gcc/ld are linking a symbol from a particular library using readelf

I'm including several libraries with gcc (-llapacke -llapack -lcblas) and I'm receiving "undefined reference" errors unless I explicitly link to the static version of one them (lapacke). I'm trying to understand why by searching the various variants of the offending library with nm and readelf. Let's take the "undefined" function zsysv_rook_:
% readelf -Wa /usr/lib/liblapacke.so | grep zsysv_rook_
00000000003c3978 000008d600000007 R_X86_64_JUMP_SLOT 000000000016e340 LAPACKE_zsysv_rook_work + 0
00000000003c5f20 000003c300000007 R_X86_64_JUMP_SLOT 0000000000000000 zsysv_rook_ + 0
963: 0000000000000000 0 FUNC GLOBAL DEFAULT UND zsysv_rook_
2262: 000000000016e340 884 FUNC GLOBAL DEFAULT 11 LAPACKE_zsysv_rook_work
That's the dynamic variant. This is the static variant:
% readelf -Wa /usr/lib/liblapacke.a | grep zsysv_rook_
00000000000000b2 0000000d00000004 R_X86_64_PLT32 0000000000000000 LAPACKE_zsysv_rook_work - 4
0000000000000146 0000000d00000004 R_X86_64_PLT32 0000000000000000 LAPACKE_zsysv_rook_work - 4
13: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND LAPACKE_zsysv_rook_work
File: /usr/lib/liblapacke.a(lapacke_zsysv_rook_work.o)
0000000000000186 0000000f00000004 R_X86_64_PLT32 0000000000000000 zsysv_rook_ - 4
0000000000000264 0000000f00000004 R_X86_64_PLT32 0000000000000000 zsysv_rook_ - 4
9: 0000000000000000 884 FUNC GLOBAL DEFAULT 1 LAPACKE_zsysv_rook_work
15: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND zsysv_rook_
Why does it compile only with the static version?
The symbol zsysv_rook_ is not defined by either library, so something in the library references it.
A static library is basically an archive of object files and the linker looks into the archive and links to each object that resolves an undefined reference in your program. If there are objects that define symbols that your program doesn't need, those objects will not be linked to. I assume what is happening is that the object that references zsysv_rook_ doesn't define any symbols you need, so that object isn't linked to, and your program doesn't need to resolve the zsysv_rook_ symbol.
When you link to a dynamic library (by default) you need to resolve all the undefined references needed by anything in the library, so because some part of the library refers to zsysv_rook_ you need to link to whatever provides it.
So if you want to use the dynamic library you need to figure out which library defines zsysv_rook_ and link to it. It's probably one of the other LAPACK libs, maybe one you're already linking to but you might be putting the -l option in the wrong place in the link command - the library that provides zsysv_rook_ needs to come after -llapacke in order to resolve the reference to it.

cmake tries to link resource file

How can I prevent cmake from linking MACOSX bundle resource files ?
When I add a resource file to a MACOSX application bundle, it is taken by the linker due to its .obj postfix. The linker tries to link it without success. He writes a warning:
Linking CXX executable mwe.app/Contents/MacOS/mwe
ld: warning: ignoring file ../star.obj, file was built for unsupported file format
( 0x23 0x20 0x42 0x6C 0x65 0x6E 0x64 0x65 0x72 0x20 0x76 0x32 0x2E 0x37 0x30 0x20 )
which is not the architecture being linked (x86_64): ../star.obj
Of course he cannot link it because star.obj is a 3D model text file in the obj format:
# Blender v2.70 (sub 0) OBJ File: 'star.blend'
o Plane
v 0.510396 -0.000389 0.998397
v -0.926169 -0.000017 -0.001603
v 0.510396 0.000355 -1.001603
[..and many more vertices]
The resulting problem is; the file is not put into the MACOSX bundle folder because the linker ignored it.
VisorZ#Mac ~/MWE> ll build/mwe.app/Contents/Resources/
total 8
-rw-r--r-- 1 Stephan staff 62B 6 Aug 22:36 star.off
(See, star.obj is missing here) ------------------------------------^
I would like to exclude that obj file from the link file lists via cmake.
But neither the source file properties
MACOSX_PACKAGE_LOCATION,
EXTERNAL_OBJECT FALSE,
LANGUAGE "myMODEL"
nor the target property
RESOURCE
can do that. Here is a minimum working example CMakeLists.txt:
# Minimum Working Example to create mwe.app on MACOSX with linker
# trying to process *.obj files which are marked as resource files
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(mwe)
SET_SOURCE_FILES_PROPERTIES(
star.obj # 3D model as OBJ txt file
star.off # 3D model as OFF txt file
PROPERTIES
MACOSX_PACKAGE_LOCATION Resources
)
ADD_EXECUTABLE(
${PROJECT_NAME}
MACOSX_BUNDLE # needs to be second argument, enables bundling
helloworld.cpp # will be compiled
star.obj # will not be bundled because it will be taken by linker
star.off # will be bundled
)
Use HEADER_FILE_ONLY and try not to think too much about the name of it.
set_source_files_properties(
star.obj # 3D model as OBJ txt file
star.off # 3D model as OFF txt file
PROPERTIES
HEADER_FILE_ONLY ON
)
If you want to stop the linker from trying to link the files you can add them to a custom target as such:
ADD_CUSTOM_TARGET (testTarget SOURCES myFile.obj myFile.off)
This is especially handy for having files show up in your project tree but not having them compiled/linked.

Avoid creating debug info in LKM with kbuild

I'm building Linux kernel module (LKM) from a big C files (>50 000 LOC). It's some generated RAID calculation code. When I try to build it from kbuild gcc eats all of the memory and crashes, while invoking gcc manually works fine.
After inspecting object files from manual gcc and kbuild I've found that kbuild object files is 20-30 times larger than manual gcc objects (900k vs 30M). And the reason is that kbuild object files contains giant section debug_info with tons of data.
Here is the fragment from objdump -x:
RELOCATION RECORDS FOR [.debug_info]:
OFFSET TYPE VALUE
0000000000000006 R_X86_64_32 .debug_abbrev
000000000000000c R_X86_64_32 .debug_str+0x0000000000000c41
0000000000000011 R_X86_64_32 .debug_str+0x0000000000000e26
0000000000000015 R_X86_64_32 .debug_str+0x0000000000000544
0000000000000019 R_X86_64_64 .text
0000000000000021 R_X86_64_64 .text+0x0000000000060957
0000000000000029 R_X86_64_32 .debug_line
0000000000000030 R_X86_64_32 .debug_str+0x0000000000000b78
0000000000000037 R_X86_64_32 .debug_str+0x000000000000011e
0000000000000040 R_X86_64_32 .debug_str+0x000000000000066b
0000000000000047 R_X86_64_32 .debug_str+0x0000000000000d38
000000000000004e R_X86_64_32 .debug_str+0x0000000000000bef
... another 60000 records ...
00000000000a0c8d R_X86_64_32 .debug_str+0x0000000000000add
00000000000a0ca0 R_X86_64_32 .debug_str+0x0000000000000526
00000000000a0cae R_X86_64_64 Calculation_1s_Func_Buf
I've already tried EXTRA_CFLAG += -S with no luck.
So is there any way to avoid creating debug info in my object files while building with kbuild?
Have you tried turning off CONFIG_DEBUG_INFO?
Look for it in 'Kernel Hacking' -> 'Compile-time checks and compiler options' -> 'Compile the kernel with debug info' in menuconfig.

Resources