Skip to content

Commit 14703b8

Browse files
authored
Merge pull request #118 from messense/sdist-vendor-crates
Add option to cargo vendor crates into sdist
2 parents 5496a9f + 7ff2642 commit 14703b8

File tree

4 files changed

+100
-0
lines changed

4 files changed

+100
-0
lines changed

.github/workflows/ci.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ jobs:
9696
python -c "from namespace_package import rust; assert rust.rust_func() == 14"
9797
python -c "from namespace_package import python; assert python.python_func() == 15"
9898
99+
- name: Test sdist vendor Rust crates
100+
shell: bash
101+
run: |
102+
cd examples/namespace_package
103+
python setup.py sdist --vendor-crates
104+
cd dist
105+
tar -zxf namespace_package-0.1.0.tar.gz
106+
cd namespace_package-0.1.0
107+
cargo build --offline --target ${{ matrix.platform.rust-target }}
108+
99109
test-abi3:
100110
runs-on: ${{ matrix.os }}
101111
strategy:

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
### Added
88
- Support building x86-64 wheel on arm64 macOS machine. [#114](https://github.com/PyO3/setuptools-rust/pull/114)
99
- Add macOS universal2 wheel building support. [#115](https://github.com/PyO3/setuptools-rust/pull/115)
10+
- Add option to cargo vendor crates into sdist. [#118](https://github.com/PyO3/setuptools-rust/pull/118)
1011

1112
### Changed
1213
- Respect `PYO3_PYTHON` and `PYTHON_SYS_EXECUTABLE` environment variables if set. [#96](https://github.com/PyO3/setuptools-rust/pull/96)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[target.x86_64-apple-darwin]
2+
rustflags = [
3+
"-C", "link-arg=-undefined",
4+
"-C", "link-arg=dynamic_lookup",
5+
]
6+
7+
[target.aarch64-apple-darwin]
8+
rustflags = [
9+
"-C", "link-arg=-undefined",
10+
"-C", "link-arg=dynamic_lookup",
11+
]

setuptools_rust/setuptools_ext.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
from setuptools.command.build_ext import build_ext
77
from setuptools.command.install import install
8+
from distutils.command.sdist import sdist
9+
import sys
10+
import subprocess
811

912
try:
1013
from wheel.bdist_wheel import bdist_wheel
@@ -13,6 +16,81 @@
1316

1417

1518
def add_rust_extension(dist):
19+
sdist_base_class = dist.cmdclass.get("sdist", sdist)
20+
sdist_options = sdist_base_class.user_options.copy()
21+
sdist_boolean_options = sdist_base_class.boolean_options.copy()
22+
sdist_negative_opt = sdist_base_class.negative_opt.copy()
23+
sdist_options.extend([
24+
('vendor-crates', None,
25+
"vendor Rust crates"),
26+
('no-vendor-crates', None,
27+
"don't vendor Rust crates."
28+
"[default; enable with --vendor-crates]"),
29+
])
30+
sdist_boolean_options.append('vendor-crates')
31+
sdist_negative_opt['no-vendor-crates'] = 'vendor-crates'
32+
33+
class sdist_rust_extension(sdist_base_class):
34+
user_options = sdist_options
35+
boolean_options = sdist_boolean_options
36+
negative_opt = sdist_negative_opt
37+
38+
def initialize_options(self):
39+
super().initialize_options()
40+
self.vendor_crates = 0
41+
42+
def get_file_list(self):
43+
super().get_file_list()
44+
if self.vendor_crates:
45+
manifest_paths = []
46+
for ext in self.distribution.rust_extensions:
47+
manifest_paths.append(ext.path)
48+
if manifest_paths:
49+
base_dir = self.distribution.get_fullname()
50+
dot_cargo_path = os.path.join(base_dir, ".cargo")
51+
self.mkpath(dot_cargo_path)
52+
cargo_config_path = os.path.join(dot_cargo_path, "config.toml")
53+
vendor_path = os.path.join(dot_cargo_path, "vendor")
54+
command = [
55+
"cargo", "vendor"
56+
]
57+
# additional Cargo.toml for extension 1..n
58+
for extra_path in manifest_paths[1:]:
59+
command.append("--sync")
60+
command.append(extra_path)
61+
# `cargo vendor --sync` accepts multiple values, for example
62+
# `cargo vendor --sync a --sync b --sync c vendor_path`
63+
# but it would also consider vendor_path as --sync value
64+
# set --manifest-path before vendor_path and after --sync to workaround that
65+
# See https://docs.rs/clap/latest/clap/struct.Arg.html#method.multiple for detail
66+
command.extend(["--manifest-path", manifest_paths[0], vendor_path])
67+
cargo_config = subprocess.check_output(command)
68+
base_dir_bytes = base_dir.encode(sys.getfilesystemencoding()) + os.sep.encode()
69+
if os.sep == '\\':
70+
# TOML escapes backslash \
71+
base_dir_bytes += os.sep.encode()
72+
cargo_config = cargo_config.replace(base_dir_bytes, b'')
73+
if os.altsep:
74+
cargo_config = cargo_config.replace(base_dir_bytes + os.altsep.encode(), b'')
75+
76+
# Check whether `.cargo/config`/`.cargo/config.toml` already exists
77+
existing_cargo_config = None
78+
for filename in (f".cargo{os.sep}config", f".cargo{os.sep}config.toml"):
79+
if filename in self.filelist.allfiles:
80+
existing_cargo_config = filename
81+
break
82+
if existing_cargo_config:
83+
cargo_config_path = os.path.join(base_dir, existing_cargo_config)
84+
# Append vendor config to original cargo config
85+
with open(existing_cargo_config, "rb") as f:
86+
cargo_config = f.read() + b'\n' + cargo_config
87+
88+
with open(cargo_config_path, "wb") as f:
89+
f.write(cargo_config)
90+
self.filelist.append(vendor_path)
91+
self.filelist.append(cargo_config_path)
92+
dist.cmdclass["sdist"] = sdist_rust_extension
93+
1694
build_ext_base_class = dist.cmdclass.get('build_ext', build_ext)
1795

1896
class build_ext_rust_extension(build_ext_base_class):

0 commit comments

Comments
 (0)