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

CMake - linking error and undefined reference

问题

我已经编写了一个 ROS 可执行文件,它依赖于一些第 3 方 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 语句,它是我们错误的来源。

#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

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

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