ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

ros2 galactic package with custom lib inside returns undefined reference

asked 2021-07-05 17:52:18 -0600

inflo gravatar image

updated 2021-07-09 17:20:39 -0600

hi, i try to build a ros2 galactic package with code from waveshare ad/da raspberry pi hat (https://www.waveshare.com/wiki/High-P...) . The package and lib compiles, but it does not link, it returns undefined reference

[ 40%] Building C object CMakeFiles/ADS1256.dir/src/ADS1256.c.o
[ 60%] Linking C shared library libADS1256.so
[ 60%] Built target ADS1256
Scanning dependencies of target ros2_galactic_waveshare_adc_node
[ 80%] Building CXX object CMakeFiles/ros2_galactic_waveshare_adc_node.dir/src/ros2_galactic_waveshare_adc_node.cpp.o
[100%] Linking CXX executable ros2_galactic_waveshare_adc_node
/usr/bin/ld: CMakeFiles/ros2_galactic_waveshare_adc_node.dir/src/ros2_galactic_waveshare_adc_node.cpp.o: in function `WaveshareAdcPublisher::WaveshareAdcPublisher()':
ros2_galactic_waveshare_adc_node.cpp:(.text._ZN21WaveshareAdcPublisherC2Ev[_ZN21WaveshareAdcPublisherC5Ev]+0x2de): undefined reference to `DEV_ModuleInit()'
/usr/bin/ld: ros2_galactic_waveshare_adc_node.cpp:(.text._ZN21WaveshareAdcPublisherC2Ev[_ZN21WaveshareAdcPublisherC5Ev]+0x2e3): undefined reference to `ADS1256_init()'
/usr/bin/ld: ros2_galactic_waveshare_adc_node.cpp:(.text._ZN21WaveshareAdcPublisherC2Ev[_ZN21WaveshareAdcPublisherC5Ev]+0x2f5): undefined reference to `DEV_ModuleExit()'
/usr/bin/ld: CMakeFiles/ros2_galactic_waveshare_adc_node.dir/src/ros2_galactic_waveshare_adc_node.cpp.o: in function `WaveshareAdcPublisher::timer_callback()':
ros2_galactic_waveshare_adc_node.cpp:(.text._ZN21WaveshareAdcPublisher14timer_callbackEv[_ZN21WaveshareAdcPublisher14timer_callbackEv]+0x4d): undefined reference to `ADS1256_GetAll(unsigned int*)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/ros2_galactic_waveshare_adc_node.dir/build.make:138: ros2_galactic_waveshare_adc_node] Error 1
make[1]: *** [CMakeFiles/Makefile2:80: CMakeFiles/ros2_galactic_waveshare_adc_node.dir/all] Error 2
make: *** [Makefile:141: all] Error 2
Failed   <<< ros2_galactic_waveshare_adc [9.83s, exited with code 2]

What do i miss in my CMakeLists.txt file that it could build ? My CMakeLists.txt file and code is here: https://github.com/flobotics/ros2_gal...

thanks in advance flo


Edit:

i put the .c files into a separate ros2 lib package and in my package i do e.g. find_package() and it does find it

-- Found ros2_galactic_waveshare_adc_lib: 0.0.0 (/home/ros2/dev_ws/install/ros2_galactic_waveshare_adc_lib/share/ros2_galactic_waveshare_adc_lib/cmake)

i use

ament_target_dependencies(ros2_galactic_waveshare_adc_node
                            rclcpp 
                            std_msgs 
                            ros2_galactic_waveshare_adc_interfaces
                            ros2_galactic_waveshare_adc_lib
                            )

but then i get:

[ 50%] Linking CXX executable ros2_galactic_waveshare_adc_node
/usr/bin/ld: CMakeFiles/ros2_galactic_waveshare_adc_node.dir/src/ros2_galactic_waveshare_adc_node.cpp.o: in function `WaveshareAdcPublisher::WaveshareAdcPublisher()':
ros2_galactic_waveshare_adc_node.cpp:(.text._ZN21WaveshareAdcPublisherC2Ev[_ZN21WaveshareAdcPublisherC5Ev]+0x2de): undefined reference to `DEV_ModuleInit()'
/usr/bin/ld: ros2_galactic_waveshare_adc_node.cpp:(.text._ZN21WaveshareAdcPublisherC2Ev[_ZN21WaveshareAdcPublisherC5Ev]+0x2e3): undefined reference to `ADS1256_init()'

i read many, also https://answers.ros.org/question/3509...

but also that does not work ??


Edit 2: if i use colcon --log-level=10 build i can see that there is no "-lros2_galactic_waveshare_adc_lib" for the linker, and so the linker returns undefined reference. I testet the ros2-build lib with a test main.c file, and only when i miss "-lros2_galactic_waveshare_adc_lib" in my gcc build command, it returns undefined reference.

How do i add a compiler or linker option?

add_compile_option() does not seem to work?


edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2021-07-09 14:46:47 -0600

gvdhoorn gravatar image

updated 2021-07-09 14:50:38 -0600

Isn't this just a regular C++ mangles C symbols but the library exports non-mangled symbols problem?

Is the waveshare lib plain C, or does it use C++? If the former, you need to enclose the #includes of the waveshare's headers with extern "C" { ... }, to prevent the C++ compiler from mangling all the function names and the linker then not being able to find them in the library.

Note: this is not special or specific to ROS 2, it's always a problem when linking C with C++.

See #q227146 and #q381206 for similar issues.

edit flag offensive delete link more

Comments

hi, thanks for your answer. I got it working. Yes your right, its C++ name mangling and using extern "C" removes these errors.

the big thing for me was wiringPi, for use with ubuntu-20.04 and raspberry pi 4. Its solved with installing sudo apt install ibwiringpi-dev and in CMakeLists.txt adding

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic -lpthread -lm -lwiringPi) endif()

target_link_libraries(my_node wiringPi)

I also wrote a tutorial about it, perhaps it gets merged into ros_documentation.

thanks

inflo gravatar image inflo  ( 2021-07-09 17:24:25 -0600 )edit

and in CMakeLists.txt adding

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic -lpthread -lm -lwiringPi) endif()

That's not really the "CMake way" and I doubt it'd be accepted into ros2_documentation.

Perhaps an IMPORTED library would be better, or a Find...cmake script.

target_link_libraries(my_node wiringPi)

If you're already linking with -lwiringPi, why link it here again?

gvdhoorn gravatar image gvdhoorn  ( 2021-07-10 00:37:04 -0600 )edit

I tested it, without target_link_libraries() it returns undefined references to e.g. digitalWrite(), a function from wiringPi lib. Its perhaps not the cmake way, but the official ROS 2 documentation also uses target_link_libraries https://docs.ros.org/en/ros2_document...

inflo gravatar image inflo  ( 2021-07-10 12:38:21 -0600 )edit

Linking libraries using add_compile_options(..) is not something you should do.

target_link_libraries(..)is what you should use.

gvdhoorn gravatar image gvdhoorn  ( 2021-07-10 12:39:40 -0600 )edit

but using add_compile_options() is also recommended by official ROS 2 documentation. https://docs.ros.org/en/galactic/Guid... states :

it is at the moment recommended to use the directory level function add_compile_options(-Wall) to not clutter the code with target-based compile options for all executables and tests.

inflo gravatar image inflo  ( 2021-07-11 09:09:05 -0600 )edit

You're linking libraries using add_compile_options(..). That's not what it's for.

The "ROS 2 documentation" also doesn't recommend that. It states that add_compile_options(..) should be used at directory level if you're going to use add_compile_options(..) for what it is intended in the first place.

If you don't believe me, try searching for whether add_compile_options(..) should be used for linking, and don't limit yourself to ROS or ROS 2.

gvdhoorn gravatar image gvdhoorn  ( 2021-07-11 13:34:53 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2021-07-05 17:52:18 -0600

Seen: 1,066 times

Last updated: Jul 09 '21