Tips

On this page, you’ll find helpful tips and techniques for optimizing your experience with Nuitka. From maximizing compilation efficiency to managing dependencies and runtime considerations.

Nuitka Options in the code

One clean way of providing options to Nuitka, that you will always use for your program, is to put them into the main file you compile. There is even support for conditional options, and options using pre-defined variables, this is an example:

# Compilation mode, support OS-specific options
# nuitka-project-if: {OS} in ("Windows", "Linux", "Darwin", "FreeBSD"):
#    nuitka-project: --onefile
# nuitka-project-else:
#    nuitka-project: --standalone

# The PySide2 plugin covers qt-plugins
# nuitka-project: --enable-plugin=pyside2
# nuitka-project: --include-qt-plugins=qml

The comments must be at the start of lines, and indentation inside of them is to be used, to end a conditional block, much like in Python. There are currently no other keywords than the used ones demonstrated above.

You can put arbitrary Python expressions there, and if you wanted to e.g. access a version information of a package, you could simply use __import__("module_name").__version__ if that would be required to e.g. enable or disable certain Nuitka settings. The only thing Nuitka does that makes this not Python expressions, is expanding {variable} for a pre-defined set of variables:

Table with supported variables:

Variable

What this Expands to

Example

{OS}

Name of the OS used

Linux, Windows, Darwin, FreeBSD, OpenBSD

{Version}

Version of Nuitka

e.g. (1, 6, 0)

{Commercial}

Version of Nuitka Commercial

e.g. (2, 1, 0)

{Arch}

Architecture used

x86_64, arm64, etc.

{MAIN_DIRECTORY}

Directory of the compiled file

some_dir/maybe_relative

{Flavor}

Variant of Python

e.g. Debian Python, Anaconda Python

The use of {MAIN_DIRECTORY} is recommended when you want to specify a filename relative to the main script, e.g. for use in data file options or user package configuration yaml files,

# nuitka-project: --include-data-files={MAIN_DIRECTORY}/my_icon.png=my_icon.png
# nuitka-project: --user-package-configuration-file={MAIN_DIRECTORY}/user.nuitka-package.config.yml

Python command line flags

For passing things like -O or -S to Python, to your compiled program, there is a command line option name --python-flag= which makes Nuitka emulate these options.

The most important ones are supported, more can certainly be added.

Caching compilation results

The C compiler, when invoked with the same input files, will take a long time and much CPU to compile over and over. Make sure you are having ccache installed and configured when using gcc (even on Windows). It will make repeated compilations much faster, even if things are not yet not perfect, i.e. changes to the program can cause many C files to change, requiring a new compilation instead of using the cached result.

On Windows, with gcc Nuitka supports using ccache.exe which it will offer to download from an official source and it automatically. This is the recommended way of using it on Windows, as other versions can e.g. hang.

Nuitka will pick up ccache if it’s found in system PATH, and it will also be possible to provide if by setting NUITKA_CCACHE_BINARY to the full path of the binary, this is for use in CI systems where things might be non-standard.

For the MSVC compilers and ClangCL setups, using the clcache is automatic and included in Nuitka.

On macOS and Intel, there is an automatic download of a ccache binary from our site, for arm64 arches, it’s recommended to use this setup, which installs Homebrew and ccache in there. Nuitka picks that one up automatically if it on that kind of machine. You need and should not use Homebrew with Nuitka otherwise, it’s not the best for standalone deployments, but we can take ccache from there.

export HOMEBREW_INSTALL_FROM_API=1
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
eval $(/opt/homebrew/bin/brew shellenv)
brew install ccache

Control where Caches live

The storage for cache results of all kinds, downloads, cached compilation results from C and Nuitka, is done in a platform dependent directory as determined by the appdirs package. However, you can override it with setting the environment variable NUITKA_CACHE_DIR to a base directory. This is for use in environments where the home directory is not persisted, but other paths are.

There is also per cache control of these caches, here is a table of environment variables that you can set before starting the compilation, to make Nuitka store some of these caches in an entirely separate space.

Cache name

Environment Variable

Data Put there

downloads

NUITKA_CACHE_DIR_DOWNLOADS

Downloads made, e.g. dependency walker

ccache

NUITKA_CACHE_DIR_CCACHE

Object files created by gcc

clcache

NUITKA_CACHE_DIR_CLCACHE

Object files created by MSVC

bytecode

NUITKA_CACHE_DIR_BYTECODE

Bytecode of demoted modules

dll-dependencies

NUITKA_CACHE_DIR_DLL_DEPENDENCIES

DLL dependencies

Runners

Avoid running the nuitka binary, doing python -m nuitka will make a 100% sure you are using what you think you are. Using the wrong Python will make it give you SyntaxError for good code or ImportError for installed modules. That is happening, when you run Nuitka with Python2 on Python3 code and vice versa. By explicitly calling the same Python interpreter binary, you avoid that issue entirely.

Fastest C Compilers

The fastest binaries of pystone.exe on Windows with 64 bits Python proved to be significantly faster with MinGW64, roughly 20% better score. So it is recommended for use over MSVC. Using clang-cl.exe of Clang7 was faster than MSVC, but still significantly slower than MinGW64, and it will be harder to use, so it is not recommended.

On Linux, for pystone.bin, the binary produced by clang6 was faster than gcc-6.3, but not by a significant margin. Since gcc is more often already installed, that is recommended to use for now.

Differences in C compilation times have not yet been examined.

Unexpected Slowdowns

Using the Python DLL, like standard CPython does, can lead to unexpected slowdowns, e.g. in uncompiled code that works with Unicode strings. This is because calling to the DLL rather than residing in the DLL causes overhead, and this even happens to the DLL with itself, being slower, than a Python all contained in one binary.

So if feasible, aim at static linking, which is currently only possible with Anaconda Python on non-Windows, Debian Python2, self compiled Pythons (do not activate --enable-shared, not needed), and installs created with pyenv.

Note

On Anaconda, you may need to execute conda install libpython-static

Standalone executables and dependencies

The process of making standalone executables for Windows traditionally involves using an external dependency walker to copy necessary libraries along with the compiled executables to the distribution folder.

There are plenty of ways to find that something is missing. Do not manually copy things into the folder, esp. not DLLs, as that’s not going to work. Instead, make bug reports to get these handled by Nuitka properly.

Windows errors with resources

On Windows, the Windows Defender tool and the Windows Indexing Service both scan the freshly created binaries, while Nuitka wants to work with it, e.g. adding more resources, and then preventing operations randomly due to holding locks. Make sure to exclude your compilation stage from these services.

Windows standalone program redistribution

Whether compiling with MingW or MSVC, the standalone programs have external dependencies to Visual C Runtime libraries. Nuitka tries to ship those dependent DLLs by copying them from your system.

Beginning with Microsoft Windows 10, Microsoft ships ucrt.dll (Universal C Runtime libraries) which handles calls to api-ms-crt-*.dll.

With earlier Windows platforms (and wine/ReactOS), you should consider installing Visual C runtime libraries before executing a Nuitka standalone compiled program.

Depending on the used C compiler, you’ll need the following redist versions on the target machines. However, notice that compilation using the 14.3 based version is always recommended, working and best supported, unless you want to target Windows 7.

Visual C version

Redist Year

CPython

14.3

2022

3.11

14.2

2019

3.5-3.10

14.1

2017

3.5-3.8

14.0

2015

3.5-3.8

10.0

2010

3.4

9.0

2008

2.6, 2.7

When using MingGW64 as downloaded by Nuitka, you’ll need the following redist versions:

MingGW64 version

Redist Year

CPython

WinLibs automatic download

2015

2.6, 2.7, 3.4- 3.11

Once the corresponding runtime libraries are installed on the target system, you may remove all api-ms-crt-*.dll files from your Nuitka compiled dist folder.

Detecting Nuitka at run time

Nuitka does not sys.frozen unlike other tools because it usually triggers inferior code for no reason. For Nuitka, we have the module attribute __compiled__ to test if a specific module was compiled, and the function attribute __compiled__ to test if a specific function was compiled.

Providing extra Options to Nuitka C compilation

Nuitka will apply values from the environment variables CCFLAGS, LDFLAGS during the compilation on top of what it determines to be necessary. Beware, of course, that is this is only useful if you know what you are doing, so should this pose issues, raise them only with perfect information.

Producing a 32 bit binary on a 64 bit Windows system

Nuitka will automatically target the architecture of the Python you are using. If this is 64 bit, it will create a 64 bit binary, if it is 32 bit, it will create a 32 bit binary. You have the option to select the bits when you download the Python. In the output of python -m nuitka --version there is a line for the architecture. It’s Arch: x86_64 for 64 bits, and just Arch: x86 for 32 bits.

The C compiler will be picked to match that more or less automatically. If you specify it explicitly, and it mismatches, you will get a warning about the mismatch and informed that your compiler choice was rejected.