Compilando rsync en Android

Martes, 15 Septiembre 2009

Hace muy pocos días que he aterrizado en el mundo de android pero creo que voy avanzando poco a poco. Voy a publicar una minireceta de como compilar utilidades linux (sencillas) nativamente en Android. Antes de empezar sería bueno recordar que los binarios de Android se compilan para arquitectura ARM por lo que o usamos un emulador (tipo qemu) o un toolchain. Yo he usado el toolchain para compilar nativamente, con el emulador deberíamos compilar en estático y el binario ocupará bastante más. Vamos por pasos:

1.- Descargar el git de android, viene muy bien explicado aquí. Yo lo he descargado en mi $HOME/toolchain.

mkdir ~/toolchain
cd toolchain
wget http://android.git.kernel.org/repo
chmod +x repo
./repo init -u git://android.git.kernel.org/platform/manifest.git
./repo sync

2.- Hora de tomarse algo, descarga la friolera de 2.1 GiB, seguimos, hay que compilar la parte base (librerías)

make BUILD_TINY_ANDROID=true

3.- Tarda otro buen ratillo, ahora compilamos la parte oprofile (lo he compilado aquí porque así tenía a mano los includes de popt.h que son los únicos que he necesitado), cargamos el entorno de ayuda y compilamos el directorio actual y subdirectorios con "mm":

cd external/oprofile
. ../../build/envsetup.sh
mm 

4.- Ahora descargamos las fuentes de rsync (pueden valer las de Debian)

dget -u http://ftp.uk.debian.org/debian/pool/main/r/rsync/rsync_3.0.6-1.dsc
cd rsync-3.0.6

5.- La parte que más me ha costado ha sido entender los Makefile de Android que se llaman Android.mk. Este es mi Android.mk para rsync:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
flist.c\
rsync.c\
generator.c\
receiver.c\
cleanup.c\
sender.c\
exclude.c\
util.c\
main.c\
checksum.c\
match.c\
syscall.c\
log.c\
backup.c\
options.c\
io.c\
compat.c\
hlink.c\
token.c\
uidlist.c\
socket.c\
hashtable.c\
fileio.c\
batch.c\
clientname.c\
chmod.c\
acls.c\
xattrs.c\
progress.c\
pipe.c\
params.c\
loadparm.c\
clientserver.c\
access.c\
connection.c\
authenticate.c\
lib/wildmatch.c\
lib/compat.c\
lib/snprintf.c\
lib/mdfour.c\
lib/md5.c\
lib/permstring.c\
lib/pool_alloc.c\
lib/sysacls.c\
lib/sysxattrs.c\
zlib/deflate.c\
zlib/inffast.c\
zlib/inflate.c\
zlib/inftrees.c\
zlib/trees.c\
zlib/zutil.c\
zlib/adler32.c\
zlib/compress.c\
zlib/crc32.c
LOCAL_SRC_FILES += netbsd_getpass.c
LOCAL_STATIC_LIBRARIES := \
libpopt
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/.. \
$(LOCAL_PATH)/../libdb \
$(LOCAL_PATH)/../libutil \
$(LOCAL_PATH)/../libop \
$(LOCAL_PATH)/../libabi
LOCAL_MODULE := rsync
include $(BUILD_EXECUTABLE)

El archivo netbsd_getpass.c lo he tomado de ~/toolchain/external/dropbear/netbsd_getpass.c ya que Android no debe tener la rutina getpass(), sólo se usa si la rutina getpassf() de rsync nativa falla.

6.- A compilar toca, sólo hay que ejecutar "mm" dentro del directorio rsync-3.0.6 y si todo va bien veremos al final:

target Executable: rsync (out/target/product/generic/obj/EXECUTABLES/rsync_intermediates/LINKED/rsync)
target Non-prelinked: rsync (out/target/product/generic/symbols/system/bin/rsync)
target Strip: rsync (out/target/product/generic/obj/EXECUTABLES/rsync_intermediates/rsync)
Install: out/target/product/generic/system/bin/rsync
make: se sale del directorio `/home/mario/toolchain'

7.- Para copiarlo al móvil (conectar el cable USB y activar el modo depuración USB en las preferencias)Necesitamos el SDK de Android.

cd ~/sdk/tools
sudo ./adb kill-server
sudo ./adb remount
sudo ./adb push ~/toolchain/out/target/product/generic/system/bin/rsync /system/bin
sudo ./adb shell chmod 755 /system/bin

Ya podemos abrir el terminal desde android (o desde adb shell) y ejecutar rsync para ver si se copio bien.

Se me ocurren miles de cosas sencillas (GScript + rsync) para tener las fotos publicadas en un blog, hacer copias de seguridad remotas (incrementales) o incluso usarlo para descargar contenido pudiendo perder la conexión temporalmente.

Rizando el rizo, estaría guapo hacer un pequeño frontend con las opciones más usadas y llamarlo desde una aplicación APK.

Como próximo objectivo compilar alguna otra cosa que hecho en falta (¿git? etc...)