CMake找到fftw库但无法链接

时间:2016-03-07 00:58:02

标签: linker cmake ros

我在使用cmake链接fftw库时遇到问题。我使用findFFTW.cmake文件来查找库。我知道这是成功找到库,因为我将REQUIRED标志设置为true以查找库并且make过程正常。

尽管将其与我的可执行文件链接,但我仍然收到未定义的引用错误。一些相关的帖子,我试过的解决方案。

Undefined reference to "function name from external library"

http://answers.ros.org/question/171326/catkin-linking-order-undefined-reference-to-symbol/

更新

感谢ComicSansMS,下面的CMake现在应该正确建模依赖关系。

CMake项目文件(更新3/7)

cmake_minimum_required(VERSION 2.8.3)
project(gist_extractor)

## Find catkin macros and libraries

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  image_transport
  cv_bridge
  sensor_msgs
  cmake_modules
)

find_package(OpenCV REQUIRED)
find_package(Eigen REQUIRED)
find_package(FFTW REQUIRED)


###########
## Build ##
###########

## Set GIST variables for building library
set(GIST_PATH /home/andy/Development/lear_gist-1.2)

## Specify additional locations of header files
include_directories(include ${catkin_INCLUDE_DIRS} ${GIST_PATH} ${FFTW_INCLUDES})

## Declare a gist library
add_library(gist SHARED ${GIST_PATH}/standalone_image.c ${GIST_PATH}/gist.c) # THIS IS NOT BEING BUILT 
target_link_libraries(gist ${FFTW_LIBRARIES})

## Add cmake target dependencies of the library
#MESSAGE( STATUS "GIST_LIBRARY_PATH: " ${GIST_PATH})

## Declare a C++ executable
add_executable(gist_extractor src/gist_extractor.cpp)
target_link_libraries(gist_extractor ${catkin_LIBRARIES} gist)

编辑2

如果我们使用上面的CMake文件,我们现在有一个链接错误。特别是当我尝试运行

时,make过程失败了
target_link_libraries(gist_extractor ${catkin_LIBRARIES} gist)

我有几点意见。首先,根据以下控制台消息正确构建我的gist库。

Linking C shared library /home/andy/Projects/ROS/robot_ws/devel/lib/libgist.so
[ 80%] Built target gist
Scanning dependencies of target gist_extractor
[100%] Building CXX object 
`gist_extractor/CMakeFiles/gist_extractor.dir/src/gist_extractor.cpp.o

但是当我们尝试将可执行文件与gist库链接时,我们可以看到存在未定义的引用错误。

Linking CXX executable gist_extractor
: undefined reference to `color_gist_scaletab'

这就是为什么我不明白为什么会这样。在gist_extractor.cpp中,我已经包含了包含' color_gist_scaletab'功能。具体来说,这个" color_gist_scaletab是在' gist.h'中定义的。并在' gist.c'中实施。我认为构建我的库gist可以让我访问' color_gist_scaletab'。我已在下面发布了相关文件。

gist.h

#ifndef GIST_H_INCLUDED
#define GIST_H_INCLUDED

#include "standalone_image.h"

/*! Graylevel GIST for various scales. Based on Torralba's Matlab
 * implementation. http://people.csail.mit.edu/torralba/code/spatialenvelope/
 *
 * Descriptor size is  w*w*sum(n_orientations[i],i=0..n_scale-1)
 *
 *    @param src Source image
 *    @param w Number of bins in x and y axis
 */

float *bw_gist_scaletab(image_t *src, int nblocks, int n_scale, const int *n_orientations);

/*! @brief implementation of grayscale GIST descriptor.
 * Descriptor size is w*w*(a+b+c)
 *
 *    @param src Source image
 *    @param w Number of bins in x and y axis
 */
float *bw_gist(image_t *scr, int nblocks, int a, int b, int c);

/*! @brief implementation of color GIST descriptor.
 *
 *    @param src Source image
 *    @param w Number of bins in x and y axis
 */

float *color_gist(color_image_t *src, int nblocks, int a, int b, int c);
/*! Color GIST for various scales. Based on Torralba's Matlab
 * implementation. http://people.csail.mit.edu/torralba/code/spatialenvelope/  */

float *color_gist_scaletab(color_image_t *src, int nblocks, int n_scale, const int *n_orientations);


#endif

gist_extractor.cpp

// color_gist_scaletab is defined in gist.h
// I'm including relevant header file 
#include "/home/andy/Development/lear_gist-1.2/gist.h"

//SOME MORE STUFF
// This is where I call the function
float *gist_descriptor = color_gist_scaletab(im, nblocks, n_scale, orientations_per_scale);

1 个答案:

答案 0 :(得分:0)

您似乎没有正确建模您的依赖项。

您使用gist.c内部的fftw,gistgist_extractor库目标的一部分。

但是,该目标不依赖于fftw,只有下游目标gist具有依赖性。这是一个麻烦的方法,特别是在静态构建中,其中工具链经常挑剔库在链接器命令行上出现的顺序。

将fftw作为依赖项添加到target_link_libraries(gist ${FFTW_LIBRARIES})

add_dependencies(gist_extractor gist)
target_link_libraries(gist_extractor ${GIST_PATH}/libleargist.a)

此外,没有必要这样做:

target_link_libraries(gist_extractor gist)

如果两个目标都是作为同一项目的一部分构建的,那么只需执行以下操作:

Map<String, String> urlVariables = new HashMap<>();
    urlVariables.put("ip_address", IP);
    urlVariables.put("port", PORT);

    ResponseObject state =
            restTemplate.getForObject("http://{ip_address}:{port}/state/", ResponseObject.class, urlVariables);

通过使用目标名称而不是硬编码输出文件,您不仅可以使构建脚本更具可移植性,还可以让CMake更好地跟踪目标之间的依赖关系。