1
- from __future__ import print_function
1
+ from __future__ import print_function , absolute_import
2
2
import glob
3
3
import os
4
4
import shutil
5
5
import sys
6
6
import subprocess
7
7
from distutils .cmd import Command
8
- from distutils .dist import Distribution
9
- from distutils .command .build import build as Build
10
8
from distutils .errors import (
9
+ CompileError ,
11
10
DistutilsExecError , DistutilsFileError , DistutilsPlatformError )
12
- from setuptools .command import develop
13
11
14
12
import semver
15
13
16
- __all__ = ('RustExtension' , 'build_rust' )
17
-
18
-
19
- # allow to use 'rust_extensions' parameter for setup() call
20
- Distribution .rust_extensions = ()
21
-
22
-
23
- def has_ext_modules (self ):
24
- return (self .ext_modules and len (self .ext_modules ) > 0 or
25
- self .rust_extensions and len (self .rust_extensions ) > 0 )
26
-
27
-
28
- Distribution .has_ext_modules = has_ext_modules
29
-
30
-
31
- # add support for build_rust sub-command
32
- def has_rust_extensions (self ):
33
- exts = [ext for ext in self .distribution .rust_extensions
34
- if isinstance (ext , RustExtension )]
35
- return bool (exts )
36
-
37
-
38
- Build .has_rust_extensions = has_rust_extensions
39
- Build .sub_commands .append (('build_rust' , Build .has_rust_extensions ))
14
+ from . import patch # noqa
40
15
41
- # monkey patch "develop" command
42
- orig_run_command = develop .develop .run_command
43
-
44
-
45
- def monkey_run_command (self , cmd ):
46
- orig_run_command (self , cmd )
47
-
48
- if cmd == 'build_ext' :
49
- self .reinitialize_command ('build_rust' , inplace = 1 )
50
- orig_run_command (self , 'build_rust' )
51
-
52
-
53
- develop .develop .run_command = monkey_run_command
16
+ __all__ = ('RustExtension' , 'build_rust' )
54
17
55
18
56
19
class RustExtension :
@@ -63,9 +26,11 @@ class RustExtension:
63
26
*not* a filename or pathname, but Python dotted name
64
27
path : string
65
28
path to the cargo.toml manifest
66
- args : [stirng ]
29
+ args : [string ]
67
30
a list of extra argumenents to be passed to cargo.
68
- version : string
31
+ features : [string]
32
+ a list of features to also build
33
+ rust_version : string
69
34
rust compiler version
70
35
quiet : bool
71
36
If True, doesn't echo cargo's output.
@@ -74,16 +39,22 @@ class RustExtension:
74
39
"""
75
40
76
41
def __init__ (self , name , path ,
77
- args = None , version = None , quiet = False , debug = False ):
42
+ args = None , features = None , rust_version = None ,
43
+ quiet = False , debug = False ):
78
44
self .name = name
79
45
self .path = path
80
46
self .args = args
81
- self .version = version
47
+ self .rust_version = rust_version
82
48
self .quiet = quiet
83
49
self .debug = debug
84
50
51
+ if features is None :
52
+ features = []
53
+
54
+ self .features = [s .strip () for s in features ]
55
+
85
56
@staticmethod
86
- def get_version ():
57
+ def get_rust_version ():
87
58
env = os .environ .copy ()
88
59
try :
89
60
output = subprocess .check_output (["rustc" , "-V" ], env = env )
@@ -117,12 +88,12 @@ def finalize_options(self):
117
88
self .extensions = [ext for ext in self .distribution .rust_extensions
118
89
if isinstance (ext , RustExtension )]
119
90
120
- def features (self ):
91
+ def _cpython_feature (self ):
121
92
version = sys .version_info
122
93
if (2 , 7 ) < version < (2 , 8 ):
123
- return "python27-sys"
94
+ return "cpython/ python27-sys"
124
95
elif (3 , 3 ) < version :
125
- return "python3-sys"
96
+ return "cpython/ python3-sys"
126
97
else :
127
98
raise DistutilsPlatformError (
128
99
"Unsupported python version: %s" % sys .version )
@@ -145,17 +116,20 @@ def build_extension(self, ext):
145
116
raise DistutilsFileError (
146
117
"Can not file rust extension project file: %s" % ext .path )
147
118
119
+ features = set (ext .features )
120
+ features .add (self ._cpython_feature ())
121
+
148
122
# Execute cargo.
149
123
try :
150
124
args = (["cargo" , "build" , "--manifest-path" , ext .path ,
151
- "--features" , self . features ( )] + list (ext .args or []))
125
+ "--features" , " " . join ( features )] + list (ext .args or []))
152
126
if not ext .debug :
153
127
args .append ("--release" )
154
128
if not ext .quiet :
155
129
print (" " .join (args ), file = sys .stderr )
156
130
output = subprocess .check_output (args , env = env )
157
131
except subprocess .CalledProcessError as e :
158
- raise DistutilsExecError (
132
+ raise CompileError (
159
133
"cargo failed with code: %d\n %s" % (e .returncode , e .output ))
160
134
except OSError :
161
135
raise DistutilsExecError (
@@ -205,15 +179,15 @@ def build_extension(self, ext):
205
179
shutil .copyfile (dylib_path , ext_path )
206
180
207
181
def run (self ):
208
- version = RustExtension .get_version ()
182
+ version = RustExtension .get_rust_version ()
209
183
if self .extensions and version is None :
210
184
raise DistutilsPlatformError ('Can not find Rust compiler' )
211
185
212
186
for ext in self .extensions :
213
- if ext .version is not None :
214
- if not semver .match (version , ext .version ):
187
+ if ext .rust_version is not None :
188
+ if not semver .match (version , ext .rust_version ):
215
189
raise DistutilsPlatformError (
216
190
"Rust %s does not match extension requirenment %s" % (
217
- version , ext .version ))
191
+ version , ext .rust_version ))
218
192
219
193
self .build_extension (ext )
0 commit comments