简体   繁体   中英

CMake - linking error and undefined reference

Problem

I have written a ROS executable, which depends on some 3rd party C code.

// ROS NODE - gist_extractor.cpp 
extern "C"{
#include "gist/gist.h"
#include "gist/standalone_image.h"
}
/* Some Code */ 
float *gist_descriptor = color_gist_scaletab(im, nblocks, n_scale, orientations_per_scale); 

My CMake file for my ROS executable is

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  image_transport
  cv_bridge
  sensor_msgs
  cmake_modules
)

find_package(OpenCV REQUIRED)
find_package(FFTW REQUIRED)

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

## Specify additional locations of header files
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} include ${catkin_INCLUDE_DIRS} 
${FFTW_INCLUDES}
)

## Add subdirectory for gist library
add_subdirectory(gist)

## Declare a C++ executable
add_executable(gist_extractor src/gist_extractor.cpp)

## Specify libraries to link a library or executable target against
target_link_libraries(gist_extractor ${catkin_LIBRARIES} gist)

The function color_gist_scaletab() is declared in gist.h. Despite including the requisite .h file, when I make I have the following error.

gist_extractor.cpp:+0x35e):... undefined reference to `color_gist_scaletab'

Solution Steps

In this section, I trace through the steps of how to find the bug and how to fix it.

1. Check if the library is being built

After running MAKE in my build repository, we looked out the libraries being built. Since libgist.so appears is being built correctly.

-lboost_date_time /opt/ros/indigo/lib/libcpp_common.so -lboost_system -lboost_thread -lpthread -lconsole_bridge **/home/andy/Projects/ROS/robot_ws/devel/lib/libgist.so** 

2. Check if the desired function is being compiled.

In our case, we want color_gist_scaletab(). We ran the "strings" command in unix. The below command runs a regex match for "color_gist_scaletab()" in the library .so file. If the function is being linked properly, then it should appear in the .so file. We realized nothing returned for color_gist_scaletab(), which meant the function was not being compiled.

strings /home/andy/Projects/ROS/robot_ws/devel/lib/libgist.so | grep color_gist_scaletab

3. Determine why the function was not being compiled.

The first thing we did, was to go back into our function declaration and add an error statement (shown below).

float *color_gist_scaletab(color_image_t *src, int w, int n_scale, const int *n_orientation) 
{
    int i;
    #error COMPILER STEP SHOULD FAIL HERE 
    if(src->width < 8 || src->height < 8)
    {
        fprintf(stderr, "Error: color_gist_scaletab() - Image not big enough !\n");
        return NULL;
    }

If the function is being compiled properly, then the error macro would be thrown. But when we ran make, we only got the linking error, which meant that the function was not even being looked out. Weird!!

4. Finding the error The original gist.c file had a ifdef statement that was the source of our bug.

#ifdef USE_GIST

/*--------------------------------------------------------------------------*/

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

#include <fftw3.h>
#include <pthread.h>

#ifdef STANDALONE_GIST

#include "gist.h"
#else 
#include <image.h>
#include <descriptors.h>
#endif

The USE_GIST variable was never defined everything below that ifdef was being ignored. Hence, we decided to look at the original make file.

gist.o: gist.c gist.h standalone_image.h
    gcc -c -Wall -g $< $(WFFTINC) -DUSE_GIST -DSTANDALONE_GIST

AHA! -DUSE_GIST was being defined in the original make file. In other words, we needed to update our original CMAKE file to also define USE_GIST variable. So we went back to our CMAKE file for building the gist library and appended the add_definitions().

project(gist)
find_package(FFTW REQUIRED)
add_library(gist gist.c standalone_image.c)
add_definitions(-DUSE_GIST -DSTANDALONE_GIST)
target_link_libraries(gist ${FFTW_LIBRARIES}) 

After making with this new CMAKE file, we successfully compiled.

andy@andy-MacBookPro:~/Projects/ROS/robot_ws/build$ make
Scanning dependencies of target gist
[ 20%] Building C object gist_extractor/gist/CMakeFiles/gist.dir/gist.c.o
[ 40%] Building C object gist_extractor/gist/CMakeFiles/gist.dir/standalone_image.c.o
Linking C shared library /home/andy/Projects/ROS/robot_ws/devel/lib/libgist.so
[ 40%] Built target gist
Linking CXX executable gist_extractor
[ 60%] Built target gist_extractor
[ 80%] Building CXX object simple_talker/CMakeFiles/listener.dir/src/listener.cpp.o
Linking CXX executable /home/andy/Projects/ROS/robot_ws/devel/lib/simple_talker/listener
[ 80%] Built target listener
[100%] Building CXX object simple_talker/CMakeFiles/talker.dir/src/talker.cpp.o
Linking CXX executable /home/andy/Projects/ROS/robot_ws/devel/lib/simple_talker/talker
[100%] Built target talker

You need to add the external library after "gist" in your target_link_libraries line. Use an absolute path if you must to where it is located on your machine (or wherever the library containing the compiled definition for color_gist_scaletab(color_image_t*, int, int, int const*) is located).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM