c++ - CMake - 链接错误和 undefined reference

标签 c++ cmake shared-libraries ros

问题

我已经编写了一个 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*) 的编译定义的库所在的位置)。

关于c++ - CMake - 链接错误和 undefined reference ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35662421/

相关文章:

c++ - 使用 std::sort 对迭代器进行排序

c++ - 知道在 Visual Studio 上运行的是哪个版本的 c++

android - 如何使用Android中的库所使用的库

c++ - 在类矩阵 mat(m,n) 中初始化 vector<vector<int>> data(m, vector<int>(n))

c++ - C++ 中的编译错误

c++ - 以编程方式分析故障转储

c++ - CMake 在我的主机中找不到用于交叉编译器的 boost 库,但在 Raspberry Pi 中找到了

python - opencv安装中的python错误

python - Linux 上的 MATLAB MEX 文件无法在 libpython.2.7.so 中找到符号

c - 共享库中的全局变量