indygreg / PyOxidizer

A modern Python application packaging and distribution tool
Mozilla Public License 2.0
5.39k stars 234 forks source link

Error only when building a Fully Statically Linked Binary on Linux #450

Open dante-signal31 opened 2 years ago

dante-signal31 commented 2 years ago

I'm using PyOxidizer to build a binary for my project Cifra (at my "pyoxidizer" branch).

My pyoxidizer.bzl is at root folder, next to setup.py:

def make_exe():
    dist = default_python_distribution()
    policy = dist.make_python_packaging_policy()
    policy.resources_location = "filesystem-relative:lib"
    python_config = dist.make_python_interpreter_config()
    python_config.run_command = "from cifra.cifra_launcher import main; main()"
    exe = dist.to_python_executable(
        name="cifra",
        packaging_policy=policy,
        config=python_config,
    )
    exe.add_python_resources(exe.setup_py_install(package_path=CWD))
    return exe

def make_embedded_resources(exe):
    return exe.to_embedded_resources()

def make_install(exe):
    files = FileManifest()
    files.add_python_resource(".", exe)
    return files

def register_code_signers():
    if not VARS.get("ENABLE_CODE_SIGNING"):
        return

register_code_signers()

register_target("exe", make_exe)
register_target("resources", make_embedded_resources, depends=["exe"], default_build_script=True)
register_target("install", make_install, depends=["exe"], default=True)

resolve_targets()

With that configuration I get a proper binary file with "pyoxidizer build".

However, problem arises when I try to build a fully statically linked binary. I've followed instructions page build static binaries. I've updated rust:

(venv)dante@Camelot:~/Projects/cifra$ rustup target add x86_64-unknown-linux-musl

But when I build process ends with this error:

(venv)dante@Camelot:~/Projects/cifra$ pyoxidizer build --target-triple x86_64-unknown-linux-musl
[...]
Running greenlet-1.1.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-futc9qp4/greenlet-1.1.1/egg-dist-tmp-zga041e7
no previously-included directories found matching 'docs/_build'
warning: no files found matching '*.py' under directory 'appveyor'
warning: no previously-included files matching '*.pyc' found anywhere in distribution
warning: no previously-included files matching '*.pyd' found anywhere in distribution
warning: no previously-included files matching '*.so' found anywhere in distribution
warning: no previously-included files matching '.coverage' found anywhere in distribution
error: Setup script exited with error: command 'musl-clang' failed: No such file or directory
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: Other, error: "command [\"/home/dante/.cache/pyoxidizer/python_distributions/python.70974f0c6874/python/install/bin/python3.9\", \"setup.py\", \"install\", \"--prefix\", \"/tmp/pyoxidizer-setup-py-installvKsIUS/install\", \"--no-compile\"] exited with code 1" }', pyoxidizer/src/py_packaging/packaging_tool.rs:336:38
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

To make it work, I've installed musl, musl-dev an clang packages but error persists. I'm in a Linux Mint 20.2 (uma).

Is it a bug or am I doing something wrong?

indygreg commented 2 years ago

The musl Linux Python distributions are compiled with clang using a musl-clang executable. The reference to that compiler and its settings leaks into the Python distribution where it is picked up by Python build tools.

To fix this, you need a musl-clang in your build environment. I'm not sure if this is something that Linux Mint has a package for.

This is definitely something that should be better documented in PyOxidizer's docs. Ideally we would provide a Docker image or otherwise make it easier to build Python extensions using the same compiler that the Python distributions do.

dante-signal31 commented 2 years ago

Thank you for your answer and for the effort to develop PyOxidizer.

Indeed, I've not found any package with musl-clang, so I guess it's something you have to compile from source. I've tried to google it but I haven't found a clear way to get that command up and running (I have to admit I'm not a C/C++ ninja).

If you find the time to document how to prepare your system to have that command it would be great. Until that I guess I'll have to use pyoxidizer without static compiling. :-)