Skip to main content

A python library that extends setuptools for binary extensions.

Project description

Milksnake

Milksnake is an extension for setuptools that allows you to distribute dynamic linked libraries in Python wheels in the most portable way imaginable.

It gives you a hook to invoke your own build process and to then take the resulting dynamic linked library.

Why?

There are already other projects that make Python and native libraries play along but this one is different. Unlike other projects that build Python extension modules the goal of this project is to build regular native libraries that are then loaded with CFFI at runtime. Why not just use CFFI? Because CFFI's setuptools support alone does not properly work with such wheels (it does not provide a way to build and properly tag wheels for shared libraries) and it does not provide a good way to invoke an external build process (like a makefile, cargo to build rust binaries etc.)

In particular you will most likely only need two wheels for Linux, one for macs and soon one for Windows independently of how many Python interpreters you want to target.

What is supported?

  • Platforms: Linux, Mac, Windows
  • setuptools commands: bdist_wheel, build, build_ext, develop
  • pip install --editable .
  • Universal wheels (PACKAGE-py2.py3-none-PLATFORM.whl); this can be disabled with milksnake_universal=False in setup() in case the package also contains stuff that does link against libpython.

How?

This example shows how to build a rust project with it:

This is what a setup.py file looks like:

from setuptools import setup

def build_native(spec):
    # build an example rust library
    build = spec.add_external_build(
        cmd=['cargo', 'build', '--release'],
        path='./rust'
    )

    spec.add_cffi_module(
        module_path='example._native',
        dylib=lambda: build.find_dylib('example', in_path='target/release'),
        header_filename=lambda: build.find_header('example.h', in_path='target'),
        rtld_flags=['NOW', 'NODELETE']
    )

setup(
    name='example',
    version='0.0.1',
    packages=['example'],
    zip_safe=False,
    platforms='any',
    setup_requires=['milksnake'],
    install_requires=['milksnake'],
    milksnake_tasks=[
        build_native
    ]
)

You then need a rust/ folder that has a Rust library (with a crate type of cdylib) and a example/ python package.

Example example/__init__.py file:

from example._native import ffi, lib


def test():
    return lib.a_function_from_rust()

And a rust/src/lib.rs:

#[no_mangle]
pub unsafe extern "C" fn a_function_from_rust() -> i32 {
    42
}

And the rust/Cargo.toml:

[package]
name = "example"
version = "0.1.0"
build = "build.rs"

[lib]
name = "example"
crate-type = ["cdylib"]

[build-dependencies]
cbindgen = "0.19"

And finally the build.rs file:

extern crate cbindgen;

use std::env;

fn main() {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let mut config: cbindgen::Config = Default::default();
    config.language = cbindgen::Language::C;
    cbindgen::generate_with_config(&crate_dir, config)
      .unwrap()
      .write_to_file("target/example.h");
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

milksnakex-0.1.6.tar.gz (9.9 kB view details)

Uploaded Source

Built Distribution

milksnakex-0.1.6-py2.py3-none-any.whl (10.9 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file milksnakex-0.1.6.tar.gz.

File metadata

  • Download URL: milksnakex-0.1.6.tar.gz
  • Upload date:
  • Size: 9.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.10.4

File hashes

Hashes for milksnakex-0.1.6.tar.gz
Algorithm Hash digest
SHA256 fa9566670d6aeb3a6ced4ae65617d534206616bb052fe8bf1a82b4e0528d5fef
MD5 cf8b0d5f9aa202267f9628865e74509f
BLAKE2b-256 604fe7a78032bcead32afffee2709739c462a16eb05f81a91c42a232ab718c6f

See more details on using hashes here.

File details

Details for the file milksnakex-0.1.6-py2.py3-none-any.whl.

File metadata

  • Download URL: milksnakex-0.1.6-py2.py3-none-any.whl
  • Upload date:
  • Size: 10.9 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.10.4

File hashes

Hashes for milksnakex-0.1.6-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 7dce35fc4410bd7207b9a64f6249d16ae5c272768419912b582e5e71d198046a
MD5 7b3be73c5038e160d13f2f46b43a44a9
BLAKE2b-256 a5b45ca3e55f0493bcf522157b65a1b5ef522818836e5a5ebe15993a57091bcf

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page