Saturday, March 25, 2017

Compiling Cython output into Windows executable

 I have been playing around with wxPython and trying to work on simple applications. The problem is how to distribute these programs easily to other people. On Windows, that means creating executable exe files. After searching through StackOverflow, and trying out various things on my own, I finally found a few ways. I will talk about one of them, which produces the smallest executable file so far. By the way, PyInstaller is easy to use, but it will generate a much bigger file.

1. First, convert the icon file that the application will be using into Python code using the script img2py.
img2py -i my_icon.ico my_icon.py


2. Copy and paste the contents of my_icon.py into my main wxPython script, which I shall call my_script.py here. Then, add the following to the __init__() method of the script's main wx.Frame() class. By the way, I got this method of doing things from Michael Driscoll's post here.
ico = my_icon.GetIcon()
self.SetIcon(ico)


3. Convert the Python script into C using cython.
cython my_script.py --embed

4. Use cl.exe from Microsoft Visual Studio to compile the C file into an exe executable.
cl.exe /nologo /Ox /MD /W3 /GS- /DNDEBUG -Ic:\Python36\include -Ic:\Python36\PC /Tcmy_script.c /link /OUT:"test.exe" /SUBSYSTEM:WINDOWS /entry:wmainCRTStartup /MACHINE:X64 /LIBPATH:c:\Python36\libs /LIBPATH:c:\Python36\PCbuild

By the way, the options
/SUBSYSTEM:WINDOWS /entry:wmainCRTStartup
are needed to suppress the console window from showing up. The generated C code may use main() instead, which means you may need to change the options to
/SUBSYSTEM:WINDOWS /entry:mainCRTStartup 
to link it properly.

This should give you a test.exe which you can run.

If your script is a console script, you can just skip steps 1 and 2, and remove the /SUBSYSTEM and /entry options.

The problem with this method is that you will likely need to distribute required DLLs with the executable file.

Meanwhile, I will continue to test out various ways to generate an executable that is fully standalone and yet small in size.

No comments: