A Deep Dive: Statically Compiling LLVM 13 on Android with Termux

posted Originally published at dev.to 2 min read

Disclaimer: This is a technical write-up intended for experienced users. All actions were performed on a non-rooted Android device using Termux + Proot Ubuntu.

1. Environment: Preparing the Battlefield

Device: Motorola Edge 2024(ARM64)

Packages:

pkg install proot-distro git cmake ninja clang python
proot-distro install ubuntu
proot-distro login ubuntu

Inside Ubuntu:

apt update && apt install build-essential git cmake ninja-build python3 g++ gcc libc6-dev

Understanding the Filesystem (SYSROOT)

Ubuntu inside proot lives at:
/data/data/com.termux/files/usr/var/lib/proot-distro/installed-rootfs/ubuntu


2. Cloning and Configuring LLVM

git clone https://github.com/llvm/llvm-project.git
cd llvm-project
git checkout llvmorg-13.0.0
mkdir build && cd build

cmake ../llvm \
  -G Ninja \
  -DCMAKE_BUILD_TYPE=Release \
  -DLLVM_ENABLE_PROJECTS='clang;lld' \
  -DLLVM_TARGETS_TO_BUILD='AArch64' \
  -DCMAKE_INSTALL_PREFIX=$HOME/.local/llvm13 \
  -DLLVM_ENABLE_TERMINFO=OFF

_Note: LLVM_ENABLE_TERMINFO=OFF avoids ncurses dependencies._

Compiling

ninja

Expect non-fatal warnings.


3. Build Failure: sancov

sancov fails due to an explicit constructor error at 95%:

error: chosen constructor is explicit in copy-initialization

Still, Clang and LLD are usable. Proceed with:

ninja install

Ignore failure related to missing sancov binary.


4. Static Linking Problem

clang++ -static test.cpp fails with:

ld: error: cannot open crt1.o
ld: error: unable to find library -lstdc++

This is expected.


5. Solution: Manual Linking

#include <iostream>
int main() {
  std::cout << "Hello from static LLVM binary!" << std::endl;
  return 0;
}

Compile to object:

clang++ -c test.cpp -o test.o

Manual static link:

export SYSROOT=/data/data/com.termux/files/usr/var/lib/proot-distro/installed-rootfs/ubuntu

clang++ test.o -o test_static \
  --sysroot=$SYSROOT -static \
  -L$SYSROOT/lib/aarch64-linux-gnu \
  -L$SYSROOT/lib/gcc/aarch64-linux-gnu/13 \
  $SYSROOT/lib/aarch64-linux-gnu/crt1.o \
  $SYSROOT/lib/aarch64-linux-gnu/crti.o \
  $SYSROOT/lib/gcc/aarch64-linux-gnu/13/crtbeginT.o \
  -lc -lm -lstdc++ \
  $SYSROOT/lib/gcc/aarch64-linux-gnu/13/libgcc.a \
  $SYSROOT/lib/gcc/aarch64-linux-gnu/13/crtend.o \
  $SYSROOT/lib/aarch64-linux-gnu/crtn.o

Link order matters. Avoid duplicate CRT symbols.


6. Validation

file ./test_static
# Output: statically linked ELF aarch64 binary

qemu-aarch64 -L $SYSROOT ./test_static
# Output:
Hello from static LLVM binary!

Why This Is Useful

  • You get full native clang++ on Android
  • Works completely offline, non-rooted, and portable
  • Enables compiling, testing, and bootstrapping real toolchains inside Termux
  • Crucial for research, malware analysis, exploit development, or Red Team tool building on mobile

Disclaimer:
This article is intended for educational and research purposes only. All techniques and methods described should only be used in environments where you have explicit, legal authorization.

Unauthorized access, testing, or exploitation of devices or systems is illegal and unethical.

By proceeding, you agree to comply with all applicable laws and regulations, and to use the information solely for lawful, responsible security research and defensive purposes.

If you read this far, tweet to the author to show them you care. Tweet a Thanks
0 votes
0 votes

More Posts

ContainerCraft: A Deep Dive into Node.js Containerization

TheToriqul - Jan 30

Deploy your application on Vercel with GitHub Actions

OctoLab - Aug 20

Assignment makes integer from pointer without a cast in c

James Dayal - Aug 21, 2023

Setting Up a WireGuard VPN Client on Linux

rothej - Oct 15

️ Help Shape Our Next FSM_API Deep Dive! Take our Developer Poll on strawpoll

The Singularity Workshop - Oct 15
chevron_left