codrsquad / portable-python

Portable python binaries
MIT License
77 stars 10 forks source link

Portable python binaries

.. image:: https://img.shields.io/pypi/v/portable-python.svg :target: https://pypi.org/project/portable-python/ :alt: Version on pypi

.. image:: https://github.com/codrsquad/portable-python/workflows/Tests/badge.svg :target: https://github.com/codrsquad/portable-python/actions :alt: Tested with Github Actions

.. image:: https://codecov.io/gh/codrsquad/portable-python/branch/main/graph/badge.svg :target: https://codecov.io/gh/codrsquad/portable-python :alt: Test coverage

.. image:: https://img.shields.io/pypi/pyversions/portable-python.svg :target: https://github.com/codrsquad/portable-python :alt: Python versions tested (link to github project)

Portable-Python is a CLI (and a python library) for compiling python binaries from source than can be decompressed in any folder, and used from there without further ado (ie: no need to run an "installer").

Motivation

The idea here is to allow for automated systems to:

Installation

portable-python is a regular python CLI, it can be installed with:

pickley_::

pickley install portable-python
portable-python --help
portable-python inspect /usr/bin/python3

Or pipx_::

pipx install portable-python
portable-python inspect /usr/bin/python3

Using pip install (a CI builder would probably do this)::

/usr/bin/python3 -mvenv /tmp/pp
/tmp/pp/bin/python -mpip install portable-python
/tmp/pp/bin/portable-python --help
/tmp/pp/bin/portable-python inspect /usr/bin/python3

Supported operating systems

Portable python binaries can be built for Linux and MacOS (Intel/M1/M2).

Currently Windows is NOT supported, contributions are welcome.

Python binaries can be produced as "portable" (statically linked, can run from any folder where the binary is unpacked in), or with a --prefix (build targeted to live in a pre-determined folder, like /apps/pythonM.m)

================ ======== ======== Operating system Portable --prefix ================ ======== ======== Linux ✅ ✅ Macos ✅ ✅ Windows ❌ ❌ ================ ======== ========

Building a portable cpython

Once portable-python is installed:

Build a binary::

cd some-temp-folder
portable-python build 3.9.7
ls -l dist/cpython-3.9.7-macos-arm64.tar.gz

Unpack it somewhere::

tar -C ~/tmp/versions/ -xf dist/cpython-3.9.7-macos-arm64.tar.gz
ls -l ~/tmp/versions/

It's ready to be used::

~/tmp/versions/3.9.7/bin/python --version

Note that you can use --dryrun mode to inspect what would be done without doing it::

$ portable-python --dryrun build 3.9.7

INFO selected: xz openssl gdbm (3 modules) xz:5.2.5 openssl:1.1.1k gdbm:1.18.1
INFO Platform: macos-x86_64
...
--------------
-- xz:5.2.5 --
--------------
Would download https://tukaani.org/xz/xz-5.2.5.tar.gz
Would untar build/sources/xz-5.2.5.tar.gz -> build/components/xz
INFO env PATH=build/deps/bin:/usr/bin:/bin
INFO env MACOSX_DEPLOYMENT_TARGET=10.14
Would run: ./configure --prefix=build/deps --enable-shared=no --enable-static=yes ...
...
-------------------
-- cpython:3.9.7 --
-------------------
Would download https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tar.xz
Would untar build/sources/Python-3.9.7.tar.xz -> build/components/cpython
...
Would run: ./configure --prefix=/ppp-marker/3.9.7 --enable-optimizations ...
Would run: /usr/bin/make
Would run: /usr/bin/make install DESTDIR=build
...
Would tar build/3.9.7 -> dist/cpython-3.9.7-macos-x86_64.tar.gz

Library

Portable Python can be used as a python library to invoke builds, or inspect an installation.

Invoke a build from python code::

from portable_python import BuildSetup

setup = BuildSetup("cpython:3.9.7")
setup.compile()

Invoke an inspection from python code::

from portable_python.inspector import PythonInspector

inspector = PythonInspector("/usr/bin/python3")
print(inspector.represented())
problem = inspector.full_so_report.get_problem(portable=True)
if problem:
    print("oops, it is not portable!: %s" % problem)

From source, contributions welcome!::

git clone https://github.com/codrsquad/portable-python.git
cd portable-python
python3 -mvenv .venv
.venv/bin/pip install -r requirements.txt -r tests/requirements.txt
.venv/bin/pip install -e .
.venv/bin/portable-python --help
.venv/bin/portable-python inspect /usr/bin/python3

tox -e py311
tox -e style

Build folder structure

portable-python uses this file structure (build/ and dist/ folders configurable)::

build/
    ppp-marker/3.9.7/                   # Full installation (after build completes)
    components/                         # Builds of statically compiled extension modules are here
    deps/                               # --prefix=.../deps passed to all component ./configure scripts
    sources/
        openssl-1.1.1k.tar.gz           # Downloaded artifacts (downloaded only once)
dist/
    cpython-3.9.7-macos-arm64.tar.gz    # Ready-to-go portable binary tarball

Guiding principles

For this repo itself:

.. _pickley: https://pypi.org/project/pickley/

.. _pipx: https://pypi.org/project/pipx/