【问题标题】:CMake finds fftw library but cannot linkCMake 找到 fftw 库但无法链接
【发布时间】:2016-03-07 00:58:02
【问题描述】:

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

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

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”中实现。我认为建立我的图书馆要点应该让我可以访问“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);

【问题讨论】:

    标签: linker cmake ros


    【解决方案1】:

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

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

    但是,该目标不依赖于 fftw,只有下游目标 gist_extractor 具有。这是一个麻烦的秘诀,尤其是在静态构建中,工具链通常对库在链接器命令行上出现的顺序很挑剔。

    将 fftw 作为依赖添加到 gist:

    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)
    

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

    【讨论】:

    • 嘿。感谢cmets。这太有用了!
    • 对依赖关系建模的方式很有意义。在采纳您的建议后,我意识到我的库“gist”尚未建立。结果我仍然得到未定义的符号错误。您有什么想法为什么会出现这种情况以及我该如何解决?正是这个问题迫使我对 libleargist.a 进行硬编码。我更新了原始帖子中的代码以更好地解释这一点。
    • @AndyLee 你确定gist 没有建立吗?因为您发布的代码中没有任何内容会导致这种情况。尝试从命令行运行make gist。你不应该收到任何投诉。
    • 抱歉,gist 实际上正在构建,因为我可以找到 libgist.so 文件。真正的问题是当我尝试 target_link_libraries(gist_extractor gist ...) 时出现链接器错误。我的可执行 gist_extractor 出现未定义的参考错误。我在 gist_extractor.cpp 中包含了相关的头文件,并且我现在正在正确地建模依赖关系,所以我不明白为什么会出现这个问题。我用相关代码更新了 EDITS2 下的帖子。任何帮助将不胜感激。