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
You can create a build script or directly track the Nuitka command line options inside the source code. The latter is a much cleaner approach than a build script that constructs a command line to invoke Nuitka.
In your build script, you use python -m nuitka some_script.py
--output-dir=dist
and put only options that are not generally
relevant; in the main script.py
you have lines like these.
# The PySide6 plugin covers qt-plugins
# nuitka-project: --enable-plugin=pyside6
# nuitka-project: --include-qt-plugins=qml
You can have conditions, you can evaluate environment variables, you can use locations relative to the main script, and many more things. For reference, check out the page Nuitka Project Options, which contains all the information.
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, but we will add more if a use case exists.
Caching compilation results
When invoked with identical input files, the C compiler will take a long
time and require a lot of CPU to compile over and over. Make sure to
have ccache
installed and configured when using gcc. It will make
repeated compilations much faster, even if things are not yet 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 the included MinGW64 Nuitka supports using
ccache.exe
and will offer to download from an official source and
use it automatically, and using that is recommended for Windows, as
other versions are known to very often have severe quality issues; for
example, they spuriously cause errors or hang indefinitely or don’t work
at all.
Nuitka will pick up ccache
if located 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
environments 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. Nuitka picks that one up
automatically if it is 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, and 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 by setting the environment variable
NUITKA_CACHE_DIR
to a base directory. This is for use in
environments where the home directory does not persist but other paths
do.
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 sure that you are using what you think you are. Using the wrong
Python will make it give you SyntaxError
or ImportError
for
installed modules. That happens, when you run Nuitka with Python2 on
Python3 code and vice versa. You avoid that issue by explicitly calling
the same Python interpreter binary.
Fastest C Compilers
The fastest binaries of pystone.exe
on Windows with 64 bits version
of 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 will be harder to use, so it that’s not
recommended as well.
On Linux, for pystone.bin
, the binary produced by clang6
was
faster than gcc-6.3
, but not significantly. Since gcc is more often
already installed, it is recommended for use for now.
Differences in C compilation times were not examined.
Unexpected Slowdowns
Using the Python DLL, as standard CPython does, can lead to unexpected slowdowns, for example 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.12-3.10 |
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 (same for all versions):
MingGW64 version |
Redist Year |
CPython |
---|---|---|
WinLibs automatic download |
2015 |
2.6, 2.7, 3.4-3.12 |
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 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.