Skip to content
 

Cross Compiling Python for Embedded Linux

This article details how to cross compile Python for the ARM and PowerPC platforms.  It should apply equally to other platforms as well, just plug-in the correct cross-compiler.  The article supports Python versions, 2.6.6 (Thanks to evadeflow), 2.7.2 and 3.1.1, 3.1.2, 3.1.3, 3.2.2.

Firstly, download the Python that you want to use from http://www.python.org/

Unpack the Python package using tar:

tar -xvzf Python-2.7.2.tgz

This will create a directory called Python-2.7.2.  Goto the directory:

cd Python-2.7.2

Then run these commands to build the host components:

./configure

make python Parser/pgen

mv python hostpython

mv Parser/pgen Parser/hostpgen

make distclean

Download the correct patch for your version of Python:

Then apply the patch:

patch -p1 < Python-2.7.2-xcompile.patch

Then run this (where ~/Python-2.7.2/_install/ is your desired installation path).  Note also that you must replace all instances of the cross compiler and the host build system in the lines below.  If you are on an x86_64 machine, then you should use x86_64-linux-gnu as the host.

CC=ppc_6xx-gcc CXX=ppc_6xx-g++ AR=ppc_6xx-ar RANLIB=ppc_6xx-ranlib ./configure --host=ppc-linux --build=x86_64-linux-gnu --prefix=/python

make HOSTPYTHON=./hostpython HOSTPGEN=./Parser/hostpgen BLDSHARED="ppc_6xx-gcc -shared" CROSS_COMPILE=ppc_6xx- CROSS_COMPILE_TARGET=yes HOSTARCH=ppc-linux BUILDARCH=x86_64-linux-gnu

make install HOSTPYTHON=./hostpython BLDSHARED="ppc_6xx-gcc -shared" CROSS_COMPILE=ppc_6xx- CROSS_COMPILE_TARGET=yes prefix=~/Python-2.7.2/_install

This will install all your python binaries and libraries in ~/Python-2.7.2/_install.

Copy the entire _install directory to the device, setup the PATH environment variable to include the path the Python executable and run:

python lib/Python-2.7/test/test___all___.py

…and hopefully all the tests will run correctly.

To speed up the importing of Python modules on the target, I recommend to zip up the lib directory to make a file called python27.zip.  This means that we do not have to copy all the Python files to the target, just the one zip file.  This technique might also save space, but that depends on your file system.  On the host machine:

cd _install/lib/python2.7

zip -r -y python27.zip .

Delete libpythonxxx.a site-packages, lib-dynload, config and anything else you do not need from the python27.zip file.

Copy the _install/bin/python to the /usr/bin directory on the target:

Copy the python27.zip file to the /usr/lib directory on the target:

Create a directory on the target called python2.7 in the /usr/lib directory and copy the following directories to that directory:

  • ./lib/python2.7/config
  • ./lib/python2.7/lib-dynload
  • ./lib/python2.7/site-packages

Your directory structure on the target must be as follows:

/usr/lib # ls

python2.7 python27.zip

/python/lib/python2.7 # ls

config lib-dynload site-packages

Set the PYTHONHOME environment variable to /usr/ and you are ready to run Python on the target.

The above patches are based on Chris Lambacher’s patches for Python 2.5 here:

http://whatschrisdoing.com/blog/2006/10/06/howto-cross-compile-python-25/

Other links and credits:

http://www.ailis.de/~k/archives/19-ARM-cross-compiling-howto.html

Bookmark and Share

76 Comments

  1. TS says:

    When I tried Dave L’s 2.7.2 patch i got this:
    ]# patch -p1 < 2.7.2.patch
    patching file configure
    patching file Makefile.pre.in
    Hunk #1 FAILED at 182.
    Hunk #2 FAILED at 215.
    Hunk #3 FAILED at 407.
    Hunk #4 FAILED at 542.
    Hunk #5 FAILED at 925.
    Hunk #6 FAILED at 1049.
    6 out of 6 hunks FAILED — saving rejects to file Makefile.pre.in.rej
    patching file setup.py

  2. Paul Gibson says:

    Hi TS,

    Yes, I have the same problem. I have a new patch that I will try and provide tonight.

    Paul

  3. TS says:

    Thank you very much. Your how-to helped me alot to get Python onto an Embedded Linux system for the company I work for. So far I have been able to successfull get Python 2.7.1 running on the system.

    Again, thanks a lot for taking your time to do all of this.

  4. TS says:

    I forgot to mention that using the 2.7.1 patch disables the ctypes module. Here is the lines that I think cause this problem:
    +# _ctypes fails to cross-compile due to the libffi configure script.
    +if os.environ.has_key(‘PYTHONXCPREFIX’):
    + disabled_module_list.append(‘_ctypes’)
    +

    When I used the patch and cross compiled it, I have ctypes in my library files, but not as a .so module in lib-dynload. Is there any way to fix the patch to allow for ctypes? What I tried so far to get around this problem was downloading and installing Python version 2.6.6, patching it with the 2.6.6 patch and then cross compiling it. Then I took the _ctypes.so from the 2.6.6 lib-dynload and then put it into my 2.7.1 cross compiled version. So far it seems to be working.

  5. CLaymore says:

    Hello all!

    I have this task, which is to make a build of Python 2.7 for the PowerPC CPU.
    I was able to follow this tutorial but i notice that my lib/python2.7/lib-dynload is empty…

    Did you guys had the same problem? If you did, how did you solve it?

    I noticed in the make install output that the make, copies the files to the right place but after that, it cleans the lib-dynload directory :S

  6. Paul Gibson says:

    Hi Claymore,

    It is working for me and the lib-dynload directory is here:
    lib/python2.7/lib-dynload/

    Paul

  7. Paul Gibson says:

    Patch for 2.7.2 and 3.2.2 has been posted.

  8. JaneS says:

    Hi all, please can you help me??? I just cross compile Python 3.2.2 and I have some problems with ELF. Python is normally cross compiles, but not modules.
    Make’s output is something like this :

    *** WARNING: renaming “_struct” since importing it failed: build/lib.linux-x86_64-3.2/_struct.cpython-32m.so: wrong ELF class: ELFCLASS32

    and in /build/tmp.linux-x86_64-3.2/libffi/config.log have this output log:

    /home/jane/libs/Python-3.2.2/Modules/_ctypes/libffi/configure: line 3699: ./conftest: cannot execute binary file
    configure:3701: $? = 126
    configure:3708: error: in `/home/jane/libs/Python-3.2.2/build/temp.linux-x86_64-3.2/libffi’:
    configure:3712: error: cannot run C compiled programs.

    P.S. I understand what the problem is in ./conftest binary file, but how can I solve this.
    in Crosscompiling I use the patch 3.2.2-xcompile.diff but without changesin setup.py.
    P.P.s. I have this problem and in python 2.2.1.
    PLEASE HELP!!!

  9. jaux says:

    Cross-compiling Python 2.7 without ctypes is not cool, I’ll try to work it out next few days, stay turned ;)

  10. jaux says:

    @paul, please contact me, I have the patch for 2.7.2 with ctypes enabled.

  11. apl says:

    @jaux: your 2.7.2 ctypes patch did not work for me :(
    Compiling for arm-unknown-linux-gnueabi-. Does anybody have the solution?
    Thanks!

    --- snip ---
    /home/apl/python/Python-2.7.2/Modules/_ctypes/cfield.c: In function 'PyCField_FromDesc':
    /home/apl/python/Python-2.7.2/Modules/_ctypes/cfield.c:50:29: warning: variable 'length' set but not used [-Wunused-but-set-variable]
    /home/apl/python/Python-2.7.2/Modules/_ctypes/libffi/src/dlmalloc.c: In function 'mmap_resize':
    /home/apl/python/Python-2.7.2/Modules/_ctypes/libffi/src/dlmalloc.c:3193:5: warning: implicit declaration of function 'mremap' [-Wimplicit-function-declaration]
    /home/apl/python/Python-2.7.2/Modules/_ctypes/libffi/src/dlmalloc.c: In function 'sys_trim':
    /home/apl/python/Python-2.7.2/Modules/_ctypes/libffi/src/dlmalloc.c:3612:62: warning: comparison between pointer and integer [enabled by default]
    /tmp/ccgf4gVM.s: Assembler messages:
    /tmp/ccgf4gVM.s:1388: Error: bad instruction `icbi 0,r0'
    /tmp/ccgf4gVM.s:1388: Error: bad instruction `dcbf 0,ip'
    /tmp/ccgf4gVM.s:1397: Error: bad instruction `icbi 0,r4'
    /tmp/ccgf4gVM.s:1397: Error: bad instruction `dcbf 0,r5'
    /tmp/ccgf4gVM.s:1406: Error: bad instruction `icbi 0,r4'
    /tmp/ccgf4gVM.s:1406: Error: bad instruction `dcbf 0,r5'
    /tmp/ccgf4gVM.s:1415: Error: bad instruction `icbi 0,r4'
    /tmp/ccgf4gVM.s:1415: Error: bad instruction `dcbf 0,r5'
    /tmp/ccgf4gVM.s:1424: Error: bad instruction `icbi 0,r4'
    /tmp/ccgf4gVM.s:1424: Error: bad instruction `dcbf 0,r5'
    /tmp/ccgf4gVM.s:1433: Error: bad instruction `icbi 0,r0'
    /tmp/ccgf4gVM.s:1433: Error: bad instruction `dcbf 0,r4'
    /tmp/ccgf4gVM.s:1433: Error: bad instruction `sync'
    /tmp/ccgf4gVM.s:1433: Error: bad instruction `isync'
    --- snip ---

    --- snip ---
    Failed to build these modules:
    _ctypes
    --- snip ---
  12. Jack says:

    HI paul
    i’m from china and my english is pool~ i’m a newer and i tried to follow you instruction .unfortrunately i fail make as i got the error: arm-none-linux-gnueabi-gcc: directory”: No such file or directory
    : warning: missing terminating ” character
    ./Modules/getbuildinfo.c: In function ‘_Py_svnversion’:
    ./Modules/getbuildinfo.c:63: error: missing terminating ” character
    ./Modules/getbuildinfo.c:63: error: expected expression before ‘;’ token

    i have no idea how to fix this . could you help me please thanks !!!

  13. Jack says:

    @Paul Gibson – I just follow the commands you posted and when i finishing patching i made the setting :
    CC=arm-linux-gcc CXX=arm-linux-g++ AR=arm-linux-ar RANLIB=arm-linux-ranlib ./configure –host=arm-linux –build=i386-linux –prefix=$PREFIX

    i successfully passed the configure step but failed in the make step:

    make HOSTPYTHON=./hostpython HOSTPGEN=./Parser/hostpgen BLDSHARED=”arm-linux-gcc -shared” CROSS_COMPILE=arm-linux- CROSS_COMPILE_TARGET=yes HOSTARCH=arm-linux BUILDARCH=i386-linux

    the error imformation was shown above.

    do you have any ideas ? thanks!

  14. Michael says:

    Hi,
    I could crosscompile and easily install this on my ARM9 System.
    Python runs – so thanks for the great work. Anyway I’m missung some modules.

    The cross compiling said:

    Python build finished, but the necessary bits to build these modules were not
    found:
    _bsddb _curses _curses_panel
    _sqlite3 _ssl _tkinter
    bsddb185 bz2 dbm
    dl gdbm imageop
    nis readline sunaudiodev
    zlib
    To find the necessary bits, look in setup.py in detect_modules() for the
    module’s name.

    Failed to build these modules:
    _ctypes

    How can I get sqlite3? I need it for my app, is there anything I can do?

  15. William Ward says:

    Thanks for posting this cross-compilation tutorial – one device came with Python preloaded, but I have three others (two BugLabs Bugs) and a rooted Nook Color that I’d like to give a go at compiling newer versions of Python for, and subsequent modules.

    A clear tutorial helps a great deal!

    :)

  16. Paul Gibson says:

    I noticed today that the 2.6 and 2.7 patches above are not working on Linux 3.0 host machines such as Ubuntu 11.10. I have updated version 2.6.6 and 2.7.2 to include a patch that works on Linux 3.0 hosts. Python 3 patches are not affected by this.

    I have also removed all previous 2.6 and 2.7 patches to make the site cleaner.

  17. yesuraj says:

    Hi,
    After following the above steps, i successfully compiled python for arm architecture. But at the end i don’t find the libpython2.7.so.1.0 anywhere.
    Can some one help me in this regard

  18. Paul Gibson says:

    Hi yesuraj,

    We don’t currently build a shared library, only the static libpython2.7.a is generated. You should link against this instead. The shared library isn’t required for running python on the target.

    Paul

  19. yesuraj says:

    Hi,
    I compiled successfully, but i am not able to use ncurses modules in my python scripts. I hope ncurses modules are not build along. I installed ncurses in my ubuntu (The host machine OS that i use, it is “2.6.38-8-server #42-Ubuntu SMP Mon Apr 11 03:49:04 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux” machine) host machine.
    When i do host configuration, that is before applying patches if i do ./configure
    the ncurses libs status shows as follows,

    checking ncurses.h usability… yes
    checking ncurses.h presence… yes
    checking for ncurses.h… yes

    But after applying patches if i do the follow configure command

    CC=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-gcc CXX=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-g++ AR=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-ar RANLIB=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-ranlib ./configure –host=arm-linux –build=x86_64-linux-gnu –prefix=/python

    The ncurses libs status shows as folows,
    checking ncurses.h usability… no
    checking ncurses.h presence… no
    checking for ncurses.h… no

    Can some one help me to build my python with ncurses modules

    Thanks in advance

    • Paul Gibson says:

      Hi yesuarj,

      I would suggest cross-compiling ncurses individually and then pass in CFLAGS and LDFLAGS to the configure to point to the ncurses that you have cross-compiled.

      eg ./configure CFLAGS=/home/yesuarj/myncurses/include LDFLAGS=/home/yesuarj/myncurses/lib

      Paul

  20. [...] [1]:??Cross Compiling Python for Embedded Linux Linux, Python ← Python ??? /* */ [...]

  21. Hiro says:

    hi,Pual.I can’t build _ctypes. Could you give me some help?

    Python build finished, but the necessary bits to build these modules were not found:
    _bsddb _curses _curses_panel
    _sqlite3 _ssl _tkinter
    bsddb185 bz2 dbm
    dl gdbm imageop
    nis readline sunaudiodev
    zlib
    To find the necessary bits, look in setup.py in detect_modules() for the module’s name.

    Failed to build these modules:
    _ctypes

Leave a Reply

(required)