Search code examples
pythonjenkinspyinstallerraspberry-pi4

Pyinstaller with Jenkins for executable file in Raspberry PI


I use Jenkins-pipeline with Docker image 'python:3.11' on 5.10.0-23-cloud-amd64 Linux for create an executable file with Pyinstaller.

Build command: pyinstaller --onefile main.py

After I tried to download and run the created file on OTHER Linux systems, I haven't got any problem but in Raspberry PI 4 I can get this error:

-bash: ./main: binary is not executable: invalid file format

Pi OS: Linux raspberrypi 6.1.0-rpi4-rpi-v8 #1 SMP PREEMPT Debian 1:6.1.54-1+rpt2 (2023-10-05) aarch64 GNU/Linux

What could be causing the problem?

I try to change the Python version, create build with manually.


Solution

  • If you want to run your software for multiple platforms, you'll have to compile it for each platform separately. As noted in the Pyinstaller documentation:

    If you need to distribute your application for more than one OS, for example both Windows and macOS, you must install PyInstaller on each platform and bundle your app separately on each.

    This also applies for installs on different platforms, such as different CPU architectures. Notably, the Raspberry Pi 4 uses an ARM-based CPU architecture, so software compiled for other CPU architectures will not work on the Raspberry Pi 4. You will need to compile the software (run pyinstaller) in an ARM-based environment in order to run the compiled software on ARM-based platforms. Most likely, you have compiled the software on an AMD64 computer.


    Since you mentioned that you're building in Docker, you can probably just use Docker's ARM platform emulation to accomplish this. For example, in your dockerfile, you may do:

    FROM --platform=linux/arm64 python:3.11
    # ...
    

    Or you can omit the --platform argument and set the environment variable DOCKER_DEFAULT_PLATFORM to control the platform used by docker.

    For example, you might build two images, one for each platform, doing something like this:

    DOCKER_DEFAULT_PLATFORM=linux/amd64 docker build ...
    
    DOCKER_DEFAULT_PLATFORM=linux/arm64 docker build ...
    

    You can also look into building multi-platform images with docker buildx to inline building of multiple platforms:

    docker buildx build --platform linux/amd64,linux/arm64 ...
    

    Alternatively you can also just run pyinstaller on a native ARM64 system (or an emulated system with ARM64), like perhaps directly on your Raspberry Pi. The pyinstaller docs also offer some virtualization suggestions.