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
Post a Comment