14
14
import subprocess
15
15
import sys
16
16
import sysconfig
17
- from distutils import log , spawn
17
+ from distutils import spawn
18
18
from distutils .command import build_ext , install_data , install_lib
19
19
20
20
from setuptools import Extension , setup
81
81
82
82
83
83
###############################################################################
84
- def _find_msbuild_tool (tool = "msbuild.exe" , use_windows_sdk = False ):
85
- """Return full path to one of the Microsoft build tools"""
86
- # Search in PATH first
87
- path = spawn .find_executable (tool )
88
- if path :
89
- return path
90
-
91
- # Search within registry to find build tools
92
- try : # PY2
93
- import _winreg as winreg
94
- except ImportError : # PY3
95
- import winreg
96
-
97
- keys_to_check = WIN_SDK_KEYS if use_windows_sdk else VS_KEYS
98
- for rkey in keys_to_check :
99
- try :
100
- with winreg .OpenKey (winreg .HKEY_LOCAL_MACHINE , rkey .key ) as hkey :
101
- val , type_ = winreg .QueryValueEx (hkey , rkey .value_name )
102
- if type_ != winreg .REG_SZ :
103
- continue
104
- path = os .path .join (val , rkey .suffix , tool )
105
- if os .path .exists (path ):
106
- log .info ("Using {0} from {1}" .format (tool , rkey .sdk_name ))
107
- return path
108
- except WindowsError :
109
- # Key doesn't exist
110
- pass
111
-
112
- # Add Visual C++ for Python as a fall-back in case one
113
- # of the other Windows SDKs isn't installed
114
- if use_windows_sdk :
115
- sdk_name = "Visual C++ for Python"
116
- localappdata = os .environ ["LOCALAPPDATA" ]
117
- suffix = "Bin\\ x64" if ARCH == "x64" else "Bin"
118
- path = os .path .join (localappdata , vs_python , suffix , tool )
119
- if os .path .exists (path ):
120
- log .info ("Using {0} from {1}" .format (tool , sdk_name ))
121
- return path
84
+ def _check_output (* args , ** kwargs ):
85
+ """Check output wrapper for py2/py3 compatibility"""
86
+ output = subprocess .check_output (* args , ** kwargs )
87
+ if PY_MAJOR == 2 :
88
+ return output
89
+ return output .decode ("ascii" )
122
90
123
- raise RuntimeError ("{0} could not be found" .format (tool ))
91
+
92
+ def _get_interop_filename ():
93
+ """interopXX.cs is auto-generated as part of the build.
94
+ For common windows platforms pre-generated files are included
95
+ as most windows users won't have Clang installed, which is
96
+ required to generate the file.
97
+ """
98
+ interop_filename = "interop{0}{1}{2}.cs" .format (
99
+ PY_MAJOR , PY_MINOR , getattr (sys , "abiflags" , "" ))
100
+ return os .path .join ("src" , "runtime" , interop_filename )
124
101
125
102
126
103
class BuildExtPythonnet (build_ext .build_ext ):
@@ -139,6 +116,7 @@ def build_extension(self, ext):
139
116
140
117
# Up to Python 3.2 sys.maxunicode is used to determine the size of
141
118
# Py_UNICODE, but from 3.3 onwards Py_UNICODE is a typedef of wchar_t.
119
+ # TODO: Is this doing the right check for Py27?
142
120
if sys .version_info [:2 ] <= (3 , 2 ):
143
121
unicode_width = 2 if sys .maxunicode < 0x10FFFF else 4
144
122
else :
@@ -186,7 +164,7 @@ def build_extension(self, ext):
186
164
subprocess .check_call ([sys .executable , geninterop , interop_file ])
187
165
188
166
if DEVTOOLS == "MsDev" :
189
- _xbuild = '"{0}"' .format (_find_msbuild_tool ("msbuild.exe" ))
167
+ _xbuild = '"{0}"' .format (self . _find_msbuild_tool ("msbuild.exe" ))
190
168
_config = "{0}Win" .format (CONFIG )
191
169
192
170
elif DEVTOOLS == "Mono" :
@@ -220,14 +198,15 @@ def build_extension(self, ext):
220
198
self ._build_monoclr ()
221
199
222
200
def _get_manifest (self , build_dir ):
223
- if DEVTOOLS == "MsDev" and sys .version_info [:2 ] > (2 , 5 ):
224
- mt = _find_msbuild_tool ("mt.exe" , use_windows_sdk = True )
225
- manifest = os .path .abspath (os .path .join (build_dir , "app.manifest" ))
226
- cmd = [mt , '-inputresource:"{0}"' .format (sys .executable ),
227
- '-out:"{0}"' .format (manifest )]
228
- self .announce ("Extracting manifest from {}" .format (sys .executable ))
229
- subprocess .check_call (" " .join (cmd ), shell = False )
230
- return manifest
201
+ if DEVTOOLS != "MsDev" :
202
+ return
203
+ mt = self ._find_msbuild_tool ("mt.exe" , use_windows_sdk = True )
204
+ manifest = os .path .abspath (os .path .join (build_dir , "app.manifest" ))
205
+ cmd = [mt , '-inputresource:"{0}"' .format (sys .executable ),
206
+ '-out:"{0}"' .format (manifest )]
207
+ self .announce ("Extracting manifest from {}" .format (sys .executable ))
208
+ subprocess .check_call (" " .join (cmd ), shell = False )
209
+ return manifest
231
210
232
211
def _build_monoclr (self ):
233
212
mono_libs = _check_output ("pkg-config --libs mono-2" , shell = True )
@@ -266,6 +245,50 @@ def _install_packages(self):
266
245
self .announce ("Installing packages: {0}" .format (cmd ))
267
246
subprocess .check_call (cmd , shell = use_shell )
268
247
248
+ def _find_msbuild_tool (self , tool = "msbuild.exe" , use_windows_sdk = False ):
249
+ """Return full path to one of the Microsoft build tools"""
250
+ # Search in PATH first
251
+ path = spawn .find_executable (tool )
252
+ if path :
253
+ return path
254
+
255
+ # Search within registry to find build tools
256
+ try : # PY2
257
+ import _winreg as winreg
258
+ except ImportError : # PY3
259
+ import winreg
260
+
261
+ keys_to_check = WIN_SDK_KEYS if use_windows_sdk else VS_KEYS
262
+ hklm = winreg .HKEY_LOCAL_MACHINE
263
+ for rkey in keys_to_check :
264
+ try :
265
+ with winreg .OpenKey (hklm , rkey .key ) as hkey :
266
+ val , type_ = winreg .QueryValueEx (hkey , rkey .value_name )
267
+ if type_ != winreg .REG_SZ :
268
+ continue
269
+ path = os .path .join (val , rkey .suffix , tool )
270
+ if os .path .exists (path ):
271
+ self .announce ("Using {0} from {1}" .format (
272
+ tool , rkey .sdk_name ))
273
+ return path
274
+ except WindowsError :
275
+ # Key doesn't exist
276
+ pass
277
+
278
+ # Add Visual C++ for Python as a fall-back in case one
279
+ # of the other Windows SDKs isn't installed.
280
+ # TODO: Extend checking by using setuptools/msvc.py?
281
+ if use_windows_sdk :
282
+ sdk_name = "Visual C++ for Python"
283
+ localappdata = os .environ ["LOCALAPPDATA" ]
284
+ suffix = "Bin\\ x64" if ARCH == "x64" else "Bin"
285
+ path = os .path .join (localappdata , vs_python , suffix , tool )
286
+ if os .path .exists (path ):
287
+ self .announce ("Using {0} from {1}" .format (tool , sdk_name ))
288
+ return path
289
+
290
+ raise RuntimeError ("{0} could not be found" .format (tool ))
291
+
269
292
270
293
class InstallLibPythonnet (install_lib .install_lib ):
271
294
def install (self ):
@@ -304,25 +327,7 @@ def run(self):
304
327
return install_data .install_data .run (self )
305
328
306
329
307
- def _check_output (* args , ** kwargs ):
308
- """Check output wrapper for py2/py3 compatibility"""
309
- output = subprocess .check_output (* args , ** kwargs )
310
- if PY_MAJOR == 2 :
311
- return output
312
- return output .decode ("ascii" )
313
-
314
-
315
- def _get_interop_filename ():
316
- """interopXX.cs is auto-generated as part of the build.
317
- For common windows platforms pre-generated files are included
318
- as most windows users won't have Clang installed, which is
319
- required to generate the file.
320
- """
321
- interop_filename = "interop{0}{1}{2}.cs" .format (
322
- PY_MAJOR , PY_MINOR , getattr (sys , "abiflags" , "" ))
323
- return os .path .join ("src" , "runtime" , interop_filename )
324
-
325
-
330
+ ###############################################################################
326
331
if __name__ == "__main__" :
327
332
setupdir = os .path .dirname (__file__ )
328
333
if setupdir :
0 commit comments