Thursday, October 10, 2013

Once upon a time there were Bell Labs...

Today is another step closer to the end of an era for the old AT&T Bell Labs (now called AT&T Labs). Our valued colleague David Korn (inventor of the famous Korn Shell - ksh) is leaving the labs, and he sent us the following farewell message in a form of (what else?) a Korn Shell script:


cd /tmp
if [[ $(print hello) != hello ]] 2> /dev/null
then echo 'You should use ksh'
 alias print=echo
fi
trap 'rm mvs2*' EXIT
trap 'print "$year: dgk raptured to dgk@xxxxxxxxx"' TERM
for x in 76 78 80 81 83 86 87 88 89 90 91 93 95 99 100 103 107 108 110 112 113
do case $((year=1900+x)) in
 1976) print "$year: Hello Bell Telephone Labs, Holmdel; Goodbye NYU";;
 1978) print "$year: create 'formshell' for RBCS from Bourne shell";;
 1980) print "$year: leave Bell Telephone Labs and return to NYU";;
 1981) print "$year: return to Bell Telephone Labs Murray Hill Bldg 5"
  print "$year: meet erg north dgb and kpv";;
 1983) print "$year: first version of ksh with editing and job control";
  print "$year: dgb becomes my supervisor"
  print "$year: UNIX for apollo with erg and ed fisher";;
 1986) print "$year: compete with kpv for best malloc library";;
 1987) print "$year: win best one liner in obfuscated C contest"
  print "$year: began long and continuing collaboration with gsf";;
 1988) print "$year: KornShell 88 book published";;
 1989) print "$year: 3d file system with gsf and ekrell";;
 1990) print "$year: sfio with kpv";;
 1991) print "$year: begin ast library with gsf";;
 1993) print "$year: first version of ksh93";;
 1995) print "$year: 1993 KornShell book published"
  print "$year: first version of UWIN"
  print "$year: Bell Labs split to AT&T Labs and Lucent";;
 1997) print "$year: move to Florham Park";;
 1999) print "$year: y2k testing software created";;
 2000)  print "$year: ast software becomes self documenting";;
 2003) > mvs2pc; print "$year: create mvs2pc";;
 2007) print "$year: Universal Biller invoicing runs with msv2pc";;
 2008) print "$year: UWIN merged into VizGems written in ksh by Dr. ek"
  print "$year: merged mfcobol compiler into mvs2pc";;
 2010) print "$year: distributed shell using coshell";;
 2012) mv mvs2pc mvs2cloud; print "$year: rename mvs2pc to mvs2cloud";;
 2013) kill -TERM $$;;
 esac
done
exit



Thursday, August 22, 2013

How to debug Android Native Code with Eclipse

This blog summarizes the steps needed to set-up your Eclipse environment to support the debugging of an Android native application written in C/C++. It's taken from an old Carlos Suoto's web page that doesn't seem to exist anymore.

1. Pre-Requisites


  • Make sure you compile your C/C++ with the "-g" option (or use -DCMAKE_BUILD_TYPE:STRING="Debug" if you use cmake).
  • Make sure APP_OPTIM is set to "APP_OPTIM:=debug" in Android.mk and Application.mk.
  • Make sure build/core/build-binary.mk in Android NDK doesn't strip executables. For example patch android-ndk-r8e/build/core/build-binary.mk to the following:

    --- build/core/build-binary.mk.orig     2013-08-21 11:06:39.818329442 -0400
    +++ build/core/build-binary.mk  2013-08-21 11:13:11.877214361 -0400
    @@ -485,10 +485,16 @@ $(LOCAL_INSTALLED): PRIVATE_DST       :=
     $(LOCAL_INSTALLED): PRIVATE_STRIP     := $(TARGET_STRIP)
     $(LOCAL_INSTALLED): PRIVATE_STRIP_CMD := $(call cmd-strip, $(PRIVATE_DST))
     
    +ifeq ($(APP_OPTIM),debug)
    +$(LOCAL_INSTALLED): $(LOCAL_BUILT_MODULE) clean-installed-binaries
    +       @$(HOST_ECHO) "Install        : $(PRIVATE_NAME) => $(call pretty-dir,$(PRIVATE_DST))"
    +       $(hide) $(call host-install,$(PRIVATE_SRC),$(PRIVATE_DST))
    +else
     $(LOCAL_INSTALLED): $(LOCAL_BUILT_MODULE) clean-installed-binaries
            @$(HOST_ECHO) "Install        : $(PRIVATE_NAME) => $(call pretty-dir,$(PRIVATE_DST))"
            $(hide) $(call host-install,$(PRIVATE_SRC),$(PRIVATE_DST))
            $(hide) $(PRIVATE_STRIP_CMD)
    +endif

1.1. Install the Eclipse Sequoyah plugin


  1. In Eclipse go to Help -> Install New Software
  2. Click on the Add button
  3. Enter 'Sequoyah Metadata Repository' in the Name field
  4. If you still see the "There are no categorized items" message, uncheck the "Group items by category" radio button
  5. Select "Sequoyah Android Native Code Support" and install the plugin

1.2. Convert The Android Java Application into C/C++ Project


You must convert your Java project to C/C++ using the Sequoyah plugin or else you won't be able to see the configuration options to set the proper debugger settings.
  1. In Eclipse select the Android Java project you need to convert
  2. Right click with the mouse and select Android Tools -> Add Native Support

1.3. Other Pre-Requisites


  1. The platform must be Android 2.2 (android-8) or later
  2. The ndk version must be r4b (it contains bugfixes to ndk-gdb that are necessary) or later
  3. Eclipse CDT 7.0 or newer must be installed
  4. The AndroidManifest.xml must have the property of the application node android:debuggable="true"
  5. The build must have been done with the ndk-build (if using the Sequoyah Android components, it will be automatic)

2. Configurations


  • 01) Create a debug configuration for an Android application (can be done with Eclipse or MOTODEV Studio)
  • 02) Create a debug configuration for a C/C++ application
03) Set the following properties:

  • 04) The process launcher must be the Standard Process Launcher. This is selected at the bottom of the Main tab:


  • 05) On the "Main" tab:
    the Field C/C++ Application: $PROJECT_PATH/obj/local/armeabi/app_process


  • 06) On the "Debugger" tab:
    • field Debugger: gdbserver
    • On the "Main" subtab:

    • 07) GDB debugger: $NDK_PATH/build/prebuilt/$ARCH/arm-eabi-$GCC_VERSION/bin/arm-eabi-gdb
    • 08) GDB command file: $PROJECT_PATH/obj/local/armeabi/gdb2.setup
      [Windows users] Uncheck the "Use full file path to set breakpoints" option

    • On the "Connection" subtab:



    • 09) Type: TCP
    • 10) Hostname or IP address: localhost
    • 11) Port number: 5039 

    3. Instructions

  • Open the ndk-gdb script that came with the android NDK and comment the last line (we are not calling the usual gdb client, but we will attach an Eclipse gdb session instead):

    •     # $GDBCLIENT -x $GDBSETUP -e $APP_PROCESS
      
  • Insert a breakpoint in your Java code, preferably after all System.loadLibrary() calls. (To make sure that the debugger is correctly attached to the Java process)
  • Launch the android debug and wait for it to reach the breakpoint
  • From a Terminal session, in the project folder, run the modified ndk-gdb command. It should not attach to an gdb client, but call the gdbserver on the emulator and open a TCP port for connection (or in alternative if you have an Android device connected to your USB port, the ndk-gdb script will run gdbserver on the device itself).
  • In the $PROJECT_PATH/obj/local/armeabi/, modify the gdb.setup file, removing the target remote:5039 statement. (For some reason, the Eclipse GDB session does not like this statement being done in the commands file). Rename this new file to gdb2.setup. This step need to be run just once, on the first debug session.
  • Launch the C/C++ Application debug and wait for the Eclipse GDB session to fully connect to the emulator's gdbserver instance.
After following these steps, one can continue to debug the application as usual, using the "continue" option to let the execution flow until the next breakpoint is hit or by using the usual "step-in" to execute each statement individually. Setting a breakpoint on a Java statement that calls a native function through JNI and stepping into will place the user at the beginning of the native code.
Another way to set breakpoints in the C/C++ code is from Eclipse to click on File -> Open File and browse to the location of your source code. Then double-click on the line where you want to set the breakpoint.

Thursday, May 9, 2013

How to compile libogg for Android

To compile libogg for Android, you just need to create an appropriate jni/Android.mk makefile with the minimum set of files and options needed to compile libogg for Android.

  1. Download ogg from http://downloads.xiph.org/releases/ogg/ (for example I downloaded libogg-1.1.4.tar.gz)
  2. untar the file in your local directory:

    $ tar zxf libogg-1.1.4.tar.gz
  3. create a jni directory and put the following text into a file named jni/Android.mk:

    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)
    LOCAL_MODULE    := ogg
    LOCAL_CFLAGS    := \
        -DFIXED_POINT -DUSE_KISS_FFT -DEXPORT="" -UHAVE_CONFIG_H \
        -D_ANDROID
    LOCAL_C_INCLUDES := \
        ../libogg-1.1.4/include
    LOCAL_SRC_FILES := \
        ../libogg-1.1.4/src/bitwise.c \
        ../libogg-1.1.4/src/framing.c
    include $(BUILD_SHARED_LIBRARY)
  4.  Now your directory should look like the following:

    $ ls
    jni/  libogg-1.1.4/  libogg-1.1.4.tar.gz
  5. change directory to jni and run ndk-build:

    $ cd jni; ndk-build V=1
That should do it.

Wednesday, February 20, 2013

How to compile busybox with Android NDK for both ARM and x86 architectures

I was looking for a way to run busybox on a Motorola RAZRi with an x86 Intel Atom processor but I couldn't find any Android app from the Google play market that was running on the phone (when running any busybox command nothing happened and I was immediately getting the prompt back).
So I decided to cross-compile busybox for Android myself. Now you will find other posts claiming to have done so by downloading an ARM-cross compiler from codesourcery.com but I had two problems with that approach:

  1. I needed an x86 cross-compiler and,
  2. I read various complaints of people not being able to run various busybox commands with this method.

Cross-compiling busybox with the Android NDK

My only option was to use the Android NDK itself, since it comes with full support of the ARM, x86, and MIPS architectures. I ended up manually configuring busybox by eliminating any module that would not cross-compile due to missing header files and/or libraries in the Android NDK.
To cut the story short, I managed to cross-compile busybox using the Android NDK compilers for both ARM and x86 architectures (I didn't try MIPS since I don't have a device with a MIPS processor to test the resulting binaries).
To build busybox yourself, download the busybox-android.patch, busybox-android.config, and build.sh script and run the latter with the following options:

$ build.sh <android NDK dir> <NDK toolchain> <Android ABI> <Toolchain compiler version> <Android Native API Level> <Install prefix>

The script will download the busybox version 1.21.0 source code, apply the busybox-android.patch and configure busybox for the right architecture.
For example if you have your Android NDK installed under /home/android/android-ndk-r8d, to build busybox for the Intel x86 architecture call the build.sh script like the following:

$ build.sh /home/android/android-ndk-r8d x86-4.7 x86 4.7 android-14 /home/android/busybox-x86

and the cross-compiled busybox binaries will be installed under  the  /home/android/busybox-x86 directory. Similarly if you want to build busybox for the ARM processor, run the following:

$ build.sh /home/android/android-ndk-r8d arm-linux-androideabi-4.7 armeabi-v7a  4.7 android-14 /home/android/busybox-arm

Download busybox binaries

The busybox binaries for x86 (compiled using the above procedure), can be found here.

Installing busybox

The above procedure was tested with release r8d of the Android NDK and for both ARM and x86 devices.

Pre-requisites

  1. Your phone must be rooted (for example check out my blog How to root Motorola RAZRi XT890 running Android 4.0.4)
  2. You must activate USB debugging mode on your device by going to Settings -> Developer Options -> USB Debugging and selecting the corresponding check box.

Installation Procedure

To install busybox on an x86 Android (rooted) device, I run the following commands with the phone connected to the computer via USB:

# logon to the phone and become root to mount the /system file system read/write
$ adb shell
shell@android:/ $ su -
shell@android:/ # mount -o rw,remount -t ext4 /dev/block/system /system
shell@android:/ # chmod 0777 /system/xbin
shell@android:/ # exit
shell@android:/ $ exit
$

then change directory to the location of the busybox binary file and push it to the phone:

$ adb push busybox /system/xbin/

log back on as root and change permissions appropriately:

$ adb shell
shell@android:/ $ su -
shell@android:/ # chmod 755 /system/xbin/busybox
shell@android:/ # chmod 0755 /system/xbin
shell@android:/ # exit
shell@android:/ $ exit
$

Installing busybox on an ARM Android device is very similar, only the mounting instruction line changes:

$ adb shell
shell@android:/ $ su -
shell@android:/ # mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system
shell@android:/ # chmod 0777 /system/xbin
shell@android:/ # exit
shell@android:/ $ exit
$
$ adb push busybox /system/xbin/
$ adb shell
shell@android:/ $ su -
shell@android:/ # chmod 755 /system/xbin/busybox
shell@android:/ # chmod 0755 /system/xbin
shell@android:/ # exit
shell@android:/ $ exit
$

Tuesday, February 12, 2013

How to build the gcc Fortran cross-compiler for Android (ARM and x86)

If you need to cross-compile for Android a program written in Fortran, you know already that the official Android NDK does not come with the gfortran compiler, and if like me you need to port to Android code that depends on Fortran (such as the lapack libraries), you are out of luck.
Fortunately I managed to compile the gcc Fortran cross-compiler with the help of  Mike Long's blog. As an added bonus, I managed to build gfortran 4.8.0 not only for the ARM but also for the x86 toolchain, as well as update the script to the latest Android NDK (currently r8d).
What you need to do is the following:
  1. download the fortran4android shell script.
  2. download the ndk-r8d fortran patch.
  3. run the script in your directory:

    $ fortran4android
  4. wait, wait, wait, ... and you will see in the android-ndk-r8d/toolchains directory two new toolchains called arm-linux-androideabi-4.8.0 and x86-4.8.0
  5. Enjoy your new gfortran compiler.

Note that I've successfully tested the script only on Ubuntu 12.04.

Addendum of August 30, 2013

I now have available a patch for the newer android-ndk-r9. To use this instead of the patch above:
  1. download the ndk-r9-fortran-patch
  2. change the fortran4android script by replacing "r8d" with "r9" everywhere
  3. run the fortran4android script in your directory.
 Note that r9 of the NDK already comes with a 4.8 gcc toolchain and to keep it separated, the fortran4android script will still generate in output a "4.8.0" toolchain.

Monday, February 11, 2013

How to root Motorola RAZRi XT890 running Android 4.0.4

This procedure is only valid for Motorola RAZRi model XT890 (Intel inside) running Android 4.0.4 (system version 81.5.39001.XT890.Retail.en.GB). The following instructions refer to rooting the RAZRi from a Windows 7 PC.

You need to download the Android SDK 

Go to the Android Developer web site and download the Android SDK for Windows.
Make sure you then set the PATH environment variable to the <sdk>\platform-tools directory where all the tools can be found from the command line.

Install the latest Motorola USB drivers for you phone

Install the latest Motorola USB Drivers. Get them here.

Your phone should be factory unlocked

This is a must or else rooting the device will fail with the phone stuck on the bootloader. Go to the Motorola Web site and follow the step by step instructions. Basically open a Command Prompt window and get your Device ID by running the fastboot command. The instructions from Motorola are the following:


  1. Put your device in fastboot mode (press the power button and volume down button at the same time and connect your device to your computer with a USB cable).
  2. On your computer, open a command prompt or Terminal session.
  3. Go to the Directory where you installed the Android SDK tools, and type:$ fastboot oem get_unlock_data
  4. This fastboot command will return a character string. This is the Device ID which you will be using to generate your unique unlock key.

    Example Device ID (PC User)$ fastboot oem get_unlock_data
    (bootloader) 0A40040192024205#4C4D3556313230
    (bootloader) 30373731363031303332323239#BD00
    (bootloader) 8A672BA4746C2CE02328A2AC0C39F95
    (bootloader) 1A3E5#1F53280002000000000000000
    (bootloader) 0000000

At this point if you submit the device ID to the web form, Motorola will send you the unlock code via e-mail (after warning you that the warranty will be void if you do so).
To unlock the device:


  1. Turn off your device.
  2. Start your device in fastboot mode. To do this on most Motorola devices, push and hold the power and volume down at the same time, release the power button then release volume down. The device will power up in fastboot mode
  3. Connect the device to the computer with a USB cable. You'll get a confirmation message on the device will indicate that it's connected.
  4. Open a command window or terminal on your computer.
  5. Change field to show the path to the tools folder within the Android SDK folder.
  6. Verify that the desktop and device are connected by entering the following in the command field:$ fastboot devicesYou should see that your device is connected.
  7. Now you will unlock the bootloader. Simply enter the following in the command line:$ fastboot oem unlock UNIQUE_KEYThe UNIQUE_KEY is the code you received in the email. It is case-sensitive.
  8. If the line was entered correctly, your device's screen will confirm that your device is unlocked. You have just unlocked your device's bootloader.


Root the device

Get the RAZRi rooting utility for Windows. Get it here.
Extract the zipped files and from a Command Prompt or terminal window, change directory to the location of the utility. Make sure your RAZRi is connected to your Windows PC via the USB cable. Finally run the Root.bat command, follow the instructions, and cross your fingers.
After rebooting at least three times the phone should be rooted.


Thursday, January 31, 2013

How to build Python-4-Android for the ARM Neon

Currently the Py4A project does not compile for the ARM Neon architecture. If you try to run ndk-build on the project by setting the APP_ABI to armeabi-v7a and setting the LOCAL_ARM_NEON variable to true, you get the following error:





libffi/src/arm/sysv.S: Assembler messages:
libffi/src/arm/sysv.S:203: Error: selected processor does not support ARM mode `stfeqs f0,[r2]'
libffi/src/arm/sysv.S:208: Error: selected processor does not support ARM mode `stfeqd f0,[r2]'
libffi/src/arm/sysv.S:283: Error: selected processor does not support ARM mode `ldfs f0,[sp]'
libffi/src/arm/sysv.S:286: Error: selected processor does not support ARM mode `ldfd f0,[sp]'
libffi/src/arm/sysv.S:289: Error: selected processor does not support ARM mode `ldfd f0,[sp]'
make: *** [obj/local/armeabi-v7a/objs/ffi/src/arm/sysv.o] Error 1


The following patch for the python-build/libffi/src/asm/sysv.S file allows you to cross-compile Py4A for the armeabi-v7a ABI and also for the Neon instruction set. The patch consists in appropriately changing the conditionals containing __SOFTFP__ and adding __SOFTFP__ || __ARM_EABI__.
For example to build for the ARM Neon instruction set, the ndk-build command line in build.sh should be the following:

ndk-build APP_ABI:=armeabi-v7a LOCAL_ARM_NEON:=true


--- libffi/src/arm/a/sysv.S    2013-01-30 14:49:29.711595414 -0500
+++ libffi/src/arm/sysv.S    2013-01-31 18:05:07.376178842 -0500
@@ -189,7 +189,7 @@ ARM_FUNC_START ffi_call_SYSV
 
 @ return INT
     cmp    r3, #FFI_TYPE_INT
-#ifdef __SOFTFP__
+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
     cmpne    r3, #FFI_TYPE_FLOAT
 #endif
     streq    r0, [r2]
@@ -197,12 +197,12 @@ ARM_FUNC_START ffi_call_SYSV
 
     @ return INT64
     cmp    r3, #FFI_TYPE_SINT64
-#ifdef __SOFTFP__
+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
     cmpne    r3, #FFI_TYPE_DOUBLE
 #endif
     stmeqia    r2, {r0, r1}
 
-#ifndef __SOFTFP__
+#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
     beq    LSYM(Lepilogue)
 
 @ return FLOAT
@@ -245,21 +245,21 @@ ARM_FUNC_START ffi_closure_SYSV
     beq    .Lretint
 
     cmp    r0, #FFI_TYPE_FLOAT
-#ifdef __SOFTFP__
+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
     beq    .Lretint
 #else
     beq    .Lretfloat
 #endif
 
     cmp    r0, #FFI_TYPE_DOUBLE
-#ifdef __SOFTFP__
+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
     beq    .Lretlonglong
 #else
     beq    .Lretdouble
 #endif
 
     cmp    r0, #FFI_TYPE_LONGDOUBLE
-#ifdef __SOFTFP__
+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
     beq    .Lretlonglong
 #else
     beq    .Lretlongdouble
@@ -278,7 +278,7 @@ ARM_FUNC_START ffi_closure_SYSV
     ldr    r1, [sp, #4]
     b    .Lclosure_epilogue
 
-#ifndef __SOFTFP__
+#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
 .Lretfloat:
     ldfs    f0, [sp]
     b    .Lclosure_epilogue


Tuesday, January 29, 2013

How to build Python-4-Android for the x86

Currently the Py4A project only compiles for the ARM architecture.

The following patch for the python-build sub-directory allows you to cross-compile Py4A for the x86 architecture. The patch consists in:
  1. Adding a set of new files to support the x86 architecture (including creating a new libffi/linux-x86/ directory):

    libffi/linux-x86/ffi.h
    libffi/linux-x86/fficonfig.h
    setup-x86.cfg
  2. changing the build.sh script to accept a new parameter - the Android ABI (for example 'armeabi' or 'x86') - so that the script can call

    ndk-build APP_ABI:=x86

    to trigger the cross-compilation for the x86 processor;
  3. changing the build.py script to parametrize the GCC strip command and the selection of the setup.cfg configuration file based on the input ABI;
  4. changing the libffi/Android.mk makefile to select the right set of source files based on the input ABI;
  5. changing the libffi/include/ffi_real.h header file to redefine FFI_TYPE_LONGDOUBLE to 4;
  6. changing the openssl/crypto/Android.mk and openssl/ssl/Android.mk makefiles to strip down the openssl library with only the bare minimum set that allows you to cross-compile the source code;
  7. changing the  python/jni/modules.mk makefile to add the -fno-stack-protector compiler and linker option when building the _socket module and exclude the openssl module.
After applying the patch, to cross-compile Py4A for the x86 architecture you should run the following:

$ cd python-build
$ ./build.sh x86

Binaries for the x86 can be downloaded here:





--- orig/python/jni/modules.mk    2013-01-21 14:39:56.000000000 -0500
+++ python/jni/modules.mk    2013-01-29 14:58:52.922096000 -0500
@@ -58,7 +58,7 @@ $(call build-module,  syslog ,  Modules/
 $(call build-module,  audioop ,  Modules/audioop.c )
 $(call build-module,  imageop ,  Modules/imageop.c )
 $(call build-module,  _csv ,  Modules/_csv.c )
-$(call build-module,  _socket ,  Modules/socketmodule.c, libc, -lc, -nostdlib )
+$(call build-module,  _socket ,  Modules/socketmodule.c, libc, -lc -fno-stack-protector, -nostdlib -fno-stack-protector )
 $(call build-module,  _sha ,  Modules/shamodule.c )
 $(call build-module,  _md5 ,  Modules/md5module.c Modules/md5.c )
 $(call build-module,  _sha256 ,  Modules/sha256module.c )
@@ -125,6 +125,7 @@ include $(BUILD_SHARED_LIBRARY)
 
 #$(call build-module,  _ssl ,  Modules/_ssl.c, ssl crypto )
 
+ifneq ($(APP_ABI), x86)
 $(call import-module, openssl)
 LOCAL_PATH :=  $(PYTHON_SRC_PATH)
 LOCAL_C_INCLUDES += $(PYTHON_SRC_PATH) $(PYTHON_SRC_PATH)/Include $(OPENSSL)/include $(OPENSSL)
@@ -133,6 +134,7 @@ LOCAL_MODULE_FILENAME := _ssl
 LOCAL_SRC_FILES := Modules/_ssl.c
 LOCAL_SHARED_LIBRARIES := libpython2.6 libcrypto libssl
 include $(BUILD_SHARED_LIBRARY)
+endif
 
 
 $(call import-module, libffi)
--- orig/setup-x86.cfg    1969-12-31 19:00:00.000000000 -0500
+++ setup-x86.cfg    2013-01-28 16:09:49.004463929 -0500
@@ -0,0 +1,2 @@
+[bdist_egg]
+plat-name=linux-x86
--- orig/openssl/ssl/Android.mk    2013-01-21 14:42:17.000000000 -0500
+++ openssl/ssl/Android.mk    2013-01-28 16:33:35.563643087 -0500
@@ -7,6 +7,10 @@ local_c_includes := \
 
 include $(CLEAR_VARS)
 
+ifeq ($(APP_ABI), x86)
+LOCAL_SRC_FILES:= \
+    kssl.c
+else
 LOCAL_SRC_FILES:= \
     s2_meth.c \
     s2_srvr.c \
@@ -45,6 +49,7 @@ LOCAL_SRC_FILES:= \
     bio_ssl.c \
     ssl_err.c \
     kssl.c
+endif
 
 include $(LOCAL_PATH)/../android-config.mk
 
--- orig/openssl/crypto/Android.mk    2013-01-21 14:42:08.000000000 -0500
+++ openssl/crypto/Android.mk    2013-01-29 14:49:00.334324159 -0500
@@ -2,27 +2,17 @@ LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_CFLAGS += -DOPENSSL_BN_ASM_MONT -DAES_ASM -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DOPENSSL_NO_STATIC_ENGINE
+ifneq ($(APP_ABI), x86)
 LOCAL_SRC_FILES:= 0.9.9-dev/bn/armv4-mont.s \
                   0.9.9-dev/aes/aes-armv4.s \
                   0.9.9-dev/sha/sha1-armv4-large.s \
                   0.9.9-dev/sha/sha256-armv4.s \
                   0.9.9-dev/sha/sha512-armv4.s
-
 LOCAL_SRC_FILES+= \
-    cryptlib.c \
-    mem.c \
-    mem_clr.c \
     mem_dbg.c \
-    cversion.c \
     dyn_lck.c \
     ex_data.c \
-    tmdiff.c \
     cpt_err.c \
-    ebcdic.c \
-    uid.c \
-    o_time.c \
-    o_str.c \
-    o_dir.c \
     aes/aes_misc.c \
     aes/aes_ecb.c \
     aes/aes_cbc.c \
@@ -474,6 +464,19 @@ LOCAL_SRC_FILES+= \
     ripemd/rmd_dgst.c \
     ripemd/rmd_one.c \
     evp/m_ripemd.c
+endif
+
+LOCAL_SRC_FILES+= \
+    cryptlib.c \
+    mem.c \
+    mem_clr.c \
+    cversion.c \
+    tmdiff.c \
+    ebcdic.c \
+    uid.c \
+    o_time.c \
+    o_str.c \
+    o_dir.c
 
 LOCAL_CFLAGS += -DNO_WINDOWS_BRAINDEATH
 
--- orig/build.py    2013-01-21 14:44:17.000000000 -0500
+++ build.py    2013-01-28 16:19:35.088015089 -0500
@@ -82,6 +82,10 @@ def rm(path):
 
 
 def strip(path):
+  if len(sys.argv) > 1:
+    if sys.argv[1] == "x86":
+      run('i686-linux-android-strip %s' % path)
+    else:
   run('arm-linux-androideabi-strip %s' % path)
 
 
@@ -153,6 +157,12 @@ map(rm, find('output.temp/usr/lib/python
 map(rm, find('output.temp', 'python$', exclude=['setuptools', 'distutils'])[0])
 run("mkdir python", cwd="output.temp/usr")
 run("cp -r %s/python-libs/py4a python" % pwd, cwd="output.temp/usr")
+if len(sys.argv) > 1:
+    if sys.argv[1] == "x86":
+        run("cp %s/setup-x86.cfg ." % pwd, cwd="output.temp/usr")
+    else:
+        run("cp %s/setup.cfg ." % pwd, cwd="output.temp/usr")
+else:
 run("cp %s/setup.cfg ." % pwd, cwd="output.temp/usr")
 run("cp %s/prepare_setuptools.sh setup.sh" % pwd, cwd="output.temp/usr")
 run("cp %s/standalone_python.sh python.sh" % pwd, cwd="output.temp/usr")
--- orig/libffi/include/ffi_real.h    2013-01-21 14:42:35.000000000 -0500
+++ libffi/include/ffi_real.h    2013-01-29 10:27:30.664550823 -0500
@@ -371,8 +371,12 @@ void ffi_call(ffi_cif *cif,
 #if CONF_HAVE_LONG_DOUBLE       // android changed
 #define FFI_TYPE_LONGDOUBLE 4
 #else
+#ifdef x86
+#define FFI_TYPE_LONGDOUBLE 4
+#else
 #define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
 #endif
+#endif
 #define FFI_TYPE_UINT8      5  
 #define FFI_TYPE_SINT8      6
 #define FFI_TYPE_UINT16     7
--- orig/libffi/Android.mk    2013-01-21 14:42:42.000000000 -0500
+++ libffi/Android.mk    2013-01-28 17:00:21.190897854 -0500
@@ -21,6 +21,17 @@ include $(CLEAR_VARS)
 
 LOCAL_MODULE := ffi
 LOCAL_MODULE_FILENAME :=
+ifeq ($(APP_ABI), x86)
+    LOCAL_SRC_FILES := src/x86/sysv.S \
+    src/x86/ffi.c \
+    src/debug.c \
+    src/java_raw_api.c \
+    src/prep_cif.c \
+    src/raw_api.c \
+    src/types.c
+
+    LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/linux-x86
+else
 LOCAL_SRC_FILES := src/arm/sysv.S \
     src/arm/ffi.c \
     src/debug.c \
@@ -30,6 +41,7 @@ LOCAL_SRC_FILES := src/arm/sysv.S \
     src/types.c
 
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/linux-arm
+endif
 LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
 
 $(call __ndk_info, Building libffi)
--- orig/libffi/linux-x86/ffi.h    1969-12-31 19:00:00.000000000 -0500
+++ libffi/linux-x86/ffi.h    2013-01-28 16:24:28.975890002 -0500
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ */
+#ifndef LIBFFI_H
+
+#define x86
+#include "../src/x86/ffitarget.h"
+#include "../include/ffi_real.h"
+
+#endif
--- orig/libffi/linux-x86/fficonfig.h    1969-12-31 19:00:00.000000000 -0500
+++ libffi/linux-x86/fficonfig.h    2013-01-28 16:23:04.047926730 -0500
@@ -0,0 +1,160 @@
+/* fficonfig.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to the flags needed for the .section .eh_frame directive. */
+#define EH_FRAME_FLAGS "aw"
+
+/* Define this if you want extra debugging. */
+#undef FFI_DEBUG
+
+/* Define this is you do not want support for the raw API. */
+#undef FFI_NO_RAW_API
+
+/* Define this is you do not want support for aggregate types. */
+#undef FFI_NO_STRUCTS
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define if your assembler supports .cfi_* directives. */
+#undef HAVE_AS_CFI_PSEUDO_OP
+
+/* Define if your assembler supports .register. */
+#undef HAVE_AS_REGISTER_PSEUDO_OP
+
+/* Define if your assembler and linker support unaligned PC relative relocs.
+   */
+#undef HAVE_AS_SPARC_UA_PCREL
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define if __attribute__((visibility("hidden"))) is supported. */
+#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have the long double type and it is bigger than a double */
+#undef HAVE_LONG_DOUBLE
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mmap' function. */
+#define HAVE_MMAP 1
+
+/* Define if mmap with MAP_ANON(YMOUS) works. */
+#define HAVE_MMAP_ANON 1
+
+/* Define if mmap of /dev/zero works. */
+#define HAVE_MMAP_DEV_ZERO 1
+
+/* Define if read-only mmap of a plain file works. */
+#define HAVE_MMAP_FILE 1
+
+/* Define if .eh_frame sections should be read-only. */
+#undef HAVE_RO_EH_FRAME
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#define PACKAGE "libffi"
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of `double', as computed by sizeof. */
+#define SIZEOF_DOUBLE 8
+
+/* The size of `long double', as computed by sizeof. */
+#undef SIZEOF_LONG_DOUBLE
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+    STACK_DIRECTION > 0 => grows toward higher addresses
+    STACK_DIRECTION < 0 => grows toward lower addresses
+    STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define this if you are using Purify and want to suppress spurious messages.
+   */
+#undef USING_PURIFY
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+
+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name) .hidden name
+#else
+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
+#endif
+#else
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name)
+#else
+#define FFI_HIDDEN
+#endif
+#endif
+


--- build.sh (orig/build.sh)
+++ build.sh (build.sh)
@@ -5,6 +5,7 @@
 set -ex
 CWD=$(pwd)
 DEBUG=no
+android_abi="$1"

 RELEASE_VERSION=$(cat LATEST_VERSION)
 echo "Building Python VM For Android Release ${RELEASE_VERSION}"
@@ -78,12 +79,12 @@
 ${CWD}/host/pgen ${CWD}/python-src/Grammar/Grammar \
  ${CWD}/python-src/Include/graminit.h \
  ${CWD}/python-src/Python/graminit.c
-ndk-build
+ndk-build APP_ABI:=$android_abi

 # copy out all the needed files
-mv obj/local/armeabi/python ${OUT}/usr/bin
-mv obj/local/armeabi/lib*.so ${OUT}/usr/lib
-mv obj/local/armeabi/*.so ${OUT}/usr/lib/python2.6/lib-dynload
+mv obj/local/$android_abi/python ${OUT}/usr/bin
+mv obj/local/$android_abi/lib*.so ${OUT}/usr/lib
+mv obj/local/$android_abi/*.so ${OUT}/usr/lib/python2.6/lib-dynload
 popd

 pushd ${CWD}/python-libs
@@ -91,7 +92,7 @@
 popd

 ${CWD}/host/bin/python ${OUT}/usr/lib/python2.6/compileall.py ${OUT}/usr/lib/python2.6
-${CWD}/host/bin/python build.py
+${CWD}/host/bin/python build.py $android_abi

 if [ "$DEBUG" != "yes" ]; then
     rm -rf output*