繁体   English   中英

仅当我在自己的库中使用犰狳链接错误时,

[英]Armadillo linking error only if I use it in my own library

在自己的库中使用犰狳时,我遇到了一些麻烦。 我安装了Armadillo,并创建了自己的库,该库调用svd_econ方法。 这是CMakeList.txt文件:

cmake_minimum_required (VERSION 2.8.9)
set(PROJECTNAME training_library)
project(${PROJECTNAME})

if (NOT DEFINED ENV{EIGEN_ROOT})
message(FATAL_ERROR "Could not find EIGEN_ROOT environment variable")
endif()

find_package(Armadillo REQUIRED)

include_directories("$ENV{EIGEN_ROOT}")

add_definitions(-g)
add_definitions(-O3)
add_definitions(-DNDEBUG)

include_directories(${ARMADILLO_INCLUDE_DIRS})
include_directories(${PROJECT_SOURCE_DIR}/include)

file(GLOB header include/*.h)
file(GLOB source src/*.cpp)

source_group("Source Files" FILES ${source})
source_group("Header Files" FILES ${header})

add_library(${PROJECTNAME} ${source} ${header})
target_link_libraries(${PROJECTNAME} ${ARMADILLO_LIBRARIES})

这是头文件:

#include <algorithm>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <armadillo>
#include <Eigen/Dense>
#include <Eigen/SVD>

namespace statistics
{
  bool findPCS(const Eigen::MatrixXd &data, Eigen::VectorXd &eigenvalues, Eigen::MatrixXd &eigenvectors);
}

#endif

这是.cpp:

#include "statistics.h"

namespace statistics
{

Eigen::MatrixXd convert(const arma::mat &data)
{
  Eigen::MatrixXd res(data.n_rows,data.n_cols);
  for (int i = 0; i < data.n_rows; i++)
  {
    for (int j = 0; j < data.n_cols; j++)
    {
      res(i,j) = data(i,j);
    }
  }
  return res;  
}

arma::mat convert(const Eigen::MatrixXd &data)
{
  arma::mat res(data.rows(),data.cols());
  for (int i = 0; i < data.rows(); i++)
  {
    for (int j = 0; j < data.cols(); j++)
    {
      res(i,j) = data(i,j);
    }
  }
  return res;  
}

Eigen::VectorXd convert(const arma::vec &data)
{
  Eigen::VectorXd res(data.size());
  for (int i = 0; i < data.size(); i++)
  {
    res(i) = data(i);
  }
  return res;  
}

arma::vec convert(const Eigen::VectorXd &data)
{
  arma::vec res(data.size());
  for (int i = 0; i < data.size(); i++)
  {
    res(i) = data(i);
  }
  return res;
}

bool findPCS(const Eigen::MatrixXd &data, Eigen::VectorXd &eigenvalues,  Eigen::MatrixXd &eigenvectors)
{  
  arma::mat arma_mat = convert(data);
  arma::mat U; arma::vec S; arma::mat V;
  arma::svd_econ(U,S,V,arma_mat);    
  eigenvalues = convert(S)/sqrt((double)(data.rows()));    
  eigenvectors = convert(V);

  return true;
}

}

现在,该库可以毫无问题地进行编译。 然后,我想从另一个名为clean_data的模块中调用findPCS方法。 的CMakeLists.txt文件如下:

cmake_minimum_required (VERSION 2.8.9)
set(PROJECTNAME clean_data)
project(${PROJECTNAME})

find_package(OpenCV REQUIRED)
find_package(Armadillo REQUIRED)

if (NOT DEFINED ENV{EIGEN_ROOT})
message(FATAL_ERROR "Could not find EIGEN_ROOT environment variable")
endif()

include_directories("$ENV{EIGEN_ROOT}")
include_directories("$ENV{training_INCLUDE}")
link_directories("$ENV{training_LIBS}")

add_definitions(-g)
add_definitions(-O3)
add_definitions(-DNDEBUG)

file(GLOB SOURCES *.c *.cpp)

add_executable(${PROJECTNAME} ${SOURCES})
target_link_libraries(${PROJECTNAME} ${OpenCV_LIBS} ${ARMADILLO_LIBRARIES} training_library)

调用findPCS方法的main.cpp如下:

#include <armadillo>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <ctime>
#include <algorithm>
#include <numeric>
#include <list>
#include <statistics.h>
#include <opencv2/opencv.hpp>
#include <Eigen/Dense>

int main() {

  Eigen::MatrixXd matrix(4,10);
  matrix << 1, 2, 2, 1, 5, 5, 4, 12, 32, 1,
        44, 34, 12, 11, 21, 5, 54, 1, 12, 3,
        33, 128, 112, 126, 3, 3, 2, 12, 1, 54,
        66, 34, 1, 54, 2, 2, 1, 43, 4, 12;
  Eigen::VectorXd eigenval; Eigen::MatrixXd eigenvec;
  statistics::findPCS(matrix,eigenval,eigenvec);

  //arma::mat x = arma::randu<arma::mat>(3,4);
  //arma::mat U; arma::vec S; arma::mat V;
  //arma::svd(U,S,V,x);

  return 0;
}

这段代码在我尝试编译时给了我这个链接错误:

/home/ilaria/Dev/training_library/build/libtraining_library.a(statistics.cpp.o):     In function `gesdd<double>':
/usr/local/include/armadillo_bits/wrapper_lapack.hpp:571: undefined     reference to `wrapper_dgesdd_'
/home/ilaria/Dev/training_library/build/libtraining_library.a(statistics.cpp.o):     In function `gesvd<double>':
/usr/local/include/armadillo_bits/wrapper_lapack.hpp:506: undefined     reference to `wrapper_dgesvd_'
/usr/local/include/armadillo_bits/wrapper_lapack.hpp:506: undefined reference to `wrapper_dgesvd_'
collect2: error: ld returned 1 exit status
make[2]: *** [clean_data] Error 1
make[1]: *** [CMakeFiles/clean_data.dir/all] Error 2
make: *** [all] Error 2

但是,如果我不推荐在main.cpp中注释的行,则代码可以毫无问题地编译,它可以很好地运行,并且可以给我正确的结果! 我看了看互联网,却找不到任何有用的答案。 我正在使用Ubuntu 14.04。 我从来源安装了犰狳,从突触安装了lapack,blas和openblas。 谁能在任何地方发现问题? 任何帮助将非常感激。

谢谢,伊拉里亚

您的问题归结为库链接顺序。 我不知道您的完整链接行,但是这里只是一个简化的示例来说明问题:

gcc -o myOutput main.o -l someLibrary -l training_library

现在training_library.a包含对外部符号的引用:特别是wrapper_dgesvd_等。 这些实际上是在someLibrary.a中定义的(我在这里不知道实际的库名,因此请使用此绰号来说明我的观点)。 但是,由于上面的-l顺序,它们无法解析(规则是链接器行上未解析的符号从左到右得到处理,并且只有-l条目出现在未解析符号所在的点的右侧引入即可解决)。

那么,为什么取消注释main.cpp的行会有帮助? 因为在注释行中进行调用(大概是在wrapper_dgesvd_ )引用了那些相同的未解析符号(例如, wrapper_dgesvd_ )。 由于现在将这些引入到-l someLibrary的左侧,因此现在可以使用它们来解析它们,因此可以将它们拉入。一旦拉入,它们现在也可用于以后在命令行中显示的内容,即对于training_library ,因此您之前的问题就消失了。

如何解决呢? 只是一个猜测,不过请尝试从以下方式更改您的CMake行:

target_link_libraries(${PROJECTNAME} ${OpenCV_LIBS} ${ARMADILLO_LIBRARIES} training_library)

至:

target_link_libraries(${PROJECTNAME} training_library ${OpenCV_LIBS} ${ARMADILLO_LIBRARIES})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM