You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ROS服务端/客户端编译报错:multiple definition of `main' 求助

问题描述

Ubuntu 20.04、cmake 3.26.0-rc4环境下,编译带边缘检测类的ROS Service服务端/客户端时,出现multiple definition of 'main'错误。已将main函数分别放在不同.cpp文件中,怀疑CMakeLists.txt配置有误。

报错信息

/usr/bin/ld:
CMakeFiles/TARGET_NAME.dir/src/edge_srv_server_node.cpp.o:
in function main':edge_srv_server_node.cpp: (.text.startup+0x0): multiple definition of main';
CMakeFiles/TARGET_NAME.dir/src/edge_srv_client_node.cpp.o:
edge_srv_client_node.cpp:(.text.startup+0x0): first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/TARGET_NAME.dir/build.make:214:
~/catkin_ws/devel/.private/edge_detection/lib/libTARGET_NAME.so]
Error 1
make[1]: *** [CMakeFiles/Makefile2:1295:
CMakeFiles/TARGET_NAME.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:146: all] Error 2

当前CMakeLists.txt内容

cmake_minimum_required(VERSION 3.9.1)

########################################################################################################################
# Metadata
########################################################################################################################
# Read the package manifest.
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/package.xml" package_xml_str)

# Extract project name.
if(NOT package_xml_str MATCHES "<name>([A-Za-z0-9_]+)</name>")
  message(FATAL_ERROR "Could not parse project name from package manifest (aborting)")
else()
  set(extracted_name ${CMAKE_MATCH_1})
endif()

# Extract project version.
if(NOT package_xml_str MATCHES "<version>([0-9]+.[0-9]+.[0-9]+)</version>")
  message(FATAL_ERROR "Could not parse project version from package manifest (aborting)")
else()
  set(extracted_version ${CMAKE_MATCH_1})
endif()

########################################################################################################################
# CMake project
########################################################################################################################
project(${extracted_name} VERSION ${extracted_version})

## Compile as C++11, supported in ROS Kinetic and newer
add_compile_options(-std=c++11)

find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  message_generation
  std_msgs
  geometry_msgs
  sensor_msgs
)

################################################
## Declare ROS messages, services and actions ##
################################################

## Generate services in the 'srv' folder
add_service_files(
  FILES
  DetectEdges.srv
)

## Generate added messages and services with any dependencies listed here
generate_messages(
  DEPENDENCIES
  std_msgs
  geometry_msgs
  sensor_msgs
)


###################################
## catkin specific configuration ##
###################################
catkin_package(
 INCLUDE_DIRS 
   include
 LIBRARIES 
   edge_detection
 CATKIN_DEPENDS 
   geometry_msgs 
   std_msgs 
   message_runtime
#  DEPENDS 
#   system_lib
)

###########
## Build ##
###########
include_directories(
  include
  ${catkin_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
)

file(GLOB_RECURSE CPP_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp)

set(SOURCES ${CPP_FILES})
add_library(TARGET_NAME SHARED ${SOURCES})
target_include_directories(TARGET_NAME PUBLIC ${INCLUDE_DIRECTORIES} )
target_link_libraries(TARGET_NAME ${OpenCV_LIBS} ${catkin_LIBRARIES}) # fill this up with the dependencies you want for eg opencv

add_executable(edge_detection_bin src/EdgeDetector.cpp )
target_include_directories(edge_detection_bin PUBLIC ${INCLUDE_DIRECTORIES} )
target_link_libraries(edge_detection_bin TARGET_NAME)

add_executable(edge_srv_server_node src/edge_srv_server_node.cpp)
target_link_libraries(edge_srv_server_node ${OpenCV_LIBS} ${catkin_LIBRARIES} edge_detection)
add_dependencies(edge_srv_server_node edge_detection)

add_executable(edge_srv_client_node src/edge_srv_client_node.cpp)
target_link_libraries(edge_srv_client_node ${catkin_LIBRARIES} edge_detection)
add_dependencies(edge_srv_client_node edge_detection)

## Declare a C++ library
add_library(${PROJECT_NAME}
  src/EdgeDetector.cpp
)
解决方案

错误根源是你用file(GLOB_RECURSE CPP_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp)把所有src下的cpp文件(包括带main函数的服务端、客户端节点文件)都打包进了TARGET_NAME共享库。库文件里不能包含main函数,因为每个可执行程序只能有一个main入口,而你把两个带main的文件都放进库,后续编译可执行文件时就会出现重复定义。

修复步骤:

  1. 移除通过GLOB_RECURSE批量打包所有cpp到库的代码,改为仅将无main函数的类实现文件(比如EdgeDetector.cpp)加入库。
  2. 清理冗余的可执行文件定义(比如edge_detection_bin是多余的,因为EdgeDetector是类不是可执行程序)。
  3. 确保服务端、客户端可执行文件仅链接必要的库,不重复打包代码。

修改后的关键Build部分代码:

###########
## Build ##
###########
include_directories(
  include
  ${catkin_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
)

# 仅将类实现文件加入库,排除带main的节点文件
add_library(${PROJECT_NAME}
  src/EdgeDetector.cpp
)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} ${catkin_LIBRARIES})

# 编译服务端节点,仅用自身cpp文件,链接项目库
add_executable(edge_srv_server_node src/edge_srv_server_node.cpp)
target_link_libraries(edge_srv_server_node ${PROJECT_NAME} ${OpenCV_LIBS} ${catkin_LIBRARIES})
add_dependencies(edge_srv_server_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

# 编译客户端节点,仅用自身cpp文件,链接项目库
add_executable(edge_srv_client_node src/edge_srv_client_node.cpp)
target_link_libraries(edge_srv_client_node ${PROJECT_NAME} ${catkin_LIBRARIES})
add_dependencies(edge_srv_client_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

额外注意点:

  • 不要用GLOB_RECURSE批量添加源文件到库,显式列出需要的文件更可靠,避免意外包含入口文件。
  • 可执行文件的依赖项建议使用${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS},确保ROS消息/服务生成的目标被正确依赖。
  • 移除冗余的TARGET_NAME库和edge_detection_bin可执行文件定义,避免重复编译和链接错误。

内容的提问来源于stack exchange,提问作者Bilal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 22:35:15