0
$\begingroup$

Rosanswers logo

[Note: Prior to this question, my code and package compiled and functioned properly, the issue came from rearranging my file structure etc.]

I am trying to make a single node reusable by separating it into multiple files. This is probably more of a c++ question, but I'm not sure if i need to do something different in my code, or in my CMakeLists...

My original file had this structure:

#include <head_loc/manythings.h>
class ClassName
{
private:
    Multiple ClassVariables;
public:
  ClassName()    // Constructor for publishers etc..
    {    }
  output function1()     // do 1st thing
    {    }
  output functionN()     // do Nth thing
    {    }
};
int main(int argc, char** argv)
{
    ros::init(argc, argv, "ClassName_Node");
    ClassName CN;
    ros::spin();
    return 0;
}

My three new files have this structure: Node file:

#include <classheader.h>
int main(int argc, char** argv)
{
  ros::init(argc, argv, "ClassName_Node");
  ClassName CN;
  ros::spin();
  return 0;
}

Header file :

#ifndef _CLASSHEADER_H
#define _CLASSHEADER_H
#include <head_loc/manythings.h>
class ClassName
{
private:
  Multiple ClassVariables;
public:
  ClassName();    // Constructor for publishers etc..
  output function1();     // do 1st thing
  output functionN();     // do Nth thing
};
#endif

Class fucntions :

#include <classheader.h>
ClassName::ClassName()    // Constructor for publishers etc..
{    }
output ClassName::function1()     // do 1st thing
{    }
output ClassName::functionN()     // do Nth thing
{    }

I assumed this format to allow two different ROS nodes to call and use the same class. I get a compile error (truncated to what i believe is the relevant error codes) :

[100%] Building CXX object CMakeFiles/handrail_end_class.dir/src/handrail_end_class.cpp.o
Linking CXX executable /home/benjamin/r2_hydro/devel_isolated/lib/nasa_r2_vision_handrail/handrail_end_class
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 10
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 1 has invalid symbol index 11
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 2 has invalid symbol index 2
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 3 has invalid symbol index 2
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 4 has invalid symbol index 10
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 5 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 6 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 7 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 8 has invalid symbol index 2
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 9 has invalid symbol index 2
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 10 has invalid symbol index 11
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 11 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 12 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 13 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 14 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 15 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 16 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 17 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 18 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 19 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 20 has invalid symbol index 19
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
make[2]: *** [/home/benjamin/r2_hydro/devel_isolated/lib/nasa_r2_vision_handrail/handrail_end_class] Error 1
make[1]: *** [CMakeFiles/handrail_end_class.dir/all] Error 2
make: *** [all] Error 2

I've searched the web and found that in non-ROS environments, this error comes from a missing main function, but I assumed the node c++ file would be sufficient. I believe I need to make some small change to make this work, I'm not sure where. For reference here is a similarly simplified CMakeLists.txt [The only difference is adding the three lines near the end for "class_functions" ]

cmake_minimum_required(VERSION 2.8.3)
project(nasa_r2_vision_handrail)

find_package(
  catkin REQUIRED COMPONENTS 
  other_things
  )

find_package(PCL REQUIRED)
find_package(OpenCV REQUIRED)

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

# Generate messages in the 'msg' folder
add_message_files(FILES message.msg)

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

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

###################################
## catkin specific configuration ##
###################################

catkin_package(
  CATKIN_DEPENDS 
  other_things
  DEPENDS PCL OpenCV
)

###########
## Build ##
###########

## Specify additional locations of header files
include_directories(include ${PCL_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})

add_executable(       class_node   src/class_node.cpp)
add_dependencies(     class_node   ${catkin_EXPORTED_TARGETS})
target_link_libraries(class_node   ${catkin_LIBRARIES}  ${PCL_LIBRARIES}  ${OpenCV_LIBRARIES})

add_executable(       class_functions   src/class_functions.cpp)
add_dependencies(     class_functions   ${catkin_EXPORTED_TARGETS})
target_link_libraries(class_functions   ${catkin_LIBRARIES}  ${PCL_LIBRARIES}  ${OpenCV_LIBRARIES})


#############
## Install ##
#############

#############
## Testing ##
#############

[Edit to address Miquel's first answer] Still getting errors. 1)Naively adding line as provided:

Target "handrail_end_class" of type EXECUTABLE may not be linked into another target.
  1. Also adding

    set_target_properties(class_functions PROPERTIES ENABLE_EXPORTS ON)

Back to the original error message

  1. Injecting "class_functions" to first bank of calls instead of adding previous two lines:

    target_link_libraries(class_node class_functions ${catkin_LIBRARIES} ${PCL_LIBRARIES} ${OpenCV_LIBRARIES})

Same error as original and second attempt


Originally posted by benabruzzo on ROS Answers with karma: 79 on 2015-03-12

Post score: 2

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

You have to change

add_executable(       class_node   src/class_node.cpp)
add_dependencies(     class_node   ${catkin_EXPORTED_TARGETS})
target_link_libraries(class_node   ${catkin_LIBRARIES}  ${PCL_LIBRARIES}  ${OpenCV_LIBRARIES})

add_executable(       class_functions   src/class_functions.cpp)
add_dependencies(     class_functions   ${catkin_EXPORTED_TARGETS})
target_link_libraries(class_functions   ${catkin_LIBRARIES}  ${PCL_LIBRARIES}  ${OpenCV_LIBRARIES})

either for

add_library(       class_functions_lib   src/class_functions.cpp)
add_dependencies(     class_functions_lib   ${catkin_EXPORTED_TARGETS})
target_link_libraries( class_functions_lib   ${catkin_LIBRARIES}  ${PCL_LIBRARIES}  ${OpenCV_LIBRARIES})

add_executable(       class_node   src/class_node.cpp)
add_dependencies(     class_node   ${catkin_EXPORTED_TARGETS})
target_link_libraries( class_node class_functions_lib   ${catkin_LIBRARIES}  ${PCL_LIBRARIES}  ${OpenCV_LIBRARIES})

or for

add_executable(       class_node   src/class_node.cpp  src/class_functions.cpp )
add_dependencies(     class_node   ${catkin_EXPORTED_TARGETS})
target_link_libraries( class_node ${catkin_LIBRARIES}  ${PCL_LIBRARIES}  ${OpenCV_LIBRARIES})

.

The first version creates you a lib ( shared object (.so) file ) and links your exec to your lib. The second version compiles boths source files to object files (.o) and links them both to an executable file containing compiled code of all your files.


Originally posted by Wolf with karma: 7555 on 2015-03-13

This answer was ACCEPTED on the original site

Post score: 7


Original comments

Comment by benabruzzo on 2015-03-13:
This fixes it, thank you!

Comment by jwin on 2019-01-03:
@Wolf thanks it worked great. I know this post is old now, but which of the two options do you recommend? Linking to a shared object (library) or linking to multiple object files?

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.