ยปCore Development>Code coverage>Lib/packaging/compiler/msvccompiler.py

Python code coverage for Lib/packaging/compiler/msvccompiler.py

#countcontent
1n/a"""CCompiler implementation for old Microsoft Visual Studio compilers.
2n/a
3n/aFor a compiler compatible with VS 2005 and 2008, use msvc9compiler.
4n/a"""
5n/a
6n/a# Written by Perry Stoll
7n/a# hacked by Robin Becker and Thomas Heller to do a better job of
8n/a# finding DevStudio (through the registry)
9n/a
10n/a
11n/aimport sys
12n/aimport os
13n/a
14n/afrom packaging.errors import (PackagingExecError, PackagingPlatformError,
15n/a CompileError, LibError, LinkError)
16n/afrom packaging.compiler.ccompiler import CCompiler
17n/afrom packaging.compiler import gen_lib_options
18n/afrom packaging import logger
19n/a
20n/a_can_read_reg = False
21n/atry:
22n/a import winreg
23n/a
24n/a _can_read_reg = True
25n/a hkey_mod = winreg
26n/a
27n/a RegOpenKeyEx = winreg.OpenKeyEx
28n/a RegEnumKey = winreg.EnumKey
29n/a RegEnumValue = winreg.EnumValue
30n/a RegError = winreg.error
31n/a
32n/aexcept ImportError:
33n/a try:
34n/a import win32api
35n/a import win32con
36n/a _can_read_reg = True
37n/a hkey_mod = win32con
38n/a
39n/a RegOpenKeyEx = win32api.RegOpenKeyEx
40n/a RegEnumKey = win32api.RegEnumKey
41n/a RegEnumValue = win32api.RegEnumValue
42n/a RegError = win32api.error
43n/a
44n/a except ImportError:
45n/a logger.warning(
46n/a "can't read registry to find the necessary compiler setting;\n"
47n/a "make sure that Python modules _winreg, win32api or win32con "
48n/a "are installed.")
49n/a
50n/aif _can_read_reg:
51n/a HKEYS = (hkey_mod.HKEY_USERS,
52n/a hkey_mod.HKEY_CURRENT_USER,
53n/a hkey_mod.HKEY_LOCAL_MACHINE,
54n/a hkey_mod.HKEY_CLASSES_ROOT)
55n/a
56n/a
57n/adef read_keys(base, key):
58n/a """Return list of registry keys."""
59n/a
60n/a try:
61n/a handle = RegOpenKeyEx(base, key)
62n/a except RegError:
63n/a return None
64n/a L = []
65n/a i = 0
66n/a while True:
67n/a try:
68n/a k = RegEnumKey(handle, i)
69n/a except RegError:
70n/a break
71n/a L.append(k)
72n/a i = i + 1
73n/a return L
74n/a
75n/a
76n/adef read_values(base, key):
77n/a """Return dict of registry keys and values.
78n/a
79n/a All names are converted to lowercase.
80n/a """
81n/a try:
82n/a handle = RegOpenKeyEx(base, key)
83n/a except RegError:
84n/a return None
85n/a d = {}
86n/a i = 0
87n/a while True:
88n/a try:
89n/a name, value, type = RegEnumValue(handle, i)
90n/a except RegError:
91n/a break
92n/a name = name.lower()
93n/a d[convert_mbcs(name)] = convert_mbcs(value)
94n/a i = i + 1
95n/a return d
96n/a
97n/a
98n/adef convert_mbcs(s):
99n/a enc = getattr(s, "encode", None)
100n/a if enc is not None:
101n/a try:
102n/a s = enc("mbcs")
103n/a except UnicodeError:
104n/a pass
105n/a return s
106n/a
107n/a
108n/aclass MacroExpander:
109n/a
110n/a def __init__(self, version):
111n/a self.macros = {}
112n/a self.load_macros(version)
113n/a
114n/a def set_macro(self, macro, path, key):
115n/a for base in HKEYS:
116n/a d = read_values(base, path)
117n/a if d:
118n/a self.macros["$(%s)" % macro] = d[key]
119n/a break
120n/a
121n/a def load_macros(self, version):
122n/a vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
123n/a self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
124n/a self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
125n/a net = r"Software\Microsoft\.NETFramework"
126n/a self.set_macro("FrameworkDir", net, "installroot")
127n/a try:
128n/a if version > 7.0:
129n/a self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
130n/a else:
131n/a self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
132n/a except KeyError:
133n/a raise PackagingPlatformError(
134n/a"""Python was built with Visual Studio 2003; extensions must be built with
135n/aa compiler than can generate compatible binaries. Visual Studio 2003 was
136n/anot found on this system. If you have Cygwin installed, you can try
137n/acompiling with MingW32, by passing "-c mingw32" to pysetup.""")
138n/a
139n/a p = r"Software\Microsoft\NET Framework Setup\Product"
140n/a for base in HKEYS:
141n/a try:
142n/a h = RegOpenKeyEx(base, p)
143n/a except RegError:
144n/a continue
145n/a key = RegEnumKey(h, 0)
146n/a d = read_values(base, r"%s\%s" % (p, key))
147n/a self.macros["$(FrameworkVersion)"] = d["version"]
148n/a
149n/a def sub(self, s):
150n/a for k, v in self.macros.items():
151n/a s = s.replace(k, v)
152n/a return s
153n/a
154n/a
155n/adef get_build_version():
156n/a """Return the version of MSVC that was used to build Python.
157n/a
158n/a For Python 2.3 and up, the version number is included in
159n/a sys.version. For earlier versions, assume the compiler is MSVC 6.
160n/a """
161n/a
162n/a prefix = "MSC v."
163n/a i = sys.version.find(prefix)
164n/a if i == -1:
165n/a return 6
166n/a i = i + len(prefix)
167n/a s, rest = sys.version[i:].split(" ", 1)
168n/a majorVersion = int(s[:-2]) - 6
169n/a minorVersion = int(s[2:3]) / 10.0
170n/a # I don't think paths are affected by minor version in version 6
171n/a if majorVersion == 6:
172n/a minorVersion = 0
173n/a if majorVersion >= 6:
174n/a return majorVersion + minorVersion
175n/a # else we don't know what version of the compiler this is
176n/a return None
177n/a
178n/a
179n/adef get_build_architecture():
180n/a """Return the processor architecture.
181n/a
182n/a Possible results are "Intel", "Itanium", or "AMD64".
183n/a """
184n/a
185n/a prefix = " bit ("
186n/a i = sys.version.find(prefix)
187n/a if i == -1:
188n/a return "Intel"
189n/a j = sys.version.find(")", i)
190n/a return sys.version[i+len(prefix):j]
191n/a
192n/a
193n/adef normalize_and_reduce_paths(paths):
194n/a """Return a list of normalized paths with duplicates removed.
195n/a
196n/a The current order of paths is maintained.
197n/a """
198n/a # Paths are normalized so things like: /a and /a/ aren't both preserved.
199n/a reduced_paths = []
200n/a for p in paths:
201n/a np = os.path.normpath(p)
202n/a # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
203n/a if np not in reduced_paths:
204n/a reduced_paths.append(np)
205n/a return reduced_paths
206n/a
207n/a
208n/aclass MSVCCompiler(CCompiler):
209n/a """Concrete class that implements an interface to Microsoft Visual C++,
210n/a as defined by the CCompiler abstract class."""
211n/a
212n/a name = 'msvc'
213n/a description = "Microsoft Visual C++"
214n/a
215n/a # Just set this so CCompiler's constructor doesn't barf. We currently
216n/a # don't use the 'set_executables()' bureaucracy provided by CCompiler,
217n/a # as it really isn't necessary for this sort of single-compiler class.
218n/a # Would be nice to have a consistent interface with UnixCCompiler,
219n/a # though, so it's worth thinking about.
220n/a executables = {}
221n/a
222n/a # Private class data (need to distinguish C from C++ source for compiler)
223n/a _c_extensions = ['.c']
224n/a _cpp_extensions = ['.cc', '.cpp', '.cxx']
225n/a _rc_extensions = ['.rc']
226n/a _mc_extensions = ['.mc']
227n/a
228n/a # Needed for the filename generation methods provided by the
229n/a # base class, CCompiler.
230n/a src_extensions = (_c_extensions + _cpp_extensions +
231n/a _rc_extensions + _mc_extensions)
232n/a res_extension = '.res'
233n/a obj_extension = '.obj'
234n/a static_lib_extension = '.lib'
235n/a shared_lib_extension = '.dll'
236n/a static_lib_format = shared_lib_format = '%s%s'
237n/a exe_extension = '.exe'
238n/a
239n/a def __init__(self, dry_run=False, force=False):
240n/a super(MSVCCompiler, self).__init__(dry_run, force)
241n/a self.__version = get_build_version()
242n/a self.__arch = get_build_architecture()
243n/a if self.__arch == "Intel":
244n/a # x86
245n/a if self.__version >= 7:
246n/a self.__root = r"Software\Microsoft\VisualStudio"
247n/a self.__macros = MacroExpander(self.__version)
248n/a else:
249n/a self.__root = r"Software\Microsoft\Devstudio"
250n/a self.__product = "Visual Studio version %s" % self.__version
251n/a else:
252n/a # Win64. Assume this was built with the platform SDK
253n/a self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
254n/a
255n/a self.initialized = False
256n/a
257n/a def initialize(self):
258n/a self.__paths = []
259n/a if ("DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and
260n/a self.find_exe("cl.exe")):
261n/a # Assume that the SDK set up everything alright; don't try to be
262n/a # smarter
263n/a self.cc = "cl.exe"
264n/a self.linker = "link.exe"
265n/a self.lib = "lib.exe"
266n/a self.rc = "rc.exe"
267n/a self.mc = "mc.exe"
268n/a else:
269n/a self.__paths = self.get_msvc_paths("path")
270n/a
271n/a if len(self.__paths) == 0:
272n/a raise PackagingPlatformError("Python was built with %s "
273n/a "and extensions need to be built with the same "
274n/a "version of the compiler, but it isn't installed." %
275n/a self.__product)
276n/a
277n/a self.cc = self.find_exe("cl.exe")
278n/a self.linker = self.find_exe("link.exe")
279n/a self.lib = self.find_exe("lib.exe")
280n/a self.rc = self.find_exe("rc.exe") # resource compiler
281n/a self.mc = self.find_exe("mc.exe") # message compiler
282n/a self.set_path_env_var('lib')
283n/a self.set_path_env_var('include')
284n/a
285n/a # extend the MSVC path with the current path
286n/a try:
287n/a for p in os.environ['path'].split(';'):
288n/a self.__paths.append(p)
289n/a except KeyError:
290n/a pass
291n/a self.__paths = normalize_and_reduce_paths(self.__paths)
292n/a os.environ['path'] = ';'.join(self.__paths)
293n/a
294n/a self.preprocess_options = None
295n/a if self.__arch == "Intel":
296n/a self.compile_options = ['/nologo', '/Ox', '/MD', '/W3', '/GX',
297n/a '/DNDEBUG']
298n/a self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
299n/a '/Z7', '/D_DEBUG']
300n/a else:
301n/a # Win64
302n/a self.compile_options = ['/nologo', '/Ox', '/MD', '/W3', '/GS-',
303n/a '/DNDEBUG']
304n/a self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
305n/a '/Z7', '/D_DEBUG']
306n/a
307n/a self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
308n/a if self.__version >= 7:
309n/a self.ldflags_shared_debug = [
310n/a '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
311n/a ]
312n/a else:
313n/a self.ldflags_shared_debug = [
314n/a '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
315n/a ]
316n/a self.ldflags_static = [ '/nologo']
317n/a
318n/a self.initialized = True
319n/a
320n/a # -- Worker methods ------------------------------------------------
321n/a
322n/a def object_filenames(self, source_filenames, strip_dir=False, output_dir=''):
323n/a # Copied from ccompiler.py, extended to return .res as 'object'-file
324n/a # for .rc input file
325n/a if output_dir is None:
326n/a output_dir = ''
327n/a obj_names = []
328n/a for src_name in source_filenames:
329n/a base, ext = os.path.splitext(src_name)
330n/a base = os.path.splitdrive(base)[1] # Chop off the drive
331n/a base = base[os.path.isabs(base):] # If abs, chop off leading /
332n/a if ext not in self.src_extensions:
333n/a # Better to raise an exception instead of silently continuing
334n/a # and later complain about sources and targets having
335n/a # different lengths
336n/a raise CompileError("Don't know how to compile %s" % src_name)
337n/a if strip_dir:
338n/a base = os.path.basename(base)
339n/a if ext in self._rc_extensions:
340n/a obj_names.append(os.path.join(output_dir,
341n/a base + self.res_extension))
342n/a elif ext in self._mc_extensions:
343n/a obj_names.append(os.path.join(output_dir,
344n/a base + self.res_extension))
345n/a else:
346n/a obj_names.append(os.path.join(output_dir,
347n/a base + self.obj_extension))
348n/a return obj_names
349n/a
350n/a def compile(self, sources,
351n/a output_dir=None, macros=None, include_dirs=None, debug=False,
352n/a extra_preargs=None, extra_postargs=None, depends=None):
353n/a
354n/a if not self.initialized:
355n/a self.initialize()
356n/a macros, objects, extra_postargs, pp_opts, build = \
357n/a self._setup_compile(output_dir, macros, include_dirs, sources,
358n/a depends, extra_postargs)
359n/a
360n/a compile_opts = extra_preargs or []
361n/a compile_opts.append('/c')
362n/a if debug:
363n/a compile_opts.extend(self.compile_options_debug)
364n/a else:
365n/a compile_opts.extend(self.compile_options)
366n/a
367n/a for obj in objects:
368n/a try:
369n/a src, ext = build[obj]
370n/a except KeyError:
371n/a continue
372n/a if debug:
373n/a # pass the full pathname to MSVC in debug mode,
374n/a # this allows the debugger to find the source file
375n/a # without asking the user to browse for it
376n/a src = os.path.abspath(src)
377n/a
378n/a if ext in self._c_extensions:
379n/a input_opt = "/Tc" + src
380n/a elif ext in self._cpp_extensions:
381n/a input_opt = "/Tp" + src
382n/a elif ext in self._rc_extensions:
383n/a # compile .RC to .RES file
384n/a input_opt = src
385n/a output_opt = "/fo" + obj
386n/a try:
387n/a self.spawn([self.rc] + pp_opts +
388n/a [output_opt] + [input_opt])
389n/a except PackagingExecError as msg:
390n/a raise CompileError(msg)
391n/a continue
392n/a elif ext in self._mc_extensions:
393n/a
394n/a # Compile .MC to .RC file to .RES file.
395n/a # * '-h dir' specifies the directory for the
396n/a # generated include file
397n/a # * '-r dir' specifies the target directory of the
398n/a # generated RC file and the binary message resource
399n/a # it includes
400n/a #
401n/a # For now (since there are no options to change this),
402n/a # we use the source-directory for the include file and
403n/a # the build directory for the RC file and message
404n/a # resources. This works at least for win32all.
405n/a
406n/a h_dir = os.path.dirname(src)
407n/a rc_dir = os.path.dirname(obj)
408n/a try:
409n/a # first compile .MC to .RC and .H file
410n/a self.spawn([self.mc] +
411n/a ['-h', h_dir, '-r', rc_dir] + [src])
412n/a base, _ = os.path.splitext(os.path.basename(src))
413n/a rc_file = os.path.join(rc_dir, base + '.rc')
414n/a # then compile .RC to .RES file
415n/a self.spawn([self.rc] +
416n/a ["/fo" + obj] + [rc_file])
417n/a
418n/a except PackagingExecError as msg:
419n/a raise CompileError(msg)
420n/a continue
421n/a else:
422n/a # how to handle this file?
423n/a raise CompileError(
424n/a "Don't know how to compile %s to %s" %
425n/a (src, obj))
426n/a
427n/a output_opt = "/Fo" + obj
428n/a try:
429n/a self.spawn([self.cc] + compile_opts + pp_opts +
430n/a [input_opt, output_opt] +
431n/a extra_postargs)
432n/a except PackagingExecError as msg:
433n/a raise CompileError(msg)
434n/a
435n/a return objects
436n/a
437n/a def create_static_lib(self, objects, output_libname, output_dir=None,
438n/a debug=False, target_lang=None):
439n/a if not self.initialized:
440n/a self.initialize()
441n/a objects, output_dir = self._fix_object_args(objects, output_dir)
442n/a output_filename = \
443n/a self.library_filename(output_libname, output_dir=output_dir)
444n/a
445n/a if self._need_link(objects, output_filename):
446n/a lib_args = objects + ['/OUT:' + output_filename]
447n/a if debug:
448n/a pass # XXX what goes here?
449n/a try:
450n/a self.spawn([self.lib] + lib_args)
451n/a except PackagingExecError as msg:
452n/a raise LibError(msg)
453n/a
454n/a else:
455n/a logger.debug("skipping %s (up-to-date)", output_filename)
456n/a
457n/a def link(self, target_desc, objects, output_filename, output_dir=None,
458n/a libraries=None, library_dirs=None, runtime_library_dirs=None,
459n/a export_symbols=None, debug=False, extra_preargs=None,
460n/a extra_postargs=None, build_temp=None, target_lang=None):
461n/a
462n/a if not self.initialized:
463n/a self.initialize()
464n/a objects, output_dir = self._fix_object_args(objects, output_dir)
465n/a libraries, library_dirs, runtime_library_dirs = \
466n/a self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
467n/a
468n/a if runtime_library_dirs:
469n/a self.warn("don't know what to do with 'runtime_library_dirs': %s"
470n/a % (runtime_library_dirs,))
471n/a
472n/a lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,
473n/a libraries)
474n/a if output_dir is not None:
475n/a output_filename = os.path.join(output_dir, output_filename)
476n/a
477n/a if self._need_link(objects, output_filename):
478n/a
479n/a if target_desc == CCompiler.EXECUTABLE:
480n/a if debug:
481n/a ldflags = self.ldflags_shared_debug[1:]
482n/a else:
483n/a ldflags = self.ldflags_shared[1:]
484n/a else:
485n/a if debug:
486n/a ldflags = self.ldflags_shared_debug
487n/a else:
488n/a ldflags = self.ldflags_shared
489n/a
490n/a export_opts = []
491n/a for sym in (export_symbols or []):
492n/a export_opts.append("/EXPORT:" + sym)
493n/a
494n/a ld_args = (ldflags + lib_opts + export_opts +
495n/a objects + ['/OUT:' + output_filename])
496n/a
497n/a # The MSVC linker generates .lib and .exp files, which cannot be
498n/a # suppressed by any linker switches. The .lib files may even be
499n/a # needed! Make sure they are generated in the temporary build
500n/a # directory. Since they have different names for debug and release
501n/a # builds, they can go into the same directory.
502n/a if export_symbols is not None:
503n/a dll_name, dll_ext = os.path.splitext(
504n/a os.path.basename(output_filename))
505n/a implib_file = os.path.join(
506n/a os.path.dirname(objects[0]),
507n/a self.library_filename(dll_name))
508n/a ld_args.append('/IMPLIB:' + implib_file)
509n/a
510n/a if extra_preargs:
511n/a ld_args[:0] = extra_preargs
512n/a if extra_postargs:
513n/a ld_args.extend(extra_postargs)
514n/a
515n/a self.mkpath(os.path.dirname(output_filename))
516n/a try:
517n/a self.spawn([self.linker] + ld_args)
518n/a except PackagingExecError as msg:
519n/a raise LinkError(msg)
520n/a
521n/a else:
522n/a logger.debug("skipping %s (up-to-date)", output_filename)
523n/a
524n/a # -- Miscellaneous methods -----------------------------------------
525n/a # These are all used by the 'gen_lib_options() function, in
526n/a # ccompiler.py.
527n/a
528n/a def library_dir_option(self, dir):
529n/a return "/LIBPATH:" + dir
530n/a
531n/a def runtime_library_dir_option(self, dir):
532n/a raise PackagingPlatformError("don't know how to set runtime library search path for MSVC++")
533n/a
534n/a def library_option(self, lib):
535n/a return self.library_filename(lib)
536n/a
537n/a def find_library_file(self, dirs, lib, debug=False):
538n/a # Prefer a debugging library if found (and requested), but deal
539n/a # with it if we don't have one.
540n/a if debug:
541n/a try_names = [lib + "_d", lib]
542n/a else:
543n/a try_names = [lib]
544n/a for dir in dirs:
545n/a for name in try_names:
546n/a libfile = os.path.join(dir, self.library_filename(name))
547n/a if os.path.exists(libfile):
548n/a return libfile
549n/a else:
550n/a # Oops, didn't find it in *any* of 'dirs'
551n/a return None
552n/a
553n/a # Helper methods for using the MSVC registry settings
554n/a
555n/a def find_exe(self, exe):
556n/a """Return path to an MSVC executable program.
557n/a
558n/a Tries to find the program in several places: first, one of the
559n/a MSVC program search paths from the registry; next, the directories
560n/a in the PATH environment variable. If any of those work, return an
561n/a absolute path that is known to exist. If none of them work, just
562n/a return the original program name, 'exe'.
563n/a """
564n/a
565n/a for p in self.__paths:
566n/a fn = os.path.join(os.path.abspath(p), exe)
567n/a if os.path.isfile(fn):
568n/a return fn
569n/a
570n/a # didn't find it; try existing path
571n/a for p in os.environ['Path'].split(';'):
572n/a fn = os.path.join(os.path.abspath(p), exe)
573n/a if os.path.isfile(fn):
574n/a return fn
575n/a
576n/a return exe
577n/a
578n/a def get_msvc_paths(self, path, platform='x86'):
579n/a """Get a list of devstudio directories (include, lib or path).
580n/a
581n/a Return a list of strings. The list will be empty if unable to
582n/a access the registry or appropriate registry keys not found.
583n/a """
584n/a
585n/a if not _can_read_reg:
586n/a return []
587n/a
588n/a path = path + " dirs"
589n/a if self.__version >= 7:
590n/a key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
591n/a % (self.__root, self.__version))
592n/a else:
593n/a key = (r"%s\6.0\Build System\Components\Platforms"
594n/a r"\Win32 (%s)\Directories" % (self.__root, platform))
595n/a
596n/a for base in HKEYS:
597n/a d = read_values(base, key)
598n/a if d:
599n/a if self.__version >= 7:
600n/a return self.__macros.sub(d[path]).split(";")
601n/a else:
602n/a return d[path].split(";")
603n/a # MSVC 6 seems to create the registry entries we need only when
604n/a # the GUI is run.
605n/a if self.__version == 6:
606n/a for base in HKEYS:
607n/a if read_values(base, r"%s\6.0" % self.__root) is not None:
608n/a self.warn("It seems you have Visual Studio 6 installed, "
609n/a "but the expected registry settings are not present.\n"
610n/a "You must at least run the Visual Studio GUI once "
611n/a "so that these entries are created.")
612n/a break
613n/a return []
614n/a
615n/a def set_path_env_var(self, name):
616n/a """Set environment variable 'name' to an MSVC path type value.
617n/a
618n/a This is equivalent to a SET command prior to execution of spawned
619n/a commands.
620n/a """
621n/a
622n/a if name == "lib":
623n/a p = self.get_msvc_paths("library")
624n/a else:
625n/a p = self.get_msvc_paths(name)
626n/a if p:
627n/a os.environ[name] = ';'.join(p)
628n/a
629n/a
630n/aif get_build_version() >= 8.0:
631n/a logger.debug("importing new compiler from distutils.msvc9compiler")
632n/a OldMSVCCompiler = MSVCCompiler
633n/a from packaging.compiler.msvc9compiler import MSVCCompiler
634n/a # get_build_architecture not really relevant now we support cross-compile
635n/a from packaging.compiler.msvc9compiler import MacroExpander