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

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

Реализация мульти‑архитектурных кросс‑компиляций в Termux через clang‑toolchain и multilib‑support

Termux — мощная среда для сборки программ на Android, однако для инженерных задач часто требуется больше: собрать одно и то же приложение под разные целевые архитектуры (например, aarch64 и armv7) и сохранить повторяемость. В этой статье разберём подход к реализации мульти‑архитектурных кросс‑компиляций в Termux с опорой на clang‑toolchain и multilib‑support, чтобы вы могли уверенно управлять ABI, sysroot и флагами линковщика.

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

Концепция: clang, multilib и sysroot

Кросс‑компиляция в Termux на практике состоит из трёх ключевых компонентов:

  1. Toolchain на базе clang: компилятор и сопутствующие инструменты (ассемблер/линкер), которые умеют собирать код для нужной архитектуры.
  2. multilib‑поддержка: наличие библиотек и runtime-компонентов под разные ABI/архитектуры в рамках одной toolchain.
  3. sysroot: корневая директория с заголовками и библиотеками, соответствующая целевому окружению (обычно Android‑ABI).

Важно понимать: multilib отвечает за то, что инструментам доступны нужные версии библиотек для разных целевых ABI, а sysroot определяет, какие именно заголовки и библиотеки вы используете при компиляции и линковке.

Подготовка Termux и архитектурные профили

Начните с базовой подготовки среды. Далее мы создадим профили сборки, чтобы переключение целевой архитектуры было управляемым и воспроизводимым.

Базовые шаги в Termux зависят от вашей схемы установки toolchain. В типичном сценарии вы используете репозитории Termux и/или пакеты с clang и библиотеками. Ниже приведён пример общего каркаса, который подойдёт для настройки (адаптируйте названия пакетов под вашу конфигурацию Termux):

pkg update
pkg install clang lld cmake ninja make git

Далее зададим переменные окружения и структуру проекта. Рекомендуется хранить настройки сборки в репозитории, чтобы команда могла повторить результаты на другой машине.

mkdir -p ~/build-multi/{aarch64,armv7}/{sysroot,build}
mkdir -p ~/toolchains
cd ~/build-multi

Для удобства создайте файлы профилей. Например, env-aarch64.sh и env-armv7.sh. Их задача — выставить ABI‑специфичные переменные: ARCH, TRIPLE, путь к SYSROOT и базовые CFLAGS/LDFLAGS.

Выбор target: GNU triplet/LLVM triple и ABI

В clang целевая архитектура задаётся через target (LLVM triple). Для Android встречаются типичные варианты (точный triple зависит от версии toolchain и вашей sysroot‑структуры). Практический принцип такой:

  • Для 64‑битного ARM используйте тройку для aarch64.
  • Для 32‑битного ARM выбирайте ABI, например hard‑float (armv7a + gnueabihf или эквивалент, в зависимости от набора библиотек).

Пример профиля для aarch64 (вставьте корректные тройки и пути под вашу sysroot):

cat > ~/build-multi/env-aarch64.sh <<'EOF'
export ARCH=aarch64
export TRIPLE=aarch64-linux-android
export SYSROOT=$HOME/build-multi/aarch64/sysroot

export COMMON_FLAGS="--target=${TRIPLE} -fPIC"
export CFLAGS="${COMMON_FLAGS} -O2"
export LDFLAGS="${COMMON_FLAGS} -fuse-ld=lld --sysroot=${SYSROOT}"
EOF

Профиль для armv7 (hard-float) — аналогично:

cat > ~/build-multi/env-armv7.sh <<'EOF'
export ARCH=armv7
export TRIPLE=armv7a-linux-androideabi
export SYSROOT=$HOME/build-multi/armv7/sysroot

export COMMON_FLAGS="--target=${TRIPLE} -fPIC -mthumb"
export CFLAGS="${COMMON_FLAGS} -O2 -march=armv7-a"
export LDFLAGS="${COMMON_FLAGS} -fuse-ld=lld --sysroot=${SYSROOT}"
EOF

Если вы используете multilib‑support, ключевой смысл в том, чтобы при переключении профиля toolchain находил библиотечные компоненты под нужный ABI, а sysroot предоставлял заголовки и системные .so/.a.

Сборка: один проект — два артефакта

Рассмотрим общий сценарий с CMake. Даже если ваш проект использует autotools или makefile, подход остаётся тем же: вы задаёте target и sysroot, затем используете соответствующие компоновочные флаги.

Подготовьте скелет сборки CMake (пример):

# Предположим, что исходники лежат в ~/src/your_project
cd ~/src/your_project

# CMake будет использовать переменные окружения из профилей
# и сформирует корректные флаги сборки.

Сборка под aarch64:

source ~/build-multi/env-aarch64.sh

cmake -S . -B ~/build-multi/aarch64/build 
  -G Ninja 
  -DCMAKE_BUILD_TYPE=Release 
  -DCMAKE_SYSROOT=${SYSROOT} 
  -DCMAKE_C_COMPILER=clang 
  -DCMAKE_CXX_COMPILER=clang++ 
  -DCMAKE_C_FLAGS="${CFLAGS} --sysroot=${SYSROOT}" 
  -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" 
  -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}"

cmake --build ~/build-multi/aarch64/build -- -j$(nproc)

Сборка под armv7:

source ~/build-multi/env-armv7.sh

cmake -S . -B ~/build-multi/armv7/build 
  -G Ninja 
  -DCMAKE_BUILD_TYPE=Release 
  -DCMAKE_SYSROOT=${SYSROOT} 
  -DCMAKE_C_COMPILER=clang 
  -DCMAKE_CXX_COMPILER=clang++ 
  -DCMAKE_C_FLAGS="${CFLAGS} --sysroot=${SYSROOT}" 
  -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" 
  -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}"

cmake --build ~/build-multi/armv7/build -- -j$(nproc)

Обратите внимание на два момента:

  • Ключевой набор флагов должен быть одинаковым по логике, но адаптированным под разные ABIs.
  • Артефакты лучше хранить в отдельных директориях, чтобы исключить пересечения конфигураций.

Линковка, статические/динамические зависимости и порядок библиотек

На Android нередко встречаются различия между статическими (.a) и динамическими (.so) зависимостями. При кросс‑сборке следуйте правилам:

  1. Убедитесь, что каждая библиотека соответствует целевой архитектуре.
  2. Если используете static linking, проверьте, что runtime-компоненты доступны под ваш ABI.
  3. Порядок библиотек на линковке иногда критичен: особенно при использовании --as-needed и при наличии сложных зависимостей.

Практический пример ручной линковки (фрагмент) через clang++ и lld:

clang++ --target=${TRIPLE} --sysroot=${SYSROOT} -fuse-ld=lld 
  -shared -Wl,--no-undefined 
  -o libyour.so build/your.o 
  -L${SYSROOT}/lib -landroid -llog

В реальном проекте зависимости могут отличаться. Главное — чтобы библиотечные пути были согласованы с целевым SYSROOT и выбранным ABI.

Что даёт multilib: быстрые переключения без переустановок

multilib‑support обычно позволяет держать в toolchain наборы библиотек/заголовков для нескольких ABI и быстро переключаться без полной пересборки toolchain. На практике вы получаете:

  • Стабильное использование одной базы toolchain (clang/lld).
  • Переключение архитектуры через --target и корректный SYSROOT.
  • Сокращение времени на настройку, если sysroot и lib‑наборы подобраны под ваш сценарий.

Однако multilib не отменяет необходимость корректного sysroot: без него вы рискуете получить несовместимые заголовки или библиотеки.

Проверка результата: валидация ABI и метаданных

После сборки стоит проверить, что артефакт действительно собран под нужный target. В Termux можно использовать инструменты уровня binutils (если доступны) или проверить библиотечные атрибуты через readelf/objdump (при наличии в вашей конфигурации).

# Пример: проверка типа ELF и архитектуры
readelf -h path/to/libyour.so | head

Ориентируйтесь на то, что для aarch64 и armv7 будут разные значения машинного кода (e_machine) и class (ELF64 vs ELF32).

Автоматизация: сборка всех архитектур одной командой

Чтобы упростить жизнь, сделайте скрипт, который по очереди запускает сборку для профилей и складывает результат в общий каталог.

cat > ~/build-multi/build-all.sh <<'EOF'
#!/data/data/com.termux/files/usr/bin/bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SRC_DIR="$HOME/src/your_project"
OUT_DIR="$HOME/build-multi/artifacts"

mkdir -p "${OUT_DIR}"

for arch in aarch64 armv7; do
  echo "=== Building ${arch} ==="
  source "${ROOT_DIR}/env-${arch}.sh"

  build_dir="$ROOT_DIR/${arch}/build"
  rm -rf "$build_dir"
  mkdir -p "$build_dir"

  cmake -S "${SRC_DIR}" -B "$build_dir" 
    -G Ninja 
    -DCMAKE_BUILD_TYPE=Release 
    -DCMAKE_SYSROOT="${SYSROOT}" 
    -DCMAKE_C_COMPILER=clang 
    -DCMAKE_CXX_COMPILER=clang++ 
    -DCMAKE_C_FLAGS="${CFLAGS} --sysroot=${SYSROOT}" 
    -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" 
    -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}"

  cmake --build "$build_dir" -- -j$(nproc)

  # Пример копирования .so (адаптируйте под вашу структуру)
  find "$build_dir" -maxdepth 3 -type f -name "*.so" -print -exec cp {} "${OUT_DIR}/" ;
done

echo "Done. Artifacts in: ${OUT_DIR}"
EOF

chmod +x ~/build-multi/build-all.sh
~/build-multi/build-all.sh

Такой подход повышает воспроизводимость и уменьшает риск “перемешивания” конфигураций.

Частые проблемы и как их диагностировать

Ниже — типовые ошибки, с которыми сталкиваются при кросс‑компиляции в мульти‑арх режиме:

  • Несовместимая архитектура библиотек: вы собрали под armv7, но подключили aarch64 .so. Решение — проверять совпадение ABI.
  • Не найден sysroot-заголовок/библиотека: неправильно задан --sysroot или пути в -L. Решение — выровнять CMAKE_SYSROOT и реальные пути.
  • Ошибка неопределённых ссылок: неверный порядок библиотек или недоступные зависимости под целевой ABI. Решение — корректировать набор -l и флаги линковщика (--no-undefined помогает выявлять проблему).
  • Неправильный ABI для armv7: hard/soft-float несоответствие. Решение — обеспечить консистентный triple и библиотечные наборы.

Ограничения и корректный контур использования VPN

Если вам нужно организовать доступ к ресурсам разработки (например, внутреннему серверу сборки или Git‑хранилищу через защищённое соединение), допускается использование VPN для создания локальной сети. Это не предназначено для обхода блокировок и должно соответствовать правилам вашей организации и действующему законодательству РФ.

Заключение

Мульти‑архитектурная кросс‑компиляция в Termux на базе clang‑toolchain и multilib‑support становится практичной, если вы строго разносите конфигурации по архитектурам, задаёте корректный --target, поддерживаете согласованный SYSROOT и контролируете ABI‑совместимость зависимостей. Такой подход позволяет получать набор артефактов для разных платформ из одной кодовой базы и с понятной логикой сборки.

Если вам нужна помощь с настройкой toolchain, подбором sysroot, организацией сборки CMake/Make под несколько ABI или аудитом флагов и зависимостей, обращайтесь в РыбинскЛАБ — мы поможем выстроить стабильный процесс кросс‑сборки под ваши требования.

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

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

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

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