Автор: Усачёв Денис Евгеньевич, ведущий эксперт РыбинскЛАБ.
Введение: зачем собирать кросс‑платформенные проекты прямо в Termux
Termux позволяет превратить Android‑устройство в удобную среду разработки и сборки под Linux‑подобную командную строку. На практике это особенно полезно для кросс‑платформенных проектов на C/C++: вы пишете код, компилируете его под целевую платформу, а затем переносите артефакты на устройство или в репозиторий. В связке Android NDK + CMake + clang можно собирать нативные библиотеки (.so) и небольшие CLI‑утилиты, сохраняя привычный workflow.
Ниже — практическое руководство: как подготовить toolchain, настроить CMake и организовать сборку под популярные Android‑ABI (arm64‑v8a, armeabi‑v7a, x86_64 и т.д.). Материал ориентирован на легальную разработку и компиляцию собственных проектов.
Требования и подготовка окружения в Termux
Перед началом проверьте базовую систему и обновите пакеты. В Termux используйте репозиторий F-Droid/встроенные пакеты (официально рекомендованный сценарий зависит от вашей версии Termux):
pkg update && pkg upgrade
Установим базовые инструменты сборки и отладочный набор:
pkg install -y git curl wget unzip tar build-essential cmake ninja clang lld pkg-config
Важно: clang в Termux может использоваться для сборки «локальных» Linux‑частей. Для сборки под Android мы будем опираться на clang из NDK. Termux‑clang при этом может оставаться полезным для вспомогательных этапов.
Установка Android NDK в Termux
Есть два корректных подхода: (1) скачать NDK архивом, (2) использовать собственные средства хранения/доступа к NDK на устройстве. Удобнее всего скачать конкретную версию NDK и распаковать в рабочую директорию.
Создайте рабочий каталог и скачайте NDK:
mkdir -p ~/android-sdk ~/work
cd ~/work
Пример загрузки (подставьте актуальную ссылку на NDK rxx):
wget -O ndk.zip "https://dl.google.com/android/repository/android-ndk-r26b-linux.zip"
unzip ndk.zip -d ~/android-sdk
После распаковки обычно появится каталог вида ~/android-sdk/android-ndk-r26b. Проверьте наличие:
ls ~/android-sdk/
Если ваш NDK распакован под именем директории иначе — скорректируйте пути в дальнейших командах.
Подготовка переменных для NDK, toolchain и ABI
Ключевая часть кросс‑сборки — правильный toolchain. В NDK поддерживаются разные ABI и платформы. Обычно вы выбираете:
- ABI:
arm64-v8a,armeabi-v7a,x86_64и др. - API level: например,
21или выше (для совместимости). - Стандартный sysroot и компилятор clang из NDK.
Сформируем удобные переменные. Например, для arm64‑v8a:
export NDK_HOME="$HOME/android-sdk/android-ndk-r26b"
export ANDROID_API=26
export TARGET_ABI=arm64-v8a
Проверим наличие clang внутри NDK:
ls "$NDK_HOME/toolchains/llvm/prebuilt"
Внутри будет директория с именем, зависящим от хоста. Для Android‑устройств чаще встречаются сборки под linux‑вариант. Например:
ls "$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64"
Определим PREBUILT_HOST автоматически (вручную тоже можно):
export PREBUILT_HOST="linux-x86_64"
export LLVM_BIN="$NDK_HOME/toolchains/llvm/prebuilt/$PREBUILT_HOST/bin"
Убедимся, что clang существует:
$LLVM_BIN/clang --version
Генерация toolchain-файла для CMake
CMake упрощает кросс‑компиляцию, если предоставить toolchain file. Для Android можно либо использовать готовый модуль NDK, либо явно задать параметры. Ниже — практичный вариант toolchain‑файла.
Создайте файл android-toolchain.cmake в корне проекта или в ~/work. Пример (универсальный шаблон, где ABI и API берутся из переменных):
cat > android-toolchain.cmake <<'EOF'
# Android toolchain for CMake
set(CMAKE_SYSTEM_NAME Android)
# Внешние параметры
set(NDK_HOME "$ENV{NDK_HOME}")
set(ANDROID_API "$ENV{ANDROID_API}")
set(TARGET_ABI "$ENV{TARGET_ABI}")
set(PREBUILT_HOST "$ENV{PREBUILT_HOST}")
set(LLVM_TRIPLE "aarch64-linux-android")
if(TARGET_ABI STREQUAL "arm64-v8a")
set(LLVM_TRIPLE "aarch64-linux-android")
elseif(TARGET_ABI STREQUAL "armeabi-v7a")
set(LLVM_TRIPLE "armv7a-linux-androideabi")
elseif(TARGET_ABI STREQUAL "x86_64")
set(LLVM_TRIPLE "x86_64-linux-android")
elseif(TARGET_ABI STREQUAL "x86")
set(LLVM_TRIPLE "i686-linux-android")
endif()
set(CMAKE_ANDROID_ARCH_ABI ${TARGET_ABI})
set(CMAKE_ANDROID_NDK ${NDK_HOME})
set(CMAKE_ANDROID_API ${ANDROID_API})
# Указываем компилятор clang из NDK
set(CMAKE_C_COMPILER "${NDK_HOME}/toolchains/llvm/prebuilt/${PREBUILT_HOST}/bin/${LLVM_TRIPLE}${ANDROID_API}-clang")
set(CMAKE_CXX_COMPILER "${NDK_HOME}/toolchains/llvm/prebuilt/${PREBUILT_HOST}/bin/${LLVM_TRIPLE}${ANDROID_API}-clang++")
# sysroot и флаги обычно подхватываются через CMAKE_ANDROID_NDK.
# Но можно добавить явные настройки при необходимости.
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
EOF
Обратите внимание: тройка LLVM_TRIPLE и суффикс ${ANDROID_API} зависят от NDK. Если у вас окажется несоответствие, проверьте точные имена clang через команду в директории .../bin. Для корректности всегда лучше сверить реальные бинарники.
Структура проекта и подготовка исходников
Рассмотрим типовой пример: у вас есть CMake‑проект с CMakeLists.txt. Для кросс‑сборки важно, чтобы вы:
- использовали
add_library/add_executableс корректными исходниками; - избегали жестко заданных системных путей;
- применяли
target_include_directoriesи зависимости черезtarget_link_libraries.
Если проект использует собственные зависимости, учитывайте, что в Android окружении они должны быть собраны или доступны как prebuilt под вашу ABI.
Пример CMakeLists.txt для сборки библиотеки
Шаблон минимальной библиотеки:
cat > CMakeLists.txt <<'EOF'
cmake_minimum_required(VERSION 3.22)
project(mini-ndk-lib LANGUAGES C CXX)
add_library(mini SHARED
src/mini.c
)
target_compile_features(mini PRIVATE c_std_11)
# Опционально: дополнительные флаги
# set_target_properties(mini PROPERTIES C_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON)
EOF
Создайте исходник src/mini.c:
mkdir -p src
cat > src/mini.c <<'EOF'
#include <stdio.h>
int mini_value(void) {
return 42;
}
EOF
Сборка под Android в Termux: запуск CMake и Ninja
Организуйте build‑каталог отдельно для каждой ABI, чтобы не смешивать артефакты.
Например, для arm64‑v8a:
export BUILD_DIR="~/work/build-${TARGET_ABI}"
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
cmake \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="$HOME/work/android-toolchain.cmake" \
-DANDROID_STL=c++_shared \
"$HOME/work/your-project"
ninja -v
Важный момент: если ваш проект на C без C++, не нужно задавать ANDROID_STL. Но для C++ — обычно нужно, чтобы корректно выбрать стандартную библиотеку рантайма (например, c++_shared или c++_static).
Список ABI и типичные отличия
Для расширения охвата просто меняйте TARGET_ABI. Например:
for ABI in arm64-v8a armeabi-v7a x86_64; do
export TARGET_ABI="$ABI"
export BUILD_DIR="~/work/build-${ABI}"
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
cmake -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="$HOME/work/android-toolchain.cmake" \
"$HOME/work/your-project"
ninja -v
done
Если сборка падает на этапе линковки — чаще всего проблема связана с несовпадением ABI зависимостей, неправильным API level или тем, что ABI/тройка не соответствует доступным бинарникам clang внутри NDK.
Вывод артефактов и размещение .so
По умолчанию CMake складывает результаты в подкаталоги build‑директории. Для удобства полезно знать где именно лежит mini.so. Проверьте:
find "$BUILD_DIR" -maxdepth 4 -name ".so"
Далее артефакты можно поместить в структуру Android проекта (например, app/src/main/jniLibs/<abi>/) или использовать для интеграции через Gradle/другие механизмы. В рамках Termux часто достаточно сохранить .so в папку, синхронизируемую с вашим репозиторием.
Отладка сборки: распространенные ошибки и быстрые проверки
1) Ошибка “C compiler cannot create executables”
Это частая проблема при кросс‑сборке. Она может возникнуть, если CMake пытается запускать собранный бинарник на хосте. Решение — корректно задать toolchain и параметры Android через android-toolchain.cmake. Для Android кросс‑сборки обычно это автоматически предотвращается правильно настроенным toolchain.
2) Не находится clang
Проверьте точное имя файла clang в директории $LLVM_BIN:
ls "$LLVM_BIN" | grep clang | head
И скорректируйте LLVM_TRIPLE и суффикс ${ANDROID_API} в toolchain‑файле.
3) Несовместимость ABI зависимостей
Если вы линковали внешнюю библиотеку, убедитесь, что её .so собрана под тот же ABI и тот же уровень/ABI‑совместимость.
Автоматизация: сборка “Android‑Linux” как кросс‑процесс
Под “Android‑Linux” в этом контексте обычно понимают процесс, где вы ведёте сборку в Linux‑подобной среде Termux (Android как хост), но получаете нативные артефакты для Android ABI. Практически вы организуете pipeline как “build on Android-host → output for Android target”.
Автоматизируйте:
- выбор ABI и API;
- создание build‑директорий по ABI;
- сохранение артефактов в единый каталог;
- ведение логов (например,
ninja -v > build.log 2>&1).
Пример структуры вывода:
export OUT_DIR="$HOME/work/out"
mkdir -p "$OUT_DIR"
# после ninja копируйте найденные .so
cp -v "$BUILD_DIR"/**/libmini.so "$OUT_DIR/" 2>/dev/null || true
Про VPN: только для создания локальной сети
Если вам нужно организовать локальную сеть между устройствами разработки (например, для доступа к общему репозиторию/тестовому серверу внутри вашей сети), допускается использование VPN для создания локальной сети. Это не предназначено для обхода блокировок или иных ограничений — выбирайте легальные и безопасные сценарии.
Заключение
Termux отлично подходит для кросс‑платформенной разработки: вы можете настроить Android NDK, подготовить toolchain для CMake и собирать нативные библиотеки под разные ABI с использованием clang из NDK. Главное — строго следить за соответствием ABI/API и проверять реальные имена бинарников в NDK, а также аккуратно отделять build‑директории по архитектурам.
Если хотите ускорить настройку под ваш проект (включая интеграцию зависимостей, поддержку нескольких ABI и оптимизации для Release/Debug), обратитесь за помощью в РыбинскЛАБ. Мы поможем выстроить сборочный пайплайн и довести окружение до стабильной работы.