Termux позволяет собирать собственные проекты и нативные библиотеки прямо на Android-устройстве. Однако для публикации библиотек в виде универсальных артефактов (например, для ARM64 и x86_64) часто нужна кросс-компиляция: сборка под целевую архитектуру, отличную от той, на которой выполняются команды.
В этой статье разберём, как собрать нативные библиотеки в Termux с использованием clang, NDK toolchain и CMake, подготовив сборочные цепочки для ARM64 и x86_64.
Важно: приведённые примеры не затрагивают обход блокировок или какие-либо незаконные действия. Мы работаем в рамках легитимного процесса сборки и компоновки нативного кода под нужные архитектуры.
Что нужно перед стартом
Перед началом убедитесь, что в Termux доступны:
- Системный инструментарий:
clang,cmake,make - Android NDK (для получения toolchain, sysroot и стандартных библиотек под нужную архитектуру)
- Исходники библиотеки (или репозиторий), которую нужно собрать
Также учтите: в зависимости от версии Android-устройства и доступной памяти сборка может быть ресурсоёмкой. Рекомендуется использовать swap/достаточный объём свободного места.
Установка базовых пакетов в Termux
Начните с обновления пакетов и установки инструментов:
pkg update -y
pkg upgrade -y
pkg install -y clang cmake make git pkg-configНа некоторых устройствах могут потребоваться дополнительные зависимости (например, python для генераторов или ninja, если вы предпочитаете Ninja). Для CMake по умолчанию обычно достаточно make.
Подготовка Android NDK
Для кросс-компиляции вам понадобится Android NDK, чтобы получить toolchain и sysroot под целевые ABI.
Есть два популярных подхода:
- Скачать NDK и распаковать в Termux (например, в
$HOME) - Использовать NDK, который уже есть в вашем проекте (если вы работаете внутри репозитория с bundled NDK)
Ниже рассмотрим типовой вариант, где NDK лежит в $HOME/android-ndk.
export NDK_HOME="$HOME/android-ndk"
ls "$NDK_HOME"Убедитесь, что внутри есть папки вида toolchains и sysroot (они должны присутствовать в NDK).
Концепция: CMake toolchain file
Чтобы CMake собирал под нужную архитектуру (ARM64 или x86_64), мы используем toolchain file. Он сообщает CMake:
- каким компилятором пользоваться (
clang) - какой target / triple использовать
- какой sysroot брать из NDK
- какой ABI и настройки языка/стандарта
Далее мы будем создавать отдельные toolchain файлы для arm64-v8a и x86_64.
Toolchain для ARM64 (arm64-v8a)
Создайте файл toolchain, например:
mkdir -p "$HOME/toolchains"
cat > "$HOME/toolchains/android-arm64.cmake" <<'EOF'
# Android ARM64 toolchain for Termux + Android NDK
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 1)
# Укажите NDK_HOME в окружении перед запуском, либо передайте -DNDK_HOME=...
if(NOT DEFINED NDK_HOME)
message(FATAL_ERROR "NDK_HOME is not set. Example: export NDK_HOME=$HOME/android-ndk")
endif()
# ABI и target
set(ANDROID_ABI arm64-v8a)
set(ANDROID_PLATFORM android-21)
# Компилятор clang из NDK
set(CMAKE_C_COMPILER "${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang")
set(CMAKE_CXX_COMPILER "${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++")
# Важно: sysroot берём из NDK в зависимости от platform/ABI
set(CMAKE_SYSROOT "${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot")
# CMake параметры
set(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")
set(CMAKE_ANDROID_NDK "${NDK_HOME}")
# Настройка поиска
set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Для воспроизводимости
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
EOFПримечание: путь к prebuilt-бинарям в NDK зависит от того, под какую ОС/архитектуру вы распаковали NDK. На практике в Termux чаще встречается, что prebuilt лежит в виде linux-x86_64 (или darwin-x86_64, windows-x86_64). Если ваш NDK распакован иначе, замените сегмент linux-x86_64 на фактический каталог внутри $NDK_HOME/toolchains/llvm/prebuilt/.
Проверить можно так:
ls "$NDK_HOME/toolchains/llvm/prebuilt"Toolchain для x86_64 (x86_64)
Создайте второй toolchain файл:
cat > "$HOME/toolchains/android-x86_64.cmake" <<'EOF'
# Android x86_64 toolchain for Termux + Android NDK
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 1)
if(NOT DEFINED NDK_HOME)
message(FATAL_ERROR "NDK_HOME is not set. Example: export NDK_HOME=$HOME/android-ndk")
endif()
set(ANDROID_ABI x86_64)
set(ANDROID_PLATFORM android-21)
# clang компиляторы для x86_64
set(CMAKE_C_COMPILER "${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang")
set(CMAKE_CXX_COMPILER "${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang++")
set(CMAKE_SYSROOT "${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot")
set(CMAKE_ANDROID_ARCH_ABI "x86_64")
set(CMAKE_ANDROID_NDK "${NDK_HOME}")
set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
EOFКак и ранее, возможно потребуется корректировка linux-x86_64 в пути до prebuilt LLVM toolchain под вашу раскладку NDK.
Структура проекта: пример с исходниками и out-of-source build
Рекомендуется делать сборку вне исходников (out-of-source), чтобы избежать загрязнения папки проекта.
Предположим, ваша библиотека лежит в текущем каталоге $HOME/src/mylib.
cd "$HOME/src/mylib"
mkdir -p "$HOME/build/mylib-arm64"
mkdir -p "$HOME/build/mylib-x86_64"Сборка ARM64 через CMake
Запустите CMake с toolchain file:
export NDK_HOME="$HOME/android-ndk"
cmake -S . -B "$HOME/build/mylib-arm64"
-DCMAKE_TOOLCHAIN_FILE="$HOME/toolchains/android-arm64.cmake"
-DCMAKE_BUILD_TYPE=Release
-DANDROID_ABI=arm64-v8a
-DANDROID_PLATFORM=android-21Затем соберите:
cmake --build "$HOME/build/mylib-arm64" -- -j$(nproc)Результаты обычно окажутся в папках вида $HOME/build/mylib-arm64/lib, $HOME/build/mylib-arm64/bin или в зависимости от конфигурации проекта.
Сборка x86_64 через CMake
Аналогично собираем под x86_64 в отдельной директории:
cmake -S . -B "$HOME/build/mylib-x86_64"
-DCMAKE_TOOLCHAIN_FILE="$HOME/toolchains/android-x86_64.cmake"
-DCMAKE_BUILD_TYPE=Release
-DANDROID_ABI=x86_64
-DANDROID_PLATFORM=android-21И выполняем сборку:
cmake --build "$HOME/build/mylib-x86_64" -- -j$(nproc)Проверка архитектуры получившихся библиотек
После сборки полезно убедиться, что получились артефакты под нужные ABI. Для проверки можно использовать readelf или file (если они доступны). Если file нет, можно ограничиться тем, что вы посмотрели, какие ABI библиотека ожидает.
Попробуйте:
find "$HOME/build/mylib-arm64" -name ".so" -o -name ".a"
find "$HOME/build/mylib-x86_64" -name ".so" -o -name ".a"И далее проверяйте конкретный файл (пример):
file "$HOME/build/mylib-arm64/path/to/libmylib.so"
file "$HOME/build/mylib-x86_64/path/to/libmylib.so"Если file недостаточно точен, установите утилиты, если доступны в репозитории Termux, или используйте readelf. В зависимости от окружения инструменты могут отличаться.
Сборка «универсального» набора артефактов
Чтобы собрать «fat»-набор для разных ABI, обычно копируют результаты в структуру наподобие:
mkdir -p "$HOME/out/mylib/arm64-v8a"
mkdir -p "$HOME/out/mylib/x86_64"
# Пример: подставьте реальные пути до .so или .a
cp "$HOME/build/mylib-arm64/path/to/libmylib.so" "$HOME/out/mylib/arm64-v8a/"
cp "$HOME/build/mylib-x86_64/path/to/libmylib.so" "$HOME/out/mylib/x86_64/"Дальше вы можете упаковать результат вместе с headers (если нужна публичная API-библиотека), либо положить в проект приложения, которое будет грузить соответствующие ABI.
Типовые проблемы и как их диагностировать
- Неправильный путь к prebuilt toolchain в NDK
Симптом: CMake не находит компилятор (clang) или команда не выполняется. Решение: проверьте каталог$NDK_HOME/toolchains/llvm/prebuilt/и заменитеlinux-x86_64на фактическое значение. - Ошибка sysroot / отсутствующие заголовки
Симптом: множество ошибок вида «file not found». Решение: убедитесь, что sysroot задан корректно и совпадает с выбранным prebuilt LLVM каталогом. - Несовместимость CMake с Android-плагинами
Симптом: проект ожидает специфичные Android переменные. Решение: добавьте нужные-Dпараметры (например,ANDROID_ABI,ANDROID_PLATFORM) и проверьте документацию конкретного проекта. - Слишком долгие сборки
Симптом: сборка долго «прогревается» и может падать из-за памяти. Решение: уменьшайте параллелизм-j, включайте кэш, используйте incremental сборки и проверьте наличие swap.
Практический шаблон команд (сводка)
Ниже краткий шаблон, которым можно пользоваться для любой библиотеки, меняя пути и имена файлов.
export NDK_HOME="$HOME/android-ndk"
# ARM64
cmake -S . -B "$HOME/build/myproj-arm64"
-DCMAKE_TOOLCHAIN_FILE="$HOME/toolchains/android-arm64.cmake"
-DCMAKE_BUILD_TYPE=Release
cmake --build "$HOME/build/myproj-arm64" -- -j$(nproc)
# x86_64
cmake -S . -B "$HOME/build/myproj-x86_64"
-DCMAKE_TOOLCHAIN_FILE="$HOME/toolchains/android-x86_64.cmake"
-DCMAKE_BUILD_TYPE=Release
cmake --build "$HOME/build/myproj-x86_64" -- -j$(nproc)Заключение
Кросс-компиляция нативных библиотек в Termux с использованием clang, NDK toolchain и CMake — это практичный способ получать сборки под разные архитектуры, прежде всего ARM64 и x86_64. Ключевой элемент — корректно настроенные toolchain file и правильные пути до clang и sysroot из NDK.
Если хотите, чтобы сборка под ваши ABI была настроена «под ключ» (включая поддержку ваших зависимостей, оптимизаций и упаковки артефактов для приложения), обратитесь в РыбинскЛАБ: мы помогаем с DevOps-подходами, сборочными пайплайнами и развертыванием toolchain в Termux.