10
10
DistutilsPlatformError , DistutilsSetupError )
11
11
12
12
from .extension import RustExtension
13
- from .utils import cpython_feature , get_rust_version
13
+ from .utils import Binding , cpython_feature , get_rust_version
14
14
15
15
16
16
class build_rust (Command ):
@@ -43,6 +43,8 @@ def finalize_options(self):
43
43
if isinstance (ext , RustExtension )]
44
44
45
45
def build_extension (self , ext ):
46
+ executable = ext .binding == Binding .Exec
47
+
46
48
# Make sure that if pythonXX-sys is used, it builds against the current
47
49
# executing python interpreter.
48
50
bindir = os .path .dirname (sys .executable )
@@ -75,20 +77,30 @@ def build_extension(self, ext):
75
77
76
78
# build cargo command
77
79
feature_args = ["--features" , " " .join (features )] if features else []
78
- args = (["cargo" , "rustc" , "--lib" , "--manifest-path" , ext .path ]
79
- + feature_args
80
- + list (ext .args or []))
81
- if not debug_build :
82
- args .append ("--release" )
83
- if quiet :
84
- args .append ("-q" )
85
80
86
- args .extend (["--" , '--crate-type' , 'cdylib' ])
81
+ if executable :
82
+ args = (["cargo" , "build" , "--manifest-path" , ext .path ]
83
+ + feature_args
84
+ + list (ext .args or []))
85
+ if not debug_build :
86
+ args .append ("--release" )
87
+ if quiet :
88
+ args .append ("-q" )
89
+ else :
90
+ args = (["cargo" , "rustc" , "--lib" , "--manifest-path" , ext .path ]
91
+ + feature_args
92
+ + list (ext .args or []))
93
+ if not debug_build :
94
+ args .append ("--release" )
95
+ if quiet :
96
+ args .append ("-q" )
97
+
98
+ args .extend (["--" , '--crate-type' , 'cdylib' ])
87
99
88
- # OSX requires special linker argument
89
- if sys .platform == "darwin" :
90
- args .extend (["-C" , "link-arg=-undefined" ,
91
- "-C" , "link-arg=dynamic_lookup" ])
100
+ # OSX requires special linker argument
101
+ if sys .platform == "darwin" :
102
+ args .extend (["-C" , "link-arg=-undefined" ,
103
+ "-C" , "link-arg=dynamic_lookup" ])
92
104
93
105
if not quiet :
94
106
print (" " .join (args ), file = sys .stderr )
@@ -129,19 +141,37 @@ def build_extension(self, ext):
129
141
target_dir = os .path .join (
130
142
os .path .dirname (ext .path ), "target/" , suffix )
131
143
132
- if sys .platform == "win32" :
133
- wildcard_so = "*.dll"
134
- elif sys .platform == "darwin" :
135
- wildcard_so = "*.dylib"
144
+ if executable :
145
+ # search executable
146
+ dylib_path = None
147
+ for name in os .listdir (target_dir ):
148
+ path = os .path .join (target_dir , name )
149
+ if name .startswith ("." ) or not os .path .isfile (path ):
150
+ continue
151
+
152
+ if os .access (path , os .X_OK ):
153
+ dylib_path = path
154
+ break
155
+
156
+ if dylib_path is None :
157
+ raise DistutilsExecError (
158
+ "rust build failed; unable to find executable in %s" %
159
+ target_dir )
136
160
else :
137
- wildcard_so = "*.so"
161
+ if sys .platform == "win32" :
162
+ wildcard_so = "*.dll"
163
+ elif sys .platform == "darwin" :
164
+ wildcard_so = "*.dylib"
165
+ else :
166
+ wildcard_so = "*.so"
138
167
139
- try :
140
- dylib_path = glob .glob (os .path .join (target_dir , wildcard_so ))[0 ]
141
- except IndexError :
142
- raise DistutilsExecError (
143
- "rust build failed; unable to find any %s in %s" %
144
- (wildcard_so , target_dir ))
168
+ try :
169
+ dylib_path = glob .glob (
170
+ os .path .join (target_dir , wildcard_so ))[0 ]
171
+ except IndexError :
172
+ raise DistutilsExecError (
173
+ "rust build failed; unable to find any %s in %s" %
174
+ (wildcard_so , target_dir ))
145
175
146
176
# Ask build_ext where the shared library would go if it had built it,
147
177
# then copy it there.
@@ -152,13 +182,23 @@ def build_extension(self, ext):
152
182
target_fname = os .path .basename (os .path .splitext (
153
183
os .path .basename (dylib_path )[3 :])[0 ])
154
184
155
- ext_path = build_ext .get_ext_fullpath (target_fname )
185
+ if executable :
186
+ ext_path = build_ext .get_ext_fullpath (target_fname )
187
+ ext_path , _ = os .path .splitext (ext_path )
188
+ else :
189
+ ext_path = build_ext .get_ext_fullpath (target_fname )
190
+
156
191
try :
157
192
os .makedirs (os .path .dirname (ext_path ))
158
193
except OSError :
159
194
pass
160
195
shutil .copyfile (dylib_path , ext_path )
161
196
197
+ if executable :
198
+ mode = os .stat (ext_path ).st_mode
199
+ mode |= (mode & 0o444 ) >> 2 # copy R bits to X
200
+ os .chmod (ext_path , mode )
201
+
162
202
def run (self ):
163
203
if not self .extensions :
164
204
return
@@ -182,10 +222,12 @@ def run(self):
182
222
version , ext .rust_version ))
183
223
184
224
self .build_extension (ext )
185
- except (DistutilsSetupError , DistutilsFileError , DistutilsExecError ,
186
- DistutilsPlatformError , CompileError ) as e :
225
+ except (DistutilsSetupError , DistutilsFileError ,
226
+ DistutilsExecError , DistutilsPlatformError ,
227
+ CompileError ) as e :
187
228
if not ext .optional :
188
229
raise
189
230
else :
190
- print ('Build optional Rust extension %s failed.' % ext .name )
231
+ print ('Build optional Rust extension %s failed.' %
232
+ ext .name )
191
233
print (str (e ))
0 commit comments