[Python-Dev] Cross compiling C-python 2.7.10 maintenance release for ARM on 64 bit x86_64 systems.

Andrew Robinson andrew3 at r3dsolutions.com
Tue Jul 14 12:22:05 CEST 2015


I'm trying to cross compile C-python 2.7.10 for an embedded system. (Eg: 
a Kobo reader).
But there appears to be some bugs that do not allow the latest 
maintenance release of Python to correctly cross compile on an x86-64 
build system, for a 32 bit arm system.

I have researched the problem, and there are apparently two different bugs;
1'st -- the Makefile doesn't disable PYTHONPATH for the arm libraries, 
and the x86 64 bit platform will attempt to link to the arm libraries 
during the compile process producing an wrong elf class error.

I found some online examples of cross compiling older versions of python 
which suggest adding a '-' before "PYTHONPATH' to prevent that from 
happening.  When I do that, it does compile -- but:

2'nd -- If I build python 2.7.10 with the above change, and with no 
debugging information or switches; it builds fine, but the resulting 
binary segfaults randomly on the Kobo reader, and will not import 
libraries without segfaulting.

If I build it with all available debugging information (-g3 -ggdb 
-gdwarf 4), the random segfaulting stops -- and instead, python raises 
an exception any time I attempt to import a library.

Python 2.7.10 (default, Jun 29 2015, 23:00:31)
[GCC 4.8.1 20130401 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
 >>> import math
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
ImportError: /mnt/user/lib/python2.7/lib-dynload/math.so: undefined 
symbol: Py_InitModule4
[40857 refs]

The symbol is indeed missing when I check with nm, and from what little 
information I can find online -- this appears to have something to do 
with a 32 bit vs. 64 bit incompatibility; eg: even though it's compiling 
for 32 bits ARM -- it still seems to be trying to use symbols associated 
with 64 bit processing.

I attempted to compile a 32 bit python interpreter on the build system, 
to make PYTHON_FOR_BUILD, and PGEN_FOR_BUILD ; but it didn't rectify the 

What is the proper way to cross compile 2.7.10 for 32 bit arm, on a 
x86_64 bit platform  / what am I doing wrong ?


Supplimentary information:

I'm using the linaro-gcc compiler from the kobolabs git repository, () 
eg: an arm-linux-gnueabihf-gcc on a 64 bit Slackware 14.1 machine with 
multilib x86 gcc available on the build system.

I have a separate 8GB partition with the Kobo kernel source code, 
stdlibs, etc. all installed from the github source and compiled to a 
target directory stored in an environment variable called ${DEVICEROOT} 
; All files found on the KOBO reader are located under ${DEVICEROOT} on 
the BUILD machine, and the arm GCC processor uses -I 
${DEVICEROOT}/usr/include and other appropriate paths so that GCC finds 
them naturally.

The following bash script shows the steps I used to compile Python with 
-- and it is followed by another bash script which sets up the compile 
environment variables, so you can see how the compiler environment is 

I have no problem compiling C source code in general using the Kobo 
compiler tools, and have compiled gnuplot, and bash, and several other 
packages with absolutely no problems.  It is only python which is not 
compiling correctly.


set -x

# A parser generator and build system version of python are supposed to be
# needed to run parts of the cross compilation;  I do see python used in 
# Makefile, but no references to a buid version of PGEN are defined,
# so I don't know if PGEN gets used or not -- but I build it anyway...
# As this is what receipies on the web say to do...

make distclean
. /etc/profile.d/32dev.sh
./configure # --build=x86_64-unknown-linux-gnu 
--host=i486-unknown-linux-gnu #(uncomment to build 32bit)

make Parser/pgen python
mv python python_for_build
mv Parser/pgen Parser/pgen_for_build
make distclean

# fix setup.py to handle installing to the target system's fake install
# directory found on the build system at $DEVICEROOT.

# We want utf-8, unicode terminal handling -- so make sure python compiles
# with ncursesw substituted for curses.

CURSESFLAGS=`pkg-config --cflags ncursesw`

# Configure python to be built
CFLAGS="${CFLAGS} ${CURSESFLAGS} -g3 -ggdb -gdwarf-4" ./configure 
--host=${CROSSTARGET} --build=i486-unknown-linux-gnu --enable-unicode 
--enable-shared --with-pydebug --prefix=/mnt/user --disable-ipv6 
--without-pymalloc ac_cv_file__dev_ptmx=yes ac_cv_file__dev_ptc=no 
ac_cv_have_long_long_format=yes PYTHON_FOR_BUILD=${PWD}/python_for_build 

# Fix a bug in the Makefile
# The build version of python, ought not try to actually use the ARM 
sed -i -e 's%\([[:space:]]\)\(PYTHONPATH=$(DESTDIR)$(LIBDEST)\)%\1-\2%' 
echo "background the process now to Fix the makefile manually if you can"
sleep 10

make PYTHON_FOR_BUILD=${PWD}/python_for_build CROSS_COMPILE_TARGET=yes

echo " Waiting to allow you to see error messages before installing "
sleep 10

# Optionally, binary file stripping could be carried out on the python 
# Don't strip if you are doing debugging of python
# strip --strip-unneeded python

make install DESTDIR=${DEVICEROOT} 


###### A bash file used to set up gcc paths for cross compiling on the 
kobo follows a (-----).
# There are two compilers in the KOBO git repository:
# https://github.com/kobolabs/Kobo-Reader/tree/master/toolchain

# a linaro-gcc, and code-sourcery-gcc.   The code sourcery gcc does not 
have the standard C libraries and
# perhaps does not use hardware floats, or have those startup files, and 
is strictly for compiling the linux kernel.
# Only the linaro compiler is needed to compile Python.
# The linaro compiler is invoked by using ${CROSSTARGET} as a prefix, 
while the kernel compiler is invoked
# using ${CROSS_COMPILE}
# eg: use arm-linux-gnueabihf-gcc for linaro  vs. 
arm-none-linux-gnueabi-gcc for code sourcercy (kernel compiler).
# All tools are installed on a partition or thumb drive, with the 
following bash script located at THUMBDRIVEPATH/.local/bin and the path 
added to my user PATH.
# The script will auto locate the gcc tools relative to its' own install 
directory, so THUMBDRIVE path can be changed without needing to 
re-editing the script.
# I installed the linaro compiler, path relative, at:
... etc.


#!/bin/bash --init-file
# this file is: use_kobo
echo "Starting subshell with KOBO/ARM linaro gcc and Sourcery_G++_Lite 
in the path"

set -e
path=`whereis -b use_kobo`
path="${path##* /}"

export SOURCERYDIR=${path}/../CodeSourcery/Sourcery_G++_Lite
echo "Adding CodeSourcery eabi and linaro eabihf compiler suites to the 

export KOBOLABS=${path}/../../KoboLabs

export DEVICEROOT=${KOBOLABS}/deviceroot
#export CROSSTARGET="arm-none-linux-gnueabi"
export CROSSTARGET="arm-linux-gnueabihf"

# Build the linux kernel with these variables
export CROSS_COMPILE="arm-none-linux-gnueabi-"
export ARCH="arm"

# Clean out system shell varaibles that can affect program compilation

unset CC
unset CFLAGS
unset CPP
unset CXX
unset CXXCPP
unset QT4DIR

mkdir -p /tmp/kobo-gcc-cross
export TMPDIR=/tmp/kobo-gcc-cross
export CPATH=${DEVICEROOT}/usr/include:${DEVICEROOT}/mnt/user/include
export LDFLAGS="-L${DEVICEROOT}/lib -L${DEVICEROOT}/usr/lib 
# Set up PKGCONFIG to prefer programs that were compiled later, over 

cleanup() {
echo -e '\033]2;Unknown xterm\007'

trap EXIT
exit $1 $2 $3 $4
trap cleanup EXIT

echo -e '\033]2;ARM Sourcery_G++_Lite & linaro-gcc for KOBO shell\007'
set +e
set -o vi

More information about the Python-Dev mailing list