In this post I’ll discuss building a Windows executable from a Python script for 32-bit and 64-bit Windows. Producing a 64-bit executable on a 64-bit machine in Windows is easy using PyInstaller, but producing a 32-bit executable on a 64-bit machine takes some tinkering. I ended up setting up a chroot environment on Ubuntu for this task.
64-bit Executable on 64-bit Host
This is relatively easy. You download and install PyInstaller, and for a windowed GUI application you run
pyinstaller -F -w --name=executable gui_script.py
And for a regular script you run,
pyinstaller -F --name=executable script.py
32-bit Executable on 64-bit Host
First, you need to have PyInstaller downloaded and unzipped somewhere, like your Downloads
folder. Next, you need to produce an almost virtual environment on your linux machine. This will be a minimal installation that is separated from the rest of your system. This can be used for developing applications, or for trying out untrusted software. I used this resource for the next few steps. First, install some stuff.
sudo apt-get install debootstrap sudo apt-get install schroot
Next create a configuration file for schroot
at /etc/schroot/chroot.d/precise_i386.conf
[precise_i386] description=Ubuntu 10.04 Precise for i386 location=/srv/chroot/precise_i386 personality=linux32 root-users=bob run-setup-scripts=true run-exec-scripts=true type=directory users=alice,bob
Then make a directory for chroot
, and run debootstrap
,
sudo mkdir -p /srv/chroot/precise_i386 sudo debootstrap --variant=buildd --arch=i386 precise /srv/chroot/precise_i386 http://archive.ubuntu.com/ubuntu/
Now you can enter this alternate linuxverse as root by running,
schroot -c precise_i386 -u root
Or you can enter it as a normal user by leaving off the -u root
, which we will do later. When I ran this, I got a handful of warnings about blah blah blah, but everything worked out in the end. Next I used this resource for these commands that seemed to help.
sudo mount -o bind /proc /srv/chroot/precise_i386/proc sudo cp /etc/resolv.conf /srv/chroot/precise_i386/etc/resolv.conf
Finally, we should have a working little chroot
thingy. We can log in as root,
schroot -c precise_i386 -u root
To make sure you did everything right, you can do a sanity-check to see if you’re really using 32-bit tools. Call Python from the command line and type the following,
import ss sys.maxsize > 2**32
You should get False
if the Python interpreter is 32-bit. Now Ctrl-Z
to get out of the Python interpreter and install python-dev
and setuptools
to get PyInstaller working,
apt-get install curl apt-get install python-dev curl https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -o - | python
Now close out of that terminal session and log back into chroot
as a regular user, not as root as we have been previously,
schroot -c precise_i386
Now we can run PyInstaller for a GUI application as we did in 64-bit land,
pyinstaller -F -w --name=executable gui_script.py
Or for a console application
pyinstaller -F --name=executable script.py
Now you can test your 32-bit executable out on your 64-bit machine. (J/k, if you could do that, you wouldn’t be here in the first place.)