c++ - Armadillo linking error only if I use it in my own library -


i'm having troubles armadillo when use within own library. installed armadillo, , created own library, calls svd_econ method. cmakelist.txt file:

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}) 

this header file:

#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 

and .cpp:

#include "statistics.h"  namespace statistics {  eigen::matrixxd convert(const arma::mat &data) {   eigen::matrixxd res(data.n_rows,data.n_cols);   (int = 0; < data.n_rows; i++)   {     (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());   (int = 0; < data.rows(); i++)   {     (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());   (int = 0; < data.size(); i++)   {     res(i) = data(i);   }   return res;   }  arma::vec convert(const eigen::vectorxd &data) {   arma::vec res(data.size());   (int = 0; < 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; }  } 

now, library compiles without problems. then, want call findpcs method different module called clean_data. cmakelists.txt file following:

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) 

the main.cpp calls findpcs method follows:

#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; } 

this code, when try compile, gives me linking error:

/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 `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 `wrapper_dgesvd_' /usr/local/include/armadillo_bits/wrapper_lapack.hpp:506: undefined reference `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 

however, if decomment lines commented in main.cpp, code compiles without problems, runs fine , gives me right results! looked on internet, , couldn't find useful answer. i'm using ubuntu 14.04. installed armadillo sources, , lapack, blas , openblas synaptic. can spot problem anywhere? appreciated.

thanks, ilaria

your problem boils down library linking order. don't know full linking line, here simplification illustrate problem:

gcc -o myoutput main.o -l somelibrary -l training_library 

now training_library.a contains references external symbols: in particular wrapper_dgesvd_ amongst others. these in fact defined in somelibrary.a (i don't know actual library name here, use moniker illustrate point). however, due -l order above cannot resolved (the rule unresolved symbols on linker line processed left-to-right, , -l entries appearing right of point unresolved symbol introduced can resolve it).

so why uncommenting lines in main.cpp help? because making calls in commented lines presumably (under hood) references same unresolved symbols (so wrapper_dgesvd_ example). because these introduced left of -l somelibrary, can used resolve them , pulled in. once pulled in available things appearing later on in command line, i.e. training_library, earlier problem goes away.

how solve this? guess, try changing cmake line from:

target_link_libraries(${projectname} ${opencv_libs} ${armadillo_libraries} training_library) 

to:

target_link_libraries(${projectname} training_library ${opencv_libs} ${armadillo_libraries}) 

Comments

Popular posts from this blog

php - How to add and update images or image url in Volusion using Volusion API -

javascript - IE9 error '$'is not defined -