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*) 的已编译定义的库所在的位置),请使用绝对路径。
问题
我已经编写了一个 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*) 的已编译定义的库所在的位置),请使用绝对路径。