So nuitka compile python code into an executable. I have always impress with Go ability to generate single binary and even cross compile for different OS. I wish we can have the same thing with python.
As always, let's start with just a simple script first:-
import requests
resp = requests.get("https://httpbin.org/get")
print(resp.content)
Actually the first I try is with just a simple print("hello world")
but that just too simple. I want to see if nuitka can handle more significant code like the requests library above. To compile the code:-
python3 -mnuitka --follow-imports hello.py
It will generate a file called hello.bin
in the same directory you run the command above. Execute the file (./hello.bin
) and it works! But if you copy the file to different system (I compiled it on ubuntu 18.04 and try to run it on my laptop running Manjaro), I got this error:-
./hello.bin: error while loading shared libraries: libpython3.6m.so.1.0: cannot open shared object file: No such file or directory
So it still need the same python libraries that it get compiled with. And since my manjaro system using python 3.7, hence the error. Fortunately there's second option:-
python3 -mnuitka --follow-imports --standalone hello.py
This time it will generate a folder instead named hello.dist
. Inside the folder you'll see various .so
files and a file named hello
. This time when I copied the folder hello.dist
from Ubuntu 18.04 to my Manjaro's laptop, the command works!
Unfortunately the reverse didn't work though. When compiling on my Manjaro and try to run it on Ubuntu 18.04:-
./hello: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /home/kamal/hello.dist/libpython3.7m.so.1.0)
./hello: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /home/kamal/hello.dist/libpython3.7m.so.1.0)
This is because manjaro is using more recent glibc than ubuntu 18.04. We can check this with ldd:-
ldd --version
ldd (GNU libc) 2.30
And the only workaround for this is to compile is on the oldest system you want to support. I try this with ubuntu 14.04, it work for simple script but then failed with missing ssl certs when compiling my tgcli script.
So a standalone distribution of your python program kind of work. For my tgcli, the installation look like:-
tar xzf tgcli.dist-glibc-2.27.tar.gz
sudo mv tgcli.dist /usr/local/
sudo ln -s /usr/local/tgcli.dist/tgcli /usr/local/bin/tgcli
For more fun story on getting standalone python program, can also read this sharing from syclladb.