Android:链接到预构建的静态库

bre*_*att 9 c++ android cmake static-libraries android-ndk

我已经为Android编译了一些静态和共享库.具体来说,我有图书馆

libcoinblas.a   libcoinlapack.a   libcoinmetis.a   libcoinmumps.a   libipopt.a
libcoinblas.so  libcoinlapack.so  libcoinmetis.so  libcoinmumps.so  libipopt.so
Run Code Online (Sandbox Code Playgroud)

此外,这些库是相互依赖的,即

Lapack requires Blas
Mumps  requires Blas and Metis
Ipopt  requires Mumps, Metis, and Lapack
Run Code Online (Sandbox Code Playgroud)

使用共享库时,Android项目正确链接和运行,但无法使用静态库构建.

在共享的情况下,我使用的是cmake文件

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
                       )
Run Code Online (Sandbox Code Playgroud)

在静态的情况下

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
                       )
Run Code Online (Sandbox Code Playgroud)

我假设我只需要改变库的添加方式

add_library(libxxx SHARED IMPORTED)
set_property(TARGET libxxx PROPERTY ... libxxx.so)
Run Code Online (Sandbox Code Playgroud)

add_library(libxxx STATIC IMPORTED)
set_property(TARGET libxxx PROPERTY ... libxxx.a)
Run Code Online (Sandbox Code Playgroud)

但这不起作用.具体来说,在静态情况下,我得到一堆(数百)

undefined reference to xxx 
Run Code Online (Sandbox Code Playgroud)

错误.例如,

../../../../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_'
Run Code Online (Sandbox Code Playgroud)

虽然错误不仅仅是因为缺少Lapack功能,还有Mumps等.


编辑

查看特定的失败命令,我相信库是按正确的顺序指定的:

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 ,现在-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."

请注意,我稍微清理了一些路径以使它们略微可读,但最后您可以看到这些库按顺序列出

libcoinblas.a libcoinlapack.a libcoinmetis.a libcoinmumps.a libipopt.a
Run Code Online (Sandbox Code Playgroud)

编辑

我也尝试将链接命令从更改target_link_librarylink_library:

link_libraries(native-lib blas lapack metis mumps ipopt)
Run Code Online (Sandbox Code Playgroud)

但这也失败了.出于某种原因,在这种情况下,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, - 致命警告-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 CMakeFi les/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:在函数`Java_io_jeti_ipopt_1static_MainActivity_stringFromJNI'中:

Ale*_*ohn 5

您的库是相互依赖的:

Lapack requires Blas
Mumps  requires Blas and Metis
Ipopt  requires Mumps, Metis, and Lapack
Run Code Online (Sandbox Code Playgroud)

这意味着链接它们的顺序应该相反:

ipopt
mumps
metis
lapack
blas 
Run Code Online (Sandbox Code Playgroud)

如果您不想浪费时间来确定最佳顺序,而是让链接器找出来(这可能会大大降低构建速度),则可以使用

target_link_libraries(native-lib -Wl,-start-group blaps metis腮红ipopt -Wl,-end-group)

您还可以通过IMPORTED_LINK_INTERFACE_LIBRARIES教CMake有关导入的静态库之间的依赖关系,例如

set_target_properties(lapack 
  PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES 
  blas)
Run Code Online (Sandbox Code Playgroud)

等等。

这将翻译

target_link_libraries( native-lib
                   blas
                   lapack
                   )
Run Code Online (Sandbox Code Playgroud)

clang++ -o libnative-lib.so … libblas.a libnlapack.a libblas.a
Run Code Online (Sandbox Code Playgroud)