1010 DistutilsPlatformError , DistutilsSetupError )
1111
1212from .extension import RustExtension
13- from .utils import cpython_feature , get_rust_version
13+ from .utils import Binding , cpython_feature , get_rust_version
1414
1515
1616class build_rust (Command ):
@@ -43,6 +43,8 @@ def finalize_options(self):
4343 if isinstance (ext , RustExtension )]
4444
4545 def build_extension (self , ext ):
46+ executable = ext .binding == Binding .Exec
47+
4648 # Make sure that if pythonXX-sys is used, it builds against the current
4749 # executing python interpreter.
4850 bindir = os .path .dirname (sys .executable )
@@ -75,20 +77,30 @@ def build_extension(self, ext):
7577
7678 # build cargo command
7779 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" )
8580
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' ])
8799
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" ])
92104
93105 if not quiet :
94106 print (" " .join (args ), file = sys .stderr )
@@ -129,19 +141,37 @@ def build_extension(self, ext):
129141 target_dir = os .path .join (
130142 os .path .dirname (ext .path ), "target/" , suffix )
131143
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 )
136160 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"
138167
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 ))
145175
146176 # Ask build_ext where the shared library would go if it had built it,
147177 # then copy it there.
@@ -152,13 +182,23 @@ def build_extension(self, ext):
152182 target_fname = os .path .basename (os .path .splitext (
153183 os .path .basename (dylib_path )[3 :])[0 ])
154184
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+
156191 try :
157192 os .makedirs (os .path .dirname (ext_path ))
158193 except OSError :
159194 pass
160195 shutil .copyfile (dylib_path , ext_path )
161196
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+
162202 def run (self ):
163203 if not self .extensions :
164204 return
@@ -182,10 +222,12 @@ def run(self):
182222 version , ext .rust_version ))
183223
184224 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 :
187228 if not ext .optional :
188229 raise
189230 else :
190- print ('Build optional Rust extension %s failed.' % ext .name )
231+ print ('Build optional Rust extension %s failed.' %
232+ ext .name )
191233 print (str (e ))
0 commit comments