CMake - ошибка связи и неопределенная ссылка
проблема
Я написал исполняемый файл 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);
Мой файл CMake для моего исполняемого файла ROS
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(). Мы запустили команду "strings" в Unix. Приведенная ниже команда запускает сопоставление регулярного выражения для "color_gist_scaletab()" в файле библиотеки.so. Если функция связана правильно, она должна появиться в файле.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, мы получили только ошибку компоновки, что означало, что функция даже не просматривается. Weird!!
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 для создания библиотеки 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 ответ
Вам нужно добавить внешнюю библиотеку после "gist" в вашей строке target_link_libraries. Используйте абсолютный путь, если вам нужно, где он находится на вашем компьютере (или там, где находится библиотека, содержащая скомпилированное определение для color_gist_scaletab(color_image_t*, int, int, int const*)).