]>
crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/setuptools/_distutils/msvccompiler.py
1 """distutils.msvccompiler
3 Contains MSVCCompiler, an implementation of the abstract CCompiler class
4 for the Microsoft Visual Studio.
7 # Written by Perry Stoll
8 # hacked by Robin Becker and Thomas Heller to do a better job of
9 # finding DevStudio (through the registry)
16 DistutilsPlatformError
,
21 from .ccompiler
import CCompiler
, gen_lib_options
31 RegOpenKeyEx
= winreg
.OpenKeyEx
32 RegEnumKey
= winreg
.EnumKey
33 RegEnumValue
= winreg
.EnumValue
34 RegError
= winreg
.error
44 RegOpenKeyEx
= win32api
.RegOpenKeyEx
45 RegEnumKey
= win32api
.RegEnumKey
46 RegEnumValue
= win32api
.RegEnumValue
47 RegError
= win32api
.error
50 "Warning: Can't read registry to find the "
51 "necessary compiler setting\n"
52 "Make sure that Python modules winreg, "
53 "win32api or win32con are installed."
60 hkey_mod
.HKEY_CURRENT_USER
,
61 hkey_mod
.HKEY_LOCAL_MACHINE
,
62 hkey_mod
.HKEY_CLASSES_ROOT
,
67 "msvccompiler is deprecated and slated to be removed "
68 "in the future. Please discontinue use or file an issue "
69 "with pypa/distutils describing your use case.",
74 def read_keys(base
, key
):
75 """Return list of registry keys."""
77 handle
= RegOpenKeyEx(base
, key
)
84 k
= RegEnumKey(handle
, i
)
92 def read_values(base
, key
):
93 """Return dict of registry keys and values.
95 All names are converted to lowercase.
98 handle
= RegOpenKeyEx(base
, key
)
105 name
, value
, type = RegEnumValue(handle
, i
)
109 d
[convert_mbcs(name
)] = convert_mbcs(value
)
115 dec
= getattr(s
, "decode", None)
125 def __init__(self
, version
):
127 self
.load_macros(version
)
129 def set_macro(self
, macro
, path
, key
):
131 d
= read_values(base
, path
)
133 self
.macros
["$(%s)" % macro
] = d
[key
]
136 def load_macros(self
, version
):
137 vsbase
= r
"Software\Microsoft\VisualStudio\%0.1f" % version
138 self
.set_macro("VCInstallDir", vsbase
+ r
"\Setup\VC", "productdir")
139 self
.set_macro("VSInstallDir", vsbase
+ r
"\Setup\VS", "productdir")
140 net
= r
"Software\Microsoft\.NETFramework"
141 self
.set_macro("FrameworkDir", net
, "installroot")
144 self
.set_macro("FrameworkSDKDir", net
, "sdkinstallrootv1.1")
146 self
.set_macro("FrameworkSDKDir", net
, "sdkinstallroot")
148 raise DistutilsPlatformError(
149 """Python was built with Visual Studio 2003;
150 extensions must be built with a compiler than can generate compatible binaries.
151 Visual Studio 2003 was not found on this system. If you have Cygwin installed,
152 you can try compiling with MingW32, by passing "-c mingw32" to setup.py."""
155 p
= r
"Software\Microsoft\NET Framework Setup\Product"
158 h
= RegOpenKeyEx(base
, p
)
161 key
= RegEnumKey(h
, 0)
162 d
= read_values(base
, r
"{}\{}".format(p
, key
))
163 self
.macros
["$(FrameworkVersion)"] = d
["version"]
166 for k
, v
in self
.macros
.items():
171 def get_build_version():
172 """Return the version of MSVC that was used to build Python.
174 For Python 2.3 and up, the version number is included in
175 sys.version. For earlier versions, assume the compiler is MSVC 6.
178 i
= sys
.version
.find(prefix
)
182 s
, rest
= sys
.version
[i
:].split(" ", 1)
183 majorVersion
= int(s
[:-2]) - 6
184 if majorVersion
>= 13:
185 # v13 was skipped and should be v14
187 minorVersion
= int(s
[2:3]) / 10.0
188 # I don't think paths are affected by minor version in version 6
189 if majorVersion
== 6:
191 if majorVersion
>= 6:
192 return majorVersion
+ minorVersion
193 # else we don't know what version of the compiler this is
197 def get_build_architecture():
198 """Return the processor architecture.
200 Possible results are "Intel" or "AMD64".
204 i
= sys
.version
.find(prefix
)
207 j
= sys
.version
.find(")", i
)
208 return sys
.version
[i
+ len(prefix
) : j
]
211 def normalize_and_reduce_paths(paths
):
212 """Return a list of normalized paths with duplicates removed.
214 The current order of paths is maintained.
216 # Paths are normalized so things like: /a and /a/ aren't both preserved.
219 np
= os
.path
.normpath(p
)
220 # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
221 if np
not in reduced_paths
:
222 reduced_paths
.append(np
)
226 class MSVCCompiler(CCompiler
):
227 """Concrete class that implements an interface to Microsoft Visual C++,
228 as defined by the CCompiler abstract class."""
230 compiler_type
= 'msvc'
232 # Just set this so CCompiler's constructor doesn't barf. We currently
233 # don't use the 'set_executables()' bureaucracy provided by CCompiler,
234 # as it really isn't necessary for this sort of single-compiler class.
235 # Would be nice to have a consistent interface with UnixCCompiler,
236 # though, so it's worth thinking about.
239 # Private class data (need to distinguish C from C++ source for compiler)
240 _c_extensions
= ['.c']
241 _cpp_extensions
= ['.cc', '.cpp', '.cxx']
242 _rc_extensions
= ['.rc']
243 _mc_extensions
= ['.mc']
245 # Needed for the filename generation methods provided by the
246 # base class, CCompiler.
247 src_extensions
= _c_extensions
+ _cpp_extensions
+ _rc_extensions
+ _mc_extensions
248 res_extension
= '.res'
249 obj_extension
= '.obj'
250 static_lib_extension
= '.lib'
251 shared_lib_extension
= '.dll'
252 static_lib_format
= shared_lib_format
= '%s%s'
253 exe_extension
= '.exe'
255 def __init__(self
, verbose
=0, dry_run
=0, force
=0):
256 super().__init
__(verbose
, dry_run
, force
)
257 self
.__version
= get_build_version()
258 self
.__arch
= get_build_architecture()
259 if self
.__arch
== "Intel":
261 if self
.__version
>= 7:
262 self
.__root
= r
"Software\Microsoft\VisualStudio"
263 self
.__macros
= MacroExpander(self
.__version
)
265 self
.__root
= r
"Software\Microsoft\Devstudio"
266 self
.__product
= "Visual Studio version %s" % self
.__version
268 # Win64. Assume this was built with the platform SDK
269 self
.__product
= "Microsoft SDK compiler %s" % (self
.__version
+ 6)
271 self
.initialized
= False
273 def initialize(self
):
276 "DISTUTILS_USE_SDK" in os
.environ
277 and "MSSdk" in os
.environ
278 and self
.find_exe("cl.exe")
280 # Assume that the SDK set up everything alright; don't try to be
283 self
.linker
= "link.exe"
288 self
.__paths
= self
.get_msvc_paths("path")
290 if len(self
.__paths
) == 0:
291 raise DistutilsPlatformError(
292 "Python was built with %s, "
293 "and extensions need to be built with the same "
294 "version of the compiler, but it isn't installed." % self
.__product
297 self
.cc
= self
.find_exe("cl.exe")
298 self
.linker
= self
.find_exe("link.exe")
299 self
.lib
= self
.find_exe("lib.exe")
300 self
.rc
= self
.find_exe("rc.exe") # resource compiler
301 self
.mc
= self
.find_exe("mc.exe") # message compiler
302 self
.set_path_env_var('lib')
303 self
.set_path_env_var('include')
305 # extend the MSVC path with the current path
307 for p
in os
.environ
['path'].split(';'):
308 self
.__paths
.append(p
)
311 self
.__paths
= normalize_and_reduce_paths(self
.__paths
)
312 os
.environ
['path'] = ";".join(self
.__paths
)
314 self
.preprocess_options
= None
315 if self
.__arch
== "Intel":
316 self
.compile_options
= ['/nologo', '/O2', '/MD', '/W3', '/GX', '/DNDEBUG']
317 self
.compile_options_debug
= [
328 self
.compile_options
= ['/nologo', '/O2', '/MD', '/W3', '/GS-', '/DNDEBUG']
329 self
.compile_options_debug
= [
339 self
.ldflags_shared
= ['/DLL', '/nologo', '/INCREMENTAL:NO']
340 if self
.__version
>= 7:
341 self
.ldflags_shared_debug
= ['/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG']
343 self
.ldflags_shared_debug
= [
350 self
.ldflags_static
= ['/nologo']
352 self
.initialized
= True
354 # -- Worker methods ------------------------------------------------
356 def object_filenames(self
, source_filenames
, strip_dir
=0, output_dir
=''):
357 # Copied from ccompiler.py, extended to return .res as 'object'-file
359 if output_dir
is None:
362 for src_name
in source_filenames
:
363 (base
, ext
) = os
.path
.splitext(src_name
)
364 base
= os
.path
.splitdrive(base
)[1] # Chop off the drive
365 base
= base
[os
.path
.isabs(base
) :] # If abs, chop off leading /
366 if ext
not in self
.src_extensions
:
367 # Better to raise an exception instead of silently continuing
368 # and later complain about sources and targets having
370 raise CompileError("Don't know how to compile %s" % src_name
)
372 base
= os
.path
.basename(base
)
373 if ext
in self
._rc
_extensions
:
374 obj_names
.append(os
.path
.join(output_dir
, base
+ self
.res_extension
))
375 elif ext
in self
._mc
_extensions
:
376 obj_names
.append(os
.path
.join(output_dir
, base
+ self
.res_extension
))
378 obj_names
.append(os
.path
.join(output_dir
, base
+ self
.obj_extension
))
381 def compile( # noqa: C901
393 if not self
.initialized
:
395 compile_info
= self
._setup
_compile
(
396 output_dir
, macros
, include_dirs
, sources
, depends
, extra_postargs
398 macros
, objects
, extra_postargs
, pp_opts
, build
= compile_info
400 compile_opts
= extra_preargs
or []
401 compile_opts
.append('/c')
403 compile_opts
.extend(self
.compile_options_debug
)
405 compile_opts
.extend(self
.compile_options
)
409 src
, ext
= build
[obj
]
413 # pass the full pathname to MSVC in debug mode,
414 # this allows the debugger to find the source file
415 # without asking the user to browse for it
416 src
= os
.path
.abspath(src
)
418 if ext
in self
._c
_extensions
:
419 input_opt
= "/Tc" + src
420 elif ext
in self
._cpp
_extensions
:
421 input_opt
= "/Tp" + src
422 elif ext
in self
._rc
_extensions
:
423 # compile .RC to .RES file
425 output_opt
= "/fo" + obj
427 self
.spawn([self
.rc
] + pp_opts
+ [output_opt
] + [input_opt
])
428 except DistutilsExecError
as msg
:
429 raise CompileError(msg
)
431 elif ext
in self
._mc
_extensions
:
432 # Compile .MC to .RC file to .RES file.
433 # * '-h dir' specifies the directory for the
434 # generated include file
435 # * '-r dir' specifies the target directory of the
436 # generated RC file and the binary message resource
439 # For now (since there are no options to change this),
440 # we use the source-directory for the include file and
441 # the build directory for the RC file and message
442 # resources. This works at least for win32all.
443 h_dir
= os
.path
.dirname(src
)
444 rc_dir
= os
.path
.dirname(obj
)
446 # first compile .MC to .RC and .H file
447 self
.spawn([self
.mc
] + ['-h', h_dir
, '-r', rc_dir
] + [src
])
448 base
, _
= os
.path
.splitext(os
.path
.basename(src
))
449 rc_file
= os
.path
.join(rc_dir
, base
+ '.rc')
450 # then compile .RC to .RES file
451 self
.spawn([self
.rc
] + ["/fo" + obj
] + [rc_file
])
453 except DistutilsExecError
as msg
:
454 raise CompileError(msg
)
457 # how to handle this file?
459 "Don't know how to compile {} to {}".format(src
, obj
)
462 output_opt
= "/Fo" + obj
468 + [input_opt
, output_opt
]
471 except DistutilsExecError
as msg
:
472 raise CompileError(msg
)
476 def create_static_lib(
477 self
, objects
, output_libname
, output_dir
=None, debug
=0, target_lang
=None
480 if not self
.initialized
:
482 (objects
, output_dir
) = self
._fix
_object
_args
(objects
, output_dir
)
483 output_filename
= self
.library_filename(output_libname
, output_dir
=output_dir
)
485 if self
._need
_link
(objects
, output_filename
):
486 lib_args
= objects
+ ['/OUT:' + output_filename
]
488 pass # XXX what goes here?
490 self
.spawn([self
.lib
] + lib_args
)
491 except DistutilsExecError
as msg
:
494 log
.debug("skipping %s (up-to-date)", output_filename
)
496 def link( # noqa: C901
504 runtime_library_dirs
=None,
513 if not self
.initialized
:
515 (objects
, output_dir
) = self
._fix
_object
_args
(objects
, output_dir
)
516 fixed_args
= self
._fix
_lib
_args
(libraries
, library_dirs
, runtime_library_dirs
)
517 (libraries
, library_dirs
, runtime_library_dirs
) = fixed_args
519 if runtime_library_dirs
:
521 "I don't know what to do with 'runtime_library_dirs': "
522 + str(runtime_library_dirs
)
525 lib_opts
= gen_lib_options(self
, library_dirs
, runtime_library_dirs
, libraries
)
526 if output_dir
is not None:
527 output_filename
= os
.path
.join(output_dir
, output_filename
)
529 if self
._need
_link
(objects
, output_filename
):
530 if target_desc
== CCompiler
.EXECUTABLE
:
532 ldflags
= self
.ldflags_shared_debug
[1:]
534 ldflags
= self
.ldflags_shared
[1:]
537 ldflags
= self
.ldflags_shared_debug
539 ldflags
= self
.ldflags_shared
542 for sym
in export_symbols
or []:
543 export_opts
.append("/EXPORT:" + sym
)
546 ldflags
+ lib_opts
+ export_opts
+ objects
+ ['/OUT:' + output_filename
]
549 # The MSVC linker generates .lib and .exp files, which cannot be
550 # suppressed by any linker switches. The .lib files may even be
551 # needed! Make sure they are generated in the temporary build
552 # directory. Since they have different names for debug and release
553 # builds, they can go into the same directory.
554 if export_symbols
is not None:
555 (dll_name
, dll_ext
) = os
.path
.splitext(
556 os
.path
.basename(output_filename
)
558 implib_file
= os
.path
.join(
559 os
.path
.dirname(objects
[0]), self
.library_filename(dll_name
)
561 ld_args
.append('/IMPLIB:' + implib_file
)
564 ld_args
[:0] = extra_preargs
566 ld_args
.extend(extra_postargs
)
568 self
.mkpath(os
.path
.dirname(output_filename
))
570 self
.spawn([self
.linker
] + ld_args
)
571 except DistutilsExecError
as msg
:
575 log
.debug("skipping %s (up-to-date)", output_filename
)
577 # -- Miscellaneous methods -----------------------------------------
578 # These are all used by the 'gen_lib_options() function, in
581 def library_dir_option(self
, dir):
582 return "/LIBPATH:" + dir
584 def runtime_library_dir_option(self
, dir):
585 raise DistutilsPlatformError(
586 "don't know how to set runtime library search path for MSVC++"
589 def library_option(self
, lib
):
590 return self
.library_filename(lib
)
592 def find_library_file(self
, dirs
, lib
, debug
=0):
593 # Prefer a debugging library if found (and requested), but deal
594 # with it if we don't have one.
596 try_names
= [lib
+ "_d", lib
]
600 for name
in try_names
:
601 libfile
= os
.path
.join(dir, self
.library_filename(name
))
602 if os
.path
.exists(libfile
):
605 # Oops, didn't find it in *any* of 'dirs'
608 # Helper methods for using the MSVC registry settings
610 def find_exe(self
, exe
):
611 """Return path to an MSVC executable program.
613 Tries to find the program in several places: first, one of the
614 MSVC program search paths from the registry; next, the directories
615 in the PATH environment variable. If any of those work, return an
616 absolute path that is known to exist. If none of them work, just
617 return the original program name, 'exe'.
619 for p
in self
.__paths
:
620 fn
= os
.path
.join(os
.path
.abspath(p
), exe
)
621 if os
.path
.isfile(fn
):
624 # didn't find it; try existing path
625 for p
in os
.environ
['Path'].split(';'):
626 fn
= os
.path
.join(os
.path
.abspath(p
), exe
)
627 if os
.path
.isfile(fn
):
632 def get_msvc_paths(self
, path
, platform
='x86'):
633 """Get a list of devstudio directories (include, lib or path).
635 Return a list of strings. The list will be empty if unable to
636 access the registry or appropriate registry keys not found.
638 if not _can_read_reg
:
641 path
= path
+ " dirs"
642 if self
.__version
>= 7:
643 key
= r
"{}\{:0.1f}\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories".format(
649 r
"%s\6.0\Build System\Components\Platforms"
650 r
"\Win32 (%s)\Directories" % (self
.__root
, platform
)
654 d
= read_values(base
, key
)
656 if self
.__version
>= 7:
657 return self
.__macros
.sub(d
[path
]).split(";")
659 return d
[path
].split(";")
660 # MSVC 6 seems to create the registry entries we need only when
662 if self
.__version
== 6:
664 if read_values(base
, r
"%s\6.0" % self
.__root
) is not None:
666 "It seems you have Visual Studio 6 installed, "
667 "but the expected registry settings are not present.\n"
668 "You must at least run the Visual Studio GUI once "
669 "so that these entries are created."
674 def set_path_env_var(self
, name
):
675 """Set environment variable 'name' to an MSVC path type value.
677 This is equivalent to a SET command prior to execution of spawned
682 p
= self
.get_msvc_paths("library")
684 p
= self
.get_msvc_paths(name
)
686 os
.environ
[name
] = ';'.join(p
)
689 if get_build_version() >= 8.0:
690 log
.debug("Importing new compiler from distutils.msvc9compiler")
691 OldMSVCCompiler
= MSVCCompiler
692 from distutils
.msvc9compiler
import MSVCCompiler
694 # get_build_architecture not really relevant now we support cross-compile
695 from distutils
.msvc9compiler
import MacroExpander
# noqa: F811