Использование Android NDK r18b (с цепочкой инструментов clang) и Android Studio 3.2.1.

Соответствующая часть моего mylib.gradle:

task ndkBuild(type: Exec) {
    commandLine "${ndkDir}/ndk-build${ndkExt}"
}

Мой Application.mk:

APP_PLATFORM := android-17
APP_ABI := armeabi-v7a
# APP_OPTIM := release
APP_CFLAGS += -D_BSD_SOURCE

И соответствующая часть моего Android.mk:

include $(CLEAR_VARS)

LOCAL_PATH := $(BASE_PATH)
LOCAL_MODULE := mylib_jni

LOCAL_STATIC_LIBRARIES := \
  lib1 \
  lib2

LOCAL_WHOLE_STATIC_LIBRARIES := \
  mylib_wrap \
  other_wrap

include $(BUILD_SHARED_LIBRARY)

Статическая библиотека mylib_jni.so успешно построена. Затем я запускаю следующую команду (из NDK):

arm-linux-androidabi-readelf -a mylib_jni.so


Символы не удалены

В выводе я вижу имена всех нестатических методов в lib1 и lib2 (а не в целых библиотеках, как показано выше). Как это возможно? Как я могу получить выходные данные команды ndk-build с информацией о том, почему символы не удаляются? (Я не могу найти options.txt для моего шага сборки NDK.)

2
l33t 7 Ноя 2018 в 04:51

1 ответ

Лучший ответ

Боюсь, вы запутались между полосой и видимостью = скрыто .

прежний - это отдельный этап создания общей библиотеки после компоновки. Его цель - уменьшить размер файла (который будет упакован в APK) путем удаления некоторой дополнительной информации, которую компоновщик оставляет для целей отладки. Обратите внимание, что gradle (в Android Studio 3.2+) выполняет эту полосу даже позже, когда собственные библиотеки из всех модулей объединяются вместе.

Полоса влияет на размер файла, но не на видимость символов.

Скрытие символов - еще один способ уменьшить размер двоичных файлов. Также настоятельно рекомендуется уменьшить подверженность ваших библиотек обратному проектированию.

По умолчанию этого не происходит. Вы должны явно добавить этот флаг компилятора:

APP_CFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden

Вы можете совместить это с отказом от неиспользуемых функций:

APP_CFLAGS += -ffunction-sections -fdata-sections
APP_LDFLAGS += -Wl,--gc-sections

Вы должны явно пометить внешние функции с помощью

__attribute__ ((visibility ("default")))

К счастью, благодаря jni.h этот атрибут установлен для всех функций JNIEXPORT.

Если вы используете предварительно созданные статические библиотеки, вам также может понадобиться

APP_LDFLAGS += -Wl,--exclude-libs,ALL

Также рассмотрите возможность предоставления скрипта версии

LOCAL_LDFLAGS += -Wl,-version-script -Wl,mylib_jni.vs
6
Alex Cohn 7 Ноя 2018 в 12:26