Search code examples
androidc++android-ndkqt-creatorceres-solver

Linking to ceres library on Android


I'm trying to compile and deploy ceres solver into an Android project.

I successfully compiled ceres (1.8.0 and 1.9.0, tried both), running ndk-build from the ceres jni folder.

Then, I use QtCreator to compile and deploy and Android project. It fails with the following error:

B:\Android\android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ --sysroot=B:\Android\android-ndk-r10e/platforms/android-9/arch-arm/ -Wl,-soname,libtest_3rdparty_inprg_ceres.so -Wl,--no-undefined -Wl,-z,noexecstack -shared -o libtest_3rdparty_inprg_ceres.so main.obj logging.obj   -LB:\Android\android-ndk-r10e/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a -LB:\Android\android-ndk-r10e/platforms/android-9/arch-arm//usr/lib -lb:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/lib/android_armeabi-v7a/gcc-4.8/libceres.a -LC:/Qt/5.5/android_armv7/lib -lQt5Widgets -Lc:\utils\android\ndk/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a -Lc:\utils\android\ndk/platforms/android-9/arch-arm//usr/lib -lQt5Gui -lQt5Core -lGLESv2 -lgnustl_shared -llog -lz -lm -ldl -lc -lgcc
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/memory:3639: error: undefined reference to 'std::__1::__shared_weak_count::~__shared_weak_count()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/memory:4448: error: undefined reference to 'std::__1::__shared_weak_count::__release_shared()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:524: error: undefined reference to 'std::__1::ios_base::clear(unsigned int)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/memory:4154: error: undefined reference to 'std::__1::__shared_weak_count::__add_shared()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/memory:4154: error: undefined reference to 'std::__1::__shared_weak_count::__add_shared()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:734: error: undefined reference to 'std::__1::ios_base::getloc() const'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/__locale:174: error: undefined reference to 'std::__1::locale::use_facet(std::__1::locale::id&) const'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:734: error: undefined reference to 'std::__1::locale::~locale()'
B:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/jni/../internal/ceres/solver_impl.cc:123: error: undefined reference to 'std::__1::cout'
B:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/jni/../internal/ceres/solver_impl.cc:123: error: undefined reference to 'std::__1::ctype<char>::id'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:734: error: undefined reference to 'std::__1::ios_base::getloc() const'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/__locale:174: error: undefined reference to 'std::__1::locale::use_facet(std::__1::locale::id&) const'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:734: error: undefined reference to 'std::__1::locale::~locale()'
B:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/jni/../internal/ceres/solver_impl.cc:158: error: undefined reference to 'std::__1::cout'
B:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/jni/../internal/ceres/solver_impl.cc:158: error: undefined reference to 'std::__1::ctype<char>::id'
b:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/lib/android_armeabi-v7a/gcc-4.8/libceres.a(solver_impl.o):solver_impl.cc:vtable for std::__1::__shared_ptr_pointer<ceres::OrderedGroups<double*>*, std::__1::default_delete<ceres::OrderedGroups<double*> >, std::__1::allocator<ceres::OrderedGroups<double*> > >: error: undefined reference to 'std::__1::__shared_weak_count::__get_deleter(std::type_info const&) const'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ostream:508: error: undefined reference to 'std::__1::ios_base::getloc() const'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/__locale:174: error: undefined reference to 'std::__1::locale::use_facet(std::__1::locale::id&) const'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ostream:508: error: undefined reference to 'std::__1::locale::~locale()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:734: error: undefined reference to 'std::__1::ios_base::getloc() const'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/__locale:174: error: undefined reference to 'std::__1::locale::use_facet(std::__1::locale::id&) const'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:734: error: undefined reference to 'std::__1::locale::~locale()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:524: error: undefined reference to 'std::__1::ios_base::clear(unsigned int)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ostream:520: error: undefined reference to 'std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > >::id'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ostream:520: error: undefined reference to 'std::__1::ctype<char>::id'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:668: error: undefined reference to 'std::__1::ios_base::init(void*)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/streambuf:370: error: undefined reference to 'std::__1::locale::locale()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/__hash_table:1944: error: undefined reference to 'std::__1::__next_prime(unsigned int)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/__hash_table:1955: error: undefined reference to 'std::__1::__next_prime(unsigned int)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/__hash_table:1944: error: undefined reference to 'std::__1::__next_prime(unsigned int)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/__hash_table:1955: error: undefined reference to 'std::__1::__next_prime(unsigned int)'
b:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/lib/android_armeabi-v7a/gcc-4.8/libceres.a(schur_eliminator.o):schur_eliminator.cc:vtable for ceres::internal::SchurEliminator<2, 4, 8>: error: undefined reference to 'ceres::internal::SchurEliminator<2, 4, 8>::~SchurEliminator()'
b:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/lib/android_armeabi-v7a/gcc-4.8/libceres.a(schur_eliminator.o):schur_eliminator.cc:vtable for ceres::internal::SchurEliminator<2, 4, 8>: error: undefined reference to 'ceres::internal::SchurEliminator<2, 4, 8>::~SchurEliminator()'
b:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/lib/android_armeabi-v7a/gcc-4.8/libceres.a(schur_eliminator.o):schur_eliminator.cc:vtable for ceres::internal::SchurEliminator<2, 4, 8>: error: undefined reference to 'ceres::internal::SchurEliminator<2, 4, 8>::Init(int, ceres::internal::CompressedRowBlockStructure const*)'
b:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/lib/android_armeabi-v7a/gcc-4.8/libceres.a(schur_eliminator.o):schur_eliminator.cc:vtable for ceres::internal::SchurEliminator<2, 4, 8>: error: undefined reference to 'ceres::internal::SchurEliminator<2, 4, 8>::Eliminate(ceres::internal::BlockSparseMatrix const*, double const*, double const*, ceres::internal::BlockRandomAccessMatrix*, double*)'
b:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/lib/android_armeabi-v7a/gcc-4.8/libceres.a(schur_eliminator.o):schur_eliminator.cc:vtable for ceres::internal::SchurEliminator<2, 4, 8>: error: undefined reference to 'ceres::internal::SchurEliminator<2, 4, 8>::BackSubstitute(ceres::internal::BlockSparseMatrix const*, double const*, double const*, double const*, double*)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:3077: error: undefined reference to 'std::__1::__rs_get()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:2912: error: undefined reference to 'std::__1::__rs_default::operator()()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:2912: error: undefined reference to 'std::__1::__rs_default::operator()()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:3083: error: undefined reference to 'std::__1::__rs_default::~__rs_default()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:3077: error: undefined reference to 'std::__1::__rs_get()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:2912: error: undefined reference to 'std::__1::__rs_default::operator()()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:2912: error: undefined reference to 'std::__1::__rs_default::operator()()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:3083: error: undefined reference to 'std::__1::__rs_default::~__rs_default()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:3077: error: undefined reference to 'std::__1::__rs_get()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:3083: error: undefined reference to 'std::__1::__rs_default::~__rs_default()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:3077: error: undefined reference to 'std::__1::__rs_get()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/algorithm:3083: error: undefined reference to 'std::__1::__rs_default::~__rs_default()'
B:/dev/vobs_ext/libcpp/ceres/ceres-solver-1.9.0/jni/../internal/ceres/partitioned_matrix_view.cc:118: error: undefined reference to 'ceres::internal::PartitionedMatrixView<2, 4, 8>::PartitionedMatrixView(ceres::internal::BlockSparseMatrix const&, int)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:661: error: undefined reference to 'std::__1::ios_base::~ios_base()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:524: error: undefined reference to 'std::__1::ios_base::clear(unsigned int)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/streambuf:370: error: undefined reference to 'std::__1::locale::locale()'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:524: error: undefined reference to 'std::__1::ios_base::clear(unsigned int)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ostream:494: error: undefined reference to 'std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > >::id'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ostream:494: error: undefined reference to 'std::__1::ctype<char>::id'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ostream:728: error: undefined reference to 'std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > >::id'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ostream:676: error: undefined reference to 'std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > >::id'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:668: error: undefined reference to 'std::__1::ios_base::init(void*)'
B:/Android/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include/ios:668: error: undefined reference to 'std::__1::ios_base::init(void*)'
collect2.exe: error: ld returned 1 exit status
makefile:82: recipe for target 'libtest_3rdparty_inprg_ceres.so' failed
mingw32-make: *** [libtest_3rdparty_inprg_ceres.so] Error 1
13:17:13: Le processus "C:\Qt\Tools\mingw492_32\bin\mingw32-make.exe" s'est terminé avec le code 2.
Erreur lors de la compilation/déploiement du projet test_3rdparty_inprg_ceres (kit : Android for armeabi-v7a (GCC 4.9, Qt 5.5.0))
When executing step "Make"
13:17:13: Temps écoulé : 00:08.

I'm wondering if this could be due to ceres linking with c++ libraries statically, while my program links then dynamically....but have no clue how to solve this.


Solution

  • All libraries in your app SHOULD use the same STL runtime. But speaking about static libraries, they MUST use the same STL configuration. If you did not change cerces-solver/jni/Application.mk, it will expect APP_STL=c++_static. You can override this to use APP_STL=c++_shared, but you need a very good reason to change the way this external library is built. Much easier to switch your program to APP_STL=c++_static.

    Edited by jpo38: There are actually other things to be changed to have libceres.so be generated instead of libceres.a:

    • Add LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog in Android.mk
    • Replace include $(BUILD_STATIC_LIBRARY) by include $(BUILD_SHARED_LIBRARY) in Android.mk
    • Add -DCERES_BUILDING_SHARED_LIBRARY and -DCERES_RESTRICT_SCHUR_SPECIALIZATION (dunno why this second one helps, looks like Shur stuff does not like shared linkage) to LOCAL_CFLAGS in Android.mk

    Then, the dynamic library is generated and may be used.