2

I'm porting a C and C++ library that currently works on iOS to be used on an Android application. I'm down to these last 3 linker errors (obfuscated for privacy reasons):

/Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10184: error: undefined reference to 'cexp' /Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10184: error: undefined reference to 'cpowf' /Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10285: error: undefined reference to 'cabs'

Now I understand these normally come from linking with libm.so (-lm), but i'm doing that already. If I go and check the offending so with nm:

nm -g /Users/fer662/Library/Android/sdk/ndk-bundle/platforms/android-22/arch-x86/usr/lib/libm.so | grep cpow

Nothing comes back. It DOES hoever, if I use api 28

nm -g  /Users/fer662/Library/Android/sdk/ndk-bundle/platforms/android-28/arch-x86/usr/lib/libm.so | grep cpow
00003900 T cpow
00003910 T cpowf
00003920 T cpowl

Also, in the static library it does show, even on api 22:

nm -g /Users/fer662/Library/Android/sdk/ndk-bundle/platforms/android-22/arch-x86/usr/lib/libm.a | grep cpow s_cpow.o: 00000000 T cpow s_cpowf.o: 00000000 T cpowf s_cpowl.o: 00000000 T cpowl

The inconsistency is puzzling. Shouldn't it be missing from the header altogether if not supported? Why does the static lib have it and the dylib not?

Would it make sense to statically link against it? And if so, how would I do it, taking into account the right path for the current api version?

My other option seems to go steal an implementation of libm (say http://openlibm.org/) or just these 3 functions I'm using from it.

4

1 回答 1

1

tl;博士:是的,静态链接 libm.a 应该没问题

检查 libm.map.txt 文件:https ://android.googlesource.com/platform/bionic/+/master/libm/libm.map.txt#289

这些功能直到 O 才被添加到 Android 中。

此外,在静态库中它确实显示,即使在 api 22

静态库不是 API 22 静态库。它实际上是从 AOSP 构建的 ToT。如果您要静态链接某些东西,那么使用旧的东西是没有意义的。

它(实际上每个 ABI 只有一个版本的 libc.a/libm.a)被复制到每个 API 目录中的原因是,为旧 NDK 制作的构建系统需要它。如果您查看 r19 中的统一工具链 (toolchains/llvm/prebuilts/$HOST),您会发现每个 ABI 只有一个副本。

这种不一致令人费解。如果不支持,它不应该完全从标题中丢失吗?为什么静态库有它而dylib没有?

标头有一个隐藏它的 ifdef 保护:https ://android.googlesource.com/platform/prebuilts/ndk/+/dev/platform/sysroot/usr/include/complex.h#237

如果您有这些函数的声明并且您认为您正在为 API 22 构建,那么您的构建系统有问题。

静态链接是否有意义?如果是这样,考虑到当前 api 版本的正确路径,我该怎么做?

一般来说,对于这类问题,这不是一个好的解决方案,因为 Zygote 已经加载了一个 libc,并且加载另一个可能会导致各种问题,因为它们可能会发生冲突。此外,libc 的大部分网络实际上是分派给 netd 的,并且 libc 和 netd 之间的协议在过去发生了变化(不幸的是,它不是版本化的协议)。

使用 libc.a 构建仅适用于独立的可执行文件(想想 strace 和 gdbserver)而不是应用程序,即使这样也只有在您不需要网络的情况下才可行。

也就是说,libm.a 要简单得多。使 libc.a 无法用于应用程序的复杂交互不会影响 libm。您最终会在 libm 中实际运行代码的唯一一次是编译器以某种方式无法内联操作。将 libm.a 静态链接到您的应用程序应该没问题。

于 2018-12-14T19:50:04.173 回答