We detected you are likely not from a Russian-speaking region. Would you like to switch to the international version of the site?

  Назад к списку статей

Разработка и отладка нативных Android‑модулей (NDK) прямо в Termux: сборка, линковка и отладка

Профессиональный гайд по сборке и отладке Android NDK-модулей в Termux: установка toolchain, сборка C/C++ библиотек, линковка, работа с Gradle/manifest и базовая отладка.

Разработчик: Усачёв Денис Евгеньевич, ведущий эксперт РыбинскЛАБ

Зачем делать NDK в Termux

Termux — мощная среда для работы в оболочке на Android. При наличии корректно собранного toolchain и понятной связки с Android-проектом (Gradle/ABI/Manifest) можно организовать разработку и отладку нативных модулей так же системно, как на Linux. Ниже — практический путь: от подготовки до сборки, линковки и отладки.

Ограничения и важные замечания

  • Архитектуры (ABI): NDK-сборка зависит от ABI (arm64-v8a, armeabi-v7a, x86_64 и т.д.). Подбирайте целевую архитектуру под устройство.
  • Платформенная интеграция: для загрузки .so в Android-приложении нужен Java/Kotlin-контур и корректная конфигурация проекта (lib + System.loadLibrary).
  • Отладка: полноценная отладка (breakpoints, step) обычно требует связки с Android Studio/LLDB. Но базовую верификацию можно делать прямо через logcat и тестовые вызовы.
  • Никаких обходов блокировок через VPN: если вы используете VPN, то только для создания локальной сети (например, для лабораторного стенда), не для обхода ограничений.

Подготовка окружения Termux

Начните с обновления пакетов и установки базовых инструментов. Мы будем использовать кросс-компиляцию под Android из Termux.

pkg update -y
pkg upgrade -y
pkg install -y clang lld make cmake ninja git curl unzip tar

Дальше важно получить NDK. Есть два типовых подхода:

  • Вариант A (рекомендуется): использовать NDK, скачанный/встроенный в ваш Android Studio-проект.
  • Вариант B: вручную скачать NDK и использовать его напрямую из Termux (потребуются аккуратные пути и версии).

Для согласованности с Android-проектом рассмотрим Вариант A, но решения в целом применимы и к B.

Структура проекта: как связать NDK и Termux

Схема обычно такая:

  • Termux — сборка нативной части (C/C++), генерация .so.
  • Android-приложение — размещение .so по ABI, загрузка библиотек и вызов нативных функций.

Минимальная структура:

your-android-app/
  app/
    src/main/
      java/... (Kotlin/Java)
      jniLibs/
        arm64-v8a/
          libnative-lib.so
        armeabi-v7a/
          libnative-lib.so
      (или src/main/jni/ + Gradle сборка, но вы идёте через Termux)

Если вы хотите “полный цикл” именно в Termux, то удобнее собирать .so вручную и класть готовые артефакты в src/main/jniLibs/<abi>.

Получение путей к NDK и toolchain

Обычно NDK хранится в каталоге Android Studio или в папке проекта. Например, внутри Gradle можно найти путь к NDK.

В Termux вам понадобятся:

  • путь к $ANDROID_NDK
  • выбранный $ABI
  • API level (минимальный Android API)

Пример установки переменных окружения (пути подставьте под ваш проект):

export ANDROID_NDK=/path/to/your-ndk
export ABI=arm64-v8a
export ANDROID_PLATFORM=android-24

Сборка нативной библиотеки: компиляция и линковка

Рассмотрим минимальный пример C++ библиотеки, которую мы соберём в .so. Предположим, что исходники находятся в каталоге native/ в вашем проекте.

native/native-lib.cpp:

#include <jni.h>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_app_MainActivity_stringFromJNI(JNIEnv env, jobject / this */) {
    return env->NewStringUTF("Hello from native (built in Termux)");
}

Далее — сборка. Ключевой момент: использовать правильный компилятор из NDK и правильные флаги для линковки.

Ниже — “ручная” схема (подходит для базовой библиотечной сборки). Пример для arm64-v8a:

# Переходим в каталог с исходниками (подстройте пути)
cd /path/to/your-android-app/app/src/main/native

# Определяем toolchain prefix
TOOLCHAIN="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android"

# Если среда prebuilt отличается (например, darwin), подстройте linux-x86_64.

# Компиляция
$TOOLCHAIN$ANDROID_PLATFORM-clang++ \
  -fPIC \
  -std=c++17 \
  -O2 \
  -c native-lib.cpp \
  -o native-lib.o

# Линковка в .so
$TOOLCHAIN$ANDROID_PLATFORM-clang++ \
  -shared \
  -Wl,--no-undefined \
  native-lib.o \
  -o /path/to/your-android-app/app/src/main/jniLibs/arm64-v8a/libnative-lib.so

Важно: путь к prebuilt/linux-x86_64 зависит от вашей хост-платформы, но в Termux “хостом” физически остаётся ваше Android-устройство. Поэтому этот вариант применим, если вы используете NDK-архив, содержащий prebuilt под нужную систему, либо заранее корректно разместили NDK. На практике чаще “безболезненнее” опираться на Gradle, но вы просите именно Termux-циклы — тогда внимательно проверьте реальный путь к компилятору в вашем NDK.

Проверка артефактов: права, ABI и символы

После линковки убедитесь, что .so действительно собрана под нужный ABI. Для первичной проверки можно использовать утилиты из NDK/бинари.

# Пример проверки (инструменты могут называться по-разному)
ls -lah /path/to/your-android-app/app/src/main/jniLibs/arm64-v8a/libnative-lib.so

# Если доступны readelf/llvm-readobj:
# readelf -h libnative-lib.so | head

Также убедитесь, что имя библиотеки соответствует тому, что будет грузиться в Android-коде: например, libnative-lib.so соответствует System.loadLibrary("native-lib").

Интеграция в Android-проект (Kotlin/Java) и загрузка .so

В MainActivity (или другом классе) объявите native-метод и загрузите библиотеку.

Пример Kotlin:

class MainActivity : AppCompatActivity() {
    companion object {
        init {
            System.loadLibrary("native-lib")
        }
    }

    external fun stringFromJNI(): String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val tv = findViewById<TextView>(R.id.textView)
        tv.text = stringFromJNI()
    }
}

Если подписи JNI не совпадут, метод не найдёт корректную реализацию. Поэтому проверьте пакет/имя класса и сигнатуру (как в C++ функции Java_..._... соответствуют имени пакета и классу).

Сборка и запуск приложения после Termux-сборки

Далее вы собираете APK/AAB стандартным способом (Gradle). Варианты:

  • в Android Studio (быстрее для отладки)
  • через Gradle из Termux при наличии подходящей JVM/Gradle (обычно удобнее всё же через Android Studio)

На практике чаще делается так: вы собираете .so в Termux, затем запускаете приложение через Android Studio, которая подхватит обновлённый файл в jniLibs.

Отладка: logcat, проверки JNI и подготовка к LLDB

Базовая диагностика обычно начинается с logcat.

adb logcat | grep -i native

Если у вас есть отладочные сообщения в native-коде — используйте Android logging (через android_log_print), но это потребует подключения android/log.h и линковки к log библиотеке.

Пример добавления логов:

#include <android/log.h>
#define LOG_TAG "native-lib"

android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Value=%d", value);

И затем при линковке иногда нужно добавить -llog (зависит от архитектуры и точных флагов).

Отладка с символами и ожидания отладчика

Для более комфортной отладки убедитесь, что линковка включает отладочную информацию. Вместо -O2 используйте -O0 -g на время отладки.

# Временно для отладки
$TOOLCHAIN$ANDROID_PLATFORM-clang++ \
  -fPIC -std=c++17 \
  -O0 -g \
  -c native-lib.cpp -o native-lib.o

$TOOLCHAIN$ANDROID_PLATFORM-clang++ \
  -shared \
  -Wl,--no-undefined \
  -g \
  native-lib.o \
  -o /path/to/your-android-app/app/src/main/jniLibs/arm64-v8a/libnative-lib.so

Для работы с точками останова и пошагового выполнения обычно требуется подключение отладчика (LLDB) через Android Studio. Однако сам факт наличия корректных symbol files (-g) и единообразных путей сильно помогает.

Рекомендованный “workflow” для ежедневной разработки

  • Шаг 1: Изменили C/C++ в native/.
  • Шаг 2: Собрали .so в Termux (компиляция + линковка с нужными флагами).
  • Шаг 3: Запустили/перезапустили приложение в Android Studio.
  • Шаг 4: Проверили поведение через UI и logcat.
  • Шаг 5: При необходимости включили -O0 -g и перешли к более “серьёзной” отладке.

Типичные проблемы и как их устранить

  • UnsatisfiedLinkError: библиотека не загрузилась или имя/пакет JNI не совпали.
  • Проблемы ABI: приложение ищет .so под конкретную архитектуру устройства. Убедитесь, что нужный ABI есть в jniLibs.
  • Проблемы с JNI-именами: проверьте соответствие функции: Java_<package>_<Class>_<method> и сигнатуры.
  • Некорректный NDK toolchain путь: проверьте реальный путь к clang++ внутри NDK.

Заключение

Разработка и отладка нативных Android‑модулей (NDK) прямо в Termux возможна и практична при правильной настройке: точные пути к NDK, дисциплина по ABI, аккуратная компиляция/линейка в .so и понятная интеграция через jniLibs + System.loadLibrary. Для отладки эффективно комбинируйте Termux-сборку (с отладочными символами) и Android-диагностику через logcat и инструменты IDE.

Если вам нужна помощь с настройкой окружения, переносом проекта на “Termux-first workflow”, отладкой JNI/ABI или выстраиванием CI для нативной сборки — обращайтесь в РыбинскЛАБ. Мы поможем довести процесс до стабильного промышленного уровня.

* Текст статьи подготовлен и структурирован с использованием технологий искусственного интеллекта. Проверен и доработан перед публикацией.

Нужна помощь с настройкой Termux, Linux и серверов?

Я оказываю ИТ-услуги: настройка серверов, автоматизация, безопасность, помощь с Linux и инфраструктурой. Материалы сайта — только в ознакомительных и образовательных целях.

Связаться со мной
Поддержать проект