Связывание ошибок при использовании функций изв использовании API уровня 22 - PullRequest
0 голосов
/ 14 декабря 2018

Я портирую библиотеку C и C ++, которая в настоящее время работает на iOS, для использования в приложении Android.Я дошел до этих последних 3 ошибок компоновщика (обфусцировано по соображениям конфиденциальности):

/ Users / fer662 / projects / xxx / jni / xxx_preprocessing.c: 10184: ошибка: неопределенная ссылка на 'cexp' / Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10184: ошибка: неопределенная ссылка на 'cpowf' /Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10285: ошибка: неопределенная ссылка на 'cabs'

Теперь я понимаю, что это обычно происходит из-за связи с libm.so (-lm), но я уже делаю это.Если я пойду и проверим оскорбление с помощью nm:

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

Ничего не вернется.Однако, если я использую 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

, в статической библиотеке он показывает даже на 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

НесоответствиеозадачиваетНе должно ли оно вообще отсутствовать в заголовке, если не поддерживается?Почему статический lib имеет его, а dylib нет?

Имеет ли смысл статически связываться с ним?И если да, то как мне это сделать, учитывая правильный путь для текущей версии API?

Кажется, что другой мой вариант - украсть реализацию libm (скажем, http://openlibm.org/) или только этиИз него я использую 3 функции.

1 Ответ

0 голосов
/ 14 декабря 2018

tl; др: да, статическое связывание libm.a должно быть в порядке

Проверьте файл libm.map.txt: https://android.googlesource.com/platform/bionic/+/master/libm/libm.map.txt#289

Эти функции не былине добавляется в Android до O.

Кроме того, в статической библиотеке она отображается, даже на API 22 * ​​1011 *

Статическая библиотека не является статической API 22библиотека.Это на самом деле сборка ToT из AOSP.Если вы собираетесь что-то статически связывать, нет смысла использовать что-то старое.

Причина, по которой это (на самом деле только одна версия libc.a / libm.a на ABI) дублируется в каждом каталоге 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 с вашим приложением должно быть в порядке.

...