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

Android:链接到预构建的静态库,android,c++,cmake,android-ndk,static-libraries,Android,C++,Cmake,Android Ndk,Static Libraries,我已经为Android编译了一些静态和共享库。具体来说,我有图书馆 libcoinblas.a libcoinlapack.a libcoinmetis.a libcoinmumps.a libipopt.a libcoinblas.so libcoinlapack.so libcoinmetis.so libcoinmumps.so libipopt.so 此外,这些库是相互依赖的,即 Lapack requires Blas Mumps requires Blas

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

libcoinblas.a   libcoinlapack.a   libcoinmetis.a   libcoinmumps.a   libipopt.a
libcoinblas.so  libcoinlapack.so  libcoinmetis.so  libcoinmumps.so  libipopt.so
此外,这些库是相互依赖的,即

Lapack requires Blas
Mumps  requires Blas and Metis
Ipopt  requires Mumps, Metis, and Lapack
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
                       )
在静态情况下

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
                       )
我假设我只需要更改库的添加方式

add_library(libxxx SHARED IMPORTED)
set_property(TARGET libxxx PROPERTY ... libxxx.so)

但这是行不通的。具体地说,在静态的情况下,我得到一堆(数百)的

错误。比如说,

../../../../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_'
虽然这些错误不仅仅是因为缺少拉帕克功能,还有腮腺炎和其他疾病


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

失败: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/prebuild/windows-x86_64 --sysroot=sysroot-fPIC-isystem C:/Android/Android sdk/ndk bundle/sysroot/usr/include/aarch64 linux-Android -D_uuAndroid_uAPI_uuu=23-g-DANDROID-fffunction sections-funwind tables-fstack protector strong-no规范前缀-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 warning-Wl,-no undefined-Wl,-z,noexecstack-qused arguments-Wl,-z,now-shared-Wl,-soname,libnative-lib.so-o……。\build\mediates\cmake\debug\obj\arm64-v8a\libnative-lib.so cmakfiles/native lib.dir/src/main/cpp/cpp_example.cpp.o cmakfiles/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

编辑 我还尝试将link命令从
target\u link\u library
更改为
link\u library

link_libraries(native-lib blas lapack metis mumps ipopt)
但这也失败了。出于某种原因,在本例中,“链接”命令甚至不包括它应该链接的库:

失败:cmd.exe/C“cd&& C:\Android\Android sdk\ndk bundle\toolchains\llvm\prebuild\windows-x86\u 64\bin\clang++.exe --target=aarch64 none-linux-android--gcc toolchain=C:/android/android sdk/ndk bundle/toolchains/aarch64-linux-android-4.9/prebuild/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_uuAndroid_uAPI_uuu=23-g-DANDROID-fffunction sections-funwind tables-fstack protector strong-no规范前缀-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 warning-Wl,-no undefined-Wl,-z,noexecstack-qused arguments-Wl,-z,now-shared-Wl,-soname,libnative-lib.so-o……。\build\mediates\cmake\debug\obj\arm64-v8a\libnative-lib.so cmakfiles/native lib.dir/src/main/cpp/cpp_example.cpp.o cmakfiles/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.“cmakfiles/native lib.dir/src/main/cpp/cpp_example.cpp.o:In 函数'Java_io_jeti_ipopt_1static_main activity_stringFromJNI':


你们的图书馆是相互依存的:

Lapack requires Blas
Mumps  requires Blas and Metis
Ipopt  requires Mumps, Metis, and Lapack
这意味着链接它们的顺序应该相反:

ipopt
mumps
metis
lapack
blas 
如果你不想把时间浪费在找出最佳顺序上,而是让链接器去发现(这可能),你可以使用

您还可以通过以下方式向CMake教授导入的静态库之间的依赖关系:

等等

这将转化为

target_link_libraries( native-lib
                   blas
                   lapack
                   )


这可能与库没有任何关系。这可能与dppsv()的原型化方式有关

与您在帖子中引用的链接器错误对应的源文件如下:

其中包含以下代码段:

extern "C" {

/** LAPACK Fortran subroutine DPPSV. */
void F77_FUNC(dppsv,DPPSV)(char *uplo, ipfint *n,
                           ipfint *nrhs, const double *A,
                           double *B, ipfint *ldB, ipfint *info);
}
F77_FUNC宏显然是为了映射到您正在使用的任何Fortran编译器所使用的函数命名约定,请参见此处:


现在这不是我的专业领域,但很可能是这个宏在您的情况下做得不对。您可以在Fortran编译器生成的相关.o文件上运行nm,以查看特定构建设置生成的内容。如果它不是dppsv\uuuu那么你就知道出了什么问题。

你最初是如何将
Lapack
构建为一个共享库的?我想,当您这样做时,您必须以某种方式指定它对
Blas
的依赖性。对于静态库,链接步骤尚未“发生”,因此必须在CMAKE文件中显式指定各种依赖项。不是100%确定,但请试一试。你能看到生成的链接器行吗,如果可以的话,请检查库是否按正确的顺序存在:最少依赖1。我在这里用gfortran构建了一些Android独立工具链:希望它们对其他人有用。下面是一个经典案例,其中有一个最小的示例,演示问题,应该对您和我们都有帮助,并且应该易于构造。如果CMake知道依赖项,您不必提供订单,CMake会自己解决。@usr1234567显然,在这种情况下,TS不会发生这种情况。您的答案是d
set_target_properties(lapack 
  PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES 
  blas)
target_link_libraries( native-lib
                   blas
                   lapack
                   )
clang++ -o libnative-lib.so … libblas.a libnlapack.a libblas.a
extern "C" {

/** LAPACK Fortran subroutine DPPSV. */
void F77_FUNC(dppsv,DPPSV)(char *uplo, ipfint *n,
                           ipfint *nrhs, const double *A,
                           double *B, ipfint *ldB, ipfint *info);
}