我为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)
到
add_library(libxxx STATIC IMPORTED)
set_property(TARGET libxxx PROPERTY ... libxxx.a)
但这不起作用。具体来说,在静态情况下,我得到一堆(数百)
undefined reference to xxx
错误。例如,
../../../../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_'
虽然错误不仅仅是由于缺少Lapack功能,还有Mumps等。
查看特定的失败命令,我相信库的顺序是正确的:
失败:cmd.exe / C" cd。 &安培;&安培;铛++。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 。所以 CMakeFiles /原生lib.dir / src目录/主/ 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束/源/ CXX-STL / GNU-的libstdc ++ / 4.9 /库/ arm64-V8A / libgnustl_static.a" &安培;&安培; cd。"
请注意,我对上面的路径进行了清理,以便它们具有可读性,但最后您可以看到库按顺序列出
libcoinblas.a libcoinlapack.a libcoinmetis.a libcoinmumps.a libipopt.a
我还尝试将链接命令从target_link_library
更改为link_library
:
link_libraries(native-lib blas lapack metis mumps ipopt)
但这也失败了。出于某种原因,在这种情况下,链接命令甚至不包括它应该链接的库:
失败:cmd.exe / C" cd。 &安培;&安培; C:\ Android的\ Android的SDK \ NDK束\工具链\ LLVM \预置的\ WINDOWS-x86_64的\ BIN \铛++ 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 。所以 CMakeFiles /原生lib.dir / src目录/主/ CPP / cpp_example.cpp.o CMakeFiles / native-lib.dir / src / main / cpp / MyNLP.cpp.o -latomic -lm " C:/ Android设备/ Android的SDK / NDK束/源/ CXX-STL / GNU-的libstdc ++ / 4.9 /库/ arm64-V8A / libgnustl_static.a" &安培;&安培; cd。" CMakeFiles / native-lib.dir / src / main / cpp / cpp_example.cpp.o:In 函数`Java_io_jeti_ipopt_1static_MainActivity_stringFromJNI':
答案 0 :(得分:5)
您的图书馆是相互依存的:
Lapack requires Blas
Mumps requires Blas and Metis
Ipopt requires Mumps, Metis, and Lapack
这意味着链接它们的顺序应相反:
ipopt
mumps
metis
lapack
blas
如果您不想浪费时间来确定最佳订单,而是让链接器找出(这可能是slow your builds significantly),您可以使用
target_link_libraries(native-lib -Wl,--start-group blas lapack metis mumps ipopt -Wl,--end-group)
您还可以通过IMPORTED_LINK_INTERFACE_LIBRARIES教授CMake关于导入的静态库之间的依赖关系,例如
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
答案 1 :(得分:0)
这可能与图书馆完全没有任何关系。这可能与dppsv()原型的方式有关。
您在帖子中引用的链接器错误对应的源文件位于:
https://github.com/coin-or/Ipopt/blob/master/Ipopt/src/LinAlg/IpLapack.cpp
这包含以下代码段:
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编译器使用的函数命名约定,请参见此处:
https://github.com/coin-or/Ipopt/blob/master/Ipopt/src/Common/IpoptConfig.h
现在这不是我的专业领域,但很可能这个宏在你的情况下没有做正确的事情。您可以在Fortran编译器生成的相关.o文件上运行 nm ,以查看它与您的特定构建设置生成的内容。如果它不是 dppsv _ ,那么你就知道错误了。