Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linking OpenBlas in AndroidStudio project #1830

Closed
jeffmorr opened this issue Oct 22, 2018 · 28 comments
Closed

Linking OpenBlas in AndroidStudio project #1830

jeffmorr opened this issue Oct 22, 2018 · 28 comments

Comments

@jeffmorr
Copy link

jeffmorr commented Oct 22, 2018

Hello,

I am having issues with linking the OpenBlas library to my Android Studio project. I am getting these type of errors:

C:/Users/Jeff/AppData/Local/Android/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/bin\ld: error: C:/Users/Jeff/Documents/neurable-library/libs/OpenBLAS/libopenblas.a:1:31: syntax error, unexpected $end
C:/Users/Jeff/AppData/Local/Android/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/bin\ld: error: C:/Users/Jeff/Documents/neurable-library/libs/OpenBLAS/libopenblas.a: not an object or archive
C:/Users/Jeff/AppData/Local/Android/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/bin\ld: error: C:/Users/Jeff/Documents/neurable-library/libs/OpenBLAS/libopenblas.a:1:31: syntax error, unexpected $end
C:/Users/Jeff/AppData/Local/Android/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/bin\ld: error: C:/Users/Jeff/Documents/neurable-library/libs/OpenBLAS/libopenblas.a: not an object or archive
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h:106: error: undefined reference to 'dgemm_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h:106: error: undefined reference to 'dgemm_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/GeneralMatrixVector_BLAS.h:120: error: undefined reference to 'dgemv_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/GeneralMatrixVector_BLAS.h:120: error: undefined reference to 'dgemv_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h:141: error: undefined reference to 'dtrsm_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h:87: error: undefined reference to 'dtrsm_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h:141: error: undefined reference to 'dtrsm_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h:102: error: undefined reference to 'dsymv_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/GeneralMatrixVector_BLAS.h:120: error: undefined reference to 'dgemv_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/GeneralMatrixVector_BLAS.h:120: error: undefined reference to 'dgemv_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h:87: error: undefined reference to 'dtrsm_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h:106: error: undefined reference to 'dgemm_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h:293: error: undefined reference to 'dtrmm_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h:106: error: undefined reference to 'dgemm_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h:183: error: undefined reference to 'dtrmm_'
C:/Users/Jeff/Documents/neurable-library/include\Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h:183: error: undefined reference to 'dtrmm_'

I am using Windows 10 with API Level 22, the OpenBlas library was built on linux as a .a and I'm trying to get Eigen to use OpenBlas.

@martin-frbg
Copy link
Collaborator

Do you use -lto/-flto somewhere in the build of your project ? That is the only search hit I got so far for your error message in conjunction with the ndk (without mentioning Android or NDK, search returns hundred of hits for problems with PHP...) The "undefined reference" are obviously consequential errors from rejecting the OpenBLAS library.

@jeffmorr
Copy link
Author

jeffmorr commented Oct 22, 2018

No I'm not, can you send me the link to the page that suggested we use -lto/-flto? I don't currently see that in the links I found.

@martin-frbg
Copy link
Collaborator

Link where problem was attributed to using lto (but older ndk, probably older compiler as well)
android/ndk#137

@jeffmorr
Copy link
Author

Compiling with -flto doesn't get rid of the errors but it changes some of them.

C:/Users/Jeff/AppData/Local/Android/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/bin\ld: error: C:/Users/Jeff/Documents/neurable-library/libs/OpenBLAS/libopenblas.a:1:31: syntax error, unexpected $end
C:/Users/Jeff/AppData/Local/Android/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/bin\ld: error: C:/Users/Jeff/Documents/neurable-library/libs/OpenBLAS/libopenblas.a: not an object or archive
C:/Users/Jeff/AppData/Local/Android/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/bin\ld: error: C:/Users/Jeff/Documents/neurable-library/libs/OpenBLAS/libopenblas.a:1:31: syntax error, unexpected $end
C:/Users/Jeff/AppData/Local/Android/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/bin\ld: error: C:/Users/Jeff/Documents/neurable-library/libs/OpenBLAS/libopenblas.a: not an object or archive
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function MDM::getRiemannianDistance(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&) const: error: undefined reference to 'dtrsm_'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function Eigen::LLT<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1>& Eigen::LLT<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1>::compute<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::EigenBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&): error: undefined reference to 'dgemv_'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function Eigen::LLT<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1>& Eigen::LLT<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1>::compute<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::EigenBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&): error: undefined reference to 'dgemv_'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function Eigen::LLT<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1>& Eigen::LLT<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1>::compute<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::EigenBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&): error: undefined reference to 'dtrsm_'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function Eigen::internal::triangular_solver_selector<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, 1, 0, -1>::run(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&): error: undefined reference to 'dtrsm_'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function void Eigen::internal::gemv_dense_selector<2, 1, true>::run<Eigen::Transpose<Eigen::Block<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, -1, false>, -1, -1, false> const>, Eigen::Transpose<Eigen::Transpose<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, -1, 1, false> const> const>, Eigen::Transpose<Eigen::Map<Eigen::Matrix<double, 1, -1, 1, 1, -1>, 0, Eigen::Stride<0, 0> > > >(Eigen::Transpose<Eigen::Block<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, -1, false>, -1, -1, false> const> const&, Eigen::Transpose<Eigen::Transpose<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, -1, 1, false> const> const> const&, Eigen::Transpose<Eigen::Map<Eigen::Matrix<double, 1, -1, 1, 1, -1>, 0, Eigen::Stride<0, 0> > >&, Eigen::Transpose<Eigen::Map<Eigen::Matrix<double, 1, -1, 1, 1, -1>, 0, Eigen::Stride<0, 0> > >::Scalar const&): error: undefined reference to 'dgemv_'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function void Eigen::internal::selfadjoint_product_impl<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, -1, false>, 17, false, Eigen::CwiseBinaryOp<Eigen::internal::scalar_product_op<double, double>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op, Eigen::Matrix<double, -1, 1, 0, -1, 1> const> const, Eigen::Block<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, 1, true>, -1, 1, false> const>, 0, true>::run<Eigen::Block<Eigen::Matrix<double, -1, 1, 0, -1, 1>, -1, 1, false> >(Eigen::Block<Eigen::Matrix<double, -1, 1, 0, -1, 1>, -1, 1, false>&, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, -1, false> const&, Eigen::CwiseBinaryOp<Eigen::internal::scalar_product_op<double, double>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op, Eigen::Matrix<double, -1, 1, 0, -1, 1> const> const, Eigen::Block<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, 1, true>, -1, 1, false> const> const&, double const&): error: undefined reference to 'dsymv_'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function Eigen::Matrix<double, -1, -1, 0, -1, -1>& Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >::set_noalias<Eigen::Product<Eigen::Product<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, 0>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, 0> >(Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, 0>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, 0> > const&): error: undefined reference to 'dgemm'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function Eigen::Matrix<double, -1, -1, 0, -1, -1>& Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >::set_noalias<Eigen::Product<Eigen::Product<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, 0>, Eigen::Transpose<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, 0> >(Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, 0>, Eigen::Transpose<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, 0> > const&): error: undefined reference to 'dgemm'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function void Eigen::internal::generic_product_impl<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::DenseShape, Eigen::DenseShape, 8>::scaleAndAddTo<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1>&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, double const&): error: undefined reference to 'dgemm_'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function void Eigen::internal::generic_product_impl<Eigen::Transpose<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::DenseShape, Eigen::DenseShape, 8>::evalTo<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1>&, Eigen::Transpose<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&): error: undefined reference to 'dgemm_'
C:\Users\Jeff\AppData\Local\Temp\lto-llvm-1cdd56.o:ld-temp.o:function Kalman::cholInverse(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&) const: error: undefined reference to 'dtrsm_'
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

@brada4
Copy link
Contributor

brada4 commented Oct 22, 2018

How did you build openblas? What EIGEN options regarding BLAS and MKL are set?
That error happens here over webs:
https://stackoverflow.com/questions/29301057/ndk-project-with-clang-linker-errors
As Martin told error means .a file is in different format that current ld does not understand - e.g. natve for windows, in gcc lto format for clang or vice versa etc.
Especially unix "ar" format does not contain text tags like $end, that are typical for gcc LTO.

@jeffmorr
Copy link
Author

I figured out the unexpected $end error, I needed to clear my CMake cache to make sure it was pointing to the right library, which it wasn't before. I still get the undefined reference to dgemm_, dgemv_, dtrsm_, etc. errors. I included cblas.h as was said in other posts but that didn't work. My OpenBlas is only compiled with Blas not Lapack, is Lapack necessary for Eigen? Also the macro I am using is EIGEN_USE_BLAS

@martin-frbg
Copy link
Collaborator

DGEMM,DGEMV and DTRSM are BLAS functions so no need for LAPACK. There is the (very slight) possibility that the symbols in your build of libopenblas.a do not have the trailing underscore, nm -s libopenblas.a can be used to check this. (If nm produces no output and/or complains about a missing symbol table, the issue could be that you need to run ranlib on the library first to make it usable to the linker.)

@jeffmorr
Copy link
Author

When I ran nm -s libopen libopenblas_armv7-r0.3.4.dev.a I got this file. I see symbols like dtrsm_LNUU or like dgemv_n but not exactly dtrsm_.

@martin-frbg
Copy link
Collaborator

That list looks like a partial library - the cblas interfaces are there, but strangely none of the blas ones generated from the interface directory - there should be e.g. a line "dgemm_ in dgemm.o" followed later by the detailed section for dgemm.o showing "T dgemm_" . Probably best to redo the build and see if there are any errors for the interface part of the directory tree in the log.

@martin-frbg
Copy link
Collaborator

What is your target hardware by the way ? In #1823 you were building OpenBLAS for ARMV8, but here it seems to me you have the libopenblas built for 32bit ARMV7 and your NDK toolchain appears to be for Android on x86_64 ?

@jeffmorr
Copy link
Author

Yeah I changed it to ARMV7, I'm double checking my toolchain to make sure it's not still using x86_64.

@brada4
Copy link
Contributor

brada4 commented Oct 22, 2018

Eigen needs fortran BLAS, not CBLAS (NO_CBLAS=1)
https://eigen.tuxfamily.org/dox/TopicUsingBlasLapack.html

@martin-frbg
Copy link
Collaborator

In your first post, the toolchain has names ending in x86_64-linux-android where your toolchain from #1823 initially had aarch64-linux-android (and probably something like arm-linux-androideabi in the end).
(And even without setting NO_CBLAS=1, the library should still have the BLAS interface besides the unneeded CBLAS one)

@jeffmorr
Copy link
Author

This link creates a toolchain for 32bit architecture but when I use make I enabled ONLY_CBLAS=1 (turning that breaks everything). Here is the make log for that. I don't see any issues with the interface.

@brada4
Copy link
Contributor

brada4 commented Oct 22, 2018

Eigen provides cblas.h and CBLAS interface over any F77 BLAS library. It is best to disable surplus CBLAS interface of OpenBLAS to avoid confusing more compilers. One can say there are no issues with the interface since it is deliberately absent from the library you compiled.

@martin-frbg
Copy link
Collaborator

Guess the wording of the associated comment in Makefile.rule can be misleading as it only mentions building without a FORTRAN compiler (where the actual issue back in #279 was with some of the tests) but not interfacing with other software like Eigen that makes BLAS rather than CBLAS calls.
Still it would have helped if you had mentioned using this non-standard setting right away.

@brada4
Copy link
Contributor

brada4 commented Oct 23, 2018

EIGEN will provide own cblas.h, that will override L1 and for small matrices also L2 and L3
e.g. GSL recommends against their cblas.h in presence of external BLAS
Armadillo tries to build netlib BLAS, then one can plant better stuff in that place etc (thats 5 years old info)
....
I was thinking of adding FAQ about how to build Rblas.dll with Rtools, how to use matlab on AMD, and probably this too.

@jeffmorr
Copy link
Author

Okay I will re-build this again on Linux using the OpenBlas Android tutorial with Fortran. Shall I close this issue and make a new issue if I have problems with that or should I keep this thread open for now?

@martin-frbg
Copy link
Collaborator

You should not even need FORTRAN for building the BLAS interface, the issue prompting creation of the ONLY_CBLAS option is/was only that the related post-build tests require FORTRAN - but these tests are not run in cross-compilation builds anyway.

@jeffmorr
Copy link
Author

I'm sorry I still don't think I quite understand. I need to turn off the ONLY_CBLAS option but I don't need to build OpenBLAS with FORTRAN?

@martin-frbg
Copy link
Collaborator

All the BLAS in OpenBLAS is written in C and assembly, you should only need FORTRAN for the LAPACK part and some of the included tests (which as mentioned are only run in native builds).

@jeffmorr
Copy link
Author

Okay well then I need to figure out a different solution for my build, because turning off the ONLY_CBLAS option causes more errors.

@martin-frbg
Copy link
Collaborator

Errors in the OpenBLAS build, or errors when linking with Eigen and your code ?

@jeffmorr
Copy link
Author

Errors in the OpenBLAS build, I'm currently not at the computer where I built OpenBLAS so once I get there I can send the build.log.

@brada4
Copy link
Contributor

brada4 commented Oct 23, 2018

There is no need for build log. You need to build with NO_CBLAS option. That will use C compiler to provide F77-only BLAS library interface for use from EIGEN.
If you need CBLAS, eigen provides it already via own cblas.h header superseding one that could be provided bu OpenBLAS too.

@jeffmorr
Copy link
Author

Yes I'm sorry that's what I meant. I am using the NO_CBLAS option and I still get errors saying command not found for -marm, which I am debugging now.

@martin-frbg
Copy link
Collaborator

Sounds as if you still have an x86 compiler involved instead of the arm compiler from the toolchain.

@jeffmorr jeffmorr closed this as completed Nov 1, 2018
@jeffmorr
Copy link
Author

jeffmorr commented Nov 1, 2018

Sorry for the late response but thank you Martin, you were correct. I was able to rebuild open BLAS on linux for ARMV7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants