I have compiled some static and shared libraries for Android. Specifically, I have the libraries
libcoinblas.a libcoinlapack.a libcoinmetis.a libcoinmumps.a libipopt.a
libcoinblas.so libcoinlapack.so libcoinmetis.so libcoinmumps.so libipopt.so
Furthermore, these libraries are inter-dependent, that is,
Lapack requires Blas
Mumps requires Blas and Metis
Ipopt requires Mumps, Metis, and Lapack
The Android project correctly links and runs when using the shared libraries, but fails to build with the static libraries.
In the shared case, I am using the cmake file
cmake_minimum_required(VERSION 3.4.1)
add_library( native-lib
SHARED
src/main/cpp/cpp_example.cpp
src/main/cpp/MyNLP.cpp)
# Add dependent libraries
add_library(blas SHARED IMPORTED)
set_property(TARGET blas PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libcoinblas.so)
add_library(lapack SHARED IMPORTED)
set_property(TARGET lapack PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libcoinlapack.so)
add_library(metis SHARED IMPORTED)
set_property(TARGET metis PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libcoinmetis.so)
add_library(mumps SHARED IMPORTED)
set_property(TARGET mumps PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libcoinmumps.so)
add_library(ipopt SHARED IMPORTED)
set_property(TARGET ipopt PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libipopt.so)
# Location of header files
include_directories(${CMAKE_SOURCE_DIR}/libs/include
${CMAKE_SOURCE_DIR}/libs/include/ThirdParty)
target_link_libraries( native-lib
blas
lapack
metis
mumps
ipopt
)
and in the static case
cmake_minimum_required(VERSION 3.4.1)
add_library( native-lib
SHARED
src/main/cpp/cpp_example.cpp
src/main/cpp/MyNLP.cpp)
# Add dependent libraries
add_library(blas STATIC IMPORTED)
set_property(TARGET blas PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libcoinblas.a)
add_library(lapack STATIC IMPORTED)
set_property(TARGET lapack PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libcoinlapack.a)
add_library(metis STATIC IMPORTED)
set_property(TARGET metis PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libcoinmetis.a)
add_library(mumps STATIC IMPORTED)
set_property(TARGET mumps PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libcoinmumps.a)
add_library(ipopt STATIC IMPORTED)
set_property(TARGET ipopt PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libipopt.a)
# Location of header files
include_directories(${CMAKE_SOURCE_DIR}/libs/include
${CMAKE_SOURCE_DIR}/libs/include/ThirdParty)
target_link_libraries( native-lib
blas
lapack
metis
mumps
ipopt
)
I presumed that I simply need to change how the libraries are added from
add_library(libxxx SHARED IMPORTED)
set_property(TARGET libxxx PROPERTY ... libxxx.so)
to
add_library(libxxx STATIC IMPORTED)
set_property(TARGET libxxx PROPERTY ... libxxx.a)
But that does not work. Specifically, in the static case, I get a bunch (hundreds) of
undefined reference to xxx
errors. For example,
../../../../libs/arm64-v8a/libipopt.a(IpLapack.o): In function `Ipopt::IpLapackDppsv(int, int, double const*, double*, int, int&)':
IpLapack.cpp:(.text+0x3d4): undefined reference to `dppsv_'
Although the errors are not just due to missing Lapack functions, but also Mumps and others.
EDIT
Looking at the specific failed command, I believe that the libraries were specified in the correct order:
FAILED: cmd.exe /C "cd . && clang++.exe --target=aarch64-none-linux-android --gcc-toolchain=C:/Android/android-sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64 --sysroot=sysroot -fPIC -isystem C:/Android/android-sdk/ndk-bundle/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=23 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a --sysroot C:/Android/android-sdk/ndk-bundle/platforms/android-23/arch-arm64 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libnative-lib.so -o ........\build\intermediates\cmake\debug\obj\arm64-v8a\libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/cpp_example.cpp.o CMakeFiles/native-lib.dir/src/main/cpp/MyNLP.cpp.o libcoinblas.a libcoinlapack.a libcoinmetis.a libcoinmumps.a libipopt.a -latomic -lm "C:/Android/android-sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/arm64-v8a/libgnustl_static.a" && cd ."
Note that I sanitized the paths a little bit above so that they are slightly readable, but towards the end you can see that the libraries are listed in the order
libcoinblas.a libcoinlapack.a libcoinmetis.a libcoinmumps.a libipopt.a
EDIT
I also tried changing the link command from target_link_library
to link_library
:
link_libraries(native-lib blas lapack metis mumps ipopt)
but this also fails. For some reason, in this case, the link command doesn't even include the libraries that it is supposed to link:
FAILED: cmd.exe /C "cd . && C:\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android --gcc-toolchain=C:/Android/android-sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64 --sysroot=C:/Android/android-sdk/ndk-bundle/sysroot -fPIC -isystem C:/Android/android-sdk/ndk-bundle/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=23 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a --sysroot C:/Android/android-sdk/ndk-bundle/platforms/android-23/arch-arm64 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libnative-lib.so -o ........\build\intermediates\cmake\debug\obj\arm64-v8a\libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/cpp_example.cpp.o CMakeFiles/native-lib.dir/src/main/cpp/MyNLP.cpp.o -latomic -lm "C:/Android/android-sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/arm64-v8a/libgnustl_static.a" && cd ." CMakeFiles/native-lib.dir/src/main/cpp/cpp_example.cpp.o: In function `Java_io_jeti_ipopt_1static_MainActivity_stringFromJNI':