Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Self contained rust boostrapping #2421

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions maturin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ def _additional_pep517_args() -> List[str]:
return []


def _get_env() -> Optional[Dict[str, str]]:
if not os.environ.get("MATURIN_NO_INSTALL_RUST") and not shutil.which("cargo"):
from puccinialin import setup_rust

print("Rust not found, installing into a temporary directory")
extra_env = setup_rust()
return {**os.environ, **extra_env}
else:
return None


# noinspection PyUnusedLocal
def _build_wheel(
wheel_directory: str,
Expand Down Expand Up @@ -97,7 +108,7 @@ def _build_wheel(

print("Running `{}`".format(" ".join(command)))
sys.stdout.flush()
result = subprocess.run(command, stdout=subprocess.PIPE)
result = subprocess.run(command, stdout=subprocess.PIPE, env=_get_env())
sys.stdout.buffer.write(result.stdout)
sys.stdout.flush()
if result.returncode != 0:
Expand Down Expand Up @@ -125,7 +136,7 @@ def build_sdist(sdist_directory: str, config_settings: Optional[Mapping[str, Any

print("Running `{}`".format(" ".join(command)))
sys.stdout.flush()
result = subprocess.run(command, stdout=subprocess.PIPE)
result = subprocess.run(command, stdout=subprocess.PIPE, env=_get_env())
sys.stdout.buffer.write(result.stdout)
sys.stdout.flush()
if result.returncode != 0:
Expand All @@ -138,9 +149,12 @@ def build_sdist(sdist_directory: str, config_settings: Optional[Mapping[str, Any
# noinspection PyUnusedLocal
def get_requires_for_build_wheel(config_settings: Optional[Mapping[str, Any]] = None) -> List[str]:
if get_config().get("bindings") == "cffi":
return ["cffi"]
requirements = ["cffi"]
else:
return []
requirements = []
if not os.environ.get("MATURIN_NO_INSTALL_RUST") and not shutil.which("cargo"):
requirements += ["puccinialin"]
return requirements


# noinspection PyUnusedLocal
Expand All @@ -158,7 +172,10 @@ def build_editable(

# noinspection PyUnusedLocal
def get_requires_for_build_sdist(config_settings: Optional[Mapping[str, Any]] = None) -> List[str]:
return []
requirements = []
if not os.environ.get("MATURIN_NO_INSTALL_RUST") and not shutil.which("cargo"):
requirements += ["puccinialin"]
return requirements


# noinspection PyUnusedLocal
Expand All @@ -168,7 +185,7 @@ def prepare_metadata_for_build_wheel(
print("Checking for Rust toolchain....")
is_cargo_installed = False
try:
output = subprocess.check_output(["cargo", "--version"]).decode("utf-8", "ignore")
output = subprocess.check_output(["cargo", "--version"], env=_get_env()).decode("utf-8", "ignore")
if "cargo" in output:
is_cargo_installed = True
except (FileNotFoundError, SubprocessError):
Expand Down Expand Up @@ -200,7 +217,7 @@ def prepare_metadata_for_build_wheel(

print("Running `{}`".format(" ".join(command)))
try:
_output = subprocess.check_output(command)
_output = subprocess.check_output(command, env=_get_env())
except subprocess.CalledProcessError as e:
sys.stderr.write(f"Error running maturin: {e}\n")
sys.exit(1)
Expand Down
31 changes: 31 additions & 0 deletions maturin/boostrap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Support installing rust before compiling (bootstrapping) maturin.

Installing a package that uses maturin as build backend on a platform without maturin
binaries, we install rust in a cache directory if the user doesn't have a rust
installation already. Since this bootstrapping requires more dependencies but is only
required if rust is missing, we check if cargo is present before requesting those
dependencies.

https://setuptools.pypa.io/en/stable/build_meta.html#dynamic-build-dependencies-and-other-build-meta-tweaks
"""

from __future__ import annotations

import os
import shutil
from typing import Any

# noinspection PyUnresolvedReferences
from setuptools.build_meta import * # noqa:F403


def get_requires_for_build_wheel(_config_settings: dict[str, Any] | None = None) -> list[str]:
if not os.environ.get("MATURIN_NO_INSTALL_RUST") and not shutil.which("cargo"):
return ["puccinialin>=0.1,<0.2"]
return []


def get_requires_for_build_sdist(_config_settings: dict[str, Any] | None = None) -> list[str]:
if not os.environ.get("MATURIN_NO_INSTALL_RUST") and not shutil.which("cargo"):
return ["puccinialin>=0.1,<0.2"]
return []
7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# Workaround to bootstrap maturin on non-manylinux platforms
[build-system]
requires = ["setuptools", "wheel>=0.36.2", "tomli>=1.1.0 ; python_version<'3.11'", "setuptools-rust>=1.4.0"]
build-backend = "setuptools.build_meta"
requires = ["setuptools", "tomli>=1.1.0 ; python_version<'3.11'", "setuptools-rust @ git+https://github.com/PyO3/setuptools-rust@konsti/add-custom-env-vars"]
backend-path = ["maturin"]
build-backend = "boostrap"

[project]
name = "maturin"
description = "Build and publish crates with pyo3, cffi and uniffi bindings as well as rust binaries as python packages"
authors = [{ name = "konstin", email = "[email protected]" }]
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.7"
license = {text = "MIT OR Apache-2.0"}
license = { text = "MIT OR Apache-2.0" }
classifiers = [
"Topic :: Software Development :: Build Tools",
"Programming Language :: Rust",
Expand Down
12 changes: 11 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import os
import shlex
import shutil

try:
import tomllib
Expand Down Expand Up @@ -47,9 +48,18 @@ def finalize_options(self):
if os.getenv("MATURIN_SETUP_ARGS"):
cargo_args = shlex.split(os.getenv("MATURIN_SETUP_ARGS", ""))

if not os.environ.get("MATURIN_NO_INSTALL_RUST") and not shutil.which("cargo"):
from puccinialin import setup_rust

print("Rust not found, installing into a temporary directory")
extra_env = setup_rust()
env = {**os.environ, **extra_env}
else:
env = None

setup(
version=version,
cmdclass={"bdist_wheel": bdist_wheel},
rust_extensions=[RustBin("maturin", args=cargo_args, cargo_manifest_args=["--locked"])],
rust_extensions=[RustBin("maturin", args=cargo_args, cargo_manifest_args=["--locked"], env=env)],
zip_safe=False,
)
Loading