Using asio but link error in pthread
Hi guys,
I am trying to compile a simple UDP server in ROS 2. I am using the async library ASIO as stand-alone. It's a header only library so I don't need to link to it. I tried to compile the code but I got the following link errors for pthread
--- stderr: oam_api
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
CMakeFiles/udp_server_main.dir/src/udp_server_main.cpp.o: In function `asio::detail::posix_event::posix_event()':
udp_server_main.cpp:(.text._ZN4asio6detail11posix_eventC2Ev[_ZN4asio6detail11posix_eventC5Ev]+0x4d): undefined reference to `pthread_condattr_setclock'
CMakeFiles/udp_server_main.dir/src/udp_server_main.cpp.o: In function `asio::detail::posix_thread::~posix_thread()':
udp_server_main.cpp:(.text._ZN4asio6detail12posix_threadD2Ev[_ZN4asio6detail12posix_threadD5Ev]+0x26): undefined reference to `pthread_detach'
CMakeFiles/udp_server_main.dir/src/udp_server_main.cpp.o: In function `asio::detail::posix_thread::join()':
udp_server_main.cpp:(.text._ZN4asio6detail12posix_thread4joinEv[_ZN4asio6detail12posix_thread4joinEv]+0x2b): undefined reference to `pthread_join'
collect2: error: ld returned 1 exit status
make[2]: *** [udp_server_main] Error 1
make[1]: *** [CMakeFiles/udp_server_main.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
make: *** [all] Error 2
I am not sure what is the problem since I added the -pthread
option to the compiler flags. Here are the CMakeLists.txt
and package.xml
file:
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(oam_api)
# Default to C99
if(NOT CMAKE_C_STANDARD)
set(CMAKE_C_STANDARD 99)
endif()
# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# for compiling asio
add_compile_options(-DASIO_STANDALONE -pthread)
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
include_directories(include)
set(CONFIGURATOR_LIB_SRC
src/oam_api.cpp
)
add_library(${PROJECT_NAME} SHARED
${CONFIGURATOR_LIB_SRC}
)
add_executable(udp_server_main src/udp_server_main.cpp)
target_include_directories(udp_server_main PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
install(TARGETS udp_server_main
EXPORT export_${PROJECT_NAME}
DESTINATION lib/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
find_package(ament_cmake_gtest REQUIRED)
# exclude some default linters from ament_lint
list(APPEND AMENT_LINT_AUTO_EXCLUDE
ament_cmake_uncrustify
)
list(APPEND AMENT_LINT_AUTO_EXCLUDE
ament_cmake_copyright
)
ament_lint_auto_find_test_dependencies()
# Add a gtest executables
ament_add_gtest(${PROJECT_NAME}-test
test/test_oam_api.cpp
)
target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
endif() # BUILD_TESTING
ament_package()
The package.xml file
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>oam_api</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="root@todo.todo">root</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake_auto</buildtool_depend>
<depend>rclcpp</depend>
<test_depend>ament_cmake</test_depend>
<test_depend>ament_cmake_gtest</test_depend>
<test_depend>rclcpp</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
Edit
I found the reason for the
undefined reference to `main'
error. I put the main() function inside a namespace so there was no global main. newbie mistake
ignoring all the rest: you don't seem to be including any object file which contains a
main(..)
function.That would be something to fix as well.
And:
please don't abuse
add_compile_options(..)
to link to additional libraries. That's really not very nice.If you really must add pthread, use FindThreads.
You also don't appear to
find_package(..)
Asio anywhere. You may not need to link against it, but you should certainly make sure the system you're attempting to build your source code on actually has it installed and add its location to the include path.@gvdhoorn
Thanks for the reply. Would I still need to add the find_package(..) part even if the Asio library is all-header? I already included the asio library in the include directories so I guess it will find it there.
Am i overusing the add_compile_options(..)? Sorry, didn't know. What do you suggest I do instead?
For the main() part. I have a main() function in the src/udp_server_main.cpp file so I am not sure what is causing the undefined main error.
I got the error for undefined reference to 'main'.
I put the main function inside a namespace declaration. sorry, newbie mistake
This is really more of a generic CMake question than a ROS one, but:
find_package(..)
it. Search for "cmake header only" and you'll find a ton of referencesadd_compile_options(..)
: just don't use it at all for this. UseFindThreads
, as I linked above