Title: Cross-compiling Python
Type: compile error Stage:
Components: Cross-Build Versions: Python 3.4
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Alex.Willmer, awilfox, eric.araujo, gregory.p.smith, kumba, loewis, martin.panter, rpetrov, tarek
Priority: normal Keywords:

Created on 2009-03-02 09:03 by kumba, last changed 2016-08-03 23:06 by martin.panter.

File name Uploaded Description Edit skrah, 2014-04-28 22:22
Messages (16)
msg83008 - (view) Author: Joshua Kinard (kumba) Date: 2009-03-02 09:03
I'm attempting to get Python to cross-compile, and I'm not sure if this
is an actual flaw in the build system or not, but thought I'd detail
what I can here and seek comment from those in the know.

What happens is under a cross-environment setup on a Gentoo installation
(using our sys-devel/crossdev and sys-devel/crossdev-wrappers package),
when cross-compiling from x86_64-pc-linux-gnu to
mipsel-unknown-linux-gnu, the Python build process fails to build
several modules/extensions.

I believe that part of the problem with building the extensions is on
our end, and is a separate item I'll track down myself.  But there is
one module in particular that looks tied to Python's core that's getting
a cross-compile error: _socket.

What happens is, somehow, the configure script (or is defining
HAVE_SYS_PARAM_H, which pulls in sys/param.h -- I think this is normal,
but for socketmodule.c, that particular call by the Makefile passes in
-I/usr/include along with the other -I calls defining the cross-include
directories.  The mipsel cross-compiler then references x86_64-specific
assembler code within the sys/param.h copy in /usr/include, and fails.

Generally, our crossdev-wrappers package sets up the buil environment
and overrides a lot of the common variables to use the cross-toolchain.
 So far, it looks like only socketmodule.c is affected with the rogue
-I/usr/include getting pulled in.  I haven't had much luck trying to
track down just how Python's build system is tied into autotools to see
where it's picking up /usr/include from.  Already tried patching some, as well as passing --oldincludedir to configure, but
neither approach worked.

I'm hoping that this is either a minor bug in the build system, or we're
missing a specific variable to be passed to the make process so that
-I/usr/include doesn't get defined.  Not sure which, so if there's any
other ideas to try, I'm all ears!
msg83021 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-03-02 15:44
In short: cross-compilation is not supported at all, and it will be very
very difficult to implement. Search this tracker for proposed solutions,
and comment in each proposed solution whether it would help in your case.
msg83028 - (view) Author: Joshua Kinard (kumba) Date: 2009-03-02 18:22
Gotcha, I'll poke around and see what I can find.  Are you guys open to
patches for 2.5.x still if we find something that needs patching (versus
passing lots of variables to the make process)?
msg83029 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-03-02 18:25
> Gotcha, I'll poke around and see what I can find.  Are you guys open to
> patches for 2.5.x still if we find something that needs patching (versus
> passing lots of variables to the make process)?

No. The Python 2.5 branch is closed; the 2.6 branch doesn't accept new
features. So any cross-compiling support can only go into the trunk
(i.e. 2.7).
msg83032 - (view) Author: Joshua Kinard (kumba) Date: 2009-03-02 18:44
Gotcha.  Not sure how far off Gentoo is from supporting 2.6 -- our
primary package manager relies on it, so the updates tend to be slow.
for moving to new versions.

Do you guys maintain any kind of an "internals" guide to the build
system anywhere?  Like an outline or such of what happens from start to
finish when you run (I think that's the start, anyways)?  I see
there's quite a bit of autotools components plugged in, but it's
intermixed with some of the python code itself.

Looking at some of the other bugs, there definitely seems to be some
cross-compiling capability that's made it in -- as evidenced by a good
chunk of the core build cross-compiling fine (the _Socket extension is
the one glaring error I'm after at the moment).  So it looks like it
just needs some better touch up....on 2.5 at least.

Currently, we're using the patch from Issue #1115, and I'm going to take
a stab at adapting the 2.5.1 patch in Issue #1597850 to see if it takes
me any farther.
msg83035 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-03-02 19:55
> Do you guys maintain any kind of an "internals" guide to the build
> system anywhere?  Like an outline or such of what happens from start to
> finish when you run (I think that's the start, anyways)?

Besides the code, and besides the very high-level "configure;make;make
install" instructions? No - use the source, Luke.
msg83068 - (view) Author: Joshua Kinard (kumba) Date: 2009-03-03 08:27
Making progress!

Adapted the cross-2.5.1.patch from Issue #1597850, integrated the %zd
printf fixup patch, and added another cross-compiler check for the
libffi configure bits in (it'd pass libffi's configure no
--host options, so libffi would compile for the build system, and that's
not good).

Now I'm just trying to figure out why for each extension module, why
CFLAGS gets passed, as far as I can tell, to both the CC and the LD
tools?  I see in the code that distutils doesn't allow one to separate
CC and CXX.  Is the same for CC and LD?  binutils' ld doesn't understand
the same range of flags that gcc does, so for a mips cross-compile case,
you may have the -mabi flag passed.  Gcc understands this, but -m on ld
is to select the output binary, of which 'abi' isn't (obviously) a valid
output type.

Is this to me a distutils limitation I'm hitting?  I've already dug
through the generated Makefile at Python's root and can't pin down
precisely where it invokes ld for each extension, so I'm assuming handles this.  However, I don't read python 100%, and some of
the tricks you can do with classes and def's seems weird to me. 
PyBuildExt seems like some of its internal functions call themselves in
a recursive fashion -- right?  I'm also not sure which function is the
actual function call that executes the compiler or the linker.
msg83074 - (view) Author: Roumen Petrov (rpetrov) * Date: 2009-03-03 14:23
may be you need patch from Issue4010 to pass LDFLAGS to distutils.
Another issue4305 - it is for mipsel.

About cross compilation - yes it is Python flaw. For past ten years the
progress is near to zero.

About you problem - #error "LONG_BIT definition appears
wrong for platform ..." ( posted in another issue ) - please attach you
config.log .

Also Python 2.5 branch is closed (I guess even for security patches) and
for 2.6 I guess new features are not acceptable.
msg83116 - (view) Author: Joshua Kinard (kumba) Date: 2009-03-04 06:32

I took a look at 4010, and tried your patch (as well as attempted to
apply the latter patch, but they changes are too great).  Neither one
helped resolve my issue, but I should probably explain the angle I'm
attacking this from so you have an idea of what I'm doing.

Currently, in Gentoo, we have a package file (called an ebuild) for
2.5.4, and this is what our primary package manager, Portage, links up
against, so that's why I'm working on getting 2.5.4 to cross-compile
properly.  I have no idea when we will move towards using 2.6.0.  I'm
trying to help our embedded team get cross-compiling working in some
packages so we can cross-compile a "base system" from a fast host.  This
all started after I decided to resurrect an old Cobalt RaQ2 from the
grave.  That machine is extremely limited -- ~144MB of RAM and a 250MHz
RM5231 MIPS Processor with no L2 Cache and a small L1 cache.  Compiling
is very, very slow, so the ability to cross-compile about ~83 base
packages in about 2 hours versus an entire day is a very desirable
thing.  It has a CHOST tuple of mipsel-unknown-linux-gnu.

Right now, the three most difficult packages to cross-compile are Perl,
gettext, and Python, in that order.  Perl is probably beyond all hope. 
I don't even know if I'll tackle it.  Gettext is just a nightmare, even
for a GNU package.  We bypass this by disabling NLS support for the
cross-build.  Python, I feel, is doable.  It's got some autotools links,
so it's got the capability.  Python code is also easy to read for me
(unlike Perl, but I digress), so I can sort of follow the logic in some
spots in

We have two packages that assist in cross-compiling.  The first is our
'crossdev' package.  It is akin to what you'll find in Debian or via Dan
Kegel's crosstools setup.  It takes care of installing cross-toolchains
of varying degrees (C-Only, Glibc/Uclibc-based, etc..) on a Gentoo
system.  Next, is 'crossdev-wrappers', which is a set of wrapper scripts
for the 'emerge' command, Gentoo's main package manager tool in Portage.
 This helps to pass a lot of the basic environment variables so that
common configure scripts can correctly identify the build system and
target/host system types, or allow simple, Makefile-only packages build
using cross-compile toolchains.

So what happens on a cross-compile of Python, is first, the _socket
module fails to cross-compile because for that very specific compiler
invocation, it passes -I/usr/include, and _socket references the
sys/param.h include.  Which it finds in my host system's /usr/include
(an amd64 machine currently, so x86_64-pc-linux-gnu is the CHOST tuple).
 This will pull in x86 assembler language, which is misunderstood by a
mipsel-based toolchain.  I dug around, and found some patches that
re-ordered how configure and do things, and after utilizing a
tool in our ebuild system to create config.sub/config.guess files, this
helps to get Python's core to compile for the most part (I also applied
a fix for the printf %zd issue).

However, the default compiling logic for python uses gcc to both compile
the *.o files AND link into the final *.so modules.  One of the patches
I dug up (and merged) converts this logic to explicitly calling $CC for
compiling the *.o files, and then $LD to link them into *.so modules. 
This is where part of my problem lies, because the patch doesn't address
the fact that $CFLAGS gets passed to the $CC call (which is fine) AND to
the $LD call (which is not fine, because 'ld' takes a different set of
arguments) -- via (I think) the $OPT variable.

The other problem was libffi, under the _ctypes/ folder.  The
script explicitly clears configure arguments out via 'config_args = []'
code, and then invokes libffi's configure.  Without a --host=${CHOST}
value passed to it, libffi's configure incorrectly assumes it's running
on an x86_64-pc-linux-gnu system, not in a cross-compile environment for
mipsel-unknown-linux-gnu.  Thus, the configure script will go on to
build for that system, BUT call the mipsel-unknown-linux-gnu-gcc
compiler to compile its internal test code.  This fails, and Python's
default behavior is to ignore build failures and continue on.

So, after addressing those two problems, I've been trying to figure out
how to pass $LD a minimal set of LDFLAGS -- mostly -L commands, although
I'd like to just send it nothing but the *.o files and see how it
handles those by itself.  The logic in the makefile is really quite
weird, though, and it's not helped by the patches I'm mixing in, some of
which are a mix of several patches from this bug tracker.

If you want to take a look at the two main patches, I've uploaded them
to an external host, because I didn't want to litter the bug tracker
with incomplete patches that don't fully address the core problem,
especially since they're for older versions.

This one addresses or hacks around:
- LONG_BIT detection (hack)
- Printf %zd (merged another patch)
- Cross-compiling _socket (merged another patch)

This one is a patch I wrote which gets libffi to compile.  It also
includes a small snippet of code to dump a variable out to a text file
-- that's debug code.  Ignore that.

If you have tips or anything on how to better attack this, I'm all ears!
msg110393 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2010-07-15 22:39
I understand that cross-compilation is not supported so this must now be aimed at 3.2.
msg210163 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2014-02-03 20:16
Cross compiling for arm works here on Ubuntu:

$ cat 
$ export CONFIG_SITE=$PWD/
$ ./configure --host=arm-linux-gnueabi --build=x86_64 --disable-ipv6
$ make

I cannot test though, since I don't have an arm platform.
msg217352 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2014-04-28 09:34
Ping. Is this still an issue for anyone in 3.4?
msg217403 - (view) Author: Gregory P. Smith (gregory.p.smith) * (Python committer) Date: 2014-04-28 19:26
I haven't tried a cross compile in ages.  If nothing else I don't think this issue should be closed until we have at least one buildbot setup to cross compile it and run it on the target platform.

That's on my long "todo for python" wish list but I haven't had time to figure out how to set that up yet.
msg217430 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2014-04-28 22:22
Here's a cross-compile script for arm-linux-gnueabi. Building 3.4 works
on Ubuntu 14.04.  I cannot run the tests, since I only have an old
Debian-ARM qemu image with the wrong glibc version.

For 3.5 we have a regression due to the new matrix operator.
msg271896 - (view) Author: A. Wilcox (awilfox) Date: 2016-08-03 11:33
Bootstrapping a Linux environment based on musl libc from glibc host requires cross-compilation to the same architecture (for example, configure is --build=i686-pc-linux-gnu --host=i686-pc-linux-musl).

The Python core will build and link fine in this configuration; unfortunately, every module in sharedmods fails to link if the ABI is different, as Lib/distutils/command/ uses sys.abiflags and the native Python is used.  For example, my distribution ships with no ABI flags (, but if I use the default enabled PyMalloc (, I will see:

/usr/libexec/gcc/i686-foxkit-linux-musl/ld: cannot find -lpython3.4
collect2: error: ld returned 1 exit status

during linking of all sharedmods.

As I am relatively unfamiliar with distutils' internals I am quite unsure how to proceed to fix this, but am willing test any patches.  For now, I just disable/enable PyMalloc and wide Unicode to match the ABI of the host computer.
msg271932 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2016-08-03 23:06
Wilcox: 3.4 is in security maintainence mode. I suggest using 3.5, or look at backporting revision d00837de03d7 (Issue 26884), which I presume fixes this.
Date User Action Args
2016-08-03 23:06:44martin.pantersetnosy: + martin.panter
messages: + msg271932
2016-08-03 11:33:36awilfoxsetversions: + Python 3.4, - Python 3.2
nosy: + Alex.Willmer, awilfox

messages: + msg271896

components: + Cross-Build, - Build
2014-05-13 22:24:58skrahsetnosy: - skrah
2014-04-28 22:23:00skrahsetfiles: +

messages: + msg217430
2014-04-28 19:26:35gregory.p.smithsetmessages: + msg217403
2014-04-28 09:34:03skrahsetmessages: + msg217352
2014-02-03 21:26:47gvanrossumsetnosy: - gvanrossum
2014-02-03 20:16:35skrahsetnosy: + skrah
messages: + msg210163
2014-02-03 19:40:59BreamoreBoysetnosy: - BreamoreBoy
2010-11-05 20:32:52eric.araujosetnosy: + eric.araujo
2010-09-02 22:48:40gvanrossumsetnosy: + gvanrossum
2010-07-15 22:39:50BreamoreBoysetnosy: + BreamoreBoy

messages: + msg110393
versions: + Python 3.2, - Python 2.5
2009-07-31 21:14:32gregory.p.smithsetnosy: + gregory.p.smith
2009-03-04 06:32:34kumbasetmessages: + msg83116
2009-03-03 14:23:39rpetrovsetmessages: + msg83074
2009-03-03 11:46:53pitrousetnosy: + tarek
2009-03-03 08:27:56kumbasetmessages: + msg83068
2009-03-02 19:55:27loewissetmessages: + msg83035
2009-03-02 18:44:55kumbasetmessages: + msg83032
2009-03-02 18:25:21loewissetmessages: + msg83029
2009-03-02 18:22:28kumbasetmessages: + msg83028
2009-03-02 16:52:14rpetrovsetnosy: + rpetrov
2009-03-02 15:44:14loewissetnosy: + loewis
messages: + msg83021
2009-03-02 09:03:47kumbacreate