0
# Build Commands
1
2
Distutils commands for building and cleaning Rust extensions, providing seamless integration with standard Python packaging workflows. These commands handle the cargo build process and manage build artifacts.
3
4
## Capabilities
5
6
### Rust Extension Building
7
8
Build Rust extensions using cargo, with support for cross-compilation, custom build options, and integration with Python packaging.
9
10
```python { .api }
11
class build_rust(RustCommand):
12
description = "build Rust extensions (compile/link to build directory)"
13
user_options = [
14
(
15
"inplace",
16
"i",
17
"ignore build-lib and put compiled extensions into the source "
18
+ "directory alongside your pure Python modules",
19
),
20
("debug", "d", "Force debug to true for all Rust extensions "),
21
("release", "r", "Force debug to false for all Rust extensions "),
22
("qbuild", None, "Force enable quiet option for all Rust extensions "),
23
(
24
"build-temp",
25
"t",
26
"directory for temporary files (cargo 'target' directory) ",
27
),
28
("target=", None, "Build for the target triple"),
29
]
30
boolean_options = ["inplace", "debug", "release", "qbuild"]
31
32
def initialize_options(self) -> None:
33
"""Initialize all command options to default values."""
34
35
def finalize_options(self) -> None:
36
"""Finalize and validate command options."""
37
38
def run_for_extension(self, ext: RustExtension) -> None:
39
"""
40
Build a single Rust extension.
41
42
Parameters:
43
- ext: RustExtension instance to build
44
"""
45
46
def build_extension(
47
self,
48
ext: RustExtension,
49
forced_target_triple: Optional[str] = None
50
) -> List[_BuiltModule]:
51
"""
52
Build a Rust extension using cargo.
53
54
Parameters:
55
- ext: RustExtension to build
56
- forced_target_triple: Override target triple for cross-compilation
57
58
Returns:
59
List[_BuiltModule]: List of built module information
60
"""
61
62
def install_extension(
63
self,
64
ext: RustExtension,
65
dylib_paths: List[_BuiltModule]
66
) -> None:
67
"""
68
Install built extension to the appropriate location.
69
70
Parameters:
71
- ext: RustExtension that was built
72
- dylib_paths: List of built modules to install
73
"""
74
75
def get_dylib_ext_path(
76
self,
77
ext: RustExtension,
78
target_fname: str
79
) -> str:
80
"""
81
Get the installation path for a built extension.
82
83
Parameters:
84
- ext: RustExtension being installed
85
- target_fname: Target filename
86
87
Returns:
88
str: Full path where extension should be installed
89
"""
90
91
def install_extension(
92
self,
93
ext: RustExtension,
94
dylib_paths: List[_BuiltModule]
95
) -> None:
96
"""
97
Install built extension to the appropriate location.
98
99
Parameters:
100
- ext: RustExtension that was built
101
- dylib_paths: List of built modules to install
102
"""
103
```
104
105
### Rust Extension Cleaning
106
107
Clean build artifacts and temporary files created during Rust extension building.
108
109
```python { .api }
110
class clean_rust(RustCommand):
111
description = "clean Rust extensions (compile/link to build directory)"
112
113
def initialize_options(self) -> None:
114
"""Initialize all command options to default values."""
115
116
def run_for_extension(self, ext: RustExtension) -> None:
117
"""
118
Clean build artifacts for a single Rust extension.
119
120
Parameters:
121
- ext: RustExtension to clean
122
"""
123
```
124
125
### Base Command Class
126
127
Abstract base class providing common functionality for Rust extension commands.
128
129
```python { .api }
130
class RustCommand(Command, ABC):
131
"""Abstract base class for Rust extension commands."""
132
133
def initialize_options(self) -> None:
134
"""Initialize all command options to default values."""
135
136
def finalize_options(self) -> None:
137
"""Finalize and validate command options."""
138
139
def run(self) -> None:
140
"""Run the command for all Rust extensions."""
141
142
@abstractmethod
143
def run_for_extension(self, extension: RustExtension) -> None:
144
"""
145
Run command for a single extension (must be implemented by subclasses).
146
147
Parameters:
148
- extension: RustExtension to process
149
"""
150
```
151
152
## Usage Examples
153
154
### Command Line Usage
155
156
```bash
157
# Build all Rust extensions
158
python setup.py build_rust
159
160
# Build with debug information
161
python setup.py build_rust --debug
162
163
# Build in release mode
164
python setup.py build_rust --release
165
166
# Build in-place (for development)
167
python setup.py build_rust --inplace
168
169
# Quiet build (suppress cargo output)
170
python setup.py build_rust --qbuild
171
172
# Custom cargo arguments
173
python setup.py build_rust --cargo-args="--features=extra"
174
175
# Clean build artifacts
176
python setup.py clean_rust
177
```
178
179
### Integration with Other Commands
180
181
```bash
182
# Build everything including Rust extensions
183
python setup.py build
184
185
# Install including Rust extensions
186
python setup.py install
187
188
# Create wheel with Rust extensions
189
python setup.py bdist_wheel
190
191
# Development installation with in-place Rust builds
192
pip install -e .
193
```
194
195
### Programmatic Usage
196
197
```python
198
from setuptools import setup, Distribution
199
from setuptools_rust import build_rust, RustExtension
200
201
# Create a distribution with Rust extensions
202
dist = Distribution({
203
'name': 'my-package',
204
'rust_extensions': [
205
RustExtension('my_package.rust_module', 'Cargo.toml')
206
]
207
})
208
209
# Build the Rust extensions
210
build_cmd = build_rust(dist)
211
build_cmd.initialize_options()
212
build_cmd.finalize_options()
213
build_cmd.run()
214
```
215
216
### Custom Build Configuration
217
218
```python
219
class CustomBuildRust(build_rust):
220
"""Custom build command with additional options."""
221
222
user_options = build_rust.user_options + [
223
("custom-flag", None, "enable custom build flag"),
224
]
225
226
def initialize_options(self):
227
super().initialize_options()
228
self.custom_flag = None
229
230
def run_for_extension(self, ext):
231
if self.custom_flag:
232
# Add custom build logic
233
ext.args = list(ext.args) + ["--features", "custom"]
234
super().run_for_extension(ext)
235
```
236
237
## Command Integration
238
239
The build commands integrate automatically with setuptools through entry points defined in pyproject.toml:
240
241
```toml
242
[project.entry-points."distutils.commands"]
243
build_rust = "setuptools_rust:build_rust"
244
clean_rust = "setuptools_rust:clean_rust"
245
```
246
247
This allows the commands to be discovered and used by setuptools automatically when setuptools-rust is installed.
248
249
## Build Process Flow
250
251
1. **Initialization**: Command options are initialized and validated
252
2. **Extension Discovery**: All RustExtension instances are collected from the distribution
253
3. **Cargo Execution**: For each extension, cargo is invoked with appropriate arguments
254
4. **Artifact Management**: Built libraries are moved to correct locations
255
5. **Integration**: Extensions are integrated with Python's import system
256
257
## Environment Integration
258
259
The commands respect standard environment variables and setuptools configuration:
260
261
- **CARGO**: Path to cargo executable
262
- **CARGO_BUILD_TARGET**: Default target triple
263
- **RUSTFLAGS**: Additional rustc flags
264
- **SETUPTOOLS_RUST_CARGO_PROFILE**: Override cargo profile
265
266
## Type Definitions
267
268
```python { .api }
269
from typing import List, Optional
270
from abc import ABC, abstractmethod
271
from distutils.cmd import Command
272
273
class _BuiltModule:
274
"""Internal type representing information about a built module."""
275
```