Компиляция под другую архитектуру процессора
По умолчанию компилятор собирает программу под ту же архитектуру, на
которой сам запущен. Флаг --целевая-платформа позволяет указать
любую другую — компилятор построен поверх LLVM, который уже умеет
генерировать код для множества архитектур, не только для той, что "под
рукой":
запустить программа.код -c --целевая-платформа aarch64-linux-gnu
Полученный файл — самый обычный, настоящий исполняемый файл под
указанную архитектуру (можно проверить командой file имя_программы).
Для запуска на машине с другой архитектурой нужен либо компьютер с
реальным таким процессором, либо эмуляция (например, qemu-aarch64
для ARM64 на Linux).
⚠️ Честное ограничение: для итоговой линковки нужен установленный
кросс-компилятор под целевую платформу (например,
gcc-aarch64-linux-gnu для ARM64 на Debian/Ubuntu) — сам компилятор
Сферы это не устанавливает автоматически.
Компиляция под Android
Требует дополнительно флаг --android-sysroot ПУТЬ — путь к папке
sysroot из настоящего Android NDK
(toolchains/llvm/prebuilt/linux-x86_64/sysroot/), плюс номер
API-уровня прямо в тройке платформы:
запустить программа.код -c --целевая-платформа aarch64-linux-android21 \
--android-sysroot /путь/к/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot
✅ Проверено полностью, включая реальный запуск на физическом Android-устройстве через Termux (не только структура файла) — программа со структурой, методом и циклом отработала корректно.
Компиляция, линковка и запуск прямо внутри APK (без root, без Termux)
Кросс-компиляция описанным выше способом даёт исполняемый файл, но
чтобы его на Android ещё и запустить, обычно нужен root или
Termux — у обычного приложения нет прав исполнять файл, скачанный или
созданный во время работы (политика W^X). Это решено без root и без
Termux: сам компилятор запустить, линковщик ld.lld и небольшая
Sfera-замена clang (переводит вызов вида clang ... в правильный
вызов ld.lld с нужными путями) кросс-собраны под ARM64 и зашиты в
APK как файлы lib/arm64-v8a/*.so — Android распаковывает всё, что
лежит в lib/<abi>/ и называется lib*.so, с правом на исполнение,
это и используется (легальный, документированный приём, не эксплойт).
Дальше внутри приложения запустить вызывается как обычная внешняя
команда (через выполнить_команду, то есть system() — на Android
это работает, вопреки более раннему предположению в этом файле и в
комментариях панель_android.код, что прямого доступа к оболочке
нет), с явно выставленным LD_LIBRARY_PATH и заранее подготовленным
--android-sysroot (символьные ссылки на crtbegin/crtend и
системные .so из собственного каталога библиотек приложения — сам
NDK на устройстве не нужен).
Подводных камней два, оба честно стоят того, чтобы их упомянуть:
- Имя файла в
lib/arm64-v8a/обязано заканчиваться ровно на.so
— иначе Android его при установке вообще не распакует, и линковка
падает с library ... not found, даже если LD_LIBRARY_PATH
указан правильно. Любой файл тулчейна, у которого родное имя не
оканчивается на .so (например, libunwind.so.1, объектные файлы
crtbegin/crtend), нужно переименовать/пересобрать с
.so-суффиксом и поправить SONAME/DT_NEEDED через patchelf.
- Путь до собственного каталога библиотек приложения на устройстве
заранее не известен (зависит от установки) — он находится изнутри
самой Сферы, без единой строчки на C, через чтение
/proc/self/maps и поиск подстроки /lib/arm64/libmain.so.
✅ Подтверждено самим adb logcat, многократно: полный цикл
компиляция → линковка → запуск результата, целиком на устройстве,
с настоящим выводом собранной программы. Эта возможность встроена в
основную панель-приложение (панель_android.код, вкладка «Запуск»,
функция выполнить_код_сферы) — компиляция и запуск в ней проверены
по отдельности, но именно эта, собранная вместе с интерфейсом панели
сборка ⚠️ ещё не проверена вживую на устройстве.