1*e0680481Safresh1# vim: syntax=pod 2*e0680481Safresh1 36fb12b70Safresh1If you read this file _as_is_, just ignore the funny characters you 46fb12b70Safresh1see. It is written in the POD format (see pod/perlpod.pod) which is 56fb12b70Safresh1specially designed to be readable as is. 66fb12b70Safresh1 76fb12b70Safresh1=head1 NAME 86fb12b70Safresh1 96fb12b70Safresh1perlandroid - Perl under Android 106fb12b70Safresh1 116fb12b70Safresh1=head1 SYNOPSIS 126fb12b70Safresh1 1356d68f1eSafresh1The first portions of this document contains instructions 146fb12b70Safresh1to cross-compile Perl for Android 2.0 and later, using the 1556d68f1eSafresh1binaries provided by Google. The latter portions describe how to build 166fb12b70Safresh1perl native using one of the toolchains available on the Play Store. 176fb12b70Safresh1 186fb12b70Safresh1=head1 DESCRIPTION 196fb12b70Safresh1 206fb12b70Safresh1This document describes how to set up your host environment when 216fb12b70Safresh1attempting to build Perl for Android. 226fb12b70Safresh1 236fb12b70Safresh1=head1 Cross-compilation 246fb12b70Safresh1 256fb12b70Safresh1These instructions assume an Unixish build environment on your host system; 266fb12b70Safresh1they've been tested on Linux and OS X, and may work on Cygwin and MSYS. 276fb12b70Safresh1While Google also provides an NDK for Windows, these steps won't work 286fb12b70Safresh1native there, although it may be possible to cross-compile through different 296fb12b70Safresh1means. 306fb12b70Safresh1 316fb12b70Safresh1If your host system's architecture is 32 bits, remember to change the 326fb12b70Safresh1C<x86_64>'s below to C<x86>'s. On a similar vein, the examples below 336fb12b70Safresh1use the 4.8 toolchain; if you want to use something older or newer (for 346fb12b70Safresh1example, the 4.4.3 toolchain included in the 8th revision of the NDK), just 356fb12b70Safresh1change those to the relevant version. 366fb12b70Safresh1 376fb12b70Safresh1=head2 Get the Android Native Development Kit (NDK) 386fb12b70Safresh1 396fb12b70Safresh1You can download the NDK from L<https://developer.android.com/tools/sdk/ndk/index.html>. 406fb12b70Safresh1You'll want the normal, non-legacy version. 416fb12b70Safresh1 426fb12b70Safresh1=head2 Determine the architecture you'll be cross-compiling for 436fb12b70Safresh1 446fb12b70Safresh1There's three possible options: arm-linux-androideabi for ARM, 456fb12b70Safresh1mipsel-linux-android for MIPS, and simply x86 for x86. 466fb12b70Safresh1As of 2014, most Android devices run on ARM, so that is generally a safe bet. 476fb12b70Safresh1 486fb12b70Safresh1With those two in hand, you should add 496fb12b70Safresh1 506fb12b70Safresh1 $ANDROID_NDK/toolchains/$TARGETARCH-4.8/prebuilt/`uname | tr '[A-Z]' '[a-z]'`-x86_64/bin 516fb12b70Safresh1 52b8851fccSafresh1to your C<PATH>, where C<$ANDROID_NDK> is the location where you unpacked the 53b8851fccSafresh1NDK, and C<$TARGETARCH> is your target's architecture. 546fb12b70Safresh1 556fb12b70Safresh1=head2 Set up a standalone toolchain 566fb12b70Safresh1 576fb12b70Safresh1This creates a working sysroot that we can feed to Configure later. 586fb12b70Safresh1 596fb12b70Safresh1 $ export ANDROID_TOOLCHAIN=/tmp/my-toolchain-$TARGETARCH 606fb12b70Safresh1 $ export SYSROOT=$ANDROID_TOOLCHAIN/sysroot 616fb12b70Safresh1 $ $ANDROID_NDK/build/tools/make-standalone-toolchain.sh \ 626fb12b70Safresh1 --platform=android-9 \ 636fb12b70Safresh1 --install-dir=$ANDROID_TOOLCHAIN \ 646fb12b70Safresh1 --system=`uname | tr '[A-Z]' '[a-z]'`-x86_64 \ 656fb12b70Safresh1 --toolchain=$TARGETARCH-4.8 666fb12b70Safresh1 676fb12b70Safresh1=head2 adb or ssh? 686fb12b70Safresh1 696fb12b70Safresh1adb is the Android Debug Bridge. For our purposes, it's basically a way 706fb12b70Safresh1of establishing an ssh connection to an Android device without having to 716fb12b70Safresh1install anything on the device itself, as long as the device is either on 726fb12b70Safresh1the same local network as the host, or it is connected to the host through 736fb12b70Safresh1USB. 74b8851fccSafresh1 756fb12b70Safresh1Perl can be cross-compiled using either adb or a normal ssh connection; 766fb12b70Safresh1in general, if you can connect your device to the host using a USB port, 776fb12b70Safresh1or if you don't feel like installing an sshd app on your device, 786fb12b70Safresh1you may want to use adb, although you may be forced to switch to ssh if 796fb12b70Safresh1your device is not rooted and you're unlucky -- more on that later. 806fb12b70Safresh1Alternatively, if you're cross-compiling to an emulator, you'll have to 816fb12b70Safresh1use adb. 826fb12b70Safresh1 836fb12b70Safresh1=head3 adb 846fb12b70Safresh1 856fb12b70Safresh1To use adb, download the Android SDK from L<https://developer.android.com/sdk/index.html>. 866fb12b70Safresh1The "SDK Tools Only" version should suffice -- if you downloaded the ADT 87b8851fccSafresh1Bundle, you can find the sdk under F<$ADT_BUNDLE/sdk/>. 886fb12b70Safresh1 89b8851fccSafresh1Add F<$ANDROID_SDK/platform-tools> to your C<PATH>, which should give you access 90b8851fccSafresh1to adb. You'll now have to find your device's name using C<adb devices>, 91b8851fccSafresh1and later pass that to Configure through C<-Dtargethost=$DEVICE>. 926fb12b70Safresh1 936fb12b70Safresh1However, before calling Configure, you need to check if using adb is a 94b8851fccSafresh1viable choice in the first place. Because Android doesn't have a F</tmp>, 956fb12b70Safresh1nor does it allow executables in the sdcard, we need to find somewhere in 966fb12b70Safresh1the device for Configure to put some files in, as well as for the tests 976fb12b70Safresh1to run in. If your device is rooted, then you're good. Try running these: 986fb12b70Safresh1 996fb12b70Safresh1 $ export TARGETDIR=/mnt/asec/perl 1006fb12b70Safresh1 $ adb -s $DEVICE shell "echo sh -c '\"mkdir $TARGETDIR\"' | su --" 1016fb12b70Safresh1 1026fb12b70Safresh1Which will create the directory we need, and you can move on to the next 103b8851fccSafresh1step. F</mnt/asec> is mounted as a tmpfs in Android, but it's only 1046fb12b70Safresh1accessible to root. 1056fb12b70Safresh1 1066fb12b70Safresh1If your device is not rooted, you may still be in luck. Try running this: 1076fb12b70Safresh1 1086fb12b70Safresh1 $ export TARGETDIR=/data/local/tmp/perl 1096fb12b70Safresh1 $ adb -s $DEVICE shell "mkdir $TARGETDIR" 1106fb12b70Safresh1 1116fb12b70Safresh1If the command works, you can move to the next step, but beware: 1126fb12b70Safresh1B<You'll have to remove the directory from the device once you are done! 113b8851fccSafresh1Unlike F</mnt/asec>, F</data/local/tmp> may not get automatically garbage 1146fb12b70Safresh1collected once you shut off the phone>. 1156fb12b70Safresh1 1166fb12b70Safresh1If neither of those work, then you can't use adb to cross-compile to your 1176fb12b70Safresh1device. Either try rooting it, or go for the ssh route. 1186fb12b70Safresh1 1196fb12b70Safresh1=head3 ssh 1206fb12b70Safresh1 1216fb12b70Safresh1To use ssh, you'll need to install and run a sshd app and set it up 1226fb12b70Safresh1properly. There are several paid and free apps that do this rather 1236fb12b70Safresh1easily, so you should be able to spot one on the store. 1246fb12b70Safresh1Remember that Perl requires a passwordless connection, so set up a 1256fb12b70Safresh1public key. 1266fb12b70Safresh1 1276fb12b70Safresh1Note that several apps spew crap to stderr every time you 1286fb12b70Safresh1connect, which can throw off Configure. You may need to monkeypatch 129b8851fccSafresh1the part of Configure that creates C<run-ssh> to have it discard stderr. 1306fb12b70Safresh1 1316fb12b70Safresh1Since you're using ssh, you'll have to pass some extra arguments to 132b8851fccSafresh1Configure: 133b8851fccSafresh1 134b8851fccSafresh1 -Dtargetrun=ssh -Dtargethost=$TARGETHOST -Dtargetuser=$TARGETUSER -Dtargetport=$TARGETPORT 1356fb12b70Safresh1 1366fb12b70Safresh1=head2 Configure and beyond 1376fb12b70Safresh1 1386fb12b70Safresh1With all of the previous done, you're now ready to call Configure. 1396fb12b70Safresh1 1406fb12b70Safresh1If using adb, a "basic" Configure line will look like this: 1416fb12b70Safresh1 1426fb12b70Safresh1 $ ./Configure -des -Dusedevel -Dusecrosscompile -Dtargetrun=adb \ 1436fb12b70Safresh1 -Dcc=$TARGETARCH-gcc \ 1446fb12b70Safresh1 -Dsysroot=$SYSROOT \ 1456fb12b70Safresh1 -Dtargetdir=$TARGETDIR \ 1466fb12b70Safresh1 -Dtargethost=$DEVICE 1476fb12b70Safresh1 1486fb12b70Safresh1If using ssh, it's not too different -- we just change targetrun to ssh, 1496fb12b70Safresh1and pass in targetuser and targetport. It ends up looking like this: 1506fb12b70Safresh1 1516fb12b70Safresh1 $ ./Configure -des -Dusedevel -Dusecrosscompile -Dtargetrun=ssh \ 1526fb12b70Safresh1 -Dcc=$TARGETARCH-gcc \ 1536fb12b70Safresh1 -Dsysroot=$SYSROOT \ 1546fb12b70Safresh1 -Dtargetdir=$TARGETDIR \ 1556fb12b70Safresh1 -Dtargethost="$TARGETHOST" \ 1566fb12b70Safresh1 -Dtargetuser=$TARGETUSER \ 1576fb12b70Safresh1 -Dtargetport=$TARGETPORT 1586fb12b70Safresh1 159b8851fccSafresh1Now you're ready to run C<make> and C<make test>! 1606fb12b70Safresh1 161b8851fccSafresh1As a final word of warning, if you're using adb, C<make test> may appear to 1626fb12b70Safresh1hang; this is because it doesn't output anything until it finishes 1636fb12b70Safresh1running all tests. You can check its progress by logging into the 164b8851fccSafresh1device, moving to F<$TARGETDIR>, and looking at the file F<output.stdout>. 1656fb12b70Safresh1 1666fb12b70Safresh1=head3 Notes 1676fb12b70Safresh1 1686fb12b70Safresh1=over 1696fb12b70Safresh1 1706fb12b70Safresh1=item * 1716fb12b70Safresh1 172b8851fccSafresh1If you are targetting x86 Android, you will have to change C<$TARGETARCH-gcc> 173b8851fccSafresh1to C<i686-linux-android-gcc>. 1746fb12b70Safresh1 1756fb12b70Safresh1=item * 1766fb12b70Safresh1 1776fb12b70Safresh1On some older low-end devices -- think early 2.2 era -- some tests, 178b8851fccSafresh1particularly F<t/re/uniprops.t>, may crash the phone, causing it to turn 1796fb12b70Safresh1itself off once, and then back on again. 1806fb12b70Safresh1 1816fb12b70Safresh1=back 1826fb12b70Safresh1 1836fb12b70Safresh1=head1 Native Builds 1846fb12b70Safresh1 1856fb12b70Safresh1While Google doesn't provide a native toolchain for Android, 18656d68f1eSafresh1you can still get one from the Play Store. 18756d68f1eSafresh1 18856d68f1eSafresh1=head2 CCTools 18956d68f1eSafresh1 19056d68f1eSafresh1You may be able to get the CCTools app, which is free. 19156d68f1eSafresh1Keep in mind that you want a full toolchain; 19256d68f1eSafresh1some apps tend to default to installing only a barebones 1936fb12b70Safresh1version without some important utilities, like ar or nm. 1946fb12b70Safresh1 1956fb12b70Safresh1Once you have the toolchain set up properly, the only 1966fb12b70Safresh1remaining hurdle is actually locating where in the device it was installed 1976fb12b70Safresh1in. For example, CCTools installs its toolchain in 198b8851fccSafresh1F</data/data/com.pdaxrom.cctools/root/cctools>. With the path in hand, 1996fb12b70Safresh1compiling perl is little more than: 2006fb12b70Safresh1 2016fb12b70Safresh1 export SYSROOT=<location of the native toolchain> 2026fb12b70Safresh1 export LD_LIBRARY_PATH="$SYSROOT/lib:`pwd`:`pwd`/lib:`pwd`/lib/auto:$LD_LIBRARY_PATH" 2036fb12b70Safresh1 sh Configure -des -Dsysroot=$SYSROOT -Alibpth="/system/lib /vendor/lib" 2046fb12b70Safresh1 20556d68f1eSafresh1=head2 Termux 20656d68f1eSafresh1 20756d68f1eSafresh1L<Termux|https://termux.com/> provides an Android terminal emulator and Linux environment. 20856d68f1eSafresh1It comes with a cross-compiled perl already installed. 20956d68f1eSafresh1 21056d68f1eSafresh1Natively compiling perl 5.30 or later should be as straightforward as: 21156d68f1eSafresh1 21256d68f1eSafresh1 sh Configure -des -Alibpth="/system/lib /vendor/lib" 21356d68f1eSafresh1 21456d68f1eSafresh1This certainly works on Android 8.1 (Oreo) at least... 21556d68f1eSafresh1 2166fb12b70Safresh1=head1 AUTHOR 2176fb12b70Safresh1 2186fb12b70Safresh1Brian Fraser <fraserbn@gmail.com> 2196fb12b70Safresh1 2206fb12b70Safresh1=cut 221