Cross-compile Perl 5.38.2 for Android with perlandroid
This guide takes you from a Perl source tree to a configured Android cross-build, using the workflow documented by the perlandroid(1) manual installed with Perl 5.38.2. It covers the older GCC 4.8 style NDK toolchain, an adb target and an SSH target. Allow an hour or more for downloading the NDK, preparing a device and running the test suite. The examples are a build recipe, not a promise that an arbitrary modern Android release still provides the same toolchain layout.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
Work on a Unix-like host with a Perl source tree, a C compiler toolchain supplied by the Android NDK, and either an Android device or an emulator. The local manual is dated 2026-09-14 and identifies the installed documentation as Perl v5.38.2. Its examples refer to Android 2.0 and later, an NDK toolchain named 4.8, and the legacy make-standalone-toolchain.sh helper. Check the NDK you intend to use before relying on those paths.
Choose the target architecture before copying commands. The manual lists arm-linux-androideabi for ARM, mipsel-linux-android for MIPS and x86 for x86. In the examples below, TARGETARCH is a placeholder, not a value to paste literally.
1. Check the host and set the NDK variables
Unpack the NDK and point ANDROID_NDK at its directory. The manual's host paths use a lower-case kernel name followed by -x86_64. On a 32-bit host, replace x86_64 with x86. This example checks the values without changing any device or system files.
export ANDROID_NDK=/path/to/android-ndk
export TARGETARCH=arm-linux-androideabi
test -d "$ANDROID_NDK" && printf 'NDK: %s\n' "$ANDROID_NDK"
printf 'host: %s\n' "$(uname | tr '[:upper:]' '[:lower:]')-x86_64"
Expected output includes the directory you selected and a host name such as linux-x86_64. If the directory check fails, stop here and correct the path.
2. Put the cross-compiler on PATH
The documented toolchain layout puts the compiler in a directory below toolchains. Add that directory to the current shell only, then check for the compiler. This is an ordinary user command.
export PATH="$ANDROID_NDK/toolchains/$TARGETARCH-4.8/prebuilt/$(uname | tr '[:upper:]' '[:lower:]')-x86_64/bin:$PATH"
command -v "$TARGETARCH-gcc"
"$TARGETARCH-gcc" --version
A successful check prints a path and the compiler version. If the compiler is missing, do not guess a toolchain directory: the manual explicitly says its 4.8 example must be changed when your NDK uses another version.
3. Create the standalone sysroot
Make the temporary toolchain under /tmp, then run the helper supplied by the documented NDK layout. The command creates files below that directory and can be removed later, so keep the path specific.
export ANDROID_TOOLCHAIN=/tmp/my-toolchain-$TARGETARCH
export SYSROOT="$ANDROID_TOOLCHAIN/sysroot"
"$ANDROID_NDK/build/tools/make-standalone-toolchain.sh" \
--platform=android-9 \
--install-dir="$ANDROID_TOOLCHAIN" \
--system="$(uname | tr '[:upper:]' '[:lower:]')-x86_64" \
--toolchain="$TARGETARCH-4.8"
test -d "$SYSROOT" && printf 'sysroot ready: %s\n' "$SYSROOT"
There is no useful undo for a partially completed helper run beyond removing this generated directory and trying again with corrected inputs:
rm -rf -- "$ANDROID_TOOLCHAIN"
That command is destructive. Run it only after checking that ANDROID_TOOLCHAIN points at the temporary directory you intended.
4. Choose and test the target transport
adb is the practical choice for an emulator or a USB-connected device. First list devices and record the exact identifier used in DEVICE.
$ adb devices
List of devices attached
DEVICE_SERIAL device
Android does not provide the host's usual /tmp, and executables cannot run from the SD card. A rooted device can use the root-only temporary filesystem path:
export DEVICE=DEVICE_SERIAL
export TARGETDIR=/mnt/asec/perl
adb -s "$DEVICE" shell "echo sh -c 'mkdir $TARGETDIR' | su --"
For an unrooted device, try the shell-writable location instead:
export TARGETDIR=/data/local/tmp/perl
adb -s "$DEVICE" shell "mkdir $TARGETDIR"
adb -s "$DEVICE" shell "ls -ld $TARGETDIR"
Checkpoint: if neither directory can be created, stop using adb for this target and use SSH. The /data/local/tmp directory may survive a reboot, so remove it when the build is finished:
adb -s "$DEVICE" shell "rm -rf -- $TARGETDIR"
5. Configure the source tree
From the top of the Perl source tree, configure the cross-build. The -des and -Dusedevel arguments come from the manual's basic command. Do not add -Dusedevel casually to a different Perl release; this recipe follows the installed document.
./Configure -des -Dusedevel -Dusecrosscompile -Dtargetrun=adb \
-Dcc="$TARGETARCH-gcc" \
-Dsysroot="$SYSROOT" \
-Dtargetdir="$TARGETDIR" \
-Dtargethost="$DEVICE"
For SSH, use a passwordless public-key connection and replace the transport settings with real values:
export TARGETHOST=android.example.invalid
export TARGETUSER=android
export TARGETPORT=8022
./Configure -des -Dusedevel -Dusecrosscompile -Dtargetrun=ssh \
-Dcc="$TARGETARCH-gcc" \
-Dsysroot="$SYSROOT" \
-Dtargetdir="$TARGETDIR" \
-Dtargethost="$TARGETHOST" \
-Dtargetuser="$TARGETUSER" \
-Dtargetport="$TARGETPORT"
SSH setup is security-sensitive: use a key restricted to this device and verify the host key before allowing an unattended build. Unexpected text on SSH standard error can confuse Configure, according to the manual.
6. Build and test
Once Configure completes, build Perl and run the tests.
make
make test
With adb, make test may appear idle because it can wait until the complete run finishes before printing anything. Inspect output.stdout inside TARGETDIR from a device shell if progress matters. Treat crashes on old low-end devices as a real device-safety warning, not as a test failure to ignore.
Done means
- The selected compiler and generated sysroot pass their checks.
Configurecompletes with the intendedadbor SSH target.makecompletes andmake testreturns successfully.- The temporary
/data/local/tmp/perldirectory is removed if you used it.