Path: blob/main/test/lib/python3.9/site-packages/setuptools/_distutils/cygwinccompiler.py
4799 views
"""distutils.cygwinccompiler12Provides the CygwinCCompiler class, a subclass of UnixCCompiler that3handles the Cygwin port of the GNU C compiler to Windows. It also contains4the Mingw32CCompiler class which handles the mingw32 port of GCC (same as5cygwin in no-cygwin mode).6"""78# problems:9#10# * if you use a msvc compiled python version (1.5.2)11# 1. you have to insert a __GNUC__ section in its config.h12# 2. you have to generate an import library for its dll13# - create a def-file for python??.dll14# - create an import library using15# dlltool --dllname python15.dll --def python15.def \16# --output-lib libpython15.a17#18# see also http://starship.python.net/crew/kernr/mingw32/Notes.html19#20# * We put export_symbols in a def-file, and don't use21# --export-all-symbols because it doesn't worked reliable in some22# tested configurations. And because other windows compilers also23# need their symbols specified this no serious problem.24#25# tested configurations:26#27# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works28# (after patching python's config.h and for C++ some other include files)29# see also http://starship.python.net/crew/kernr/mingw32/Notes.html30# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works31# (ld doesn't support -shared, so we use dllwrap)32# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now33# - its dllwrap doesn't work, there is a bug in binutils 2.10.9034# see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html35# - using gcc -mdll instead dllwrap doesn't work without -static because36# it tries to link against dlls instead their import libraries. (If37# it finds the dll first.)38# By specifying -static we force ld to link against the import libraries,39# this is windows standard and there are normally not the necessary symbols40# in the dlls.41# *** only the version of June 2000 shows these problems42# * cygwin gcc 3.2/ld 2.13.90 works43# (ld supports -shared)44# * mingw gcc 3.2/ld 2.13 works45# (ld supports -shared)46# * llvm-mingw with Clang 11 works47# (lld supports -shared)4849import os50import sys51import copy52import shlex53import warnings54from subprocess import check_output5556from distutils.unixccompiler import UnixCCompiler57from distutils.file_util import write_file58from distutils.errors import (DistutilsExecError, CCompilerError,59CompileError, UnknownFileError)60from distutils.version import LooseVersion, suppress_known_deprecation6162def get_msvcr():63"""Include the appropriate MSVC runtime library if Python was built64with MSVC 7.0 or later.65"""66msc_pos = sys.version.find('MSC v.')67if msc_pos != -1:68msc_ver = sys.version[msc_pos+6:msc_pos+10]69if msc_ver == '1300':70# MSVC 7.071return ['msvcr70']72elif msc_ver == '1310':73# MSVC 7.174return ['msvcr71']75elif msc_ver == '1400':76# VS2005 / MSVC 8.077return ['msvcr80']78elif msc_ver == '1500':79# VS2008 / MSVC 9.080return ['msvcr90']81elif msc_ver == '1600':82# VS2010 / MSVC 10.083return ['msvcr100']84elif msc_ver == '1700':85# VS2012 / MSVC 11.086return ['msvcr110']87elif msc_ver == '1800':88# VS2013 / MSVC 12.089return ['msvcr120']90elif 1900 <= int(msc_ver) < 2000:91# VS2015 / MSVC 14.092return ['ucrt', 'vcruntime140']93else:94raise ValueError("Unknown MS Compiler version %s " % msc_ver)959697class CygwinCCompiler(UnixCCompiler):98""" Handles the Cygwin port of the GNU C compiler to Windows.99"""100compiler_type = 'cygwin'101obj_extension = ".o"102static_lib_extension = ".a"103shared_lib_extension = ".dll"104static_lib_format = "lib%s%s"105shared_lib_format = "%s%s"106exe_extension = ".exe"107108def __init__(self, verbose=0, dry_run=0, force=0):109110super().__init__(verbose, dry_run, force)111112status, details = check_config_h()113self.debug_print("Python's GCC status: %s (details: %s)" %114(status, details))115if status is not CONFIG_H_OK:116self.warn(117"Python's pyconfig.h doesn't seem to support your compiler. "118"Reason: %s. "119"Compiling may fail because of undefined preprocessor macros."120% details)121122self.cc = os.environ.get('CC', 'gcc')123self.cxx = os.environ.get('CXX', 'g++')124125self.linker_dll = self.cc126shared_option = "-shared"127128self.set_executables(compiler='%s -mcygwin -O -Wall' % self.cc,129compiler_so='%s -mcygwin -mdll -O -Wall' % self.cc,130compiler_cxx='%s -mcygwin -O -Wall' % self.cxx,131linker_exe='%s -mcygwin' % self.cc,132linker_so=('%s -mcygwin %s' %133(self.linker_dll, shared_option)))134135# Include the appropriate MSVC runtime library if Python was built136# with MSVC 7.0 or later.137self.dll_libraries = get_msvcr()138139@property140def gcc_version(self):141# Older numpy dependend on this existing to check for ancient142# gcc versions. This doesn't make much sense with clang etc so143# just hardcode to something recent.144# https://github.com/numpy/numpy/pull/20333145warnings.warn(146"gcc_version attribute of CygwinCCompiler is deprecated. "147"Instead of returning actual gcc version a fixed value 11.2.0 is returned.",148DeprecationWarning,149stacklevel=2,150)151with suppress_known_deprecation():152return LooseVersion("11.2.0")153154def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):155"""Compiles the source by spawning GCC and windres if needed."""156if ext == '.rc' or ext == '.res':157# gcc needs '.res' and '.rc' compiled to object files !!!158try:159self.spawn(["windres", "-i", src, "-o", obj])160except DistutilsExecError as msg:161raise CompileError(msg)162else: # for other files use the C-compiler163try:164self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +165extra_postargs)166except DistutilsExecError as msg:167raise CompileError(msg)168169def link(self, target_desc, objects, output_filename, output_dir=None,170libraries=None, library_dirs=None, runtime_library_dirs=None,171export_symbols=None, debug=0, extra_preargs=None,172extra_postargs=None, build_temp=None, target_lang=None):173"""Link the objects."""174# use separate copies, so we can modify the lists175extra_preargs = copy.copy(extra_preargs or [])176libraries = copy.copy(libraries or [])177objects = copy.copy(objects or [])178179# Additional libraries180libraries.extend(self.dll_libraries)181182# handle export symbols by creating a def-file183# with executables this only works with gcc/ld as linker184if ((export_symbols is not None) and185(target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):186# (The linker doesn't do anything if output is up-to-date.187# So it would probably better to check if we really need this,188# but for this we had to insert some unchanged parts of189# UnixCCompiler, and this is not what we want.)190191# we want to put some files in the same directory as the192# object files are, build_temp doesn't help much193# where are the object files194temp_dir = os.path.dirname(objects[0])195# name of dll to give the helper files the same base name196(dll_name, dll_extension) = os.path.splitext(197os.path.basename(output_filename))198199# generate the filenames for these files200def_file = os.path.join(temp_dir, dll_name + ".def")201lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a")202203# Generate .def file204contents = [205"LIBRARY %s" % os.path.basename(output_filename),206"EXPORTS"]207for sym in export_symbols:208contents.append(sym)209self.execute(write_file, (def_file, contents),210"writing %s" % def_file)211212# next add options for def-file and to creating import libraries213214# doesn't work: bfd_close build\...\libfoo.a: Invalid operation215#extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])216# for gcc/ld the def-file is specified as any object files217objects.append(def_file)218219#end: if ((export_symbols is not None) and220# (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):221222# who wants symbols and a many times larger output file223# should explicitly switch the debug mode on224# otherwise we let ld strip the output file225# (On my machine: 10KiB < stripped_file < ??100KiB226# unstripped_file = stripped_file + XXX KiB227# ( XXX=254 for a typical python extension))228if not debug:229extra_preargs.append("-s")230231UnixCCompiler.link(self, target_desc, objects, output_filename,232output_dir, libraries, library_dirs,233runtime_library_dirs,234None, # export_symbols, we do this in our def-file235debug, extra_preargs, extra_postargs, build_temp,236target_lang)237238# -- Miscellaneous methods -----------------------------------------239240def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):241"""Adds supports for rc and res files."""242if output_dir is None:243output_dir = ''244obj_names = []245for src_name in source_filenames:246# use normcase to make sure '.rc' is really '.rc' and not '.RC'247base, ext = os.path.splitext(os.path.normcase(src_name))248if ext not in (self.src_extensions + ['.rc','.res']):249raise UnknownFileError("unknown file type '%s' (from '%s')" % \250(ext, src_name))251if strip_dir:252base = os.path.basename (base)253if ext in ('.res', '.rc'):254# these need to be compiled to object files255obj_names.append (os.path.join(output_dir,256base + ext + self.obj_extension))257else:258obj_names.append (os.path.join(output_dir,259base + self.obj_extension))260return obj_names261262# the same as cygwin plus some additional parameters263class Mingw32CCompiler(CygwinCCompiler):264""" Handles the Mingw32 port of the GNU C compiler to Windows.265"""266compiler_type = 'mingw32'267268def __init__(self, verbose=0, dry_run=0, force=0):269270super().__init__ (verbose, dry_run, force)271272shared_option = "-shared"273274if is_cygwincc(self.cc):275raise CCompilerError(276'Cygwin gcc cannot be used with --compiler=mingw32')277278self.set_executables(compiler='%s -O -Wall' % self.cc,279compiler_so='%s -mdll -O -Wall' % self.cc,280compiler_cxx='%s -O -Wall' % self.cxx,281linker_exe='%s' % self.cc,282linker_so='%s %s'283% (self.linker_dll, shared_option))284285# Maybe we should also append -mthreads, but then the finished286# dlls need another dll (mingwm10.dll see Mingw32 docs)287# (-mthreads: Support thread-safe exception handling on `Mingw32')288289# no additional libraries needed290self.dll_libraries=[]291292# Include the appropriate MSVC runtime library if Python was built293# with MSVC 7.0 or later.294self.dll_libraries = get_msvcr()295296# Because these compilers aren't configured in Python's pyconfig.h file by297# default, we should at least warn the user if he is using an unmodified298# version.299300CONFIG_H_OK = "ok"301CONFIG_H_NOTOK = "not ok"302CONFIG_H_UNCERTAIN = "uncertain"303304def check_config_h():305"""Check if the current Python installation appears amenable to building306extensions with GCC.307308Returns a tuple (status, details), where 'status' is one of the following309constants:310311- CONFIG_H_OK: all is well, go ahead and compile312- CONFIG_H_NOTOK: doesn't look good313- CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h314315'details' is a human-readable string explaining the situation.316317Note there are two ways to conclude "OK": either 'sys.version' contains318the string "GCC" (implying that this Python was built with GCC), or the319installed "pyconfig.h" contains the string "__GNUC__".320"""321322# XXX since this function also checks sys.version, it's not strictly a323# "pyconfig.h" check -- should probably be renamed...324325from distutils import sysconfig326327# if sys.version contains GCC then python was compiled with GCC, and the328# pyconfig.h file should be OK329if "GCC" in sys.version:330return CONFIG_H_OK, "sys.version mentions 'GCC'"331332# Clang would also work333if "Clang" in sys.version:334return CONFIG_H_OK, "sys.version mentions 'Clang'"335336# let's see if __GNUC__ is mentioned in python.h337fn = sysconfig.get_config_h_filename()338try:339config_h = open(fn)340try:341if "__GNUC__" in config_h.read():342return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn343else:344return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn345finally:346config_h.close()347except OSError as exc:348return (CONFIG_H_UNCERTAIN,349"couldn't read '%s': %s" % (fn, exc.strerror))350351def is_cygwincc(cc):352'''Try to determine if the compiler that would be used is from cygwin.'''353out_string = check_output(shlex.split(cc) + ['-dumpmachine'])354return out_string.strip().endswith(b'cygwin')355356357get_versions = None358"""359A stand-in for the previous get_versions() function to prevent failures360when monkeypatched. See pypa/setuptools#2969.361"""362363364