17db96d56Sopenharmony_ci"""distutils.cygwinccompiler 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciProvides the CygwinCCompiler class, a subclass of UnixCCompiler that 47db96d56Sopenharmony_cihandles the Cygwin port of the GNU C compiler to Windows. It also contains 57db96d56Sopenharmony_cithe Mingw32CCompiler class which handles the mingw32 port of GCC (same as 67db96d56Sopenharmony_cicygwin in no-cygwin mode). 77db96d56Sopenharmony_ci""" 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci# problems: 107db96d56Sopenharmony_ci# 117db96d56Sopenharmony_ci# * if you use a msvc compiled python version (1.5.2) 127db96d56Sopenharmony_ci# 1. you have to insert a __GNUC__ section in its config.h 137db96d56Sopenharmony_ci# 2. you have to generate an import library for its dll 147db96d56Sopenharmony_ci# - create a def-file for python??.dll 157db96d56Sopenharmony_ci# - create an import library using 167db96d56Sopenharmony_ci# dlltool --dllname python15.dll --def python15.def \ 177db96d56Sopenharmony_ci# --output-lib libpython15.a 187db96d56Sopenharmony_ci# 197db96d56Sopenharmony_ci# see also http://starship.python.net/crew/kernr/mingw32/Notes.html 207db96d56Sopenharmony_ci# 217db96d56Sopenharmony_ci# * We put export_symbols in a def-file, and don't use 227db96d56Sopenharmony_ci# --export-all-symbols because it doesn't worked reliable in some 237db96d56Sopenharmony_ci# tested configurations. And because other windows compilers also 247db96d56Sopenharmony_ci# need their symbols specified this no serious problem. 257db96d56Sopenharmony_ci# 267db96d56Sopenharmony_ci# tested configurations: 277db96d56Sopenharmony_ci# 287db96d56Sopenharmony_ci# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works 297db96d56Sopenharmony_ci# (after patching python's config.h and for C++ some other include files) 307db96d56Sopenharmony_ci# see also http://starship.python.net/crew/kernr/mingw32/Notes.html 317db96d56Sopenharmony_ci# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works 327db96d56Sopenharmony_ci# (ld doesn't support -shared, so we use dllwrap) 337db96d56Sopenharmony_ci# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now 347db96d56Sopenharmony_ci# - its dllwrap doesn't work, there is a bug in binutils 2.10.90 357db96d56Sopenharmony_ci# see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html 367db96d56Sopenharmony_ci# - using gcc -mdll instead dllwrap doesn't work without -static because 377db96d56Sopenharmony_ci# it tries to link against dlls instead their import libraries. (If 387db96d56Sopenharmony_ci# it finds the dll first.) 397db96d56Sopenharmony_ci# By specifying -static we force ld to link against the import libraries, 407db96d56Sopenharmony_ci# this is windows standard and there are normally not the necessary symbols 417db96d56Sopenharmony_ci# in the dlls. 427db96d56Sopenharmony_ci# *** only the version of June 2000 shows these problems 437db96d56Sopenharmony_ci# * cygwin gcc 3.2/ld 2.13.90 works 447db96d56Sopenharmony_ci# (ld supports -shared) 457db96d56Sopenharmony_ci# * mingw gcc 3.2/ld 2.13 works 467db96d56Sopenharmony_ci# (ld supports -shared) 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ciimport os 497db96d56Sopenharmony_ciimport sys 507db96d56Sopenharmony_ciimport copy 517db96d56Sopenharmony_cifrom subprocess import Popen, PIPE, check_output 527db96d56Sopenharmony_ciimport re 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_cifrom distutils.unixccompiler import UnixCCompiler 557db96d56Sopenharmony_cifrom distutils.file_util import write_file 567db96d56Sopenharmony_cifrom distutils.errors import (DistutilsExecError, CCompilerError, 577db96d56Sopenharmony_ci CompileError, UnknownFileError) 587db96d56Sopenharmony_cifrom distutils.version import LooseVersion 597db96d56Sopenharmony_cifrom distutils.spawn import find_executable 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_cidef get_msvcr(): 627db96d56Sopenharmony_ci """Include the appropriate MSVC runtime library if Python was built 637db96d56Sopenharmony_ci with MSVC 7.0 or later. 647db96d56Sopenharmony_ci """ 657db96d56Sopenharmony_ci msc_pos = sys.version.find('MSC v.') 667db96d56Sopenharmony_ci if msc_pos != -1: 677db96d56Sopenharmony_ci msc_ver = sys.version[msc_pos+6:msc_pos+10] 687db96d56Sopenharmony_ci if msc_ver == '1300': 697db96d56Sopenharmony_ci # MSVC 7.0 707db96d56Sopenharmony_ci return ['msvcr70'] 717db96d56Sopenharmony_ci elif msc_ver == '1310': 727db96d56Sopenharmony_ci # MSVC 7.1 737db96d56Sopenharmony_ci return ['msvcr71'] 747db96d56Sopenharmony_ci elif msc_ver == '1400': 757db96d56Sopenharmony_ci # VS2005 / MSVC 8.0 767db96d56Sopenharmony_ci return ['msvcr80'] 777db96d56Sopenharmony_ci elif msc_ver == '1500': 787db96d56Sopenharmony_ci # VS2008 / MSVC 9.0 797db96d56Sopenharmony_ci return ['msvcr90'] 807db96d56Sopenharmony_ci elif msc_ver == '1600': 817db96d56Sopenharmony_ci # VS2010 / MSVC 10.0 827db96d56Sopenharmony_ci return ['msvcr100'] 837db96d56Sopenharmony_ci else: 847db96d56Sopenharmony_ci raise ValueError("Unknown MS Compiler version %s " % msc_ver) 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ciclass CygwinCCompiler(UnixCCompiler): 887db96d56Sopenharmony_ci """ Handles the Cygwin port of the GNU C compiler to Windows. 897db96d56Sopenharmony_ci """ 907db96d56Sopenharmony_ci compiler_type = 'cygwin' 917db96d56Sopenharmony_ci obj_extension = ".o" 927db96d56Sopenharmony_ci static_lib_extension = ".a" 937db96d56Sopenharmony_ci shared_lib_extension = ".dll" 947db96d56Sopenharmony_ci static_lib_format = "lib%s%s" 957db96d56Sopenharmony_ci shared_lib_format = "%s%s" 967db96d56Sopenharmony_ci exe_extension = ".exe" 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci def __init__(self, verbose=0, dry_run=0, force=0): 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci UnixCCompiler.__init__(self, verbose, dry_run, force) 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci status, details = check_config_h() 1037db96d56Sopenharmony_ci self.debug_print("Python's GCC status: %s (details: %s)" % 1047db96d56Sopenharmony_ci (status, details)) 1057db96d56Sopenharmony_ci if status is not CONFIG_H_OK: 1067db96d56Sopenharmony_ci self.warn( 1077db96d56Sopenharmony_ci "Python's pyconfig.h doesn't seem to support your compiler. " 1087db96d56Sopenharmony_ci "Reason: %s. " 1097db96d56Sopenharmony_ci "Compiling may fail because of undefined preprocessor macros." 1107db96d56Sopenharmony_ci % details) 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci self.gcc_version, self.ld_version, self.dllwrap_version = \ 1137db96d56Sopenharmony_ci get_versions() 1147db96d56Sopenharmony_ci self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" % 1157db96d56Sopenharmony_ci (self.gcc_version, 1167db96d56Sopenharmony_ci self.ld_version, 1177db96d56Sopenharmony_ci self.dllwrap_version) ) 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci # ld_version >= "2.10.90" and < "2.13" should also be able to use 1207db96d56Sopenharmony_ci # gcc -mdll instead of dllwrap 1217db96d56Sopenharmony_ci # Older dllwraps had own version numbers, newer ones use the 1227db96d56Sopenharmony_ci # same as the rest of binutils ( also ld ) 1237db96d56Sopenharmony_ci # dllwrap 2.10.90 is buggy 1247db96d56Sopenharmony_ci if self.ld_version >= "2.10.90": 1257db96d56Sopenharmony_ci self.linker_dll = "gcc" 1267db96d56Sopenharmony_ci else: 1277db96d56Sopenharmony_ci self.linker_dll = "dllwrap" 1287db96d56Sopenharmony_ci 1297db96d56Sopenharmony_ci # ld_version >= "2.13" support -shared so use it instead of 1307db96d56Sopenharmony_ci # -mdll -static 1317db96d56Sopenharmony_ci if self.ld_version >= "2.13": 1327db96d56Sopenharmony_ci shared_option = "-shared" 1337db96d56Sopenharmony_ci else: 1347db96d56Sopenharmony_ci shared_option = "-mdll -static" 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_ci # Hard-code GCC because that's what this is all about. 1377db96d56Sopenharmony_ci # XXX optimization, warnings etc. should be customizable. 1387db96d56Sopenharmony_ci self.set_executables(compiler='gcc -mcygwin -O -Wall', 1397db96d56Sopenharmony_ci compiler_so='gcc -mcygwin -mdll -O -Wall', 1407db96d56Sopenharmony_ci compiler_cxx='g++ -mcygwin -O -Wall', 1417db96d56Sopenharmony_ci linker_exe='gcc -mcygwin', 1427db96d56Sopenharmony_ci linker_so=('%s -mcygwin %s' % 1437db96d56Sopenharmony_ci (self.linker_dll, shared_option))) 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_ci # cygwin and mingw32 need different sets of libraries 1467db96d56Sopenharmony_ci if self.gcc_version == "2.91.57": 1477db96d56Sopenharmony_ci # cygwin shouldn't need msvcrt, but without the dlls will crash 1487db96d56Sopenharmony_ci # (gcc version 2.91.57) -- perhaps something about initialization 1497db96d56Sopenharmony_ci self.dll_libraries=["msvcrt"] 1507db96d56Sopenharmony_ci self.warn( 1517db96d56Sopenharmony_ci "Consider upgrading to a newer version of gcc") 1527db96d56Sopenharmony_ci else: 1537db96d56Sopenharmony_ci # Include the appropriate MSVC runtime library if Python was built 1547db96d56Sopenharmony_ci # with MSVC 7.0 or later. 1557db96d56Sopenharmony_ci self.dll_libraries = get_msvcr() 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_ci def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): 1587db96d56Sopenharmony_ci """Compiles the source by spawning GCC and windres if needed.""" 1597db96d56Sopenharmony_ci if ext == '.rc' or ext == '.res': 1607db96d56Sopenharmony_ci # gcc needs '.res' and '.rc' compiled to object files !!! 1617db96d56Sopenharmony_ci try: 1627db96d56Sopenharmony_ci self.spawn(["windres", "-i", src, "-o", obj]) 1637db96d56Sopenharmony_ci except DistutilsExecError as msg: 1647db96d56Sopenharmony_ci raise CompileError(msg) 1657db96d56Sopenharmony_ci else: # for other files use the C-compiler 1667db96d56Sopenharmony_ci try: 1677db96d56Sopenharmony_ci self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + 1687db96d56Sopenharmony_ci extra_postargs) 1697db96d56Sopenharmony_ci except DistutilsExecError as msg: 1707db96d56Sopenharmony_ci raise CompileError(msg) 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_ci def link(self, target_desc, objects, output_filename, output_dir=None, 1737db96d56Sopenharmony_ci libraries=None, library_dirs=None, runtime_library_dirs=None, 1747db96d56Sopenharmony_ci export_symbols=None, debug=0, extra_preargs=None, 1757db96d56Sopenharmony_ci extra_postargs=None, build_temp=None, target_lang=None): 1767db96d56Sopenharmony_ci """Link the objects.""" 1777db96d56Sopenharmony_ci # use separate copies, so we can modify the lists 1787db96d56Sopenharmony_ci extra_preargs = copy.copy(extra_preargs or []) 1797db96d56Sopenharmony_ci libraries = copy.copy(libraries or []) 1807db96d56Sopenharmony_ci objects = copy.copy(objects or []) 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci # Additional libraries 1837db96d56Sopenharmony_ci libraries.extend(self.dll_libraries) 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci # handle export symbols by creating a def-file 1867db96d56Sopenharmony_ci # with executables this only works with gcc/ld as linker 1877db96d56Sopenharmony_ci if ((export_symbols is not None) and 1887db96d56Sopenharmony_ci (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")): 1897db96d56Sopenharmony_ci # (The linker doesn't do anything if output is up-to-date. 1907db96d56Sopenharmony_ci # So it would probably better to check if we really need this, 1917db96d56Sopenharmony_ci # but for this we had to insert some unchanged parts of 1927db96d56Sopenharmony_ci # UnixCCompiler, and this is not what we want.) 1937db96d56Sopenharmony_ci 1947db96d56Sopenharmony_ci # we want to put some files in the same directory as the 1957db96d56Sopenharmony_ci # object files are, build_temp doesn't help much 1967db96d56Sopenharmony_ci # where are the object files 1977db96d56Sopenharmony_ci temp_dir = os.path.dirname(objects[0]) 1987db96d56Sopenharmony_ci # name of dll to give the helper files the same base name 1997db96d56Sopenharmony_ci (dll_name, dll_extension) = os.path.splitext( 2007db96d56Sopenharmony_ci os.path.basename(output_filename)) 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci # generate the filenames for these files 2037db96d56Sopenharmony_ci def_file = os.path.join(temp_dir, dll_name + ".def") 2047db96d56Sopenharmony_ci lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a") 2057db96d56Sopenharmony_ci 2067db96d56Sopenharmony_ci # Generate .def file 2077db96d56Sopenharmony_ci contents = [ 2087db96d56Sopenharmony_ci "LIBRARY %s" % os.path.basename(output_filename), 2097db96d56Sopenharmony_ci "EXPORTS"] 2107db96d56Sopenharmony_ci for sym in export_symbols: 2117db96d56Sopenharmony_ci contents.append(sym) 2127db96d56Sopenharmony_ci self.execute(write_file, (def_file, contents), 2137db96d56Sopenharmony_ci "writing %s" % def_file) 2147db96d56Sopenharmony_ci 2157db96d56Sopenharmony_ci # next add options for def-file and to creating import libraries 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci # dllwrap uses different options than gcc/ld 2187db96d56Sopenharmony_ci if self.linker_dll == "dllwrap": 2197db96d56Sopenharmony_ci extra_preargs.extend(["--output-lib", lib_file]) 2207db96d56Sopenharmony_ci # for dllwrap we have to use a special option 2217db96d56Sopenharmony_ci extra_preargs.extend(["--def", def_file]) 2227db96d56Sopenharmony_ci # we use gcc/ld here and can be sure ld is >= 2.9.10 2237db96d56Sopenharmony_ci else: 2247db96d56Sopenharmony_ci # doesn't work: bfd_close build\...\libfoo.a: Invalid operation 2257db96d56Sopenharmony_ci #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file]) 2267db96d56Sopenharmony_ci # for gcc/ld the def-file is specified as any object files 2277db96d56Sopenharmony_ci objects.append(def_file) 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci #end: if ((export_symbols is not None) and 2307db96d56Sopenharmony_ci # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")): 2317db96d56Sopenharmony_ci 2327db96d56Sopenharmony_ci # who wants symbols and a many times larger output file 2337db96d56Sopenharmony_ci # should explicitly switch the debug mode on 2347db96d56Sopenharmony_ci # otherwise we let dllwrap/ld strip the output file 2357db96d56Sopenharmony_ci # (On my machine: 10KiB < stripped_file < ??100KiB 2367db96d56Sopenharmony_ci # unstripped_file = stripped_file + XXX KiB 2377db96d56Sopenharmony_ci # ( XXX=254 for a typical python extension)) 2387db96d56Sopenharmony_ci if not debug: 2397db96d56Sopenharmony_ci extra_preargs.append("-s") 2407db96d56Sopenharmony_ci 2417db96d56Sopenharmony_ci UnixCCompiler.link(self, target_desc, objects, output_filename, 2427db96d56Sopenharmony_ci output_dir, libraries, library_dirs, 2437db96d56Sopenharmony_ci runtime_library_dirs, 2447db96d56Sopenharmony_ci None, # export_symbols, we do this in our def-file 2457db96d56Sopenharmony_ci debug, extra_preargs, extra_postargs, build_temp, 2467db96d56Sopenharmony_ci target_lang) 2477db96d56Sopenharmony_ci 2487db96d56Sopenharmony_ci # -- Miscellaneous methods ----------------------------------------- 2497db96d56Sopenharmony_ci 2507db96d56Sopenharmony_ci def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): 2517db96d56Sopenharmony_ci """Adds supports for rc and res files.""" 2527db96d56Sopenharmony_ci if output_dir is None: 2537db96d56Sopenharmony_ci output_dir = '' 2547db96d56Sopenharmony_ci obj_names = [] 2557db96d56Sopenharmony_ci for src_name in source_filenames: 2567db96d56Sopenharmony_ci # use normcase to make sure '.rc' is really '.rc' and not '.RC' 2577db96d56Sopenharmony_ci base, ext = os.path.splitext(os.path.normcase(src_name)) 2587db96d56Sopenharmony_ci if ext not in (self.src_extensions + ['.rc','.res']): 2597db96d56Sopenharmony_ci raise UnknownFileError("unknown file type '%s' (from '%s')" % \ 2607db96d56Sopenharmony_ci (ext, src_name)) 2617db96d56Sopenharmony_ci if strip_dir: 2627db96d56Sopenharmony_ci base = os.path.basename (base) 2637db96d56Sopenharmony_ci if ext in ('.res', '.rc'): 2647db96d56Sopenharmony_ci # these need to be compiled to object files 2657db96d56Sopenharmony_ci obj_names.append (os.path.join(output_dir, 2667db96d56Sopenharmony_ci base + ext + self.obj_extension)) 2677db96d56Sopenharmony_ci else: 2687db96d56Sopenharmony_ci obj_names.append (os.path.join(output_dir, 2697db96d56Sopenharmony_ci base + self.obj_extension)) 2707db96d56Sopenharmony_ci return obj_names 2717db96d56Sopenharmony_ci 2727db96d56Sopenharmony_ci# the same as cygwin plus some additional parameters 2737db96d56Sopenharmony_ciclass Mingw32CCompiler(CygwinCCompiler): 2747db96d56Sopenharmony_ci """ Handles the Mingw32 port of the GNU C compiler to Windows. 2757db96d56Sopenharmony_ci """ 2767db96d56Sopenharmony_ci compiler_type = 'mingw32' 2777db96d56Sopenharmony_ci 2787db96d56Sopenharmony_ci def __init__(self, verbose=0, dry_run=0, force=0): 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci CygwinCCompiler.__init__ (self, verbose, dry_run, force) 2817db96d56Sopenharmony_ci 2827db96d56Sopenharmony_ci # ld_version >= "2.13" support -shared so use it instead of 2837db96d56Sopenharmony_ci # -mdll -static 2847db96d56Sopenharmony_ci if self.ld_version >= "2.13": 2857db96d56Sopenharmony_ci shared_option = "-shared" 2867db96d56Sopenharmony_ci else: 2877db96d56Sopenharmony_ci shared_option = "-mdll -static" 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_ci # A real mingw32 doesn't need to specify a different entry point, 2907db96d56Sopenharmony_ci # but cygwin 2.91.57 in no-cygwin-mode needs it. 2917db96d56Sopenharmony_ci if self.gcc_version <= "2.91.57": 2927db96d56Sopenharmony_ci entry_point = '--entry _DllMain@12' 2937db96d56Sopenharmony_ci else: 2947db96d56Sopenharmony_ci entry_point = '' 2957db96d56Sopenharmony_ci 2967db96d56Sopenharmony_ci if is_cygwingcc(): 2977db96d56Sopenharmony_ci raise CCompilerError( 2987db96d56Sopenharmony_ci 'Cygwin gcc cannot be used with --compiler=mingw32') 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci self.set_executables(compiler='gcc -O -Wall', 3017db96d56Sopenharmony_ci compiler_so='gcc -mdll -O -Wall', 3027db96d56Sopenharmony_ci compiler_cxx='g++ -O -Wall', 3037db96d56Sopenharmony_ci linker_exe='gcc', 3047db96d56Sopenharmony_ci linker_so='%s %s %s' 3057db96d56Sopenharmony_ci % (self.linker_dll, shared_option, 3067db96d56Sopenharmony_ci entry_point)) 3077db96d56Sopenharmony_ci # Maybe we should also append -mthreads, but then the finished 3087db96d56Sopenharmony_ci # dlls need another dll (mingwm10.dll see Mingw32 docs) 3097db96d56Sopenharmony_ci # (-mthreads: Support thread-safe exception handling on `Mingw32') 3107db96d56Sopenharmony_ci 3117db96d56Sopenharmony_ci # no additional libraries needed 3127db96d56Sopenharmony_ci self.dll_libraries=[] 3137db96d56Sopenharmony_ci 3147db96d56Sopenharmony_ci # Include the appropriate MSVC runtime library if Python was built 3157db96d56Sopenharmony_ci # with MSVC 7.0 or later. 3167db96d56Sopenharmony_ci self.dll_libraries = get_msvcr() 3177db96d56Sopenharmony_ci 3187db96d56Sopenharmony_ci# Because these compilers aren't configured in Python's pyconfig.h file by 3197db96d56Sopenharmony_ci# default, we should at least warn the user if he is using an unmodified 3207db96d56Sopenharmony_ci# version. 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ciCONFIG_H_OK = "ok" 3237db96d56Sopenharmony_ciCONFIG_H_NOTOK = "not ok" 3247db96d56Sopenharmony_ciCONFIG_H_UNCERTAIN = "uncertain" 3257db96d56Sopenharmony_ci 3267db96d56Sopenharmony_cidef check_config_h(): 3277db96d56Sopenharmony_ci """Check if the current Python installation appears amenable to building 3287db96d56Sopenharmony_ci extensions with GCC. 3297db96d56Sopenharmony_ci 3307db96d56Sopenharmony_ci Returns a tuple (status, details), where 'status' is one of the following 3317db96d56Sopenharmony_ci constants: 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_ci - CONFIG_H_OK: all is well, go ahead and compile 3347db96d56Sopenharmony_ci - CONFIG_H_NOTOK: doesn't look good 3357db96d56Sopenharmony_ci - CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h 3367db96d56Sopenharmony_ci 3377db96d56Sopenharmony_ci 'details' is a human-readable string explaining the situation. 3387db96d56Sopenharmony_ci 3397db96d56Sopenharmony_ci Note there are two ways to conclude "OK": either 'sys.version' contains 3407db96d56Sopenharmony_ci the string "GCC" (implying that this Python was built with GCC), or the 3417db96d56Sopenharmony_ci installed "pyconfig.h" contains the string "__GNUC__". 3427db96d56Sopenharmony_ci """ 3437db96d56Sopenharmony_ci 3447db96d56Sopenharmony_ci # XXX since this function also checks sys.version, it's not strictly a 3457db96d56Sopenharmony_ci # "pyconfig.h" check -- should probably be renamed... 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_ci from distutils import sysconfig 3487db96d56Sopenharmony_ci 3497db96d56Sopenharmony_ci # if sys.version contains GCC then python was compiled with GCC, and the 3507db96d56Sopenharmony_ci # pyconfig.h file should be OK 3517db96d56Sopenharmony_ci if "GCC" in sys.version: 3527db96d56Sopenharmony_ci return CONFIG_H_OK, "sys.version mentions 'GCC'" 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_ci # let's see if __GNUC__ is mentioned in python.h 3557db96d56Sopenharmony_ci fn = sysconfig.get_config_h_filename() 3567db96d56Sopenharmony_ci try: 3577db96d56Sopenharmony_ci config_h = open(fn) 3587db96d56Sopenharmony_ci try: 3597db96d56Sopenharmony_ci if "__GNUC__" in config_h.read(): 3607db96d56Sopenharmony_ci return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn 3617db96d56Sopenharmony_ci else: 3627db96d56Sopenharmony_ci return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn 3637db96d56Sopenharmony_ci finally: 3647db96d56Sopenharmony_ci config_h.close() 3657db96d56Sopenharmony_ci except OSError as exc: 3667db96d56Sopenharmony_ci return (CONFIG_H_UNCERTAIN, 3677db96d56Sopenharmony_ci "couldn't read '%s': %s" % (fn, exc.strerror)) 3687db96d56Sopenharmony_ci 3697db96d56Sopenharmony_ciRE_VERSION = re.compile(br'(\d+\.\d+(\.\d+)*)') 3707db96d56Sopenharmony_ci 3717db96d56Sopenharmony_cidef _find_exe_version(cmd): 3727db96d56Sopenharmony_ci """Find the version of an executable by running `cmd` in the shell. 3737db96d56Sopenharmony_ci 3747db96d56Sopenharmony_ci If the command is not found, or the output does not match 3757db96d56Sopenharmony_ci `RE_VERSION`, returns None. 3767db96d56Sopenharmony_ci """ 3777db96d56Sopenharmony_ci executable = cmd.split()[0] 3787db96d56Sopenharmony_ci if find_executable(executable) is None: 3797db96d56Sopenharmony_ci return None 3807db96d56Sopenharmony_ci out = Popen(cmd, shell=True, stdout=PIPE).stdout 3817db96d56Sopenharmony_ci try: 3827db96d56Sopenharmony_ci out_string = out.read() 3837db96d56Sopenharmony_ci finally: 3847db96d56Sopenharmony_ci out.close() 3857db96d56Sopenharmony_ci result = RE_VERSION.search(out_string) 3867db96d56Sopenharmony_ci if result is None: 3877db96d56Sopenharmony_ci return None 3887db96d56Sopenharmony_ci # LooseVersion works with strings 3897db96d56Sopenharmony_ci # so we need to decode our bytes 3907db96d56Sopenharmony_ci return LooseVersion(result.group(1).decode()) 3917db96d56Sopenharmony_ci 3927db96d56Sopenharmony_cidef get_versions(): 3937db96d56Sopenharmony_ci """ Try to find out the versions of gcc, ld and dllwrap. 3947db96d56Sopenharmony_ci 3957db96d56Sopenharmony_ci If not possible it returns None for it. 3967db96d56Sopenharmony_ci """ 3977db96d56Sopenharmony_ci commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version'] 3987db96d56Sopenharmony_ci return tuple([_find_exe_version(cmd) for cmd in commands]) 3997db96d56Sopenharmony_ci 4007db96d56Sopenharmony_cidef is_cygwingcc(): 4017db96d56Sopenharmony_ci '''Try to determine if the gcc that would be used is from cygwin.''' 4027db96d56Sopenharmony_ci out_string = check_output(['gcc', '-dumpmachine']) 4037db96d56Sopenharmony_ci return out_string.strip().endswith(b'cygwin') 404