summaryrefslogtreecommitdiff
path: root/src/SW/perl-on-android/document.en.rest.txt
blob: 33c63d45173a8f2c7610f997db7a1b759d1f00f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
=========================
Compiling Perl on Android
=========================
:CreationDate: 2012-09-01 09:19:00
:Id: SW/perl-on-android
:tags: - software
       - perl
 
.. admonition:: use Termux
 
   In the years since this page was written, a much better alternative
   has emerged: `Termux <https://termux.com/>`_. It gives you a Debian
   chroot, with Perl, Rakudo, Python, Ruby, EMACS…
 
At `YAPC::EU 2012`_, I only had my Asus TF101, and I wanted to play
with some of the modules that the speakers were talking about.
 
The Google-provided "Perl for Android" (part of the `Android Scripting
Environment`_) is nearly useless, since you don't get the whole Perl
core, the CPAN shell does not work, and you don't have a compiler for
XS modules.
 
Another option would be to cross-compile from a normal computer, but
apart from the fact that I did not another computer with me, you still
would not be able to install XS modules directly from the
cross-compiled Perl.
 
So I did what any self-respecting programmer would do: tried to build
my own. I haven't yet managed to completely build the Perl
distribution, but I have come some way, and I thought that it would be
nice to write things down.
 
Prerequisites
=============
 
First of all, you need root access on your device: we have to create
filesystems, change owners and permissions, mount images.
 
Then, you need quite some RAM, storage, and processor. I wouldn't try
it on a phone or a low-powered tablet.
 
Finally, you need ``busybox``: the bare-bones command line tools
shipped with most Android images are so limited that not even the very
conservative Perl ``Configure`` can use them. You'll want to execute
this (or something similar) to get ``busybox`` binaries in preference
to the built-in ones::
 
 export PATH=/system/xbin:$PATH
 
Preparations
============
 
We need a native compiler. I found a well-built ``gcc`` on a wiki
about ``R``:
http://rwiki.sciviews.org/doku.php?id=getting-started:installation:android
 
Get the two ``gcc`` tarballs.
 
We're going to build a filesystem image, mount it via the loopback
device, and install everything there: this way, the image can be moved
between devices (we'll make sure everything is as relocatable as
possible). I stored everything under ``/data/media/native`` (I created
that directory). ``/data/media`` is, on my device, the actual store
that is exposed (via a sort of bind-mount) as ``/sdcard``, with the
difference that the latter has ``noexec``, the former doesn't.
 
We want a rather large image, let's say 3 GB. I tried to make a sparse
file with ``dd if=/dev/zero of=native.e2.diskimg bs=1024 seek=3000000
count=1`` but it failed. I ended up creating two smaller files and
concatenating them. Then::
 
 # cd /data/media/native
 
 # mke2fs -f native.e2.diskimg
 
 # cat >  /data/media/native/start <<EOF
 #!/xbin/ash
 export PATH=/system/xbin:$PATH
 BASE="$(dirname "$(readlink -f "$0")")"
 DEST=/Removable
 if [[ -d $DEST/fs/bin ]]; then
    true
 else
    mkdir -p $DEST/fs
    mount -o loop -t ext2 $BASE/native.e2.diskimg $DEST/fs
 fi
 echo PATH=\"$DEST/fs/bin:/system/xbin:$PATH\"
 echo LD_LIBRARY_PATH=\"$DEST/fs/lib\"
 EOF
 
 # cat >  /data/media/native/stop <<EOF
 #!/xbin/ash
 export PATH=/system/xbin:$PATH
 BASE="$(dirname "$(readlink -f "$0")")"
 DEST=/Removable
 if [[ -d $DEST/fs/bin ]]; then
    umount $DEST/fs
 else
    true
 fi
 EOF
 
 # chmod +x start stop
 
Let's mount the (still empty) image (as a normal user, not ``root``)::
 
 $ eval $(su -c /data/media/native/start)
 
and fill it up::
 
 # cd /Removable/fs
 # bzcat2 $wherever/android_gcc_r2a.tar.bz2|tar xvf -
 # bzcat2 $wherever/android_gcc_supplement.tar.bz2|tar xvf -
 
(my ``tar`` does not understand ``bzip``-ed archives, so I had to
decompress them separately)
 
We need some temporary directories::
 
 # mkdir -p /Removable/fs/tmp
 # chown root:root /Removable/fs/tmp
 # chmod 1777 /Removable/fs/tmp
 
My shell (the built-in ``/bin/sh``) needs a temporary space under
``/sqlite_stmt_journals`` for its "here-docs", but my image did not
mount it, so I had to do it manually::
 
 # mkdir /sqlite_stmt_journals
 # mount -t tmpfs none /sqlite_stmt_journals
 
My installation also lacked a ``true`` binary, which is needed by lots
of makefiles. I created it this way::
 
 # cat > /Removable/bin/true <<EOF
 #!/bin/sh
 EOF
 # chmod +x /Removable/bin/true
 
Building ``perl``
=================
 
From here on, we can run as a normal user.
 
Get a ``perl`` source tarball, and expand it::
 
 $ cd /Removable/fs/tmp
 $ tar zxf $perl_tarball
 $ cd perl-*
 
We're now ready to build::
 
 $ BASE=/Removable/fs ./Configure -de -Dprefix=$BASE \
   -Duserelocatableinc -Dcc=gcc -Dlibpth=$BASE/lib
 
At the end of the configuration (which should run without errors),
you'll still not be able to just run ``make``: we have to edit a few
files.
 
First, in ``perl.h``, just before ``# endif /* !USE_LOCALE_NUMERIC
*/``, add this line::
 
 #define IN_LOCALE_COMPILETIME 0
 
In the source file for ``Cwd``, we have to tell it to look for the
``pwd`` binary all over the ``$PATH``, or at least in
``/system/xbin/pwd``, otherwise it won't find it, and return empty
strings.
 
In the source file for ``Errno``, we have to add
``/Removable/fs/include`` to the list of places where it looks for
``errno.h``. It should probably ask the compiler for the search list,
but different compilers do it differently, and it's a mess anyway.
 
Now, running ``make`` should build ``miniperl``, some core libraries,
``perl``, some more libraries, and fail as soon as ``XSLoader`` is
needed. I'm still investigating this.
 
Future work
===========
 
- get to the end of the build
- package the image and make it available
- submit patches to reduce the need to muck about with paths and
  headers
 
*UPDATE*
========
 
Other people have been working on this, putting in way more effort, and
getting better results: the master branch of perl now can be compiled
(natively or cross) on Android:
https://github.com/Perl/perl5/commit/b373396993794bd428d71821e0a3f89d22a2ccb0
 
 
.. _`YAPC::EU 2012`: http://act.yapc.eu/ye2012/
.. _`Android Scripting Environment`: http://code.google.com/p/android-scripting/