2016-02-26 5 views
0

ПроблемыCMake - увязка ошибка и неопределенная ссылка

Я написал 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); 

Мой 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 

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 мы успешно скомпилировали.

[email protected]:~/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 *)).

+0

Не можете ли вы представить пример кода, как изменить мой файл CMake? Я добавил библиотеку, а также связал библиотеку с target_link_libraries. Но это еще не проблема. Благодаря! –

+0

Итак, в файле CMake вы буквально просто вводите путь к библиотеке, содержащей предварительно скомпилированное определение color_gist_scaletab() после «$ catkin_LIBRARIES» в записи target_link_libraries. Итак, финальная часть этой строки будет выглядеть как target_link_libraries (... $ {catkin_LIBRARIES} /usr/local/lib/library.so ...) и т. Д. Если это не сработает, то ваша версия предварительно скомпилированной библиотеки не будет Включить определение этой функции. Загрузите архив из библиотеки gist, который имеет правильную версию функции, которую вы хотите, и перекомпилируйте новый объект библиотеки для компоновщика. –

+0

Спасибо. Это сработало! Я отправлю обновленный код через несколько дней. –