CMake - 链接错误和未定义的引用

时间:2016-02-26 21:50:54

标签: c++ cmake shared-libraries ros

问题

我编写了一个ROS可执行文件,它依赖于某些第三方C代码。

// 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); 

我的ROS可执行文件的CMake文件是

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)

函数 color_gist_scaletab()在gist.h中声明。尽管包含了必需的.h文件,但当我犯下以下错误时。

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

解决方案步骤

在本节中,我将介绍如何查找错误以及如何修复错误的步骤。

1。检查库是否正在构建

在我的构建存储库中运行MAKE之后,我们查看了正在构建的库。由于libgist.so出现正在正确构建。

-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。检查是否正在编译所需的功能。

在我们的例子中,我们需要color_gist_scaletab()。我们在unix中运行了“strings”命令。以下命令在库.so文件中为“color_gist_scaletab()”运行正则表达式匹配。如果函数正确链接,则它应出现在.so文件中。我们没有意识到color_gist_scaletab()没有返回任何内容,这意味着函数没有被编译。

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

3。确定函数未编译的原因。

我们做的第一件事是回到我们的函数声明并添加一个错误声明(如下所示)。

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;
    }

如果正确编译函数,则会抛出错误宏。但是当我们运行make时,我们只得到了链接错误,这意味着该函数甚至没有被查看。奇怪的!!

4。找到错误 原始的gist.c文件有一个ifdef语句,它是我们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

USE_GIST变量从未定义过ifdef被忽略的所有内容。因此,我们决定查看原始的make文件。

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

AHA! -DUSE_GIST正在原始make文件中定义。换句话说,我们需要更新我们的原始CMAKE文件以定义USE_GIST变量。所以我们回到我们的CMAKE文件来构建gist库并附加了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}) 

使用这个新的CMAKE文件后,我们成功编译了。

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

1 个答案:

答案 0 :(得分:1)

您需要在target_link_libraries行中的“gist”之后添加外部库。如果必须在机器上的位置(或包含color_gist_scaletab(color_image_t *,int,int,int const *)的编译定义的库所在的位置),请使用绝对路径。