From 2ad8784dfeb816829995613fb5fd9818f3e88922 Mon Sep 17 00:00:00 2001 From: Naveen M K Date: Tue, 4 Oct 2022 13:49:49 +0530 Subject: [PATCH] Add support for building extensions using MinGW compilers --- distutils/ccompiler.py | 6 +++++- distutils/command/build_ext.py | 8 ++++---- distutils/cygwinccompiler.py | 4 ++-- distutils/sysconfig.py | 9 ++++++--- distutils/util.py | 9 +++++++++ 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/distutils/ccompiler.py b/distutils/ccompiler.py index c1c7d5476e..dba2e61551 100644 --- a/distutils/ccompiler.py +++ b/distutils/ccompiler.py @@ -19,7 +19,7 @@ from .file_util import move_file from .dir_util import mkpath from ._modified import newer_group -from .util import split_quoted, execute +from .util import split_quoted, execute, is_mingw from ._log import log @@ -1076,6 +1076,10 @@ def get_default_compiler(osname=None, platform=None): osname = os.name if platform is None: platform = sys.platform + # Mingw is a special case where sys.platform is 'win32' but we + # want to use the 'mingw32' compiler, so check it first + if is_mingw(): + return 'mingw32' for pattern, compiler in _default_compilers: if ( re.match(pattern, platform) is not None diff --git a/distutils/command/build_ext.py b/distutils/command/build_ext.py index b48f462626..4a69e9c113 100644 --- a/distutils/command/build_ext.py +++ b/distutils/command/build_ext.py @@ -21,7 +21,7 @@ from ..sysconfig import get_config_h_filename from .._modified import newer_group from ..extension import Extension -from ..util import get_platform +from ..util import get_platform, is_mingw from distutils._log import log from . import py37compat @@ -189,7 +189,7 @@ def finalize_options(self): # noqa: C901 # for extensions under windows use different directories # for Release and Debug builds. # also Python's library directory must be appended to library_dirs - if os.name == 'nt': + if os.name == 'nt' and not is_mingw(): # the 'libs' directory is for binary installs - we assume that # must be the *native* platform. But we don't really support # cross-compiling via a binary install anyway, so we let it go. @@ -742,7 +742,7 @@ def get_libraries(self, ext): # noqa: C901 # pyconfig.h that MSVC groks. The other Windows compilers all seem # to need it mentioned explicitly, though, so that's what we do. # Append '_d' to the python import library on debug builds. - if sys.platform == "win32": + if sys.platform == "win32" and not is_mingw(): from .._msvccompiler import MSVCCompiler if not isinstance(self.compiler, MSVCCompiler): @@ -772,7 +772,7 @@ def get_libraries(self, ext): # noqa: C901 # A native build on an Android device or on Cygwin if hasattr(sys, 'getandroidapilevel'): link_libpython = True - elif sys.platform == 'cygwin': + elif sys.platform == 'cygwin' or is_mingw(): link_libpython = True elif '_PYTHON_HOST_PLATFORM' in os.environ: # We are cross-compiling for one of the relevant platforms diff --git a/distutils/cygwinccompiler.py b/distutils/cygwinccompiler.py index 47efa377c5..7ed169f330 100644 --- a/distutils/cygwinccompiler.py +++ b/distutils/cygwinccompiler.py @@ -57,7 +57,7 @@ def get_msvcr(): try: msc_ver = int(match.group(1)) except AttributeError: - return + return [] try: return _msvcr_lookup[msc_ver] except KeyError: @@ -277,7 +277,7 @@ def __init__(self, verbose=0, dry_run=0, force=0): self.set_executables( compiler='%s -O -Wall' % self.cc, - compiler_so='%s -mdll -O -Wall' % self.cc, + compiler_so='%s -shared -O -Wall' % self.cc, compiler_cxx='%s -O -Wall' % self.cxx, linker_exe='%s' % self.cc, linker_so='{} {}'.format(self.linker_dll, shared_option), diff --git a/distutils/sysconfig.py b/distutils/sysconfig.py index a40a7231b3..166d85437a 100644 --- a/distutils/sysconfig.py +++ b/distutils/sysconfig.py @@ -18,6 +18,7 @@ from .errors import DistutilsPlatformError from . import py39compat from ._functools import pass_none +from .util import is_mingw IS_PYPY = '__pypy__' in sys.builtin_module_names @@ -120,8 +121,10 @@ def get_python_inc(plat_specific=0, prefix=None): """ default_prefix = BASE_EXEC_PREFIX if plat_specific else BASE_PREFIX resolved_prefix = prefix if prefix is not None else default_prefix + # MinGW imitates posix like layout, but os.name != posix + os_name = "posix" if is_mingw() else os.name try: - getter = globals()[f'_get_python_inc_{os.name}'] + getter = globals()[f'_get_python_inc_{os_name}'] except KeyError: raise DistutilsPlatformError( "I don't know where Python installs its C header files " @@ -244,7 +247,7 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): else: prefix = plat_specific and EXEC_PREFIX or PREFIX - if os.name == "posix": + if os.name == "posix" or is_mingw(): if plat_specific or standard_lib: # Platform-specific modules (any module from a non-pure-Python # module distribution) or standard Python library modules. @@ -273,7 +276,7 @@ def customize_compiler(compiler): # noqa: C901 Mainly needed on Unix, so we can plug in the information that varies across Unices and is stored in Python's Makefile. """ - if compiler.compiler_type == "unix": + if compiler.compiler_type in ["unix", "cygwin", "mingw32"]: if sys.platform == "darwin": # Perform first-time customization of compiler-related # config vars on OS X now that we know we need a compiler. diff --git a/distutils/util.py b/distutils/util.py index 5408b16032..bec979d7da 100644 --- a/distutils/util.py +++ b/distutils/util.py @@ -517,3 +517,12 @@ def rfc822_escape(header): suffix = indent if ends_in_newline else "" return indent.join(lines) + suffix + + +def is_mingw(): + """Returns True if the current platform is mingw. + + Python compiled with Mingw-w64 has sys.platform == 'win32' and + get_platform() starts with 'mingw'. + """ + return sys.platform == 'win32' and get_platform().startswith('mingw')