| 1 | If you read this file _as_is_, just ignore the funny characters you |
| 2 | see. It is written in the POD format (see pod/perlpod.pod) which is |
| 3 | specially designed to be readable as is. |
| 4 | |
| 5 | =head1 NAME |
| 6 | |
| 7 | perlandroid - Perl under Android |
| 8 | |
| 9 | =head1 SYNOPSIS |
| 10 | |
| 11 | The first portions of this documents contains instructions |
| 12 | to cross-compile Perl for Android 2.0 and later, using the |
| 13 | binaries provided by Google. The latter portion describes how to build |
| 14 | perl native using one of the toolchains available on the Play Store. |
| 15 | |
| 16 | =head1 DESCRIPTION |
| 17 | |
| 18 | This document describes how to set up your host environment when |
| 19 | attempting to build Perl for Android. |
| 20 | |
| 21 | =head1 Cross-compilation |
| 22 | |
| 23 | These instructions assume an Unixish build environment on your host system; |
| 24 | they've been tested on Linux and OS X, and may work on Cygwin and MSYS. |
| 25 | While Google also provides an NDK for Windows, these steps won't work |
| 26 | native there, although it may be possible to cross-compile through different |
| 27 | means. |
| 28 | |
| 29 | If your host system's architecture is 32 bits, remember to change the |
| 30 | C<x86_64>'s below to C<x86>'s. On a similar vein, the examples below |
| 31 | use the 4.8 toolchain; if you want to use something older or newer (for |
| 32 | example, the 4.4.3 toolchain included in the 8th revision of the NDK), just |
| 33 | change those to the relevant version. |
| 34 | |
| 35 | =head2 Get the Android Native Development Kit (NDK) |
| 36 | |
| 37 | You can download the NDK from L<https://developer.android.com/tools/sdk/ndk/index.html>. |
| 38 | You'll want the normal, non-legacy version. |
| 39 | |
| 40 | =head2 Determine the architecture you'll be cross-compiling for |
| 41 | |
| 42 | There's three possible options: arm-linux-androideabi for ARM, |
| 43 | mipsel-linux-android for MIPS, and simply x86 for x86. |
| 44 | As of 2014, most Android devices run on ARM, so that is generally a safe bet. |
| 45 | |
| 46 | With those two in hand, you should add |
| 47 | |
| 48 | $ANDROID_NDK/toolchains/$TARGETARCH-4.8/prebuilt/`uname | tr '[A-Z]' '[a-z]'`-x86_64/bin |
| 49 | |
| 50 | to your PATH, where $ANDROID_NDK is the location where you unpacked the |
| 51 | NDK, and $TARGETARCH is your target's architecture. |
| 52 | |
| 53 | =head2 Set up a standalone toolchain |
| 54 | |
| 55 | This creates a working sysroot that we can feed to Configure later. |
| 56 | |
| 57 | $ export ANDROID_TOOLCHAIN=/tmp/my-toolchain-$TARGETARCH |
| 58 | $ export SYSROOT=$ANDROID_TOOLCHAIN/sysroot |
| 59 | $ $ANDROID_NDK/build/tools/make-standalone-toolchain.sh \ |
| 60 | --platform=android-9 \ |
| 61 | --install-dir=$ANDROID_TOOLCHAIN \ |
| 62 | --system=`uname | tr '[A-Z]' '[a-z]'`-x86_64 \ |
| 63 | --toolchain=$TARGETARCH-4.8 |
| 64 | |
| 65 | =head2 adb or ssh? |
| 66 | |
| 67 | adb is the Android Debug Bridge. For our purposes, it's basically a way |
| 68 | of establishing an ssh connection to an Android device without having to |
| 69 | install anything on the device itself, as long as the device is either on |
| 70 | the same local network as the host, or it is connected to the host through |
| 71 | USB. |
| 72 | Perl can be cross-compiled using either adb or a normal ssh connection; |
| 73 | in general, if you can connect your device to the host using a USB port, |
| 74 | or if you don't feel like installing an sshd app on your device, |
| 75 | you may want to use adb, although you may be forced to switch to ssh if |
| 76 | your device is not rooted and you're unlucky -- more on that later. |
| 77 | Alternatively, if you're cross-compiling to an emulator, you'll have to |
| 78 | use adb. |
| 79 | |
| 80 | =head3 adb |
| 81 | |
| 82 | To use adb, download the Android SDK from L<https://developer.android.com/sdk/index.html>. |
| 83 | The "SDK Tools Only" version should suffice -- if you downloaded the ADT |
| 84 | Bundle, you can find the sdk under $ADT_BUNDLE/sdk/. |
| 85 | |
| 86 | Add $ANDROID_SDK/platform-tools to your PATH, which should give you access |
| 87 | to adb. You'll now have to find your device's name using 'adb devices', |
| 88 | and later pass that to Configure through '-Dtargethost=$DEVICE'. |
| 89 | |
| 90 | However, before calling Configure, you need to check if using adb is a |
| 91 | viable choice in the first place. Because Android doesn't have a /tmp, |
| 92 | nor does it allow executables in the sdcard, we need to find somewhere in |
| 93 | the device for Configure to put some files in, as well as for the tests |
| 94 | to run in. If your device is rooted, then you're good. Try running these: |
| 95 | |
| 96 | $ export TARGETDIR=/mnt/asec/perl |
| 97 | $ adb -s $DEVICE shell "echo sh -c '\"mkdir $TARGETDIR\"' | su --" |
| 98 | |
| 99 | Which will create the directory we need, and you can move on to the next |
| 100 | step. /mnt/asec is mounted as a tmpfs in Android, but it's only |
| 101 | accessible to root. |
| 102 | |
| 103 | If your device is not rooted, you may still be in luck. Try running this: |
| 104 | |
| 105 | $ export TARGETDIR=/data/local/tmp/perl |
| 106 | $ adb -s $DEVICE shell "mkdir $TARGETDIR" |
| 107 | |
| 108 | If the command works, you can move to the next step, but beware: |
| 109 | B<You'll have to remove the directory from the device once you are done! |
| 110 | Unlike /mnt/asec, /data/local/tmp may not get automatically garbage |
| 111 | collected once you shut off the phone>. |
| 112 | |
| 113 | If neither of those work, then you can't use adb to cross-compile to your |
| 114 | device. Either try rooting it, or go for the ssh route. |
| 115 | |
| 116 | =head3 ssh |
| 117 | |
| 118 | To use ssh, you'll need to install and run a sshd app and set it up |
| 119 | properly. There are several paid and free apps that do this rather |
| 120 | easily, so you should be able to spot one on the store. |
| 121 | Remember that Perl requires a passwordless connection, so set up a |
| 122 | public key. |
| 123 | |
| 124 | Note that several apps spew crap to stderr every time you |
| 125 | connect, which can throw off Configure. You may need to monkeypatch |
| 126 | the part of Configure that creates 'run-ssh' to have it discard stderr. |
| 127 | |
| 128 | Since you're using ssh, you'll have to pass some extra arguments to |
| 129 | Configure: -Dtargetrun=ssh -Dtargethost=$TARGETHOST -Dtargetuser=$TARGETUSER -Dtargetport=$TARGETPORT |
| 130 | |
| 131 | =head2 Configure and beyond |
| 132 | |
| 133 | With all of the previous done, you're now ready to call Configure. |
| 134 | |
| 135 | If using adb, a "basic" Configure line will look like this: |
| 136 | |
| 137 | $ ./Configure -des -Dusedevel -Dusecrosscompile -Dtargetrun=adb \ |
| 138 | -Dcc=$TARGETARCH-gcc \ |
| 139 | -Dsysroot=$SYSROOT \ |
| 140 | -Dtargetdir=$TARGETDIR \ |
| 141 | -Dtargethost=$DEVICE |
| 142 | |
| 143 | If using ssh, it's not too different -- we just change targetrun to ssh, |
| 144 | and pass in targetuser and targetport. It ends up looking like this: |
| 145 | |
| 146 | $ ./Configure -des -Dusedevel -Dusecrosscompile -Dtargetrun=ssh \ |
| 147 | -Dcc=$TARGETARCH-gcc \ |
| 148 | -Dsysroot=$SYSROOT \ |
| 149 | -Dtargetdir=$TARGETDIR \ |
| 150 | -Dtargethost="$TARGETHOST" \ |
| 151 | -Dtargetuser=$TARGETUSER \ |
| 152 | -Dtargetport=$TARGETPORT |
| 153 | |
| 154 | Now you're ready to run make and make test! |
| 155 | |
| 156 | As a final word of warning, if you're using adb, make test may appear to |
| 157 | hang; this is because it doesn't output anything until it finishes |
| 158 | running all tests. You can check its progress by logging into the |
| 159 | device, moving to $TARGETDIR, and looking at the file output.stdout. |
| 160 | |
| 161 | =head3 Notes |
| 162 | |
| 163 | =over |
| 164 | |
| 165 | =item * |
| 166 | |
| 167 | If you are targetting x86 Android, you will have to change $TARGETARCH-gcc |
| 168 | to i686-linux-android-gcc. |
| 169 | |
| 170 | =item * |
| 171 | |
| 172 | On some older low-end devices -- think early 2.2 era -- some tests, |
| 173 | particularly t/re/uniprops, may crash the phone, causing it to turn |
| 174 | itself off once, and then back on again. |
| 175 | |
| 176 | =back |
| 177 | |
| 178 | =head1 Native Builds |
| 179 | |
| 180 | While Google doesn't provide a native toolchain for Android, |
| 181 | you can still get one from the Play Store; for example, there's the CCTools |
| 182 | app which you can get for free. |
| 183 | Keep in mind that you want a full |
| 184 | toolchain; some apps tend to default to installing only a barebones |
| 185 | version without some important utilities, like ar or nm. |
| 186 | |
| 187 | Once you have the toolchain set up properly, the only |
| 188 | remaining hurdle is actually locating where in the device it was installed |
| 189 | in. For example, CCTools installs its toolchain in |
| 190 | /data/data/com.pdaxrom.cctools/root/cctools. With the path in hand, |
| 191 | compiling perl is little more than: |
| 192 | |
| 193 | export SYSROOT=<location of the native toolchain> |
| 194 | export LD_LIBRARY_PATH="$SYSROOT/lib:`pwd`:`pwd`/lib:`pwd`/lib/auto:$LD_LIBRARY_PATH" |
| 195 | sh Configure -des -Dsysroot=$SYSROOT -Alibpth="/system/lib /vendor/lib" |
| 196 | |
| 197 | =head1 AUTHOR |
| 198 | |
| 199 | Brian Fraser <fraserbn@gmail.com> |
| 200 | |
| 201 | =cut |