• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
2new file mode 100644
3index 0000000..c2293cb
4--- /dev/null
5+++ b/.github/workflows/build.yml
6@@ -0,0 +1,418 @@
7+name: Tests
8+
9+# gh-84728: "paths-ignore" is not used to skip documentation-only PRs, because
10+# it prevents to mark a job as mandatory. A PR cannot be merged if a job is
11+# mandatory but not scheduled because of "paths-ignore".
12+on:
13+  workflow_dispatch:
14+  push:
15+    branches:
16+    - 'main'
17+    - '3.11'
18+    - '3.10'
19+    - '3.9'
20+    - '3.8'
21+    - '3.7'
22+  pull_request:
23+    branches:
24+    - 'main'
25+    - '3.11'
26+    - '3.10'
27+    - '3.9'
28+    - '3.8'
29+    - '3.7'
30+
31+permissions:
32+  contents: read
33+
34+concurrency:
35+  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
36+  cancel-in-progress: true
37+
38+jobs:
39+  check_source:
40+    name: 'Check for source changes'
41+    runs-on: ubuntu-latest
42+    timeout-minutes: 10
43+    outputs:
44+      run_tests: ${{ steps.check.outputs.run_tests }}
45+      run_ssl_tests: ${{ steps.check.outputs.run_ssl_tests }}
46+      config_hash: ${{ steps.config_hash.outputs.hash }}
47+    steps:
48+      - uses: actions/checkout@v3
49+      - name: Check for source changes
50+        id: check
51+        run: |
52+          if [ -z "$GITHUB_BASE_REF" ]; then
53+            echo "run_tests=true" >> $GITHUB_OUTPUT
54+            echo "run_ssl_tests=true" >> $GITHUB_OUTPUT
55+          else
56+            git fetch origin $GITHUB_BASE_REF --depth=1
57+            # git diff "origin/$GITHUB_BASE_REF..." (3 dots) may be more
58+            # reliable than git diff "origin/$GITHUB_BASE_REF.." (2 dots),
59+            # but it requires to download more commits (this job uses
60+            # "git fetch --depth=1").
61+            #
62+            # git diff "origin/$GITHUB_BASE_REF..." (3 dots) works with Git
63+            # 2.26, but Git 2.28 is stricter and fails with "no merge base".
64+            #
65+            # git diff "origin/$GITHUB_BASE_REF.." (2 dots) should be enough on
66+            # GitHub, since GitHub starts by merging origin/$GITHUB_BASE_REF
67+            # into the PR branch anyway.
68+            #
69+            # https://github.com/python/core-workflow/issues/373
70+            git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qvE '(\.rst$|^Doc|^Misc)' && echo "run_tests=true" >> $GITHUB_OUTPUT || true
71+            git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qE '(ssl|hashlib|hmac|^.github)' && echo "run_ssl_tests=true" >> $GITHUB_OUTPUT || true
72+          fi
73+      - name: Compute hash for config cache key
74+        id: config_hash
75+        run: |
76+          echo "hash=${{ hashFiles('configure', 'configure.ac', '.github/workflows/build.yml') }}" >> $GITHUB_OUTPUT
77+
78+  check_abi:
79+    name: 'Check if the ABI has changed'
80+    runs-on: ubuntu-20.04
81+    needs: check_source
82+    if: needs.check_source.outputs.run_tests == 'true'
83+    steps:
84+      - uses: actions/checkout@v2
85+      - uses: actions/setup-python@v2
86+      - name: Install Dependencies
87+        run: |
88+            sudo ./.github/workflows/posix-deps-apt.sh
89+            sudo apt-get install -yq abigail-tools
90+      - name: Build CPython
91+        env:
92+          CFLAGS: -g3 -O0
93+        run: |
94+          # Build Python with the libpython dynamic library
95+          ./configure --enable-shared
96+          make -j4
97+      - name: Check for changes in the ABI
98+        id: check
99+        run: |
100+          if ! make check-abidump; then
101+            echo "Generated ABI file is not up to date."
102+            echo "Please, add the release manager of this branch as a reviewer of this PR."
103+            echo ""
104+            echo "The up to date ABI file should be attached to this build as an artifact."
105+            echo ""
106+            echo "To learn more about this check: https://devguide.python.org/setup/#regenerate-the-abi-dump"
107+            echo ""
108+            exit 1
109+          fi
110+      - name: Generate updated ABI files
111+        if: ${{ failure() && steps.check.conclusion == 'failure' }}
112+        run: |
113+          make regen-abidump
114+      - uses: actions/upload-artifact@v3
115+        name: Publish updated ABI files
116+        if: ${{ failure() && steps.check.conclusion == 'failure' }}
117+        with:
118+          name: abi-data
119+          path: ./Doc/data/*.abi
120+
121+  check_generated_files:
122+    name: 'Check if generated files are up to date'
123+    runs-on: ubuntu-latest
124+    timeout-minutes: 60
125+    needs: check_source
126+    if: needs.check_source.outputs.run_tests == 'true'
127+    steps:
128+      - uses: actions/checkout@v3
129+      - name: Restore config.cache
130+        uses: actions/cache@v3
131+        with:
132+          path: config.cache
133+          key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }}
134+      - uses: actions/setup-python@v3
135+      - name: Install Dependencies
136+        run: sudo ./.github/workflows/posix-deps-apt.sh
137+      - name: Add ccache to PATH
138+        run: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
139+      - name: Configure ccache action
140+        uses: hendrikmuhs/ccache-action@v1.2
141+      - name: Check Autoconf version 2.69 and aclocal 1.16.3
142+        run: |
143+          grep "Generated by GNU Autoconf 2.69" configure
144+          grep "aclocal 1.16.3" aclocal.m4
145+          grep -q "runstatedir" configure
146+          grep -q "PKG_PROG_PKG_CONFIG" aclocal.m4
147+      - name: Configure CPython
148+        run: |
149+          # Build Python with the libpython dynamic library
150+          ./configure --config-cache --with-pydebug --enable-shared
151+      - name: Regenerate autoconf files with container image
152+        run: make regen-configure
153+      - name: Build CPython
154+        run: |
155+          # Deepfreeze will usually cause global objects to be added or removed,
156+          # so we run it before regen-global-objects gets rum (in regen-all).
157+          make regen-deepfreeze
158+          make -j4 regen-all
159+          make regen-stdlib-module-names
160+      - name: Check for changes
161+        run: |
162+          git add -u
163+          changes=$(git status --porcelain)
164+          # Check for changes in regenerated files
165+          if test -n "$changes"; then
166+            echo "Generated files not up to date."
167+            echo "Perhaps you forgot to run make regen-all or build.bat --regen. ;)"
168+            echo "configure files must be regenerated with a specific version of autoconf."
169+            echo "$changes"
170+            echo ""
171+            git diff --staged || true
172+            exit 1
173+          fi
174+      - name: Check exported libpython symbols
175+        run: make smelly
176+      - name: Check limited ABI symbols
177+        run: make check-limited-abi
178+
179+  build_win32:
180+    name: 'Windows (x86)'
181+    runs-on: windows-latest
182+    timeout-minutes: 60
183+    needs: check_source
184+    if: needs.check_source.outputs.run_tests == 'true'
185+    env:
186+       IncludeUwp: 'true'
187+    steps:
188+    - uses: actions/checkout@v3
189+    - name: Build CPython
190+      run: .\PCbuild\build.bat -e -d -p Win32
191+    - name: Display build info
192+      run: .\python.bat -m test.pythoninfo
193+    - name: Tests
194+      run: .\PCbuild\rt.bat -p Win32 -d -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0
195+
196+  build_win_amd64:
197+    name: 'Windows (x64)'
198+    runs-on: windows-latest
199+    timeout-minutes: 60
200+    needs: check_source
201+    if: needs.check_source.outputs.run_tests == 'true'
202+    env:
203+       IncludeUwp: 'true'
204+    steps:
205+    - uses: actions/checkout@v3
206+    - name: Register MSVC problem matcher
207+      run: echo "::add-matcher::.github/problem-matchers/msvc.json"
208+    - name: Build CPython
209+      run: .\PCbuild\build.bat -e -d -p x64
210+    - name: Display build info
211+      run: .\python.bat -m test.pythoninfo
212+    - name: Tests
213+      run: .\PCbuild\rt.bat -p x64 -d -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0
214+
215+  build_macos:
216+    name: 'macOS'
217+    runs-on: macos-latest
218+    timeout-minutes: 60
219+    needs: check_source
220+    if: needs.check_source.outputs.run_tests == 'true'
221+    env:
222+      HOMEBREW_NO_ANALYTICS: 1
223+      HOMEBREW_NO_AUTO_UPDATE: 1
224+      HOMEBREW_NO_INSTALL_CLEANUP: 1
225+      PYTHONSTRICTEXTENSIONBUILD: 1
226+    steps:
227+    - uses: actions/checkout@v3
228+    - name: Restore config.cache
229+      uses: actions/cache@v3
230+      with:
231+        path: config.cache
232+        key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }}
233+    - name: Install Homebrew dependencies
234+      run: brew install pkg-config openssl@1.1 xz gdbm tcl-tk
235+    - name: Configure CPython
236+      run: |
237+        CFLAGS="-I$(brew --prefix gdbm)/include -I$(brew --prefix xz)/include" \
238+        LDFLAGS="-L$(brew --prefix gdbm)/lib -I$(brew --prefix xz)/lib" \
239+        PKG_CONFIG_PATH="$(brew --prefix tcl-tk)/lib/pkgconfig" \
240+        ./configure \
241+          --config-cache \
242+          --with-pydebug \
243+          --prefix=/opt/python-dev \
244+          --with-openssl="$(brew --prefix openssl@1.1)"
245+    - name: Build CPython
246+      run: make -j4
247+    - name: Display build info
248+      run: make pythoninfo
249+    - name: Tests
250+      run: make buildbottest TESTOPTS="-j4 -uall,-cpu"
251+
252+  build_ubuntu:
253+    name: 'Ubuntu'
254+    runs-on: ubuntu-20.04
255+    timeout-minutes: 60
256+    needs: check_source
257+    if: needs.check_source.outputs.run_tests == 'true'
258+    env:
259+      OPENSSL_VER: 1.1.1u
260+      PYTHONSTRICTEXTENSIONBUILD: 1
261+    steps:
262+    - uses: actions/checkout@v3
263+    - name: Register gcc problem matcher
264+      run: echo "::add-matcher::.github/problem-matchers/gcc.json"
265+    - name: Install Dependencies
266+      run: sudo ./.github/workflows/posix-deps-apt.sh
267+    - name: Configure OpenSSL env vars
268+      run: |
269+        echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> $GITHUB_ENV
270+        echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}" >> $GITHUB_ENV
271+        echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV
272+    - name: 'Restore OpenSSL build'
273+      id: cache-openssl
274+      uses: actions/cache@v3
275+      with:
276+        path: ./multissl/openssl/${{ env.OPENSSL_VER }}
277+        key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
278+    - name: Install OpenSSL
279+      if: steps.cache-openssl.outputs.cache-hit != 'true'
280+      run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux
281+    - name: Add ccache to PATH
282+      run: |
283+        echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
284+    - name: Configure ccache action
285+      uses: hendrikmuhs/ccache-action@v1.2
286+    - name: Setup directory envs for out-of-tree builds
287+      run: |
288+        echo "CPYTHON_RO_SRCDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-ro-srcdir)" >> $GITHUB_ENV
289+        echo "CPYTHON_BUILDDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-builddir)" >> $GITHUB_ENV
290+    - name: Create directories for read-only out-of-tree builds
291+      run: mkdir -p $CPYTHON_RO_SRCDIR $CPYTHON_BUILDDIR
292+    - name: Bind mount sources read-only
293+      run: sudo mount --bind -o ro $GITHUB_WORKSPACE $CPYTHON_RO_SRCDIR
294+    - name: Restore config.cache
295+      uses: actions/cache@v3
296+      with:
297+        path: ${{ env.CPYTHON_BUILDDIR }}/config.cache
298+        key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }}
299+    - name: Configure CPython out-of-tree
300+      working-directory: ${{ env.CPYTHON_BUILDDIR }}
301+      run: |
302+        ../cpython-ro-srcdir/configure \
303+          --config-cache \
304+          --with-pydebug \
305+          --with-openssl=$OPENSSL_DIR
306+    - name: Build CPython out-of-tree
307+      working-directory: ${{ env.CPYTHON_BUILDDIR }}
308+      run: make -j4
309+    - name: Display build info
310+      working-directory: ${{ env.CPYTHON_BUILDDIR }}
311+      run: make pythoninfo
312+    - name: Remount sources writable for tests
313+      # some tests write to srcdir, lack of pyc files slows down testing
314+      run: sudo mount $CPYTHON_RO_SRCDIR -oremount,rw
315+    - name: Tests
316+      working-directory: ${{ env.CPYTHON_BUILDDIR }}
317+      run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu"
318+
319+  build_ubuntu_ssltests:
320+    name: 'Ubuntu SSL tests with OpenSSL'
321+    runs-on: ubuntu-20.04
322+    timeout-minutes: 60
323+    needs: check_source
324+    if: needs.check_source.outputs.run_tests == 'true' && needs.check_source.outputs.run_ssl_tests == 'true'
325+    strategy:
326+      fail-fast: false
327+      matrix:
328+        openssl_ver: [1.1.1u, 3.0.9, 3.1.1]
329+    env:
330+      OPENSSL_VER: ${{ matrix.openssl_ver }}
331+      MULTISSL_DIR: ${{ github.workspace }}/multissl
332+      OPENSSL_DIR: ${{ github.workspace }}/multissl/openssl/${{ matrix.openssl_ver }}
333+      LD_LIBRARY_PATH: ${{ github.workspace }}/multissl/openssl/${{ matrix.openssl_ver }}/lib
334+    steps:
335+    - uses: actions/checkout@v3
336+    - name: Restore config.cache
337+      uses: actions/cache@v3
338+      with:
339+        path: config.cache
340+        key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }}
341+    - name: Register gcc problem matcher
342+      run: echo "::add-matcher::.github/problem-matchers/gcc.json"
343+    - name: Install Dependencies
344+      run: sudo ./.github/workflows/posix-deps-apt.sh
345+    - name: Configure OpenSSL env vars
346+      run: |
347+        echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> $GITHUB_ENV
348+        echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}" >> $GITHUB_ENV
349+        echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV
350+    - name: 'Restore OpenSSL build'
351+      id: cache-openssl
352+      uses: actions/cache@v3
353+      with:
354+        path: ./multissl/openssl/${{ env.OPENSSL_VER }}
355+        key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
356+    - name: Install OpenSSL
357+      if: steps.cache-openssl.outputs.cache-hit != 'true'
358+      run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux
359+    - name: Add ccache to PATH
360+      run: |
361+        echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
362+    - name: Configure ccache action
363+      uses: hendrikmuhs/ccache-action@v1.2
364+    - name: Configure CPython
365+      run: ./configure --config-cache --with-pydebug --with-openssl=$OPENSSL_DIR
366+    - name: Build CPython
367+      run: make -j4
368+    - name: Display build info
369+      run: make pythoninfo
370+    - name: SSL tests
371+      run: ./python Lib/test/ssltests.py
372+
373+  build_asan:
374+    name: 'Address sanitizer'
375+    runs-on: ubuntu-20.04
376+    timeout-minutes: 60
377+    needs: check_source
378+    if: needs.check_source.outputs.run_tests == 'true'
379+    env:
380+      OPENSSL_VER: 1.1.1u
381+      PYTHONSTRICTEXTENSIONBUILD: 1
382+      ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0
383+    steps:
384+    - uses: actions/checkout@v3
385+    - name: Restore config.cache
386+      uses: actions/cache@v3
387+      with:
388+        path: config.cache
389+        key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }}
390+    - name: Register gcc problem matcher
391+      run: echo "::add-matcher::.github/problem-matchers/gcc.json"
392+    - name: Install Dependencies
393+      run: sudo ./.github/workflows/posix-deps-apt.sh
394+    - name: Set up GCC-10 for ASAN
395+      uses: egor-tensin/setup-gcc@v1
396+      with:
397+        version: 10
398+    - name: Configure OpenSSL env vars
399+      run: |
400+        echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> $GITHUB_ENV
401+        echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}" >> $GITHUB_ENV
402+        echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV
403+    - name: 'Restore OpenSSL build'
404+      id: cache-openssl
405+      uses: actions/cache@v3
406+      with:
407+        path: ./multissl/openssl/${{ env.OPENSSL_VER }}
408+        key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
409+    - name: Install OpenSSL
410+      if: steps.cache-openssl.outputs.cache-hit != 'true'
411+      run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux
412+    - name: Add ccache to PATH
413+      run: |
414+        echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
415+    - name: Configure ccache action
416+      uses: hendrikmuhs/ccache-action@v1.2
417+    - name: Configure CPython
418+      run: ./configure --config-cache --with-address-sanitizer --without-pymalloc
419+    - name: Build CPython
420+      run: make -j4
421+    - name: Display build info
422+      run: make pythoninfo
423+    - name: Tests
424+      run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu"
425diff --git a/.gitignore b/.gitignore
426index 0ddfd71..d42e111 100644
427--- a/.gitignore
428+++ b/.gitignore
429@@ -114,6 +114,7 @@ PCbuild/win32/
430 Tools/unicode/data/
431 /autom4te.cache
432 /build/
433+/builddir/
434 /config.cache
435 /config.log
436 /config.status
437@@ -150,6 +151,3 @@ Python/frozen_modules/MANIFEST
438 # Ignore ./python binary on Unix but still look into ./Python/ directory.
439 /python
440 !/Python/
441-
442-# main branch only: ABI files are not checked/maintained
443-Doc/data/python*.abi
444diff --git a/Include/bytesobject.h b/Include/bytesobject.h
445index 4c4dc40..cd88bed 100644
446--- a/Include/bytesobject.h
447+++ b/Include/bytesobject.h
448@@ -35,9 +35,9 @@ PyAPI_FUNC(PyObject *) PyBytes_FromStringAndSize(const char *, Py_ssize_t);
449 PyAPI_FUNC(PyObject *) PyBytes_FromString(const char *);
450 PyAPI_FUNC(PyObject *) PyBytes_FromObject(PyObject *);
451 PyAPI_FUNC(PyObject *) PyBytes_FromFormatV(const char*, va_list)
452-                                Py_GCC_ATTRIBUTE((format(printf, 1, 0)));
453+                                Py_PRINTF(1, 0);
454 PyAPI_FUNC(PyObject *) PyBytes_FromFormat(const char*, ...)
455-                                Py_GCC_ATTRIBUTE((format(printf, 1, 2)));
456+                                Py_PRINTF(1, 2);
457 PyAPI_FUNC(Py_ssize_t) PyBytes_Size(PyObject *);
458 PyAPI_FUNC(char *) PyBytes_AsString(PyObject *);
459 PyAPI_FUNC(PyObject *) PyBytes_Repr(PyObject *, int);
460diff --git a/Include/fileobject.h b/Include/fileobject.h
461index 4c983e7..260e4c1 100644
462--- a/Include/fileobject.h
463+++ b/Include/fileobject.h
464@@ -30,7 +30,7 @@ PyAPI_DATA(int) Py_UTF8Mode;
465 #endif
466
467 /* A routine to check if a file descriptor can be select()-ed. */
468-#ifdef _MSC_VER
469+#ifdef MS_WINDOWS
470     /* On Windows, any socket fd can be select()-ed, no matter how high */
471     #define _PyIsSelectable_fd(FD) (1)
472 #else
473diff --git a/Include/internal/pycore_condvar.h b/Include/internal/pycore_condvar.h
474index 981c962..ed9e6a7 100644
475--- a/Include/internal/pycore_condvar.h
476+++ b/Include/internal/pycore_condvar.h
477@@ -5,6 +5,12 @@
478 #  error "this header requires Py_BUILD_CORE define"
479 #endif
480
481+#ifdef __MINGW32__
482+# if !defined(HAVE_PTHREAD_H) || defined(NT_THREADS)
483+#  undef _POSIX_THREADS
484+# endif
485+#endif
486+
487 #ifndef _POSIX_THREADS
488 /* This means pthreads are not implemented in libc headers, hence the macro
489    not present in unistd.h. But they still can be implemented as an external
490@@ -39,6 +45,10 @@
491 /* include windows if it hasn't been done before */
492 #define WIN32_LEAN_AND_MEAN
493 #include <windows.h>
494+/* winpthreads are involved via windows header, so need undef _POSIX_THREADS after header include */
495+#if defined(_POSIX_THREADS)
496+#undef _POSIX_THREADS
497+#endif
498
499 /* options */
500 /* non-emulated condition variables are provided for those that want
501diff --git a/Include/iscygpty.h b/Include/iscygpty.h
502new file mode 100644
503index 0000000..82fd0af
504--- /dev/null
505+++ b/Include/iscygpty.h
506@@ -0,0 +1,41 @@
507+/*
508+ * iscygpty.h -- part of ptycheck
509+ * https://github.com/k-takata/ptycheck
510+ *
511+ * Copyright (c) 2015-2017 K.Takata
512+ *
513+ * You can redistribute it and/or modify it under the terms of either
514+ * the MIT license (as described below) or the Vim license.
515+ *
516+ * Permission is hereby granted, free of charge, to any person obtaining
517+ * a copy of this software and associated documentation files (the
518+ * "Software"), to deal in the Software without restriction, including
519+ * without limitation the rights to use, copy, modify, merge, publish,
520+ * distribute, sublicense, and/or sell copies of the Software, and to
521+ * permit persons to whom the Software is furnished to do so, subject to
522+ * the following conditions:
523+ *
524+ * The above copyright notice and this permission notice shall be
525+ * included in all copies or substantial portions of the Software.
526+ *
527+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
528+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
529+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
530+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
531+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
532+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
533+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
534+ */
535+
536+#ifndef _ISCYGPTY_H
537+#define _ISCYGPTY_H
538+
539+#ifdef _WIN32
540+int is_cygpty(int fd);
541+int is_cygpty_used(void);
542+#else
543+#define is_cygpty(fd)		0
544+#define is_cygpty_used()	0
545+#endif
546+
547+#endif /* _ISCYGPTY_H */
548diff --git a/Include/osdefs.h b/Include/osdefs.h
549index 3243944..99d4977 100644
550--- a/Include/osdefs.h
551+++ b/Include/osdefs.h
552@@ -10,7 +10,6 @@ extern "C" {
553 #ifdef MS_WINDOWS
554 #define SEP L'\\'
555 #define ALTSEP L'/'
556-#define MAXPATHLEN 256
557 #define DELIM L';'
558 #endif
559
560diff --git a/Include/py_curses.h b/Include/py_curses.h
561index b2c7f1b..e6fc813 100644
562--- a/Include/py_curses.h
563+++ b/Include/py_curses.h
564@@ -36,6 +36,13 @@
565 #include <curses.h>
566 #endif
567
568+#if defined(__MINGW32__)
569+#include <windows.h>
570+#if !defined(_ISPAD)
571+#define _ISPAD 0x10
572+#endif
573+#endif
574+
575 #ifdef HAVE_NCURSES_H
576 /* configure was checking <curses.h>, but we will
577    use <ncurses.h>, which has some or all these features. */
578diff --git a/Include/pyerrors.h b/Include/pyerrors.h
579index 34e3de3..fb71fde 100644
580--- a/Include/pyerrors.h
581+++ b/Include/pyerrors.h
582@@ -315,9 +315,9 @@ PyAPI_FUNC(int) PyUnicodeTranslateError_SetReason(
583     );
584
585 PyAPI_FUNC(int) PyOS_snprintf(char *str, size_t size, const char  *format, ...)
586-                        Py_GCC_ATTRIBUTE((format(printf, 3, 4)));
587+                        Py_PRINTF(3, 4);
588 PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
589-                        Py_GCC_ATTRIBUTE((format(printf, 3, 0)));
590+                        Py_PRINTF(3, 0);
591
592 #ifndef Py_LIMITED_API
593 #  define Py_CPYTHON_ERRORS_H
594diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h
595index e4c3b09..21346ba 100644
596--- a/Include/pylifecycle.h
597+++ b/Include/pylifecycle.h
598@@ -21,6 +21,15 @@ PyAPI_FUNC(int) Py_IsInitialized(void);
599 PyAPI_FUNC(PyThreadState *) Py_NewInterpreter(void);
600 PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *);
601
602+PyAPI_FUNC(wchar_t) Py_GetAltSepW(const wchar_t *);
603+PyAPI_FUNC(wchar_t) Py_GetSepW(const wchar_t *);
604+PyAPI_FUNC(char) Py_GetSepA(const char *);
605+
606+PyAPI_FUNC(void) Py_NormalizeSepsW(wchar_t *);
607+PyAPI_FUNC(void) Py_NormalizeSepsA(char *);
608+
609+PyAPI_FUNC(void) Py_NormalizeSepsPathcchW(wchar_t *);
610+
611
612 /* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level
613  * exit functions.
614diff --git a/Include/pyport.h b/Include/pyport.h
615index 93250f4..b816c90 100644
616--- a/Include/pyport.h
617+++ b/Include/pyport.h
618@@ -53,6 +53,21 @@
619 #endif
620
621
622+#ifdef __MINGW32__
623+/* Translate GCC[mingw*] platform specific defines to those
624+ * used in python code.
625+ */
626+#if !defined(MS_WIN64) && defined(_WIN64)
627+#  define MS_WIN64
628+#endif
629+#if !defined(MS_WIN32) && defined(_WIN32)
630+#  define MS_WIN32
631+#endif
632+#if !defined(MS_WINDOWS) && defined(MS_WIN32)
633+#  define MS_WINDOWS
634+#endif
635+#endif /* __MINGW32__*/
636+
637 /**************************************************************************
638 Symbols and macros to supply platform-independent interfaces to basic
639 C language & library operations whose spellings vary across platforms.
640@@ -509,12 +524,12 @@ extern char * _getpty(int *, int, mode_t, int);
641 */
642
643 /*
644-  All windows ports, except cygwin, are handled in PC/pyconfig.h.
645+  Only MSVC windows ports is handled in PC/pyconfig.h.
646
647-  Cygwin is the only other autoconf platform requiring special
648+  Cygwin and Mingw is the only other autoconf platform requiring special
649   linkage handling and it uses __declspec().
650 */
651-#if defined(__CYGWIN__)
652+#if defined(__CYGWIN__) || defined(__MINGW32__)
653 #       define HAVE_DECLSPEC_DLL
654 #endif
655
656@@ -527,21 +542,23 @@ extern char * _getpty(int *, int, mode_t, int);
657 #                       define PyAPI_FUNC(RTYPE) Py_EXPORTED_SYMBOL RTYPE
658 #                       define PyAPI_DATA(RTYPE) extern Py_EXPORTED_SYMBOL RTYPE
659         /* module init functions inside the core need no external linkage */
660-        /* except for Cygwin to handle embedding */
661-#                       if defined(__CYGWIN__)
662+        /* except for Cygwin/Mingw to handle embedding */
663+#                       if defined(__CYGWIN__) || defined(__MINGW32__)
664 #                               define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*
665-#                       else /* __CYGWIN__ */
666+#                       else /* __CYGWIN__ || __MINGW32__*/
667 #                               define PyMODINIT_FUNC PyObject*
668-#                       endif /* __CYGWIN__ */
669+#                       endif /* __CYGWIN__ || __MINGW32__*/
670 #               else /* Py_BUILD_CORE */
671         /* Building an extension module, or an embedded situation */
672         /* public Python functions and data are imported */
673         /* Under Cygwin, auto-import functions to prevent compilation */
674         /* failures similar to those described at the bottom of 4.1: */
675         /* http://docs.python.org/extending/windows.html#a-cookbook-approach */
676-#                       if !defined(__CYGWIN__)
677+#                       if defined(__CYGWIN__) || defined(__MINGW32__)
678+#                               define PyAPI_FUNC(RTYPE) RTYPE
679+#                       else
680 #                               define PyAPI_FUNC(RTYPE) Py_IMPORTED_SYMBOL RTYPE
681-#                       endif /* !__CYGWIN__ */
682+#                       endif /* __CYGWIN__ || __MINGW32__*/
683 #                       define PyAPI_DATA(RTYPE) extern Py_IMPORTED_SYMBOL RTYPE
684         /* module init functions outside the core must be exported */
685 #                       if defined(__cplusplus)
686@@ -641,6 +658,12 @@ extern char * _getpty(int *, int, mode_t, int);
687
688 #define Py_VA_COPY va_copy
689
690+#if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__>= 4) || __GNUC__ > 4)
691+#  define Py_PRINTF(X,Y) Py_GCC_ATTRIBUTE((format(gnu_printf,X,Y)))
692+#else
693+#  define Py_PRINTF(X,Y) Py_GCC_ATTRIBUTE((format(printf,X,Y)))
694+#endif
695+
696 /*
697  * Convenient macros to deal with endianness of the platform. WORDS_BIGENDIAN is
698  * detected by configure and defined in pyconfig.h. The code in pyconfig.h
699diff --git a/Include/pythread.h b/Include/pythread.h
700index a483290..9bf8bd6 100644
701--- a/Include/pythread.h
702+++ b/Include/pythread.h
703@@ -7,6 +7,12 @@ typedef void *PyThread_type_lock;
704 extern "C" {
705 #endif
706
707+#ifdef __MINGW32__
708+# if !defined(HAVE_PTHREAD_H) || defined(NT_THREADS)
709+#  undef _POSIX_THREADS
710+# endif
711+#endif
712+
713 /* Return status codes for Python lock acquisition.  Chosen for maximum
714  * backwards compatibility, ie failure -> 0, success -> 1.  */
715 typedef enum PyLockStatus {
716diff --git a/Include/sysmodule.h b/Include/sysmodule.h
717index b508711..d6767dc 100644
718--- a/Include/sysmodule.h
719+++ b/Include/sysmodule.h
720@@ -15,9 +15,9 @@ Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int);
721 Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetPath(const wchar_t *);
722
723 PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...)
724-                 Py_GCC_ATTRIBUTE((format(printf, 1, 2)));
725+                 Py_PRINTF(1, 2);
726 PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...)
727-                 Py_GCC_ATTRIBUTE((format(printf, 1, 2)));
728+                 Py_PRINTF(1, 2);
729 PyAPI_FUNC(void) PySys_FormatStdout(const char *format, ...);
730 PyAPI_FUNC(void) PySys_FormatStderr(const char *format, ...);
731
732diff --git a/Lib/compileall.py b/Lib/compileall.py
733index a388931..069ea2b 100644
734--- a/Lib/compileall.py
735+++ b/Lib/compileall.py
736@@ -38,6 +38,8 @@ def _walk_dir(dir, maxlevels, quiet=0):
737         if name == '__pycache__':
738             continue
739         fullname = os.path.join(dir, name)
740+        if sys.platform == "win32" and sys.version.find("GCC") >= 0:
741+            fullname = fullname.replace('\\','/')
742         if not os.path.isdir(fullname):
743             yield fullname
744         elif (maxlevels > 0 and name != os.curdir and name != os.pardir and
745diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py
746index 26135ad..76d583b 100644
747--- a/Lib/ctypes/__init__.py
748+++ b/Lib/ctypes/__init__.py
749@@ -458,7 +458,9 @@ def LoadLibrary(self, name):
750 cdll = LibraryLoader(CDLL)
751 pydll = LibraryLoader(PyDLL)
752
753-if _os.name == "nt":
754+if _os.name == "nt" and _sys.version.find('GCC') >= 0:
755+    pythonapi = PyDLL("libpython%d.%d%s.dll" % (_sys.version_info[:2] + (_sys.abiflags,)), None)
756+elif _os.name == "nt":
757     pythonapi = PyDLL("python dll", None, _sys.dllhandle)
758 elif _sys.platform == "cygwin":
759     pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
760diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py
761index 0c2510e..48ddb3b 100644
762--- a/Lib/ctypes/util.py
763+++ b/Lib/ctypes/util.py
764@@ -31,6 +31,12 @@ def _get_build_version():
765         # else we don't know what version of the compiler this is
766         return None
767
768+    def find_msvcrt_mingw():
769+        is_ucrt = 'clang' in sys.version.lower() or 'ucrt' in sys.version.lower()
770+        if is_ucrt:
771+            return None
772+        return 'msvcrt.dll'
773+
774     def find_msvcrt():
775         """Return the name of the VC runtime dll"""
776         version = _get_build_version()
777@@ -54,6 +60,9 @@ def find_msvcrt():
778
779     def find_library(name):
780         if name in ('c', 'm'):
781+            import sysconfig
782+            if sysconfig.get_platform().startswith('mingw'):
783+                return find_msvcrt_mingw()
784             return find_msvcrt()
785         # See MSDN for the REAL search order.
786         for directory in os.environ['PATH'].split(os.pathsep):
787diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py
788index 4c47f2e..ab61a86 100644
789--- a/Lib/distutils/ccompiler.py
790+++ b/Lib/distutils/ccompiler.py
791@@ -9,7 +9,7 @@
792 from distutils.file_util import move_file
793 from distutils.dir_util import mkpath
794 from distutils.dep_util import newer_group
795-from distutils.util import split_quoted, execute
796+from distutils.util import split_quoted, execute, get_platform
797 from distutils import log
798
799 class CCompiler:
800@@ -948,6 +948,8 @@ def get_default_compiler(osname=None, platform=None):
801         osname = os.name
802     if platform is None:
803         platform = sys.platform
804+    if get_platform().startswith('mingw'):
805+        return 'mingw32'
806     for pattern, compiler in _default_compilers:
807         if re.match(pattern, platform) is not None or \
808            re.match(pattern, osname) is not None:
809diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py
810index f287b34..e87e3ad 100644
811--- a/Lib/distutils/command/build_ext.py
812+++ b/Lib/distutils/command/build_ext.py
813@@ -186,7 +186,7 @@ def finalize_options(self):
814         # for extensions under windows use different directories
815         # for Release and Debug builds.
816         # also Python's library directory must be appended to library_dirs
817-        if os.name == 'nt':
818+        if os.name == 'nt' and not self.plat_name.startswith(('mingw')):
819             # the 'libs' directory is for binary installs - we assume that
820             # must be the *native* platform.  But we don't really support
821             # cross-compiling via a binary install anyway, so we let it go.
822@@ -218,15 +218,16 @@ def finalize_options(self):
823
824         # For extensions under Cygwin, Python's library directory must be
825         # appended to library_dirs
826-        if sys.platform[:6] == 'cygwin':
827-            if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
828+        if sys.platform[:6] == 'cygwin' or self.plat_name.startswith(('mingw')):
829+            if not sysconfig.python_build:
830                 # building third party extensions
831+                config_dir_name = os.path.basename(sysconfig.get_config_var('LIBPL'))
832                 self.library_dirs.append(os.path.join(sys.prefix, "lib",
833                                                       "python" + get_python_version(),
834-                                                      "config"))
835+                                                      config_dir_name))
836             else:
837                 # building python standard extensions
838-                self.library_dirs.append('.')
839+                self.library_dirs.append(sysconfig.project_base)
840
841         # For building extensions with a shared Python library,
842         # Python's library directory must be appended to library_dirs
843@@ -237,7 +238,7 @@ def finalize_options(self):
844                 self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
845             else:
846                 # building python standard extensions
847-                self.library_dirs.append('.')
848+                self.library_dirs.append(sysconfig.project_base)
849
850         # The argument parsing will result in self.define being a string, but
851         # it has to be a list of 2-tuples.  All the preprocessor symbols
852@@ -712,6 +713,20 @@ def get_libraries(self, ext):
853         # pyconfig.h that MSVC groks.  The other Windows compilers all seem
854         # to need it mentioned explicitly, though, so that's what we do.
855         # Append '_d' to the python import library on debug builds.
856+
857+        # Use self.plat_name as it works even in case of
858+        # cross-compilation (at least for mingw build).
859+        if self.plat_name.startswith('mingw'):
860+            from distutils import sysconfig
861+            extra = []
862+            for lib in (
863+                sysconfig.get_config_var('BLDLIBRARY').split()
864+                + sysconfig.get_config_var('SHLIBS').split()
865+                ):
866+                if lib.startswith('-l'):
867+                    extra.append(lib[2:])
868+            return ext.libraries + extra
869+
870         if sys.platform == "win32":
871             from distutils._msvccompiler import MSVCCompiler
872             if not isinstance(self.compiler, MSVCCompiler):
873diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
874index 01d5331..25eb3d8 100644
875--- a/Lib/distutils/command/install.py
876+++ b/Lib/distutils/command/install.py
877@@ -72,8 +72,8 @@
878     INSTALL_SCHEMES['nt_user'] = {
879         'purelib': '$usersite',
880         'platlib': '$usersite',
881-        'headers': '$userbase/Python$py_version_nodot/Include/$dist_name',
882-        'scripts': '$userbase/Python$py_version_nodot/Scripts',
883+        'headers': '$userbase/include/python$py_version_short_plat$abiflags/$dist_name',
884+        'scripts': '$userbase/bin',
885         'data'   : '$userbase',
886         }
887
888@@ -81,7 +81,7 @@
889         'purelib': '$usersite',
890         'platlib': '$usersite',
891         'headers':
892-            '$userbase/include/python$py_version_short$abiflags/$dist_name',
893+            '$userbase/include/python$py_version_short_plat$abiflags/$dist_name',
894         'scripts': '$userbase/bin',
895         'data'   : '$userbase',
896         }
897@@ -311,6 +311,7 @@ def finalize_options(self):
898                             'py_version': py_version,
899                             'py_version_short': '%d.%d' % sys.version_info[:2],
900                             'py_version_nodot': '%d%d' % sys.version_info[:2],
901+                            'py_version_short_plat': f'{sys.version_info[0]}.{sys.version_info[1]}-{get_platform()}' if os.name == 'nt' and 'gcc' in sys.version.lower() else f'{sys.version_info[0]}.{sys.version_info[1]}',
902                             'sys_prefix': prefix,
903                             'prefix': prefix,
904                             'sys_exec_prefix': exec_prefix,
905@@ -363,7 +364,8 @@ def finalize_options(self):
906
907         # Convert directories from Unix /-separated syntax to the local
908         # convention.
909-        self.convert_paths('lib', 'purelib', 'platlib',
910+        self.convert_paths('base', 'platbase',
911+                           'lib', 'purelib', 'platlib',
912                            'scripts', 'data', 'headers')
913         if HAS_USER_SITE:
914             self.convert_paths('userbase', 'usersite')
915diff --git a/Lib/distutils/cygwinccompiler.py b/Lib/distutils/cygwinccompiler.py
916index 66c12dd..d8c8428 100644
917--- a/Lib/distutils/cygwinccompiler.py
918+++ b/Lib/distutils/cygwinccompiler.py
919@@ -44,12 +44,13 @@
920 #   (ld supports -shared)
921 # * mingw gcc 3.2/ld 2.13 works
922 #   (ld supports -shared)
923+# * llvm-mingw with Clang 11 works
924+#   (lld supports -shared)
925
926 import os
927 import sys
928 import copy
929-from subprocess import Popen, PIPE, check_output
930-import re
931+import shlex
932
933 from distutils.unixccompiler import UnixCCompiler
934 from distutils.file_util import write_file
935@@ -57,6 +58,7 @@
936         CompileError, UnknownFileError)
937 from distutils.version import LooseVersion
938 from distutils.spawn import find_executable
939+from subprocess import Popen, check_output
940
941 def get_msvcr():
942     """Include the appropriate MSVC runtime library if Python was built
943@@ -91,6 +93,7 @@ class CygwinCCompiler(UnixCCompiler):
944     obj_extension = ".o"
945     static_lib_extension = ".a"
946     shared_lib_extension = ".dll"
947+    dylib_lib_extension = ".dll.a"
948     static_lib_format = "lib%s%s"
949     shared_lib_format = "%s%s"
950     exe_extension = ".exe"
951@@ -109,50 +112,28 @@ def __init__(self, verbose=0, dry_run=0, force=0):
952                 "Compiling may fail because of undefined preprocessor macros."
953                 % details)
954
955-        self.gcc_version, self.ld_version, self.dllwrap_version = \
956-            get_versions()
957-        self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
958-                         (self.gcc_version,
959-                          self.ld_version,
960-                          self.dllwrap_version) )
961-
962-        # ld_version >= "2.10.90" and < "2.13" should also be able to use
963-        # gcc -mdll instead of dllwrap
964-        # Older dllwraps had own version numbers, newer ones use the
965-        # same as the rest of binutils ( also ld )
966-        # dllwrap 2.10.90 is buggy
967-        if self.ld_version >= "2.10.90":
968-            self.linker_dll = "gcc"
969-        else:
970-            self.linker_dll = "dllwrap"
971+        self.cc = os.environ.get('CC', 'gcc')
972+        self.cxx = os.environ.get('CXX', 'g++')
973
974-        # ld_version >= "2.13" support -shared so use it instead of
975-        # -mdll -static
976-        if self.ld_version >= "2.13":
977-            shared_option = "-shared"
978-        else:
979-            shared_option = "-mdll -static"
980-
981-        # Hard-code GCC because that's what this is all about.
982-        # XXX optimization, warnings etc. should be customizable.
983-        self.set_executables(compiler='gcc -mcygwin -O -Wall',
984-                             compiler_so='gcc -mcygwin -mdll -O -Wall',
985-                             compiler_cxx='g++ -mcygwin -O -Wall',
986-                             linker_exe='gcc -mcygwin',
987+        # Older numpy dependend on this existing to check for ancient
988+        # gcc versions. This doesn't make much sense with clang etc so
989+        # just hardcode to something recent.
990+        # https://github.com/numpy/numpy/pull/20333
991+        self.gcc_version = LooseVersion("11.2.0")
992+
993+        self.linker_dll = self.cc
994+        shared_option = "-shared"
995+
996+        self.set_executables(compiler='%s -mcygwin -O -Wall' % self.cc,
997+                             compiler_so='%s -mcygwin -mdll -O -Wall' % self.cc,
998+                             compiler_cxx='%s -mcygwin -O -Wall' % self.cxx,
999+                             linker_exe='%s -mcygwin' % self.cc,
1000                              linker_so=('%s -mcygwin %s' %
1001                                         (self.linker_dll, shared_option)))
1002
1003-        # cygwin and mingw32 need different sets of libraries
1004-        if self.gcc_version == "2.91.57":
1005-            # cygwin shouldn't need msvcrt, but without the dlls will crash
1006-            # (gcc version 2.91.57) -- perhaps something about initialization
1007-            self.dll_libraries=["msvcrt"]
1008-            self.warn(
1009-                "Consider upgrading to a newer version of gcc")
1010-        else:
1011-            # Include the appropriate MSVC runtime library if Python was built
1012-            # with MSVC 7.0 or later.
1013-            self.dll_libraries = get_msvcr()
1014+        # Include the appropriate MSVC runtime library if Python was built
1015+        # with MSVC 7.0 or later.
1016+        self.dll_libraries = get_msvcr()
1017
1018     def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
1019         """Compiles the source by spawning GCC and windres if needed."""
1020@@ -162,6 +143,28 @@ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
1021                 self.spawn(["windres", "-i", src, "-o", obj])
1022             except DistutilsExecError as msg:
1023                 raise CompileError(msg)
1024+        elif ext == '.mc':
1025+            # Adapted from msvc9compiler:
1026+            #
1027+            # Compile .MC to .RC file to .RES file.
1028+            #   * '-h dir' specifies the directory for the generated include file
1029+            #   * '-r dir' specifies the target directory of the generated RC file and the binary message resource it includes
1030+            #
1031+            # For now (since there are no options to change this),
1032+            # we use the source-directory for the include file and
1033+            # the build directory for the RC file and message
1034+            # resources. This works at least for win32all.
1035+            h_dir = os.path.dirname(src)
1036+            rc_dir = os.path.dirname(obj)
1037+            try:
1038+                # first compile .MC to .RC and .H file
1039+                self.spawn(['windmc'] + ['-h', h_dir, '-r', rc_dir] + [src])
1040+                base, _ = os.path.splitext(os.path.basename(src))
1041+                rc_file = os.path.join(rc_dir, base + '.rc')
1042+                # then compile .RC to .RES file
1043+                self.spawn(['windres', '-i', rc_file, '-o', obj])
1044+            except DistutilsExecError as msg:
1045+                raise CompileError(msg)
1046         else: # for other files use the C-compiler
1047             try:
1048                 self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
1049@@ -214,28 +217,21 @@ def link(self, target_desc, objects, output_filename, output_dir=None,
1050
1051             # next add options for def-file and to creating import libraries
1052
1053-            # dllwrap uses different options than gcc/ld
1054-            if self.linker_dll == "dllwrap":
1055-                extra_preargs.extend(["--output-lib", lib_file])
1056-                # for dllwrap we have to use a special option
1057-                extra_preargs.extend(["--def", def_file])
1058-            # we use gcc/ld here and can be sure ld is >= 2.9.10
1059-            else:
1060-                # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
1061-                #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
1062-                # for gcc/ld the def-file is specified as any object files
1063-                objects.append(def_file)
1064+            # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
1065+            #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
1066+            # for gcc/ld the def-file is specified as any object files
1067+            objects.append(def_file)
1068
1069         #end: if ((export_symbols is not None) and
1070         #        (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
1071
1072         # who wants symbols and a many times larger output file
1073         # should explicitly switch the debug mode on
1074-        # otherwise we let dllwrap/ld strip the output file
1075+        # otherwise we let ld strip the output file
1076         # (On my machine: 10KiB < stripped_file < ??100KiB
1077         #   unstripped_file = stripped_file + XXX KiB
1078         #  ( XXX=254 for a typical python extension))
1079-        if not debug:
1080+        if not debug and not hasattr(sys, 'gettotalrefcount'):
1081             extra_preargs.append("-s")
1082
1083         UnixCCompiler.link(self, target_desc, objects, output_filename,
1084@@ -253,11 +249,16 @@ def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
1085             output_dir = ''
1086         obj_names = []
1087         for src_name in source_filenames:
1088-            # use normcase to make sure '.rc' is really '.rc' and not '.RC'
1089-            base, ext = os.path.splitext(os.path.normcase(src_name))
1090-            if ext not in (self.src_extensions + ['.rc','.res']):
1091+            base, ext = os.path.splitext(src_name)
1092+            # use 'normcase' only for resource suffixes
1093+            ext_normcase = os.path.normcase(ext)
1094+            if ext_normcase in ['.rc', '.res', '.mc']:
1095+                ext = ext_normcase
1096+            if ext not in (self.src_extensions + ['.rc', '.res', '.mc']):
1097                 raise UnknownFileError("unknown file type '%s' (from '%s')" % \
1098                       (ext, src_name))
1099+            base = os.path.splitdrive(base)[1] # Chop off the drive
1100+            base = base[os.path.isabs(base):]  # If abs, chop off leading /
1101             if strip_dir:
1102                 base = os.path.basename (base)
1103             if ext in ('.res', '.rc'):
1104@@ -279,31 +280,18 @@ def __init__(self, verbose=0, dry_run=0, force=0):
1105
1106         CygwinCCompiler.__init__ (self, verbose, dry_run, force)
1107
1108-        # ld_version >= "2.13" support -shared so use it instead of
1109-        # -mdll -static
1110-        if self.ld_version >= "2.13":
1111-            shared_option = "-shared"
1112-        else:
1113-            shared_option = "-mdll -static"
1114-
1115-        # A real mingw32 doesn't need to specify a different entry point,
1116-        # but cygwin 2.91.57 in no-cygwin-mode needs it.
1117-        if self.gcc_version <= "2.91.57":
1118-            entry_point = '--entry _DllMain@12'
1119-        else:
1120-            entry_point = ''
1121+        shared_option = "-shared"
1122
1123-        if is_cygwingcc():
1124+        if is_cygwincc(self.cc):
1125             raise CCompilerError(
1126                 'Cygwin gcc cannot be used with --compiler=mingw32')
1127
1128-        self.set_executables(compiler='gcc -O -Wall',
1129-                             compiler_so='gcc -mdll -O -Wall',
1130-                             compiler_cxx='g++ -O -Wall',
1131-                             linker_exe='gcc',
1132-                             linker_so='%s %s %s'
1133-                                        % (self.linker_dll, shared_option,
1134-                                           entry_point))
1135+        self.set_executables(compiler='%s -O2 -Wall' % self.cc,
1136+                             compiler_so='%s -mdll -O2 -Wall' % self.cc,
1137+                             compiler_cxx='%s -O2 -Wall' % self.cxx,
1138+                             linker_exe='%s' % self.cc,
1139+                             linker_so='%s %s'
1140+                                        % (self.linker_dll, shared_option))
1141         # Maybe we should also append -mthreads, but then the finished
1142         # dlls need another dll (mingwm10.dll see Mingw32 docs)
1143         # (-mthreads: Support thread-safe exception handling on `Mingw32')
1144@@ -313,7 +301,7 @@ def __init__(self, verbose=0, dry_run=0, force=0):
1145
1146         # Include the appropriate MSVC runtime library if Python was built
1147         # with MSVC 7.0 or later.
1148-        self.dll_libraries = get_msvcr()
1149+        self.dll_libraries = get_msvcr() or []
1150
1151 # Because these compilers aren't configured in Python's pyconfig.h file by
1152 # default, we should at least warn the user if he is using an unmodified
1153@@ -351,6 +339,10 @@ def check_config_h():
1154     if "GCC" in sys.version:
1155         return CONFIG_H_OK, "sys.version mentions 'GCC'"
1156
1157+    # Clang would also work
1158+    if "Clang" in sys.version:
1159+        return CONFIG_H_OK, "sys.version mentions 'Clang'"
1160+
1161     # let's see if __GNUC__ is mentioned in python.h
1162     fn = sysconfig.get_config_h_filename()
1163     try:
1164@@ -366,38 +358,8 @@ def check_config_h():
1165         return (CONFIG_H_UNCERTAIN,
1166                 "couldn't read '%s': %s" % (fn, exc.strerror))
1167
1168-RE_VERSION = re.compile(br'(\d+\.\d+(\.\d+)*)')
1169-
1170-def _find_exe_version(cmd):
1171-    """Find the version of an executable by running `cmd` in the shell.
1172-
1173-    If the command is not found, or the output does not match
1174-    `RE_VERSION`, returns None.
1175-    """
1176-    executable = cmd.split()[0]
1177-    if find_executable(executable) is None:
1178-        return None
1179-    out = Popen(cmd, shell=True, stdout=PIPE).stdout
1180-    try:
1181-        out_string = out.read()
1182-    finally:
1183-        out.close()
1184-    result = RE_VERSION.search(out_string)
1185-    if result is None:
1186-        return None
1187-    # LooseVersion works with strings
1188-    # so we need to decode our bytes
1189-    return LooseVersion(result.group(1).decode())
1190-
1191-def get_versions():
1192-    """ Try to find out the versions of gcc, ld and dllwrap.
1193-
1194-    If not possible it returns None for it.
1195-    """
1196-    commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version']
1197-    return tuple([_find_exe_version(cmd) for cmd in commands])
1198
1199-def is_cygwingcc():
1200-    '''Try to determine if the gcc that would be used is from cygwin.'''
1201-    out_string = check_output(['gcc', '-dumpmachine'])
1202+def is_cygwincc(cc):
1203+    '''Try to determine if the compiler that would be used is from cygwin.'''
1204+    out_string = check_output(shlex.split(cc) + ['-dumpmachine'])
1205     return out_string.strip().endswith(b'cygwin')
1206diff --git a/Lib/distutils/msvc9compiler.py b/Lib/distutils/msvc9compiler.py
1207index a7976fb..c341679 100644
1208--- a/Lib/distutils/msvc9compiler.py
1209+++ b/Lib/distutils/msvc9compiler.py
1210@@ -291,8 +291,6 @@ def query_vcvarsall(version, arch="x86"):
1211
1212 # More globals
1213 VERSION = get_build_version()
1214-if VERSION < 8.0:
1215-    raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION)
1216 # MACROS = MacroExpander(VERSION)
1217
1218 class MSVCCompiler(CCompiler) :
1219@@ -327,6 +325,8 @@ class MSVCCompiler(CCompiler) :
1220
1221     def __init__(self, verbose=0, dry_run=0, force=0):
1222         CCompiler.__init__ (self, verbose, dry_run, force)
1223+        if VERSION < 8.0:
1224+            raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION)
1225         self.__version = VERSION
1226         self.__root = r"Software\Microsoft\VisualStudio"
1227         # self.__macros = MACROS
1228diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
1229index 03b8558..024c15c 100644
1230--- a/Lib/distutils/sysconfig.py
1231+++ b/Lib/distutils/sysconfig.py
1232@@ -64,8 +64,23 @@ def parse_config_h(fp, g=None):
1233
1234 _python_build = partial(is_python_build, check_home=True)
1235 _init_posix = partial(sysconfig_init_posix, _config_vars)
1236-_init_nt = partial(_init_non_posix, _config_vars)
1237
1238+def _posix_build():
1239+    # GCC[mingw*] use posix build system
1240+    # Check for cross builds explicitly
1241+    host_platform = os.environ.get("_PYTHON_HOST_PLATFORM")
1242+    if host_platform:
1243+        if host_platform.startswith('mingw'):
1244+            return True
1245+    return os.name == 'posix' or \
1246+        (os.name == "nt" and 'GCC' in sys.version)
1247+posix_build = _posix_build()
1248+
1249+
1250+def _init_nt():
1251+    if posix_build:
1252+        return _init_posix(_config_vars)
1253+    return _init_non_posix(_config_vars)
1254
1255 # Similar function is also implemented in sysconfig as _parse_makefile
1256 # but without the parsing capabilities of distutils.text_file.TextFile.
1257@@ -196,7 +211,23 @@ def customize_compiler(compiler):
1258     Mainly needed on Unix, so we can plug in the information that
1259     varies across Unices and is stored in Python's Makefile.
1260     """
1261-    if compiler.compiler_type == "unix":
1262+    global _config_vars
1263+    if compiler.compiler_type in ["cygwin", "mingw32"]:
1264+        # Note that cygwin use posix build and 'unix' compiler.
1265+        # If build is not based on posix then we must predefine
1266+        # some environment variables corresponding to posix
1267+        # build rules and defaults.
1268+        if not 'GCC' in sys.version:
1269+            _config_vars['CC'] = "gcc"
1270+            _config_vars['CXX'] = "g++"
1271+            _config_vars['OPT'] = "-fwrapv -O3 -Wall -Wstrict-prototypes"
1272+            _config_vars['CFLAGS'] = ""
1273+            _config_vars['CCSHARED'] = ""
1274+            _config_vars['LDSHARED'] = "gcc -shared -Wl,--enable-auto-image-base"
1275+            _config_vars['AR'] = "ar"
1276+            _config_vars['ARFLAGS'] = "rc"
1277+
1278+    if compiler.compiler_type in ["unix", "cygwin", "mingw32"]:
1279         if sys.platform == "darwin":
1280             # Perform first-time customization of compiler-related
1281             # config vars on OS X now that we know we need a compiler.
1282@@ -274,7 +305,7 @@ def get_python_inc(plat_specific=0, prefix=None):
1283     """
1284     if prefix is None:
1285         prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
1286-    if os.name == "posix":
1287+    if posix_build:
1288         if python_build:
1289             # Assume the executable is in the build directory.  The
1290             # pyconfig.h file should be in the same directory.  Since
1291@@ -321,7 +352,7 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
1292         else:
1293             prefix = plat_specific and EXEC_PREFIX or PREFIX
1294
1295-    if os.name == "posix":
1296+    if posix_build:
1297         if plat_specific or standard_lib:
1298             # Platform-specific modules (any module from a non-pure-Python
1299             # module distribution) or standard Python library modules.
1300diff --git a/Lib/distutils/tests/test_cygwinccompiler.py b/Lib/distutils/tests/test_cygwinccompiler.py
1301index 0912ffd..a93c174 100644
1302--- a/Lib/distutils/tests/test_cygwinccompiler.py
1303+++ b/Lib/distutils/tests/test_cygwinccompiler.py
1304@@ -8,7 +8,7 @@
1305 from distutils import cygwinccompiler
1306 from distutils.cygwinccompiler import (check_config_h,
1307                                        CONFIG_H_OK, CONFIG_H_NOTOK,
1308-                                       CONFIG_H_UNCERTAIN, get_versions,
1309+                                       CONFIG_H_UNCERTAIN,
1310                                        get_msvcr)
1311 from distutils.tests import support
1312
1313@@ -81,40 +81,6 @@ def test_check_config_h(self):
1314         self.write_file(self.python_h, 'xxx __GNUC__ xxx')
1315         self.assertEqual(check_config_h()[0], CONFIG_H_OK)
1316
1317-    def test_get_versions(self):
1318-
1319-        # get_versions calls distutils.spawn.find_executable on
1320-        # 'gcc', 'ld' and 'dllwrap'
1321-        self.assertEqual(get_versions(), (None, None, None))
1322-
1323-        # Let's fake we have 'gcc' and it returns '3.4.5'
1324-        self._exes['gcc'] = b'gcc (GCC) 3.4.5 (mingw special)\nFSF'
1325-        res = get_versions()
1326-        self.assertEqual(str(res[0]), '3.4.5')
1327-
1328-        # and let's see what happens when the version
1329-        # doesn't match the regular expression
1330-        # (\d+\.\d+(\.\d+)*)
1331-        self._exes['gcc'] = b'very strange output'
1332-        res = get_versions()
1333-        self.assertEqual(res[0], None)
1334-
1335-        # same thing for ld
1336-        self._exes['ld'] = b'GNU ld version 2.17.50 20060824'
1337-        res = get_versions()
1338-        self.assertEqual(str(res[1]), '2.17.50')
1339-        self._exes['ld'] = b'@(#)PROGRAM:ld  PROJECT:ld64-77'
1340-        res = get_versions()
1341-        self.assertEqual(res[1], None)
1342-
1343-        # and dllwrap
1344-        self._exes['dllwrap'] = b'GNU dllwrap 2.17.50 20060824\nFSF'
1345-        res = get_versions()
1346-        self.assertEqual(str(res[2]), '2.17.50')
1347-        self._exes['dllwrap'] = b'Cheese Wrap'
1348-        res = get_versions()
1349-        self.assertEqual(res[2], None)
1350-
1351     def test_get_msvcr(self):
1352
1353         # none
1354diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py
1355index d00c489..76a7d82 100644
1356--- a/Lib/distutils/unixccompiler.py
1357+++ b/Lib/distutils/unixccompiler.py
1358@@ -249,9 +249,13 @@ def runtime_library_dir_option(self, dir):
1359                 # -Wl whenever gcc was used in the past it is probably
1360                 # safest to keep doing so.
1361                 if sysconfig.get_config_var("GNULD") == "yes":
1362-                    # GNU ld needs an extra option to get a RUNPATH
1363+                    # GNU ELF ld needs an extra option to get a RUNPATH
1364                     # instead of just an RPATH.
1365-                    return "-Wl,--enable-new-dtags,-R" + dir
1366+                    if sys.platform in ["win32", "cygwin"] or \
1367+                       "mingw" in compiler:
1368+                        return []
1369+                    else:
1370+                        return "-Wl,--enable-new-dtags,-R" + dir
1371                 else:
1372                     return "-Wl,-R" + dir
1373             else:
1374diff --git a/Lib/distutils/util.py b/Lib/distutils/util.py
1375index 2ce5c5b..81626b3 100644
1376--- a/Lib/distutils/util.py
1377+++ b/Lib/distutils/util.py
1378@@ -37,6 +37,22 @@ def get_host_platform():
1379
1380     """
1381     if os.name == 'nt':
1382+        if 'gcc' in sys.version.lower():
1383+            if 'ucrt' in sys.version.lower():
1384+                if 'amd64' in sys.version.lower():
1385+                    return 'mingw_x86_64_ucrt'
1386+                return 'mingw_i686_ucrt'
1387+            if 'clang' in sys.version.lower():
1388+                if 'amd64' in sys.version.lower():
1389+                    return 'mingw_x86_64_clang'
1390+                if 'arm64' in sys.version.lower():
1391+                    return 'mingw_aarch64'
1392+                if 'arm' in sys.version.lower():
1393+                    return 'mingw_armv7'
1394+                return 'mingw_i686_clang'
1395+            if 'amd64' in sys.version.lower():
1396+                return 'mingw_x86_64'
1397+            return 'mingw_i686'
1398         if 'amd64' in sys.version.lower():
1399             return 'win-amd64'
1400         if '(arm)' in sys.version.lower():
1401@@ -130,6 +146,13 @@ def convert_path (pathname):
1402         paths.remove('.')
1403     if not paths:
1404         return os.curdir
1405+    # On Windows, if paths is ['C:','folder','subfolder'] then
1406+    # os.path.join(*paths) will return 'C:folder\subfolder' which
1407+    # is thus relative to the CWD on that drive. So we work around
1408+    # this by adding a \ to path[0]
1409+    if (len(paths) > 0 and paths[0].endswith(':') and
1410+        sys.platform == "win32" and sys.version.find("GCC") >= 0):
1411+        paths[0] += '\\'
1412     return os.path.join(*paths)
1413
1414 # convert_path ()
1415@@ -140,6 +163,10 @@ def change_root (new_root, pathname):
1416     relative, this is equivalent to "os.path.join(new_root,pathname)".
1417     Otherwise, it requires making 'pathname' relative and then joining the
1418     two, which is tricky on DOS/Windows and Mac OS.
1419+
1420+    If on Windows or OS/2 and both new_root and pathname are on different
1421+    drives, raises DistutilsChangeRootError as this is nonsensical,
1422+    otherwise use drive which can be in either of new_root or pathname.
1423     """
1424     if os.name == 'posix':
1425         if not os.path.isabs(pathname):
1426@@ -149,9 +176,20 @@ def change_root (new_root, pathname):
1427
1428     elif os.name == 'nt':
1429         (drive, path) = os.path.splitdrive(pathname)
1430-        if path[0] == '\\':
1431+        if path[0] == os.sep:
1432             path = path[1:]
1433-        return os.path.join(new_root, path)
1434+        (drive_r, path_r) = os.path.splitdrive(new_root)
1435+        if path_r and path_r[0] == os.sep:
1436+            path_r = path_r[1:]
1437+        drive_used = ''
1438+        if len(drive) == 2 and len(drive_r) == 2 and drive != drive_r:
1439+            raise DistutilsChangeRootError("root and pathname not on same drive (%s, %s)"
1440+                   % (drive_r,drive))
1441+        elif len(drive_r) == 2:
1442+            drive_used = drive_r+os.sep
1443+        elif len(drive) == 2:
1444+            drive_used = drive+os.sep
1445+        return os.path.join(drive_used+path_r, path)
1446
1447     else:
1448         raise DistutilsPlatformError("nothing known about platform '%s'" % os.name)
1449diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
1450index f603a89..7693d05 100644
1451--- a/Lib/importlib/_bootstrap_external.py
1452+++ b/Lib/importlib/_bootstrap_external.py
1453@@ -42,6 +42,10 @@
1454     path_separators = ['\\', '/']
1455 else:
1456     path_separators = ['/']
1457+
1458+if _os.environ.get('MSYSTEM', ''):
1459+    path_separators = path_separators[::-1]
1460+
1461 # Assumption made in _path_join()
1462 assert all(len(sep) == 1 for sep in path_separators)
1463 path_sep = path_separators[0]
1464diff --git a/Lib/ntpath.py b/Lib/ntpath.py
1465index 0246419..7d5c3a5 100644
1466--- a/Lib/ntpath.py
1467+++ b/Lib/ntpath.py
1468@@ -11,9 +11,7 @@
1469 curdir = '.'
1470 pardir = '..'
1471 extsep = '.'
1472-sep = '\\'
1473 pathsep = ';'
1474-altsep = '/'
1475 defpath = '.;C:\\bin'
1476 devnull = 'nul'
1477
1478@@ -23,6 +21,14 @@
1479 import genericpath
1480 from genericpath import *
1481
1482+if sys.platform == "win32" and os.environ.get("MSYSTEM", ""):
1483+    sep = '/'
1484+    altsep = '\\'
1485+else:
1486+    sep = '\\'
1487+    altsep = '/'
1488+bsep = str.encode(sep)
1489+baltsep = str.encode(altsep)
1490
1491 __all__ = ["normcase","isabs","join","splitdrive","split","splitext",
1492            "basename","dirname","commonprefix","getsize","getmtime",
1493@@ -34,9 +40,33 @@
1494
1495 def _get_bothseps(path):
1496     if isinstance(path, bytes):
1497-        return b'\\/'
1498+        return bsep+baltsep
1499+    else:
1500+        return sep+altsep
1501+
1502+def _get_sep(path):
1503+    if isinstance(path, bytes):
1504+        return bsep
1505+    else:
1506+        return sep
1507+
1508+def _get_altsep(path):
1509+    if isinstance(path, bytes):
1510+        return baltsep
1511+    else:
1512+        return altsep
1513+
1514+def _get_colon(path):
1515+    if isinstance(path, bytes):
1516+        return b':'
1517+    else:
1518+        return ':'
1519+
1520+def _get_unc_prefix(path):
1521+    if isinstance(path, bytes):
1522+        return b'\\\\?\\UNC\\'
1523     else:
1524-        return '\\/'
1525+        return '\\\\?\\UNC\\'
1526
1527 # Normalize the case of a pathname and map slashes to backslashes.
1528 # Other normalizations (such as optimizing '../' away) are not done
1529@@ -58,14 +88,14 @@ def normcase(s):
1530             return s
1531         if isinstance(s, bytes):
1532             encoding = sys.getfilesystemencoding()
1533-            s = s.decode(encoding, 'surrogateescape').replace('/', '\\')
1534+            s = s.decode(encoding, 'surrogateescape').replace(altsep, sep)
1535             s = _LCMapStringEx(_LOCALE_NAME_INVARIANT,
1536                                _LCMAP_LOWERCASE, s)
1537             return s.encode(encoding, 'surrogateescape')
1538         else:
1539             return _LCMapStringEx(_LOCALE_NAME_INVARIANT,
1540                                   _LCMAP_LOWERCASE,
1541-                                  s.replace('/', '\\'))
1542+                                  s.replace(altsep, sep))
1543 except ImportError:
1544     def normcase(s):
1545         """Normalize case of pathname.
1546@@ -74,8 +104,8 @@ def normcase(s):
1547         """
1548         s = os.fspath(s)
1549         if isinstance(s, bytes):
1550-            return os.fsencode(os.fsdecode(s).replace('/', '\\').lower())
1551-        return s.replace('/', '\\').lower()
1552+            return os.fsencode(os.fsdecode(s).replace(altsep, sep).lower())
1553+        return s.replace(altsep, sep).lower()
1554
1555
1556 # Return whether a path is absolute.
1557@@ -87,14 +117,9 @@ def normcase(s):
1558 def isabs(s):
1559     """Test whether a path is absolute"""
1560     s = os.fspath(s)
1561-    if isinstance(s, bytes):
1562-        sep = b'\\'
1563-        altsep = b'/'
1564-        colon_sep = b':\\'
1565-    else:
1566-        sep = '\\'
1567-        altsep = '/'
1568-        colon_sep = ':\\'
1569+    sep = _get_sep(s)
1570+    altsep = _get_altsep(s)
1571+    colon_sep = _get_colon(s) + sep
1572     s = s[:3].replace(altsep, sep)
1573     # Absolute: UNC, device, and paths with a drive and root.
1574     # LEGACY BUG: isabs("/x") should be false since the path has no drive.
1575@@ -106,14 +131,9 @@ def isabs(s):
1576 # Join two (or more) paths.
1577 def join(path, *paths):
1578     path = os.fspath(path)
1579-    if isinstance(path, bytes):
1580-        sep = b'\\'
1581-        seps = b'\\/'
1582-        colon = b':'
1583-    else:
1584-        sep = '\\'
1585-        seps = '\\/'
1586-        colon = ':'
1587+    sep = _get_sep(path)
1588+    seps = _get_bothseps(path)
1589+    colon = _get_colon(path)
1590     try:
1591         if not paths:
1592             path[:0] + sep  #23780: Ensure compatible data type even if p is null.
1593@@ -172,16 +192,10 @@ def splitdrive(p):
1594     """
1595     p = os.fspath(p)
1596     if len(p) >= 2:
1597-        if isinstance(p, bytes):
1598-            sep = b'\\'
1599-            altsep = b'/'
1600-            colon = b':'
1601-            unc_prefix = b'\\\\?\\UNC\\'
1602-        else:
1603-            sep = '\\'
1604-            altsep = '/'
1605-            colon = ':'
1606-            unc_prefix = '\\\\?\\UNC\\'
1607+        sep = _get_sep(p)
1608+        altsep = _get_altsep(p)
1609+        colon = _get_colon(p)
1610+        unc_prefix = _get_unc_prefix(p)
1611         normp = p.replace(altsep, sep)
1612         if normp[0:2] == sep * 2:
1613             # UNC drives, e.g. \\server\share or \\?\UNC\server\share
1614@@ -231,9 +245,9 @@ def split(p):
1615 def splitext(p):
1616     p = os.fspath(p)
1617     if isinstance(p, bytes):
1618-        return genericpath._splitext(p, b'\\', b'/', b'.')
1619+        return genericpath._splitext(p, bsep, baltsep, b'.')
1620     else:
1621-        return genericpath._splitext(p, '\\', '/', '.')
1622+        return genericpath._splitext(p, sep, altsep, '.')
1623 splitext.__doc__ = genericpath._splitext.__doc__
1624
1625
1626@@ -334,7 +348,7 @@ def expanduser(path):
1627     if 'USERPROFILE' in os.environ:
1628         userhome = os.environ['USERPROFILE']
1629     elif not 'HOMEPATH' in os.environ:
1630-        return path
1631+        return os.path.normpath(path)
1632     else:
1633         try:
1634             drive = os.environ['HOMEDRIVE']
1635@@ -361,7 +375,7 @@ def expanduser(path):
1636     if isinstance(path, bytes):
1637         userhome = os.fsencode(userhome)
1638
1639-    return userhome + path[i:]
1640+    return os.path.normpath(userhome) + path[i:]
1641
1642
1643 # Expand paths containing shell variable substitutions.
1644@@ -496,14 +510,12 @@ def expandvars(path):
1645     def normpath(path):
1646         """Normalize path, eliminating double slashes, etc."""
1647         path = os.fspath(path)
1648+        sep = _get_sep(path)
1649+        altsep = _get_altsep(path)
1650         if isinstance(path, bytes):
1651-            sep = b'\\'
1652-            altsep = b'/'
1653             curdir = b'.'
1654             pardir = b'..'
1655         else:
1656-            sep = '\\'
1657-            altsep = '/'
1658             curdir = '.'
1659             pardir = '..'
1660         path = path.replace(altsep, sep)
1661@@ -570,7 +582,7 @@ def _abspath_fallback(path):
1662     def abspath(path):
1663         """Return the absolute version of a path."""
1664         try:
1665-            return _getfullpathname(normpath(path))
1666+            return normpath(_getfullpathname(normpath(path)))
1667         except (OSError, ValueError):
1668             return _abspath_fallback(path)
1669
1670@@ -731,6 +743,7 @@ def realpath(path, *, strict=False):
1671                 # strip the prefix anyway.
1672                 if ex.winerror == initial_winerror:
1673                     path = spath
1674+        path = normpath(path)
1675         return path
1676
1677
1678@@ -741,12 +754,11 @@ def realpath(path, *, strict=False):
1679 def relpath(path, start=None):
1680     """Return a relative version of a path"""
1681     path = os.fspath(path)
1682+    sep = _get_sep(path)
1683     if isinstance(path, bytes):
1684-        sep = b'\\'
1685         curdir = b'.'
1686         pardir = b'..'
1687     else:
1688-        sep = '\\'
1689         curdir = '.'
1690         pardir = '..'
1691
1692@@ -801,13 +813,11 @@ def commonpath(paths):
1693         raise ValueError('commonpath() arg is an empty sequence')
1694
1695     paths = tuple(map(os.fspath, paths))
1696+    sep = _get_sep(paths[0])
1697+    altsep = _get_altsep(paths[0])
1698     if isinstance(paths[0], bytes):
1699-        sep = b'\\'
1700-        altsep = b'/'
1701         curdir = b'.'
1702     else:
1703-        sep = '\\'
1704-        altsep = '/'
1705         curdir = '.'
1706
1707     try:
1708diff --git a/Lib/pathlib.py b/Lib/pathlib.py
1709index ecb1e8a..eec8a9e 100644
1710--- a/Lib/pathlib.py
1711+++ b/Lib/pathlib.py
1712@@ -115,6 +115,8 @@ class _WindowsFlavour(_Flavour):
1713
1714     sep = '\\'
1715     altsep = '/'
1716+    if os.environ.get('MSYSTEM', ''):
1717+        sep, altsep = altsep, sep
1718     has_drv = True
1719     pathmod = ntpath
1720
1721diff --git a/Lib/site.py b/Lib/site.py
1722index 69670d9..41b9cf1 100644
1723--- a/Lib/site.py
1724+++ b/Lib/site.py
1725@@ -88,6 +88,12 @@
1726 USER_BASE = None
1727
1728
1729+# Same as defined in Lib/sysconfig.py
1730+# redeclared since sysconfig is large for site.
1731+# GCC[mingw*] use posix build system
1732+_POSIX_BUILD = os.name == 'posix' or \
1733+    (os.name == "nt" and 'GCC' in sys.version)
1734+
1735 def _trace(message):
1736     if sys.flags.verbose:
1737         print(message, file=sys.stderr)
1738@@ -273,7 +279,7 @@ def _getuserbase():
1739     def joinuser(*args):
1740         return os.path.expanduser(os.path.join(*args))
1741
1742-    if os.name == "nt":
1743+    if os.name == "nt" and not _POSIX_BUILD:
1744         base = os.environ.get("APPDATA") or "~"
1745         return joinuser(base, "Python")
1746
1747@@ -283,14 +289,36 @@ def joinuser(*args):
1748
1749     return joinuser("~", ".local")
1750
1751+# Copy of sysconfig.get_platform() but only for MinGW
1752+def _get_platform():
1753+    if os.name == 'nt':
1754+        if 'gcc' in sys.version.lower():
1755+            if 'ucrt' in sys.version.lower():
1756+                if 'amd64' in sys.version.lower():
1757+                    return 'mingw_x86_64_ucrt'
1758+                return 'mingw_i686_ucrt'
1759+            if 'clang' in sys.version.lower():
1760+                if 'amd64' in sys.version.lower():
1761+                    return 'mingw_x86_64_clang'
1762+                if 'arm64' in sys.version.lower():
1763+                    return 'mingw_aarch64'
1764+                if 'arm' in sys.version.lower():
1765+                    return 'mingw_armv7'
1766+                return 'mingw_i686_clang'
1767+            if 'amd64' in sys.version.lower():
1768+                return 'mingw_x86_64'
1769+            return 'mingw_i686'
1770+    return sys.platform
1771
1772 # Same to sysconfig.get_path('purelib', os.name+'_user')
1773 def _get_path(userbase):
1774     version = sys.version_info
1775
1776     if os.name == 'nt':
1777-        ver_nodot = sys.winver.replace('.', '')
1778-        return f'{userbase}\\Python{ver_nodot}\\site-packages'
1779+        if not _POSIX_BUILD:
1780+            ver_nodot = sys.winver.replace('.', '')
1781+            return f'{userbase}\\Python{ver_nodot}\\site-packages'
1782+        return f'{userbase}/lib/python{version[0]}.{version[1]}-{_get_platform()}/site-packages'
1783
1784     if sys.platform == 'darwin' and sys._framework:
1785         return f'{userbase}/lib/python/site-packages'
1786@@ -361,7 +389,7 @@ def getsitepackages(prefixes=None):
1787             continue
1788         seen.add(prefix)
1789
1790-        if os.sep == '/':
1791+        if _POSIX_BUILD:
1792             libdirs = [sys.platlibdir]
1793             if sys.platlibdir != "lib":
1794                 libdirs.append("lib")
1795@@ -392,7 +420,7 @@ def setquit():
1796     The repr of each object contains a hint at how it works.
1797
1798     """
1799-    if os.sep == '\\':
1800+    if sys.platform == 'win32':
1801         eof = 'Ctrl-Z plus Return'
1802     else:
1803         eof = 'Ctrl-D (i.e. EOF)'
1804diff --git a/Lib/ssl.py b/Lib/ssl.py
1805index ced87d4..ebb6b6f 100644
1806--- a/Lib/ssl.py
1807+++ b/Lib/ssl.py
1808@@ -254,7 +254,7 @@ class _TLSMessageType:
1809     CHANGE_CIPHER_SPEC = 0x0101
1810
1811
1812-if sys.platform == "win32":
1813+if sys.platform == "win32" and sys.version.find("GCC") == -1:
1814     from _ssl import enum_certificates, enum_crls
1815
1816 from socket import socket, SOCK_STREAM, create_connection
1817@@ -591,7 +591,7 @@ def _load_windows_store_certs(self, storename, purpose):
1818     def load_default_certs(self, purpose=Purpose.SERVER_AUTH):
1819         if not isinstance(purpose, _ASN1Object):
1820             raise TypeError(purpose)
1821-        if sys.platform == "win32":
1822+        if sys.platform == "win32" and sys.version.find("GCC") == -1:
1823             for storename in self._windows_cert_stores:
1824                 self._load_windows_store_certs(storename, purpose)
1825         self.set_default_verify_paths()
1826diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py
1827index ebe3711..8035d2e 100644
1828--- a/Lib/sysconfig.py
1829+++ b/Lib/sysconfig.py
1830@@ -2,6 +2,7 @@
1831
1832 import os
1833 import sys
1834+import textwrap
1835 from os.path import pardir, realpath
1836
1837 __all__ = [
1838@@ -47,13 +48,13 @@
1839         'data': '{base}',
1840         },
1841     'nt': {
1842-        'stdlib': '{installed_base}/Lib',
1843-        'platstdlib': '{base}/Lib',
1844-        'purelib': '{base}/Lib/site-packages',
1845-        'platlib': '{base}/Lib/site-packages',
1846-        'include': '{installed_base}/Include',
1847-        'platinclude': '{installed_base}/Include',
1848-        'scripts': '{base}/Scripts',
1849+        'stdlib': '{installed_base}/lib/python{py_version_short}',
1850+        'platstdlib': '{base}/lib/python{py_version_short}',
1851+        'purelib': '{base}/lib/python{py_version_short}/site-packages',
1852+        'platlib': '{base}/lib/python{py_version_short}/site-packages',
1853+        'include': '{installed_base}/include/python{py_version_short}',
1854+        'platinclude': '{installed_base}/include/python{py_version_short}',
1855+        'scripts': '{base}/bin',
1856         'data': '{base}',
1857         },
1858     # Downstream distributors can overwrite the default install scheme.
1859@@ -97,13 +98,18 @@
1860         },
1861     }
1862
1863+# GCC[mingw*] use posix build system
1864+_POSIX_BUILD = os.name == 'posix' or \
1865+    (os.name == "nt" and 'GCC' in sys.version)
1866+
1867 # For the OS-native venv scheme, we essentially provide an alias:
1868-if os.name == 'nt':
1869+if os.name == 'nt' and not _POSIX_BUILD:
1870     _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['nt_venv']
1871 else:
1872     _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_venv']
1873
1874
1875+
1876 # NOTE: site.py has copy of this function.
1877 # Sync it when modify this function.
1878 def _getuserbase():
1879@@ -118,7 +124,7 @@ def _getuserbase():
1880     def joinuser(*args):
1881         return os.path.expanduser(os.path.join(*args))
1882
1883-    if os.name == "nt":
1884+    if os.name == "nt" and not _POSIX_BUILD:
1885         base = os.environ.get("APPDATA") or "~"
1886         return joinuser(base, "Python")
1887
1888@@ -134,20 +140,20 @@ def joinuser(*args):
1889     _INSTALL_SCHEMES |= {
1890         # NOTE: When modifying "purelib" scheme, update site._get_path() too.
1891         'nt_user': {
1892-            'stdlib': '{userbase}/Python{py_version_nodot_plat}',
1893-            'platstdlib': '{userbase}/Python{py_version_nodot_plat}',
1894-            'purelib': '{userbase}/Python{py_version_nodot_plat}/site-packages',
1895-            'platlib': '{userbase}/Python{py_version_nodot_plat}/site-packages',
1896-            'include': '{userbase}/Python{py_version_nodot_plat}/Include',
1897-            'scripts': '{userbase}/Python{py_version_nodot_plat}/Scripts',
1898+            'stdlib': '{userbase}/lib/python{py_version_short_plat}',
1899+            'platstdlib': '{userbase}/lib/python{py_version_short_plat}',
1900+            'purelib': '{userbase}/lib/python{py_version_short_plat}/site-packages',
1901+            'platlib': '{userbase}/lib/python{py_version_short_plat}/site-packages',
1902+            'include': '{userbase}/include/python{py_version_short_plat}',
1903+            'scripts': '{userbase}/bin',
1904             'data': '{userbase}',
1905             },
1906         'posix_user': {
1907-            'stdlib': '{userbase}/{platlibdir}/python{py_version_short}',
1908-            'platstdlib': '{userbase}/{platlibdir}/python{py_version_short}',
1909-            'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
1910-            'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
1911-            'include': '{userbase}/include/python{py_version_short}',
1912+            'stdlib': '{userbase}/{platlibdir}/python{py_version_short_plat}',
1913+            'platstdlib': '{userbase}/{platlibdir}/python{py_version_short_plat}',
1914+            'purelib': '{userbase}/lib/python{py_version_short_plat}/site-packages',
1915+            'platlib': '{userbase}/lib/python{py_version_short_plat}/site-packages',
1916+            'include': '{userbase}/include/python{py_version_short_plat}',
1917             'scripts': '{userbase}/bin',
1918             'data': '{userbase}',
1919             },
1920@@ -277,7 +283,7 @@ def _expand_vars(scheme, vars):
1921
1922
1923 def _get_preferred_schemes():
1924-    if os.name == 'nt':
1925+    if os.name == 'nt' and not _POSIX_BUILD:
1926         return {
1927             'prefix': 'nt',
1928             'home': 'posix_home',
1929@@ -435,6 +441,14 @@ def _parse_makefile(filename, vars=None, keep_unresolved=True):
1930         if isinstance(v, str):
1931             done[k] = v.strip()
1932
1933+    # any keys that have one with the same name suffixed with _b2h
1934+    # need to be replaced with the value of the _b2h key.
1935+    # This converts from MSYS*/Cygwin paths to Windows paths.
1936+    for k, v in dict(done).items():
1937+        if isinstance(k, str):
1938+            if k.endswith("_b2h"):
1939+                done[k[:-4]]=v
1940+
1941     # save the results in the global dictionary
1942     vars.update(done)
1943     return vars
1944@@ -514,11 +528,30 @@ def _generate_posix_vars():
1945     os.makedirs(pybuilddir, exist_ok=True)
1946     destfile = os.path.join(pybuilddir, name + '.py')
1947
1948+    replacement = """
1949+        keys_to_replace = [
1950+            'BINDIR', 'BINLIBDEST', 'CONFINCLUDEDIR',
1951+            'CONFINCLUDEPY', 'DESTDIRS', 'DESTLIB', 'DESTSHARED',
1952+            'INCLDIRSTOMAKE', 'INCLUDEDIR', 'INCLUDEPY',
1953+            'LIBDEST', 'LIBDIR', 'LIBPC', 'LIBPL', 'MACHDESTLIB',
1954+            'MANDIR', 'SCRIPTDIR', 'datarootdir', 'exec_prefix',
1955+            'TZPATH',
1956+        ]
1957+
1958+        prefix = build_time_vars['BINDIR'][:-4]
1959+
1960+        for key in keys_to_replace:
1961+            value = build_time_vars[key]
1962+            build_time_vars[key] = value.replace(prefix, sys.prefix)
1963+    """
1964+
1965     with open(destfile, 'w', encoding='utf8') as f:
1966+        f.write('import sys\n')
1967         f.write('# system configuration generated and used by'
1968                 ' the sysconfig module\n')
1969         f.write('build_time_vars = ')
1970         pprint.pprint(vars, stream=f)
1971+        f.write('\n%s' % textwrap.dedent(replacement))
1972
1973     # Create file used for sys.path fixup -- see Modules/getpath.c
1974     with open('pybuilddir.txt', 'w', encoding='utf8') as f:
1975@@ -541,7 +574,7 @@ def _init_non_posix(vars):
1976     vars['INCLUDEPY'] = get_path('include')
1977     vars['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
1978     vars['EXE'] = '.exe'
1979-    vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
1980+    vars['VERSION'] = _PY_VERSION_SHORT
1981     vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
1982     vars['TZPATH'] = ''
1983
1984@@ -587,7 +620,7 @@ def parse_config_h(fp, vars=None):
1985 def get_config_h_filename():
1986     """Return the path of pyconfig.h."""
1987     if _PYTHON_BUILD:
1988-        if os.name == "nt":
1989+        if os.name == "nt" and not _POSIX_BUILD:
1990             inc_dir = os.path.join(_PROJECT_BASE, "PC")
1991         else:
1992             inc_dir = _PROJECT_BASE
1993@@ -662,11 +695,15 @@ def get_config_vars(*args):
1994             _CONFIG_VARS['py_version_nodot_plat'] = sys.winver.replace('.', '')
1995         except AttributeError:
1996             _CONFIG_VARS['py_version_nodot_plat'] = ''
1997+        if os.name == 'nt' and _POSIX_BUILD:
1998+            _CONFIG_VARS['py_version_short_plat'] = f'{_PY_VERSION_SHORT}-{get_platform()}'
1999+        else:
2000+            _CONFIG_VARS['py_version_short_plat'] = _PY_VERSION_SHORT
2001
2002-        if os.name == 'nt':
2003+        if os.name == 'nt' and not _POSIX_BUILD:
2004             _init_non_posix(_CONFIG_VARS)
2005             _CONFIG_VARS['VPATH'] = sys._vpath
2006-        if os.name == 'posix':
2007+        if _POSIX_BUILD:
2008             _init_posix(_CONFIG_VARS)
2009         if _HAS_USER_BASE:
2010             # Setting 'userbase' is done below the call to the
2011@@ -676,7 +713,7 @@ def get_config_vars(*args):
2012
2013         # Always convert srcdir to an absolute path
2014         srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
2015-        if os.name == 'posix':
2016+        if _POSIX_BUILD:
2017             if _PYTHON_BUILD:
2018                 # If srcdir is a relative path (typically '.' or '..')
2019                 # then it should be interpreted relative to the directory
2020@@ -714,7 +751,7 @@ def get_config_var(name):
2021     """
2022     return get_config_vars().get(name)
2023
2024-
2025+# make sure to change site._get_platform() while changing this function
2026 def get_platform():
2027     """Return a string that identifies the current platform.
2028
2029@@ -737,6 +774,22 @@ def get_platform():
2030
2031     """
2032     if os.name == 'nt':
2033+        if 'gcc' in sys.version.lower():
2034+            if 'ucrt' in sys.version.lower():
2035+                if 'amd64' in sys.version.lower():
2036+                    return 'mingw_x86_64_ucrt'
2037+                return 'mingw_i686_ucrt'
2038+            if 'clang' in sys.version.lower():
2039+                if 'amd64' in sys.version.lower():
2040+                    return 'mingw_x86_64_clang'
2041+                if 'arm64' in sys.version.lower():
2042+                    return 'mingw_aarch64'
2043+                if 'arm' in sys.version.lower():
2044+                    return 'mingw_armv7'
2045+                return 'mingw_i686_clang'
2046+            if 'amd64' in sys.version.lower():
2047+                return 'mingw_x86_64'
2048+            return 'mingw_i686'
2049         if 'amd64' in sys.version.lower():
2050             return 'win-amd64'
2051         if '(arm)' in sys.version.lower():
2052diff --git a/Lib/test/__main__.py b/Lib/test/__main__.py
2053index 19a6b2b..7641b32 100644
2054--- a/Lib/test/__main__.py
2055+++ b/Lib/test/__main__.py
2056@@ -1,2 +1,10 @@
2057+import os
2058+import sys
2059+
2060 from test.libregrtest import main
2061+
2062+if sys.platform == "win32":
2063+    # Enable DLL loading from PATH.
2064+    os.environ["PYTHONLEGACYWINDOWSDLLLOADING"] = "1"
2065+
2066 main()
2067diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
2068index 53ba1ad..3b6f4ab 100644
2069--- a/Lib/test/test_bytes.py
2070+++ b/Lib/test/test_bytes.py
2071@@ -1105,7 +1105,7 @@ def test_from_format(self):
2072
2073         if os.name == 'nt':
2074             # Windows (MSCRT)
2075-            ptr_format = '0x%0{}X'.format(2 * sizeof_ptr)
2076+            ptr_format = '0x%0{}x'.format(2 * sizeof_ptr)
2077             def ptr_formatter(ptr):
2078                 return (ptr_format % ptr)
2079         else:
2080diff --git a/Lib/test/test_getpath.py b/Lib/test/test_getpath.py
2081index 8d5b426..82ad71d 100644
2082--- a/Lib/test/test_getpath.py
2083+++ b/Lib/test/test_getpath.py
2084@@ -838,6 +838,7 @@ def test_symlink_buildpath_macos(self):
2085     ENV_PYTHONHOME="",
2086     ENV_PYTHONEXECUTABLE="",
2087     ENV___PYVENV_LAUNCHER__="",
2088+    ENV_MSYSTEM="",
2089     argv0="",
2090     py_setpath="",
2091     real_executable="",
2092@@ -877,6 +878,7 @@ def __init__(self, *a, argv0=None, config=None, **kw):
2093         self.update(DEFAULT_NAMESPACE)
2094         self["config"] = DEFAULT_CONFIG.copy()
2095         self["os_name"] = "nt"
2096+        self["is_mingw"] = 0
2097         self["PLATLIBDIR"] = "DLLs"
2098         self["PYWINVER"] = "9.8-XY"
2099         self["VPATH"] = r"..\.."
2100@@ -912,6 +914,9 @@ def __missing__(self, key):
2101         except AttributeError:
2102             raise KeyError(key) from None
2103
2104+    def normpath(self, path):
2105+        return ntpath.normpath(path)
2106+
2107     def abspath(self, path):
2108         if self.isabs(path):
2109             return path
2110@@ -1053,6 +1058,7 @@ def __init__(self, *a, argv0=None, config=None, **kw):
2111         self.update(DEFAULT_NAMESPACE)
2112         self["config"] = DEFAULT_CONFIG.copy()
2113         self["os_name"] = "posix"
2114+        self["is_mingw"] = 0
2115         self["PLATLIBDIR"] = "lib"
2116         self["WITH_NEXT_FRAMEWORK"] = 0
2117         super().__init__(*a, **kw)
2118@@ -1089,6 +1095,9 @@ def __missing__(self, key):
2119         except AttributeError:
2120             raise KeyError(key) from None
2121
2122+    def normpath(self, path):
2123+        return path
2124+
2125     def abspath(self, path):
2126         if self.isabs(path):
2127             return path
2128diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py
2129index cdd1bea..cfd8a10 100644
2130--- a/Lib/test/test_httpservers.py
2131+++ b/Lib/test/test_httpservers.py
2132@@ -442,10 +442,10 @@ def test_undecodable_filename(self):
2133     def test_undecodable_parameter(self):
2134         # sanity check using a valid parameter
2135         response = self.request(self.base_url + '/?x=123').read()
2136-        self.assertRegex(response, f'listing for {self.base_url}/\?x=123'.encode('latin1'))
2137+        self.assertRegex(response, rf'listing for {self.base_url}/\?x=123'.encode('latin1'))
2138         # now the bogus encoding
2139         response = self.request(self.base_url + '/?x=%bb').read()
2140-        self.assertRegex(response, f'listing for {self.base_url}/\?x=\xef\xbf\xbd'.encode('latin1'))
2141+        self.assertRegex(response, rf'listing for {self.base_url}/\?x=\xef\xbf\xbd'.encode('latin1'))
2142
2143     def test_get_dir_redirect_location_domain_injection_bug(self):
2144         """Ensure //evil.co/..%2f../../X does not put //evil.co/ in Location.
2145diff --git a/Lib/test/test_importlib/test_windows.py b/Lib/test/test_importlib/test_windows.py
2146index b7dfe86..58a8f5d 100644
2147--- a/Lib/test/test_importlib/test_windows.py
2148+++ b/Lib/test/test_importlib/test_windows.py
2149@@ -24,6 +24,23 @@ def get_platform():
2150             'x64' : 'win-amd64',
2151             'arm' : 'win-arm32',
2152         }
2153+    if os.name == 'nt':
2154+        if 'gcc' in sys.version.lower():
2155+            if 'ucrt' in sys.version.lower():
2156+                if 'amd64' in sys.version.lower():
2157+                    return 'mingw_x86_64_ucrt'
2158+                return 'mingw_i686_ucrt'
2159+            if 'clang' in sys.version.lower():
2160+                if 'amd64' in sys.version.lower():
2161+                    return 'mingw_x86_64_clang'
2162+                if 'arm64' in sys.version.lower():
2163+                    return 'mingw_aarch64'
2164+                if 'arm' in sys.version.lower():
2165+                    return 'mingw_armv7'
2166+                return 'mingw_i686_clang'
2167+            if 'amd64' in sys.version.lower():
2168+                return 'mingw_x86_64'
2169+            return 'mingw_i686'
2170     if ('VSCMD_ARG_TGT_ARCH' in os.environ and
2171         os.environ['VSCMD_ARG_TGT_ARCH'] in TARGET_TO_PLAT):
2172         return TARGET_TO_PLAT[os.environ['VSCMD_ARG_TGT_ARCH']]
2173diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
2174index d96371d..a75a664 100644
2175--- a/Lib/test/test_sysconfig.py
2176+++ b/Lib/test/test_sysconfig.py
2177@@ -17,7 +17,7 @@
2178 from sysconfig import (get_paths, get_platform, get_config_vars,
2179                        get_path, get_path_names, _INSTALL_SCHEMES,
2180                        get_default_scheme, get_scheme_names, get_config_var,
2181-                       _expand_vars, _get_preferred_schemes, _main)
2182+                       _expand_vars, _get_preferred_schemes, _main, _POSIX_BUILD)
2183 import _osx_support
2184
2185
2186@@ -180,7 +180,7 @@ def test_nt_venv_scheme(self):
2187         self.assertEqual(libpath, sysconfig.get_path('purelib', scheme='nt_venv'))
2188
2189     def test_venv_scheme(self):
2190-        if sys.platform == 'win32':
2191+        if not _POSIX_BUILD and sys.platform == 'win32':
2192             self.assertEqual(
2193                 sysconfig.get_path('scripts', scheme='venv'),
2194                 sysconfig.get_path('scripts', scheme='nt_venv')
2195@@ -371,6 +371,10 @@ def test_user_similar(self):
2196             if HAS_USER_BASE:
2197                 user_path = get_path(name, 'posix_user')
2198                 expected = os.path.normpath(global_path.replace(base, user, 1))
2199+                if os.name == 'nt' and _POSIX_BUILD:
2200+                    expected = expected.replace(
2201+                        f'python{sysconfig.get_python_version()}',
2202+                        f'python{sysconfig.get_python_version()}-{get_platform()}')
2203                 # bpo-44860: platlib of posix_user doesn't use sys.platlibdir,
2204                 # whereas posix_prefix does.
2205                 if name == 'platlib':
2206diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py
2207index 4403f2b..ab5be51 100644
2208--- a/Lib/venv/__init__.py
2209+++ b/Lib/venv/__init__.py
2210@@ -302,7 +302,7 @@ def setup_python(self, context):
2211                     if not os.path.islink(path):
2212                         os.chmod(path, 0o755)
2213         else:
2214-            if self.symlinks:
2215+            if self.symlinks and not _POSIX_BUILD:
2216                 # For symlinking, we need a complete copy of the root directory
2217                 # If symlinks fail, you'll get unnecessary copies of files, but
2218                 # we assume that if you've opted into symlinks on Windows then
2219@@ -326,6 +326,12 @@ def setup_python(self, context):
2220                 if os.path.lexists(src):
2221                     copier(src, os.path.join(binpath, suffix))
2222
2223+            if _POSIX_BUILD:
2224+                # copy from python/pythonw so the venvlauncher magic in symlink_or_copy triggers
2225+                copier(os.path.join(dirname, 'python.exe'), os.path.join(binpath, 'python3.exe'))
2226+                copier(os.path.join(dirname, 'python.exe'), os.path.join(binpath, 'python%d.%d.exe' % sys.version_info[:2]))
2227+                copier(os.path.join(dirname, 'pythonw.exe'), os.path.join(binpath, 'python3w.exe'))
2228+
2229             if sysconfig.is_python_build():
2230                 # copy init.tcl
2231                 for root, dirs, files in os.walk(context.python_dir):
2232@@ -350,6 +356,7 @@ def _call_new_python(self, context, *py_args, **kwargs):
2233         env['VIRTUAL_ENV'] = context.env_dir
2234         env.pop('PYTHONHOME', None)
2235         env.pop('PYTHONPATH', None)
2236+        env.pop("MSYSTEM", None)
2237         kwargs['cwd'] = context.env_dir
2238         kwargs['executable'] = context.env_exec_cmd
2239         subprocess.check_output(args, **kwargs)
2240diff --git a/Makefile.pre.in b/Makefile.pre.in
2241index 3ea8653..e4730eb 100644
2242--- a/Makefile.pre.in
2243+++ b/Makefile.pre.in
2244@@ -39,6 +39,7 @@ CXX=		@CXX@
2245 MAINCC=		@MAINCC@
2246 LINKCC=		@LINKCC@
2247 AR=		@AR@
2248+WINDRES=	@WINDRES@
2249 READELF=	@READELF@
2250 SOABI=		@SOABI@
2251 LDVERSION=	@LDVERSION@
2252@@ -123,6 +124,7 @@ PY_CORE_CFLAGS=	$(PY_STDMODULE_CFLAGS) -DPy_BUILD_CORE
2253 PY_CORE_LDFLAGS=$(PY_LDFLAGS) $(PY_LDFLAGS_NODIST)
2254 # Strict or non-strict aliasing flags used to compile dtoa.c, see above
2255 CFLAGS_ALIASING=@CFLAGS_ALIASING@
2256+RCFLAGS=@RCFLAGS@
2257
2258
2259 # Machine-dependent subdirectories
2260@@ -141,6 +143,12 @@ exec_prefix=	@exec_prefix@
2261 # Install prefix for data files
2262 datarootdir=    @datarootdir@
2263
2264+# Locations needed for semi-native fixup of sysconfig.
2265+srcdir_b2h=		@srcdir_b2h@
2266+abs_srcdir_b2h=		@abs_srcdir_b2h@
2267+abs_builddir_b2h=	@abs_builddir_b2h@
2268+prefix_b2h=		@prefix_b2h@
2269+
2270 # Expanded directories
2271 BINDIR=		@bindir@
2272 LIBDIR=		@libdir@
2273@@ -158,10 +166,12 @@ BINLIBDEST=	@BINLIBDEST@
2274 LIBDEST=	$(SCRIPTDIR)/python$(VERSION)
2275 INCLUDEPY=	$(INCLUDEDIR)/python$(LDVERSION)
2276 CONFINCLUDEPY=	$(CONFINCLUDEDIR)/python$(LDVERSION)
2277+VENVLAUNCHERDIR=	$(BINLIBDEST)/venv/scripts/nt
2278
2279 # Symbols used for using shared libraries
2280 SHLIB_SUFFIX=	@SHLIB_SUFFIX@
2281 EXT_SUFFIX=	@EXT_SUFFIX@
2282+PYD_PLATFORM_TAG = @PYD_PLATFORM_TAG@
2283 LDSHARED=	@LDSHARED@ $(PY_LDFLAGS)
2284 BLDSHARED=	@BLDSHARED@ $(PY_CORE_LDFLAGS)
2285 LDCXXSHARED=	@LDCXXSHARED@
2286@@ -268,6 +278,8 @@ LIBRARY_DEPS=	@LIBRARY_DEPS@
2287 LINK_PYTHON_DEPS=@LINK_PYTHON_DEPS@
2288 PY_ENABLE_SHARED=	@PY_ENABLE_SHARED@
2289 STATIC_LIBPYTHON=	@STATIC_LIBPYTHON@
2290+ABI3DLLLIBRARY= libpython3.dll
2291+ABI3LDLIBRARY=  libpython3.dll.a
2292
2293
2294 LIBS=		@LIBS@
2295@@ -284,6 +296,7 @@ LIBOBJS=	@LIBOBJS@
2296
2297 PYTHON=		python$(EXE)
2298 BUILDPYTHON=	python$(BUILDEXE)
2299+BUILDPYTHONW=	pythonw$(BUILDEXE)
2300
2301 HOSTRUNNER= @HOSTRUNNER@
2302
2303@@ -344,6 +357,7 @@ IO_OBJS=	\
2304 ##########################################################################
2305
2306 LIBFFI_INCLUDEDIR=	@LIBFFI_INCLUDEDIR@
2307+NCURSESW_INCLUDEDIR=	@NCURSESW_INCLUDEDIR@
2308
2309 ##########################################################################
2310 # Parser
2311@@ -390,7 +404,7 @@ PYTHON_OBJS=	\
2312 		Python/dynamic_annotations.o \
2313 		Python/errors.o \
2314 		Python/frame.o \
2315-		Python/frozenmain.o \
2316+		@PYTHON_OBJS_FROZENMAIN@ \
2317 		Python/future.o \
2318 		Python/getargs.o \
2319 		Python/getcompiler.o \
2320@@ -402,6 +416,7 @@ PYTHON_OBJS=	\
2321 		Python/import.o \
2322 		Python/importdl.o \
2323 		Python/initconfig.o \
2324+		Python/iscygpty.o \
2325 		Python/marshal.o \
2326 		Python/modsupport.o \
2327 		Python/mysnprintf.o \
2328@@ -584,8 +599,8 @@ LIBEXPAT_HEADERS= \
2329
2330 # Default target
2331 all:		@DEF_MAKE_ALL_RULE@
2332-build_all:	check-clean-src $(BUILDPYTHON) platform oldsharedmods sharedmods \
2333-		gdbhooks Programs/_testembed python-config
2334+build_all:	check-clean-src $(BUILDPYTHON) $(BUILDPYTHONW) platform oldsharedmods sharedmods \
2335+		gdbhooks Programs/_testembed python-config $(ABI3DLLLIBRARY) $(ABI3LDLIBRARY)
2336 build_wasm: check-clean-src $(BUILDPYTHON) platform oldsharedmods python-config
2337
2338 # Check that the source is clean when building out of source.
2339@@ -700,9 +715,30 @@ coverage-report: regen-token regen-frozen
2340 clinic: check-clean-src $(srcdir)/Modules/_blake2/blake2s_impl.c
2341 	$(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py --make --srcdir $(srcdir)
2342
2343+python_exe.o: $(srcdir)/PC/python_exe.rc
2344+	$(WINDRES) $(RCFLAGS) -I$(srcdir)/Include -I$(srcdir)/PC -I. $(srcdir)/PC/python_exe.rc $@
2345+
2346+pythonw_exe.o: $(srcdir)/PC/pythonw_exe.rc
2347+	$(WINDRES) $(RCFLAGS) -I$(srcdir)/Include -I$(srcdir)/PC -I. $(srcdir)/PC/pythonw_exe.rc $@
2348+
2349+python_nt.o: $(srcdir)/PC/python_nt.rc
2350+	$(WINDRES) $(RCFLAGS) -DORIGINAL_FILENAME=\\\"$(DLLLIBRARY)\\\" -I$(srcdir)/Include -I$(srcdir)/PC -I. $(srcdir)/PC/python_nt.rc $@
2351+
2352+python3dll_nt.o: $(srcdir)/PC/python_nt.rc
2353+	$(WINDRES) $(RCFLAGS) -DORIGINAL_FILENAME=\\\"$(ABI3DLLLIBRARY)\\\" -I$(srcdir)/Include -I$(srcdir)/PC -I. $(srcdir)/PC/python_nt.rc $@
2354+
2355+venvlauncher.o: $(srcdir)/PC/pylauncher.rc
2356+	$(WINDRES) $(RCFLAGS) -DPY_ICON -I$(srcdir)/Include -I$(srcdir)/PC -I. $(srcdir)/PC/pylauncher.rc $@
2357+
2358+venvwlauncher.o: $(srcdir)/PC/pylauncher.rc
2359+	$(WINDRES) $(RCFLAGS) -DPYW_ICON -I$(srcdir)/Include -I$(srcdir)/PC -I. $(srcdir)/PC/pylauncher.rc $@
2360+
2361+$(BUILDPYTHONW): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) pythonw_exe.o
2362+	$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -municode -mwindows -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) pythonw_exe.o
2363+
2364 # Build the interpreter
2365-$(BUILDPYTHON):	Programs/python.o $(LINK_PYTHON_DEPS)
2366-	$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS)
2367+$(BUILDPYTHON):	Programs/python.o $(LINK_PYTHON_DEPS) python_exe.o
2368+	$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -municode -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) python_exe.o
2369
2370 platform: $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt
2371 	$(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform
2372@@ -806,13 +842,17 @@ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK): \
2373
2374 # This rule builds the Cygwin Python DLL and import library if configured
2375 # for a shared core library; otherwise, this rule is a noop.
2376-$(DLLLIBRARY) libpython$(LDVERSION).dll.a: $(LIBRARY_OBJS)
2377+$(DLLLIBRARY) libpython$(LDVERSION).dll.a: $(LIBRARY_OBJS) python_nt.o
2378 	if test -n "$(DLLLIBRARY)"; then \
2379 		$(LDSHARED) -Wl,--out-implib=$@ -o $(DLLLIBRARY) $^ \
2380-			$(LIBS) $(MODLIBS) $(SYSLIBS); \
2381+			$(LIBS) $(LDFLAGS_NODIST) $(MODLIBS) $(SYSLIBS) python_nt.o; \
2382 	else true; \
2383 	fi
2384
2385+$(ABI3DLLLIBRARY) $(ABI3LDLIBRARY): python3dll_nt.o $(srcdir)/PC/launcher.c
2386+	$(LDSHARED) -DPYTHON_DLL_NAME=\"$(DLLLIBRARY)\" $(srcdir)/PC/python3dll.c -Wl,--out-implib=$(ABI3LDLIBRARY) -o $(ABI3DLLLIBRARY) python3dll_nt.o \
2387+		$(LDFLAGS_NODIST);
2388+
2389 # wasm32-emscripten browser build
2390 # wasm assets directory is relative to current build dir, e.g. "./usr/local".
2391 # --preload-file turns a relative asset path into an absolute path.
2392@@ -974,7 +1014,7 @@ BOOTSTRAP_HEADERS = \
2393 Programs/_bootstrap_python.o: Programs/_bootstrap_python.c $(BOOTSTRAP_HEADERS) $(PYTHON_HEADERS)
2394
2395 _bootstrap_python: $(LIBRARY_OBJS_OMIT_FROZEN) Programs/_bootstrap_python.o Modules/getpath.o Modules/Setup.local
2396-	$(LINKCC) $(PY_LDFLAGS_NOLTO) -o $@ $(LIBRARY_OBJS_OMIT_FROZEN) \
2397+	$(LINKCC) $(PY_LDFLAGS_NOLTO) -o $@ -municode -mwindows $(LIBRARY_OBJS_OMIT_FROZEN) \
2398 		Programs/_bootstrap_python.o Modules/getpath.o $(LIBS) $(MODLIBS) $(SYSLIBS)
2399
2400
2401@@ -1276,9 +1316,15 @@ Python/dynload_hpux.o: $(srcdir)/Python/dynload_hpux.c Makefile
2402 		-DSHLIB_EXT='"$(EXT_SUFFIX)"' \
2403 		-o $@ $(srcdir)/Python/dynload_hpux.c
2404
2405+Python/dynload_win.o: $(srcdir)/Python/dynload_win.c Makefile
2406+	$(CC) -c $(PY_CORE_CFLAGS) \
2407+		-DPYD_PLATFORM_TAG='"$(PYD_PLATFORM_TAG)"' \
2408+		-o $@ $(srcdir)/Python/dynload_win.c
2409+
2410 Python/sysmodule.o: $(srcdir)/Python/sysmodule.c Makefile $(srcdir)/Include/pydtrace.h
2411 	$(CC) -c $(PY_CORE_CFLAGS) \
2412 		-DABIFLAGS='"$(ABIFLAGS)"' \
2413+		-DVPATH='"$(VPATH)"' \
2414 		$(MULTIARCH_CPPFLAGS) \
2415 		-o $@ $(srcdir)/Python/sysmodule.c
2416
2417@@ -1496,6 +1542,7 @@ PYTHON_HEADERS= \
2418 		$(srcdir)/Include/frameobject.h \
2419 		$(srcdir)/Include/import.h \
2420 		$(srcdir)/Include/intrcheck.h \
2421+		$(srcdir)/Include/iscygpty.h \
2422 		$(srcdir)/Include/iterobject.h \
2423 		$(srcdir)/Include/listobject.h \
2424 		$(srcdir)/Include/longobject.h \
2425@@ -1791,7 +1838,7 @@ $(DESTSHARED):
2426 # Install the interpreter with $(VERSION) affixed
2427 # This goes into $(exec_prefix)
2428 altbininstall: $(BUILDPYTHON) @FRAMEWORKPYTHONW@
2429-	@for i in $(BINDIR) $(LIBDIR); \
2430+	@for i in $(BINDIR) $(LIBDIR) $(VENVLAUNCHERDIR); \
2431 	do \
2432 		if test ! -d $(DESTDIR)$$i; then \
2433 			echo "Creating directory $$i"; \
2434@@ -1801,6 +1848,7 @@ altbininstall: $(BUILDPYTHON) @FRAMEWORKPYTHONW@
2435 	done
2436 	if test "$(PYTHONFRAMEWORKDIR)" = "no-framework" ; then \
2437 		$(INSTALL_PROGRAM) $(BUILDPYTHON) $(DESTDIR)$(BINDIR)/python$(LDVERSION)$(EXE); \
2438+		$(INSTALL_PROGRAM) $(BUILDPYTHONW) $(DESTDIR)$(BINDIR)/python3w$(EXE); \
2439 	else \
2440 		$(INSTALL_PROGRAM) $(STRIPFLAG) Mac/pythonw $(DESTDIR)$(BINDIR)/python$(LDVERSION)$(EXE); \
2441 	fi
2442@@ -1814,6 +1862,7 @@ altbininstall: $(BUILDPYTHON) @FRAMEWORKPYTHONW@
2443 		if test -f $(LDLIBRARY) && test "$(PYTHONFRAMEWORKDIR)" = "no-framework" ; then \
2444 			if test -n "$(DLLLIBRARY)" ; then \
2445 				$(INSTALL_SHARED) $(DLLLIBRARY) $(DESTDIR)$(BINDIR); \
2446+				$(INSTALL_SHARED) $(ABI3DLLLIBRARY) $(DESTDIR)$(BINDIR); \
2447 			else \
2448 				$(INSTALL_SHARED) $(LDLIBRARY) $(DESTDIR)$(LIBDIR)/$(INSTSONAME); \
2449 				if test $(LDLIBRARY) != $(INSTSONAME); then \
2450@@ -1924,6 +1973,7 @@ LIBSUBDIRS=	asyncio \
2451 		tkinter \
2452 		tomllib \
2453 		turtledemo \
2454+		msilib \
2455 		unittest \
2456 		urllib \
2457 		venv venv/scripts venv/scripts/common venv/scripts/posix \
2458@@ -2223,8 +2273,9 @@ libainstall: all python-config
2459 	@if test "$(STATIC_LIBPYTHON)" = 1; then \
2460 		if test -d $(LIBRARY); then :; else \
2461 			if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \
2462-				if test "$(SHLIB_SUFFIX)" = .dll; then \
2463-					$(INSTALL_DATA) $(LDLIBRARY) $(DESTDIR)$(LIBPL) ; \
2464+				if test "$(SHLIB_SUFFIX)" = .dll -o "$(SHLIB_SUFFIX)" = .pyd; then \
2465+					$(INSTALL_DATA) $(LDLIBRARY) $(DESTDIR)$(LIBDIR) ; \
2466+					$(INSTALL_DATA) $(ABI3LDLIBRARY) $(DESTDIR)$(LIBDIR) ; \
2467 				else \
2468 					$(INSTALL_DATA) $(LIBRARY) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \
2469 				fi; \
2470@@ -2263,16 +2314,23 @@ libainstall: all python-config
2471 	else true; \
2472 	fi
2473
2474+ifeq ($(shell uname -o),Msys)
2475+DESTDIRFINAL=$(DESTDIR)
2476+else
2477+DESTDIRFINAL=$(DESTDIR)/
2478+endif
2479+
2480 # Install the dynamically loadable modules
2481 # This goes into $(exec_prefix)
2482 sharedinstall: all
2483+	MSYS2_ARG_CONV_EXCL="--prefix=;--install-scripts=;--install-platlib=" \
2484 	$(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \
2485 	   	--prefix=$(prefix) \
2486 		--install-scripts=$(BINDIR) \
2487 		--install-platlib=$(DESTSHARED) \
2488-		--root=$(DESTDIR)/
2489-	-rm $(DESTDIR)$(DESTSHARED)/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py
2490-	-rm -r $(DESTDIR)$(DESTSHARED)/__pycache__
2491+		--root=$(DESTDIRFINAL)
2492+	-rm $(DESTDIRFINAL)$(DESTSHARED)/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py
2493+	-rm -r $(DESTDIRFINAL)$(DESTSHARED)/__pycache__
2494
2495 # Here are a couple of targets for MacOSX again, to install a full
2496 # framework-based Python. frameworkinstall installs everything, the
2497@@ -2464,7 +2522,7 @@ clean: clean-retain-profile
2498 	fi
2499
2500 clobber: clean
2501-	-rm -f $(BUILDPYTHON) $(LIBRARY) $(LDLIBRARY) $(DLLLIBRARY) \
2502+	-rm -f $(BUILDPYTHON) $(LIBRARY) $(LDLIBRARY) $(DLLLIBRARY)$(ABI3LDLIBRARY) $(ABI3DLLLIBRARY) \
2503 		tags TAGS \
2504 		config.cache config.log pyconfig.h Modules/config.c
2505 	-rm -rf build platform
2506diff --git a/Misc/NEWS.d/3.11.4.rst b/Misc/NEWS.d/3.11.4.rst
2507new file mode 100644
2508index 0000000..71ed43d
2509--- /dev/null
2510+++ b/Misc/NEWS.d/3.11.4.rst
2511@@ -0,0 +1,785 @@
2512+.. date: 2023-06-01-03-24-58
2513+.. gh-issue: 103142
2514+.. nonce: GLWDMX
2515+.. release date: 2023-06-06
2516+.. section: Security
2517+
2518+The version of OpenSSL used in our binary builds has been upgraded to 1.1.1u
2519+to address several CVEs.
2520+
2521+..
2522+
2523+.. date: 2023-05-02-17-56-32
2524+.. gh-issue: 99889
2525+.. nonce: l664SU
2526+.. section: Security
2527+
2528+Fixed a security in flaw in :func:`uu.decode` that could allow for directory
2529+traversal based on the input if no ``out_file`` was specified.
2530+
2531+..
2532+
2533+.. date: 2023-05-01-15-03-25
2534+.. gh-issue: 104049
2535+.. nonce: b01Y3g
2536+.. section: Security
2537+
2538+Do not expose the local on-disk location in directory indexes produced by
2539+:class:`http.client.SimpleHTTPRequestHandler`.
2540+
2541+..
2542+
2543+.. date: 2023-03-07-20-59-17
2544+.. gh-issue: 102153
2545+.. nonce: 14CLSZ
2546+.. section: Security
2547+
2548+:func:`urllib.parse.urlsplit` now strips leading C0 control and space
2549+characters following the specification for URLs defined by WHATWG in
2550+response to CVE-2023-24329. Patch by Illia Volochii.
2551+
2552+..
2553+
2554+.. date: 2023-05-31-19-35-22
2555+.. gh-issue: 105164
2556+.. nonce: 6Wajph
2557+.. section: Core and Builtins
2558+
2559+Ensure annotations are set up correctly if the only annotation in a block is
2560+within a :keyword:`match` block. Patch by Jelle Zijlstra.
2561+
2562+..
2563+
2564+.. date: 2023-05-18-13-00-21
2565+.. gh-issue: 104615
2566+.. nonce: h_rtw2
2567+.. section: Core and Builtins
2568+
2569+Fix wrong ordering of assignments in code like ``a, a = x, y``. Contributed
2570+by Carl Meyer.
2571+
2572+..
2573+
2574+.. date: 2023-05-14-18-56-54
2575+.. gh-issue: 104482
2576+.. nonce: yaQsv8
2577+.. section: Core and Builtins
2578+
2579+Fix three error handling bugs in ast.c's validation of pattern matching
2580+statements.
2581+
2582+..
2583+
2584+.. date: 2023-05-13-06-22-52
2585+.. gh-issue: 102818
2586+.. nonce: HIX1Dr
2587+.. section: Core and Builtins
2588+
2589+Do not add a frame to the traceback in the ``sys.setprofile`` and
2590+``sys.settrace`` trampoline functions. This ensures that frames are not
2591+duplicated if an exception is raised in the callback function, and ensures
2592+that frames are not omitted if a C callback is used and that does not add
2593+the frame.
2594+
2595+..
2596+
2597+.. date: 2023-05-12-00-19-02
2598+.. gh-issue: 104405
2599+.. nonce: tXV5fn
2600+.. section: Core and Builtins
2601+
2602+Fix an issue where some :term:`bytecode` instructions could ignore
2603+:pep:`523` when "inlining" calls.
2604+
2605+..
2606+
2607+.. date: 2023-05-01-12-03-52
2608+.. gh-issue: 104018
2609+.. nonce: PFxGS4
2610+.. section: Core and Builtins
2611+
2612+Disallow the "z" format specifier in %-format of bytes objects.
2613+
2614+..
2615+
2616+.. date: 2023-04-28-18-57-13
2617+.. gh-issue: 103971
2618+.. nonce: Q3U9lv
2619+.. section: Core and Builtins
2620+
2621+Fix an issue where incorrect locations numbers could be assigned to code
2622+following ``case`` blocks.
2623+
2624+..
2625+
2626+.. date: 2023-04-21-17-03-14
2627+.. gh-issue: 102310
2628+.. nonce: anLjDx
2629+.. section: Core and Builtins
2630+
2631+Change the error range for invalid bytes literals.
2632+
2633+..
2634+
2635+.. date: 2023-04-21-16-12-41
2636+.. gh-issue: 103590
2637+.. nonce: 7DHDOE
2638+.. section: Core and Builtins
2639+
2640+Do not wrap a single exception raised from a ``try-except*`` construct in an
2641+:exc:`ExceptionGroup`.
2642+
2643+..
2644+
2645+.. date: 2023-04-14-22-35-23
2646+.. gh-issue: 101517
2647+.. nonce: 5EqM-S
2648+.. section: Core and Builtins
2649+
2650+Fix bug in line numbers of instructions emitted for :keyword:`except*
2651+<except_star>`.
2652+
2653+..
2654+
2655+.. date: 2023-04-08-17-13-07
2656+.. gh-issue: 103242
2657+.. nonce: ysI1b3
2658+.. section: Core and Builtins
2659+
2660+Migrate :meth:`~ssl.SSLContext.set_ecdh_curve` method not to use deprecated
2661+OpenSSL APIs. Patch by Dong-hee Na.
2662+
2663+..
2664+
2665+.. date: 2023-04-01-00-46-31
2666+.. gh-issue: 102700
2667+.. nonce: 493NB4
2668+.. section: Core and Builtins
2669+
2670+Allow built-in modules to be submodules. This allows submodules to be
2671+statically linked into a CPython binary.
2672+
2673+..
2674+
2675+.. date: 2023-02-12-22-40-22
2676+.. gh-issue: 101857
2677+.. nonce: _bribG
2678+.. section: Core and Builtins
2679+
2680+Fix xattr support detection on Linux systems by widening the check to linux,
2681+not just glibc. This fixes support for musl.
2682+
2683+..
2684+
2685+.. date: 2022-11-08-12-36-25
2686+.. gh-issue: 99184
2687+.. nonce: KIaqzz
2688+.. section: Core and Builtins
2689+
2690+Bypass instance attribute access of ``__name__`` in ``repr`` of
2691+:class:`weakref.ref`.
2692+
2693+..
2694+
2695+.. date: 2022-09-27-11-59-13
2696+.. gh-issue: 96670
2697+.. nonce: XrBBit
2698+.. section: Core and Builtins
2699+
2700+The parser now raises :exc:`SyntaxError` when parsing source code containing
2701+null bytes. Backported from ``aab01e3``. Patch by Pablo Galindo
2702+
2703+..
2704+
2705+.. bpo: 31821
2706+.. date: 2019-12-01-12-58-31
2707+.. nonce: 1FNmwk
2708+.. section: Core and Builtins
2709+
2710+Fix :func:`!pause_reading` to work when called from :func:`!connection_made`
2711+in :mod:`asyncio`.
2712+
2713+..
2714+
2715+.. date: 2023-06-02-02-38-26
2716+.. gh-issue: 105080
2717+.. nonce: 2imGMg
2718+.. section: Library
2719+
2720+Fixed inconsistent signature on derived classes for
2721+:func:`inspect.signature`
2722+
2723+..
2724+
2725+.. date: 2023-05-24-09-34-23
2726+.. gh-issue: 104874
2727+.. nonce: oqyJSy
2728+.. section: Library
2729+
2730+Document the ``__name__`` and ``__supertype__`` attributes of
2731+:class:`typing.NewType`. Patch by Jelle Zijlstra.
2732+
2733+..
2734+
2735+.. date: 2023-05-17-20-03-01
2736+.. gh-issue: 104340
2737+.. nonce: kp_XmX
2738+.. section: Library
2739+
2740+When an ``asyncio`` pipe protocol loses its connection due to an error, and
2741+the caller doesn't await ``wait_closed()`` on the corresponding
2742+``StreamWriter``, don't log a warning about an exception that was never
2743+retrieved. After all, according to the ``StreamWriter.close()`` docs, the
2744+``wait_closed()`` call is optional ("not mandatory").
2745+
2746+..
2747+
2748+.. date: 2023-05-17-08-01-36
2749+.. gh-issue: 104372
2750+.. nonce: jpoWs6
2751+.. section: Library
2752+
2753+Refactored the ``_posixsubprocess`` internals to avoid Python C API usage
2754+between fork and exec when marking ``pass_fds=`` file descriptors
2755+inheritable.
2756+
2757+..
2758+
2759+.. date: 2023-05-16-11-02-44
2760+.. gh-issue: 75367
2761+.. nonce: qLWR35
2762+.. section: Library
2763+
2764+Fix data descriptor detection in  :func:`inspect.getattr_static`.
2765+
2766+..
2767+
2768+.. date: 2023-05-16-10-07-16
2769+.. gh-issue: 104536
2770+.. nonce: hFWD8f
2771+.. section: Library
2772+
2773+Fix a race condition in the internal :mod:`multiprocessing.process` cleanup
2774+logic that could manifest as an unintended ``AttributeError`` when calling
2775+``process.close()``.
2776+
2777+..
2778+
2779+.. date: 2023-05-11-23-03-00
2780+.. gh-issue: 104399
2781+.. nonce: MMatTP
2782+.. section: Library
2783+
2784+Prepare the ``_tkinter`` module for building with Tcl 9.0 and future
2785+libtommath by replacing usage of deprecated functions
2786+:c:func:`mp_to_unsigned_bin_n` and :c:func:`mp_unsigned_bin_size` when
2787+necessary.
2788+
2789+..
2790+
2791+.. date: 2023-05-08-20-57-17
2792+.. gh-issue: 104307
2793+.. nonce: DSB93G
2794+.. section: Library
2795+
2796+:func:`socket.getnameinfo` now releases the GIL while contacting the DNS
2797+server
2798+
2799+..
2800+
2801+.. date: 2023-05-08-15-39-00
2802+.. gh-issue: 87695
2803+.. nonce: f6iO7v
2804+.. section: Library
2805+
2806+Fix issue where :meth:`pathlib.Path.glob` raised :exc:`OSError` when it
2807+encountered a symlink to an overly long path.
2808+
2809+..
2810+
2811+.. date: 2023-05-07-19-56-45
2812+.. gh-issue: 104265
2813+.. nonce: fVblry
2814+.. section: Library
2815+
2816+Prevent possible crash by disallowing instantiation of the
2817+:class:`!_csv.Reader` and :class:`!_csv.Writer` types. The regression was
2818+introduced in 3.10.0a4 with PR 23224 (:issue:`14935`). Patch by Radislav
2819+Chugunov.
2820+
2821+..
2822+
2823+.. date: 2023-05-01-16-43-28
2824+.. gh-issue: 104035
2825+.. nonce: MrJBw8
2826+.. section: Library
2827+
2828+Do not ignore user-defined ``__getstate__`` and ``__setstate__`` methods for
2829+slotted frozen dataclasses.
2830+
2831+..
2832+
2833+.. date: 2023-04-29-18-23-16
2834+.. gh-issue: 103987
2835+.. nonce: sRgALL
2836+.. section: Library
2837+
2838+In :mod:`mmap`, fix several bugs that could lead to access to memory-mapped
2839+files after they have been invalidated.
2840+
2841+..
2842+
2843+.. date: 2023-04-27-20-03-08
2844+.. gh-issue: 103935
2845+.. nonce: Uaf2M0
2846+.. section: Library
2847+
2848+Use :func:`io.open_code` for files to be executed instead of raw
2849+:func:`open`
2850+
2851+..
2852+
2853+.. date: 2023-04-27-00-45-41
2854+.. gh-issue: 100370
2855+.. nonce: MgZ3KY
2856+.. section: Library
2857+
2858+Fix potential :exc:`OverflowError` in :meth:`sqlite3.Connection.blobopen`
2859+for 32-bit builds. Patch by Erlend E. Aasland.
2860+
2861+..
2862+
2863+.. date: 2023-04-26-09-54-25
2864+.. gh-issue: 103848
2865+.. nonce: aDSnpR
2866+.. section: Library
2867+
2868+Add checks to ensure that ``[`` bracketed ``]`` hosts found by
2869+:func:`urllib.parse.urlsplit` are of IPv6 or IPvFuture format.
2870+
2871+..
2872+
2873+.. date: 2023-04-26-09-38-47
2874+.. gh-issue: 103872
2875+.. nonce: 8LBsDz
2876+.. section: Library
2877+
2878+Update the bundled copy of pip to version 23.1.2.
2879+
2880+..
2881+
2882+.. date: 2023-04-25-19-58-13
2883+.. gh-issue: 103861
2884+.. nonce: JeozgD
2885+.. section: Library
2886+
2887+Fix ``zipfile.Zipfile`` creating invalid zip files when ``force_zip64`` was
2888+used to add files to them. Patch by Carey Metcalfe.
2889+
2890+..
2891+
2892+.. date: 2023-04-24-00-34-23
2893+.. gh-issue: 103685
2894+.. nonce: U14jBM
2895+.. section: Library
2896+
2897+Prepare :meth:`tkinter.Menu.index` for Tk 8.7 so that it does not raise
2898+``TclError: expected integer but got ""`` when it should return ``None``.
2899+
2900+..
2901+
2902+.. date: 2023-04-22-22-14-09
2903+.. gh-issue: 81403
2904+.. nonce: zVz9Td
2905+.. section: Library
2906+
2907+:class:`urllib.request.CacheFTPHandler` no longer raises :class:`URLError`
2908+if a cached FTP instance is reused. ftplib's endtransfer method calls
2909+voidresp to drain the connection to handle FTP instance reuse properly.
2910+
2911+..
2912+
2913+.. date: 2023-04-16-18-29-04
2914+.. gh-issue: 103578
2915+.. nonce: fly1wc
2916+.. section: Library
2917+
2918+Fixed a bug where :mod:`pdb` crashes when reading source file with different
2919+encoding by replacing :func:`io.open` with :func:`io.open_code`. The new
2920+method would also call into the hook set by :func:`PyFile_SetOpenCodeHook`.
2921+
2922+..
2923+
2924+.. date: 2023-04-15-12-19-14
2925+.. gh-issue: 103556
2926+.. nonce: TEf-2m
2927+.. section: Library
2928+
2929+Now creating :class:`inspect.Signature` objects with positional-only
2930+parameter with a default followed by a positional-or-keyword parameter
2931+without one is impossible.
2932+
2933+..
2934+
2935+.. date: 2023-04-15-11-21-38
2936+.. gh-issue: 103559
2937+.. nonce: a9rYHG
2938+.. section: Library
2939+
2940+Update the bundled copy of pip to version 23.1.1.
2941+
2942+..
2943+
2944+.. date: 2023-04-12-17-59-55
2945+.. gh-issue: 103365
2946+.. nonce: UBEE0U
2947+.. section: Library
2948+
2949+Set default Flag boundary to ``STRICT`` and fix bitwise operations.
2950+
2951+..
2952+
2953+.. date: 2023-04-12-13-04-16
2954+.. gh-issue: 103472
2955+.. nonce: C6bOHv
2956+.. section: Library
2957+
2958+Avoid a potential :exc:`ResourceWarning` in
2959+:class:`http.client.HTTPConnection` by closing the proxy / tunnel's CONNECT
2960+response explicitly.
2961+
2962+..
2963+
2964+.. date: 2023-04-11-21-38-39
2965+.. gh-issue: 103449
2966+.. nonce: -nxmhb
2967+.. section: Library
2968+
2969+Fix a bug in doc string generation in :func:`dataclasses.dataclass`.
2970+
2971+..
2972+
2973+.. date: 2023-04-06-17-28-36
2974+.. gh-issue: 103256
2975+.. nonce: 1syxfs
2976+.. section: Library
2977+
2978+Fixed a bug that caused :mod:`hmac` to raise an exception when the requested
2979+hash algorithm was not available in OpenSSL despite being available
2980+separately as part of ``hashlib`` itself.  It now falls back properly to the
2981+built-in. This could happen when, for example, your OpenSSL does not include
2982+SHA3 support and you want to compute ``hmac.digest(b'K', b'M',
2983+'sha3_256')``.
2984+
2985+..
2986+
2987+.. date: 2023-04-05-01-28-53
2988+.. gh-issue: 103225
2989+.. nonce: QD3JVU
2990+.. section: Library
2991+
2992+Fix a bug in :mod:`pdb` when displaying line numbers of module-level source
2993+code.
2994+
2995+..
2996+
2997+.. date: 2023-04-04-12-43-38
2998+.. gh-issue: 93910
2999+.. nonce: jurMzv
3000+.. section: Library
3001+
3002+Remove deprecation of enum ``memmber.member`` access.
3003+
3004+..
3005+
3006+.. date: 2023-04-03-23-44-34
3007+.. gh-issue: 102978
3008+.. nonce: gy9eVk
3009+.. section: Library
3010+
3011+Fixes :func:`unittest.mock.patch` not enforcing function signatures for
3012+methods decorated with ``@classmethod`` or ``@staticmethod`` when patch is
3013+called with ``autospec=True``.
3014+
3015+..
3016+
3017+.. date: 2023-04-02-23-05-22
3018+.. gh-issue: 103204
3019+.. nonce: bbDmu0
3020+.. section: Library
3021+
3022+Fixes :mod:`http.server` accepting HTTP requests with HTTP version numbers
3023+preceded by '+', or '-', or with digit-separating '_' characters.  The
3024+length of the version numbers is also constrained.
3025+
3026+..
3027+
3028+.. date: 2023-03-23-15-24-38
3029+.. gh-issue: 102953
3030+.. nonce: YR4KaK
3031+.. section: Library
3032+
3033+The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`,
3034+have a new a *filter* argument that allows limiting tar features than may be
3035+surprising or dangerous, such as creating files outside the destination
3036+directory. See :ref:`tarfile-extraction-filter` for details.
3037+
3038+..
3039+
3040+.. date: 2023-02-09-22-24-34
3041+.. gh-issue: 101640
3042+.. nonce: oFuEpB
3043+.. section: Library
3044+
3045+:class:`argparse.ArgumentParser` now catches errors when writing messages,
3046+such as when :data:`sys.stderr` is ``None``. Patch by Oleg Iarygin.
3047+
3048+..
3049+
3050+.. date: 2022-09-07-09-32-07
3051+.. gh-issue: 96522
3052+.. nonce: t73oqp
3053+.. section: Library
3054+
3055+Fix potential deadlock in pty.spawn()
3056+
3057+..
3058+
3059+.. date: 2022-08-27-21-41-41
3060+.. gh-issue: 87474
3061+.. nonce: 9X-kxt
3062+.. section: Library
3063+
3064+Fix potential file descriptor leaks in :class:`subprocess.Popen`.
3065+
3066+..
3067+
3068+.. date: 2023-05-28-21-01-00
3069+.. gh-issue: 89455
3070+.. nonce: qAKRrA
3071+.. section: Documentation
3072+
3073+Add missing documentation for the ``max_group_depth`` and
3074+``max_group_width`` parameters and the ``exceptions`` attribute of the
3075+:class:`traceback.TracebackException` class.
3076+
3077+..
3078+
3079+.. date: 2023-05-28-19-08-42
3080+.. gh-issue: 89412
3081+.. nonce: j4cg7K
3082+.. section: Documentation
3083+
3084+Add missing documentation for the ``end_lineno`` and ``end_offset``
3085+attributes of the :class:`traceback.TracebackException` class.
3086+
3087+..
3088+
3089+.. date: 2023-05-25-22-34-31
3090+.. gh-issue: 104943
3091+.. nonce: J2v1Pc
3092+.. section: Documentation
3093+
3094+Remove mentions of old Python versions in :class:`typing.NamedTuple`.
3095+
3096+..
3097+
3098+.. date: 2023-05-14-12-11-28
3099+.. gh-issue: 67056
3100+.. nonce: nVC2Rf
3101+.. section: Documentation
3102+
3103+Document that the effect of registering or unregistering an :mod:`atexit`
3104+cleanup function from within a registered cleanup function is undefined.
3105+
3106+..
3107+
3108+.. date: 2023-04-25-22-58-08
3109+.. gh-issue: 48241
3110+.. nonce: l1Gxxh
3111+.. section: Documentation
3112+
3113+Clarifying documentation about the url parameter to urllib.request.urlopen
3114+and urllib.request.Requst needing to be encoded properly.
3115+
3116+..
3117+
3118+.. date: 2023-05-15-02-22-44
3119+.. gh-issue: 104494
3120+.. nonce: Bkrbfn
3121+.. section: Tests
3122+
3123+Update ``test_pack_configure_in`` and ``test_place_configure_in`` for
3124+changes to error message formatting in Tk 8.7.
3125+
3126+..
3127+
3128+.. date: 2023-05-14-03-00-00
3129+.. gh-issue: 104461
3130+.. nonce: Rmex11
3131+.. section: Tests
3132+
3133+Run test_configure_screen on X11 only, since the ``DISPLAY`` environment
3134+variable and ``-screen`` option for toplevels are not useful on Tk for Win32
3135+or Aqua.
3136+
3137+..
3138+
3139+.. date: 2023-04-08-00-50-23
3140+.. gh-issue: 103329
3141+.. nonce: M38tqF
3142+.. section: Tests
3143+
3144+Regression tests for the behaviour of ``unittest.mock.PropertyMock`` were
3145+added.
3146+
3147+..
3148+
3149+.. date: 2023-02-11-22-36-10
3150+.. gh-issue: 85984
3151+.. nonce: EVXjT9
3152+.. section: Tests
3153+
3154+Utilize new "winsize" functions from termios in pty tests.
3155+
3156+..
3157+
3158+.. date: 2022-11-06-18-42-38
3159+.. gh-issue: 75729
3160+.. nonce: uGYJrv
3161+.. section: Tests
3162+
3163+Fix the :func:`os.spawn* <os.spawnl>` tests failing on Windows when the
3164+working directory or interpreter path contains spaces.
3165+
3166+..
3167+
3168+.. date: 2023-06-06-09-08-10
3169+.. gh-issue: 90005
3170+.. nonce: 8mmeJQ
3171+.. section: Build
3172+
3173+Fix a regression in :file:`configure` where we could end up unintentionally
3174+linking with ``libbsd``.
3175+
3176+..
3177+
3178+.. date: 2023-05-04-10-56-14
3179+.. gh-issue: 104106
3180+.. nonce: -W9BJS
3181+.. section: Build
3182+
3183+Add gcc fallback of mkfifoat/mknodat for macOS. Patch by Dong-hee Na.
3184+
3185+..
3186+
3187+.. date: 2023-02-11-05-31-05
3188+.. gh-issue: 99069
3189+.. nonce: X4LDvY
3190+.. section: Build
3191+
3192+Extended workaround defining ``static_assert`` when missing from the libc
3193+headers to all clang and gcc builds. In particular, this fixes building on
3194+macOS <= 10.10.
3195+
3196+..
3197+
3198+.. date: 2023-05-31-16-14-31
3199+.. gh-issue: 105146
3200+.. nonce: gNjqq8
3201+.. section: Windows
3202+
3203+Updated the links at the end of the installer to point to Discourse rather
3204+than the mailing lists.
3205+
3206+..
3207+
3208+.. date: 2023-05-18-22-46-03
3209+.. gh-issue: 104623
3210+.. nonce: HJZhm1
3211+.. section: Windows
3212+
3213+Update Windows installer to use SQLite 3.42.0.
3214+
3215+..
3216+
3217+.. date: 2023-03-24-11-25-28
3218+.. gh-issue: 102997
3219+.. nonce: dredy2
3220+.. section: Windows
3221+
3222+Update Windows installer to use SQLite 3.41.2.
3223+
3224+..
3225+
3226+.. date: 2023-03-18-21-38-00
3227+.. gh-issue: 88013
3228+.. nonce: Z3loxC
3229+.. section: Windows
3230+
3231+Fixed a bug where :exc:`TypeError` was raised when calling
3232+:func:`ntpath.realpath` with a bytes parameter in some cases.
3233+
3234+..
3235+
3236+.. date: 2023-05-30-23-30-46
3237+.. gh-issue: 103142
3238+.. nonce: 55lMXQ
3239+.. section: macOS
3240+
3241+Update macOS installer to use OpenSSL 1.1.1u.
3242+
3243+..
3244+
3245+.. date: 2023-05-18-22-31-49
3246+.. gh-issue: 104623
3247+.. nonce: 6h7Xfx
3248+.. section: macOS
3249+
3250+Update macOS installer to SQLite 3.42.0.
3251+
3252+..
3253+
3254+.. date: 2023-03-24-11-20-47
3255+.. gh-issue: 102997
3256+.. nonce: ZgQkbq
3257+.. section: macOS
3258+
3259+Update macOS installer to SQLite 3.41.2.
3260+
3261+..
3262+
3263+.. date: 2023-05-23-17-19-49
3264+.. gh-issue: 104719
3265+.. nonce: rvYXH-
3266+.. section: IDLE
3267+
3268+Remove IDLE's modification of tokenize.tabsize and test other uses of
3269+tokenize data and methods.
3270+
3271+..
3272+
3273+.. date: 2023-05-17-17-32-21
3274+.. gh-issue: 104499
3275+.. nonce: hNeqV4
3276+.. section: IDLE
3277+
3278+Fix completions for Tk Aqua 8.7 (currently blank).
3279+
3280+..
3281+
3282+.. date: 2023-05-17-15-11-11
3283+.. gh-issue: 104496
3284+.. nonce: wjav-y
3285+.. section: IDLE
3286+
3287+About prints both tcl and tk versions if different (expected someday).
3288+
3289+..
3290+
3291+.. date: 2023-04-30-20-01-18
3292+.. gh-issue: 88496
3293+.. nonce: y65vUb
3294+.. section: IDLE
3295+
3296+Fix IDLE test hang on macOS.
3297diff --git a/Misc/config_mingw b/Misc/config_mingw
3298new file mode 100644
3299index 0000000..9be43fd
3300--- /dev/null
3301+++ b/Misc/config_mingw
3302@@ -0,0 +1,15 @@
3303+# configure defaults for mingw* hosts
3304+
3305+# mingw functions to ignore
3306+ac_cv_func_ftruncate=ignore	# implement it as _chsize
3307+
3308+# mingw-w64 functions to ignore
3309+ac_cv_func_truncate=ignore
3310+ac_cv_func_alarm=ignore
3311+
3312+# files to ignore
3313+ac_cv_file__dev_ptmx=ignore #NOTE: under MSYS environment device exist
3314+ac_cv_file__dev_ptc=no
3315+
3316+# force detection of winsock2 functionality - require wxp or newer
3317+ac_cv_func_getpeername=yes
3318diff --git a/Misc/cross_mingw32 b/Misc/cross_mingw32
3319new file mode 100644
3320index 0000000..03fde9e
3321--- /dev/null
3322+++ b/Misc/cross_mingw32
3323@@ -0,0 +1,11 @@
3324+# configure defaults for mingw32 host if cross-build
3325+
3326+ac_cv_little_endian_double=yes
3327+ac_cv_big_endian_double=no
3328+ac_cv_mixed_endian_double=no
3329+
3330+ac_cv_tanh_preserves_zero_sign=yes
3331+
3332+ac_cv_wchar_t_signed=no
3333+
3334+ac_cv_have_size_t_format=no
3335diff --git a/Misc/python-config.sh.in b/Misc/python-config.sh.in
3336index 2602fe2..e0e048a 100644
3337--- a/Misc/python-config.sh.in
3338+++ b/Misc/python-config.sh.in
3339@@ -1,32 +1,44 @@
3340 #!/bin/sh
3341
3342-# Keep this script in sync with python-config.in
3343-
3344 exit_with_usage ()
3345 {
3346     echo "Usage: $0 --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--help|--abiflags|--configdir|--embed"
3347-    exit $1
3348+    exit 1
3349 }
3350
3351+# Really, python-config.py (and thus .sh) should be called directly, but
3352+# sometimes software (e.g. GDB) calls python-config.sh as if it were the
3353+# Python executable, passing python-config.py as the first argument.
3354+# Work around that oddness by ignoring any .py passed as first arg.
3355+case "$1" in
3356+    *.py)
3357+        shift
3358+    ;;
3359+esac
3360+
3361 if [ "$1" = "" ] ; then
3362-    exit_with_usage 1
3363+    exit_with_usage
3364 fi
3365
3366 # Returns the actual prefix where this script was installed to.
3367 installed_prefix ()
3368 {
3369-    RESULT=$(dirname $(cd $(dirname "$1") && pwd -P))
3370-    if which readlink >/dev/null 2>&1 ; then
3371-        if readlink -f "$RESULT" >/dev/null 2>&1; then
3372-          RESULT=$(readlink -f "$RESULT")
3373-        fi
3374+    local RESULT=$(dirname $(cd $(dirname "$1") && pwd -P))
3375+    if [ $(which readlink) ] ; then
3376+        RESULT=$(readlink -f "$RESULT")
3377+    fi
3378+    # Since we don't know where the output from this script will end up
3379+    # we keep all paths in Windows-land since MSYS2 can handle that
3380+    # while native tools can't handle paths in MSYS2-land.
3381+    if [ "$OSTYPE" = "msys" ]; then
3382+        RESULT=$(cd "$RESULT" && pwd -W)
3383     fi
3384     echo $RESULT
3385 }
3386
3387 prefix_real=$(installed_prefix "$0")
3388
3389-# Use sed to fix paths from their built-to locations to their installed-to
3390+# Use sed to fix paths from their built-to locations to their installed to
3391 # locations. Keep prefix & exec_prefix using their original values in case
3392 # they are referenced in other configure variables, to prevent double
3393 # substitution, issue #22140.
3394@@ -41,13 +53,17 @@ LIBM="@LIBM@"
3395 LIBC="@LIBC@"
3396 SYSLIBS="$LIBM $LIBC"
3397 ABIFLAGS="@ABIFLAGS@"
3398+# Protect against lack of substitution.
3399+if [ "$ABIFLAGS" = "@""ABIFLAGS""@" ] ; then
3400+    ABIFLAGS=
3401+fi
3402 LIBS="@LIBPYTHON@ @LIBS@ $SYSLIBS"
3403 LIBS_EMBED="-lpython${VERSION}${ABIFLAGS} @LIBS@ $SYSLIBS"
3404 BASECFLAGS="@BASECFLAGS@"
3405-LDLIBRARY="@LDLIBRARY@"
3406 OPT="@OPT@"
3407 PY_ENABLE_SHARED="@PY_ENABLE_SHARED@"
3408 LDVERSION="@LDVERSION@"
3409+LDLIBRARY="@LDLIBRARY@"
3410 LIBDEST=${prefix_real}/lib/python${VERSION}
3411 LIBPL=$(echo "@LIBPL@" | sed "s#$prefix#$prefix_real#")
3412 SO="@EXT_SUFFIX@"
3413@@ -61,7 +77,7 @@ for ARG in $*
3414 do
3415     case $ARG in
3416         --help)
3417-            exit_with_usage 0
3418+            exit_with_usage
3419         ;;
3420         --embed)
3421             PY_EMBED=1
3422@@ -69,7 +85,7 @@ do
3423         --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--abiflags|--configdir)
3424         ;;
3425         *)
3426-            exit_with_usage 1
3427+            exit_with_usage
3428         ;;
3429     esac
3430 done
3431@@ -80,37 +96,37 @@ fi
3432
3433 for ARG in "$@"
3434 do
3435-    case "$ARG" in
3436+    case $ARG in
3437         --prefix)
3438-            echo "$prefix_real"
3439+            echo -ne "$prefix_real"
3440         ;;
3441         --exec-prefix)
3442-            echo "$exec_prefix_real"
3443+            echo -ne "$exec_prefix_real "
3444         ;;
3445         --includes)
3446-            echo "$INCDIR $PLATINCDIR"
3447+            echo -ne "$INCDIR $PLATINCDIR"
3448         ;;
3449         --cflags)
3450-            echo "$INCDIR $PLATINCDIR $BASECFLAGS $CFLAGS $OPT"
3451+            echo -ne "$INCDIR $PLATINCDIR $BASECFLAGS $CFLAGS $OPT"
3452         ;;
3453         --libs)
3454-            echo "$LIBS"
3455+            echo -ne "$LIBS"
3456         ;;
3457         --ldflags)
3458             LIBPLUSED=
3459             if [ "$PY_ENABLE_SHARED" = "0" ] ; then
3460                 LIBPLUSED="-L$LIBPL"
3461             fi
3462-            echo "$LIBPLUSED -L$libdir $LIBS"
3463+            echo -ne "$LIBPLUSED -L$libdir $LIBS "
3464         ;;
3465         --extension-suffix)
3466-            echo "$SO"
3467+            echo -ne "$SO "
3468         ;;
3469         --abiflags)
3470-            echo "$ABIFLAGS"
3471+            echo -ne "$ABIFLAGS "
3472         ;;
3473         --configdir)
3474-            echo "$LIBPL"
3475+            echo -ne "$LIBPL "
3476         ;;
3477 esac
3478 done
3479diff --git a/Misc/python.pc.in b/Misc/python.pc.in
3480index 87e04de..3900190 100644
3481--- a/Misc/python.pc.in
3482+++ b/Misc/python.pc.in
3483@@ -9,5 +9,5 @@ Description: Build a C extension for Python
3484 Requires:
3485 Version: @VERSION@
3486 Libs.private: @LIBS@
3487-Libs:
3488+Libs: -L${libdir} -lpython@VERSION@@ABIFLAGS@
3489 Cflags: -I${includedir}/python@VERSION@@ABIFLAGS@
3490diff --git a/Modules/Setup.bootstrap.in b/Modules/Setup.bootstrap.in
3491index e3e9b96..6986290 100644
3492--- a/Modules/Setup.bootstrap.in
3493+++ b/Modules/Setup.bootstrap.in
3494@@ -8,15 +8,15 @@
3495 # module C APIs are used in core
3496 atexit atexitmodule.c
3497 faulthandler faulthandler.c
3498-posix posixmodule.c
3499-_signal signalmodule.c
3500+@INITSYS@ posixmodule.c
3501+_signal signalmodule.c -lws2_32
3502 _tracemalloc _tracemalloc.c
3503
3504 # modules used by importlib, deepfreeze, freeze, runpy, and sysconfig
3505 _codecs _codecsmodule.c
3506 _collections _collectionsmodule.c
3507 errno errnomodule.c
3508-_io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c
3509+_io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c _io/winconsoleio.c
3510 itertools itertoolsmodule.c
3511 _sre _sre/sre.c
3512 _thread _threadmodule.c
3513@@ -33,3 +33,8 @@ _symtable symtablemodule.c
3514
3515 # for systems without $HOME env, used by site._getuserbase()
3516 @MODULE_PWD_TRUE@pwd pwdmodule.c
3517+
3518+# build-in modules for windows platform:
3519+@USE_WIN32_MODULE@winreg ../PC/winreg.c
3520+@MODULE_MSVCRT_TRUE@msvcrt -DPy_BUILD_CORE ../PC/msvcrtmodule.c
3521+@MODULE__WINAPI_TRUE@_winapi _winapi.c
3522diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
3523index fc73264..6ed71fa 100644
3524--- a/Modules/_ctypes/_ctypes.c
3525+++ b/Modules/_ctypes/_ctypes.c
3526@@ -3403,6 +3403,18 @@ static PPROC FindAddress(void *handle, const char *name, PyObject *type)
3527     mangled_name = alloca(strlen(name) + 1 + 1 + 1 + 3); /* \0 _ @ %d */
3528     if (!mangled_name)
3529         return NULL;
3530+    /* Issue: for stdcall decorated export functions MSVC compiler adds
3531+     * underscore, but GCC compiler create them without. This is
3532+     * visible by example for _ctypes_test.pyd module.
3533+     * As well functions from system libraries are without underscore.
3534+     * Solutions:
3535+     * - If a python module is build with gcc option --add-stdcall-alias
3536+     * the module will contain XXX as alias for function XXX@ as result
3537+     * first search in this method will succeed.
3538+     * - Distutil may use compiler to create def-file, to modify it as
3539+     * add underscore alias and with new def file to create module.
3540+     * - Or may be just to search for function without underscore.
3541+     */
3542     for (i = 0; i < 32; ++i) {
3543         sprintf(mangled_name, "_%s@%d", name, i*4);
3544         Py_BEGIN_ALLOW_THREADS
3545@@ -3410,6 +3422,13 @@ static PPROC FindAddress(void *handle, const char *name, PyObject *type)
3546         Py_END_ALLOW_THREADS
3547         if (address)
3548             return address;
3549+        /* search for function without underscore as weel */
3550+        sprintf(mangled_name, "%s@%d", name, i*4);
3551+        Py_BEGIN_ALLOW_THREADS
3552+        address = (PPROC)GetProcAddress(handle, mangled_name);
3553+        Py_END_ALLOW_THREADS
3554+        if (address)
3555+            return address;
3556     }
3557     return NULL;
3558 #endif
3559diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c
3560index e6440fa..f42714a 100644
3561--- a/Modules/_gdbmmodule.c
3562+++ b/Modules/_gdbmmodule.c
3563@@ -12,7 +12,7 @@
3564 #include <sys/stat.h>
3565 #include <sys/types.h>
3566
3567-#if defined(WIN32) && !defined(__CYGWIN__)
3568+#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
3569 #include "gdbmerrno.h"
3570 extern const char * gdbm_strerror(gdbm_error);
3571 #endif
3572diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
3573index 4496609..80cc6f9 100644
3574--- a/Modules/_io/fileio.c
3575+++ b/Modules/_io/fileio.c
3576@@ -20,6 +20,7 @@
3577 #endif
3578 #include <stddef.h> /* For offsetof */
3579 #include "_iomodule.h"
3580+#include "iscygpty.h"
3581
3582 /*
3583  * Known likely problems:
3584@@ -1129,7 +1130,7 @@ _io_FileIO_isatty_impl(fileio *self)
3585         return err_closed();
3586     Py_BEGIN_ALLOW_THREADS
3587     _Py_BEGIN_SUPPRESS_IPH
3588-    res = isatty(self->fd);
3589+    res = isatty(self->fd) || is_cygpty(self->fd);
3590     _Py_END_SUPPRESS_IPH
3591     Py_END_ALLOW_THREADS
3592     return PyBool_FromLong(res);
3593diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c
3594index 23c38e1..dfb6c7e 100644
3595--- a/Modules/_localemodule.c
3596+++ b/Modules/_localemodule.c
3597@@ -12,6 +12,13 @@ This software comes with no warranty. Use at your own risk.
3598 #define PY_SSIZE_T_CLEAN
3599 #include "Python.h"
3600 #include "pycore_fileutils.h"
3601+#ifdef __MINGW32__
3602+/* The header libintl.h and library libintl may exist on mingw host.
3603+ * To be compatible with MSVC build we has to undef some defines.
3604+ */
3605+#undef HAVE_LIBINTL_H
3606+#undef HAVE_BIND_TEXTDOMAIN_CODESET
3607+#endif
3608
3609 #include <stdio.h>
3610 #include <locale.h>
3611diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c
3612index 0809c24..bbb1b38 100644
3613--- a/Modules/_multiprocessing/multiprocessing.c
3614+++ b/Modules/_multiprocessing/multiprocessing.c
3615@@ -172,7 +172,7 @@ static PyMethodDef module_methods[] = {
3616     _MULTIPROCESSING_RECV_METHODDEF
3617     _MULTIPROCESSING_SEND_METHODDEF
3618 #endif
3619-#if !defined(POSIX_SEMAPHORES_NOT_ENABLED) && !defined(__ANDROID__)
3620+#if defined(MS_WINDOWS) || (!defined(POSIX_SEMAPHORES_NOT_ENABLED) && !defined(__ANDROID__))
3621     _MULTIPROCESSING_SEM_UNLINK_METHODDEF
3622 #endif
3623     {NULL}
3624diff --git a/Modules/_multiprocessing/multiprocessing.h b/Modules/_multiprocessing/multiprocessing.h
3625index 3a8314b..c07cfe8 100644
3626--- a/Modules/_multiprocessing/multiprocessing.h
3627+++ b/Modules/_multiprocessing/multiprocessing.h
3628@@ -21,7 +21,10 @@
3629 #  endif
3630 #  define SEM_HANDLE HANDLE
3631 #  define SEM_VALUE_MAX LONG_MAX
3632-#  define HAVE_MP_SEMAPHORE
3633+#    define HAVE_MP_SEMAPHORE
3634+#  if defined(HAVE_SEM_OPEN) && defined(_POSIX_THREADS)
3635+#    include <semaphore.h>
3636+#  endif
3637 #else
3638 #  include <fcntl.h>                 /* O_CREAT and O_EXCL */
3639 #  if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)
3640diff --git a/Modules/_winapi.c b/Modules/_winapi.c
3641index f6bb07f..56f3306 100644
3642--- a/Modules/_winapi.c
3643+++ b/Modules/_winapi.c
3644@@ -41,7 +41,9 @@
3645
3646 #define WINDOWS_LEAN_AND_MEAN
3647 #include "windows.h"
3648+#if defined(Py_DEBUG)
3649 #include <crtdbg.h>
3650+#endif
3651 #include "winreparse.h"
3652
3653 #if defined(MS_WIN32) && !defined(MS_WIN64)
3654@@ -957,7 +959,7 @@ getattributelist(PyObject *obj, const char *name, AttributeList *attribute_list)
3655     DWORD err;
3656     BOOL result;
3657     PyObject *value;
3658-    Py_ssize_t handle_list_size;
3659+    Py_ssize_t handle_list_size = 0;
3660     DWORD attribute_count = 0;
3661     SIZE_T attribute_list_size = 0;
3662
3663diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c
3664index e5b96be..0e5ab45 100644
3665--- a/Modules/_xxsubinterpretersmodule.c
3666+++ b/Modules/_xxsubinterpretersmodule.c
3667@@ -1765,7 +1765,7 @@ PyDoc_STRVAR(channelid_doc,
3668 "A channel ID identifies a channel and may be used as an int.");
3669
3670 static PyTypeObject ChannelIDtype = {
3671-    PyVarObject_HEAD_INIT(&PyType_Type, 0)
3672+    PyVarObject_HEAD_INIT(NULL, 0)
3673     "_xxsubinterpreters.ChannelID", /* tp_name */
3674     sizeof(channelid),              /* tp_basicsize */
3675     0,                              /* tp_itemsize */
3676diff --git a/Modules/getpath.c b/Modules/getpath.c
3677index bc730fc..0419c2a 100644
3678--- a/Modules/getpath.c
3679+++ b/Modules/getpath.c
3680@@ -54,6 +54,25 @@
3681
3682 /* HELPER FUNCTIONS for getpath.py */
3683
3684+static PyObject *
3685+getpath_normpath(PyObject *Py_UNUSED(self), PyObject *args)
3686+{
3687+    PyObject *r = NULL;
3688+    PyObject *pathobj;
3689+    wchar_t *path;
3690+    if (!PyArg_ParseTuple(args, "U", &pathobj)) {
3691+        return NULL;
3692+    }
3693+    Py_ssize_t len;
3694+    wchar_t *buffer = PyUnicode_AsWideCharString(pathobj, &len);
3695+    if (!buffer) {
3696+        return NULL;
3697+    }
3698+    r = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1);
3699+    PyMem_Free(buffer);
3700+    return r;
3701+}
3702+
3703 static PyObject *
3704 getpath_abspath(PyObject *Py_UNUSED(self), PyObject *args)
3705 {
3706@@ -88,6 +107,12 @@ getpath_basename(PyObject *Py_UNUSED(self), PyObject *args)
3707     }
3708     Py_ssize_t end = PyUnicode_GET_LENGTH(path);
3709     Py_ssize_t pos = PyUnicode_FindChar(path, SEP, 0, end, -1);
3710+#ifdef ALTSEP
3711+    if (pos < 0) {
3712+        // try using altsep
3713+        pos = PyUnicode_FindChar(path, ALTSEP, 0, end, -1);
3714+    }
3715+#endif
3716     if (pos < 0) {
3717         return Py_NewRef(path);
3718     }
3719@@ -104,6 +129,12 @@ getpath_dirname(PyObject *Py_UNUSED(self), PyObject *args)
3720     }
3721     Py_ssize_t end = PyUnicode_GET_LENGTH(path);
3722     Py_ssize_t pos = PyUnicode_FindChar(path, SEP, 0, end, -1);
3723+#ifdef ALTSEP
3724+    if (pos < 0) {
3725+        // try using altsep
3726+        pos = PyUnicode_FindChar(path, ALTSEP, 0, end, -1);
3727+    }
3728+#endif
3729     if (pos < 0) {
3730         return PyUnicode_FromStringAndSize(NULL, 0);
3731     }
3732@@ -513,6 +544,7 @@ getpath_realpath(PyObject *Py_UNUSED(self) , PyObject *args)
3733
3734
3735 static PyMethodDef getpath_methods[] = {
3736+    {"normpath", getpath_normpath, METH_VARARGS, NULL},
3737     {"abspath", getpath_abspath, METH_VARARGS, NULL},
3738     {"basename", getpath_basename, METH_VARARGS, NULL},
3739     {"dirname", getpath_dirname, METH_VARARGS, NULL},
3740@@ -884,6 +916,11 @@ _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config)
3741 #else
3742         !decode_to_dict(dict, "os_name", "posix") ||
3743 #endif
3744+#ifdef __MINGW32__
3745+        !int_to_dict(dict, "is_mingw", 1) ||
3746+#else
3747+        !int_to_dict(dict, "is_mingw", 0) ||
3748+#endif
3749 #ifdef WITH_NEXT_FRAMEWORK
3750         !int_to_dict(dict, "WITH_NEXT_FRAMEWORK", 1) ||
3751 #else
3752@@ -910,6 +947,9 @@ _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config)
3753         !funcs_to_dict(dict, config->pathconfig_warnings) ||
3754 #ifndef MS_WINDOWS
3755         PyDict_SetItemString(dict, "winreg", Py_None) < 0 ||
3756+#endif
3757+#ifdef __MINGW32__
3758+        !env_to_dict(dict, "ENV_MSYSTEM", 0) ||
3759 #endif
3760         PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()) < 0
3761     ) {
3762diff --git a/Modules/getpath.py b/Modules/getpath.py
3763index 74f918c..c98cb1f 100644
3764--- a/Modules/getpath.py
3765+++ b/Modules/getpath.py
3766@@ -30,6 +30,7 @@
3767
3768 # ** Values known at compile time **
3769 # os_name           -- [in] one of 'nt', 'posix', 'darwin'
3770+# is_mingw          -- [in] True if targeting MinGW
3771 # PREFIX            -- [in] sysconfig.get_config_var(...)
3772 # EXEC_PREFIX       -- [in] sysconfig.get_config_var(...)
3773 # PYTHONPATH        -- [in] sysconfig.get_config_var(...)
3774@@ -51,6 +52,7 @@
3775 # ENV_PYTHONHOME          -- [in] getenv(...)
3776 # ENV_PYTHONEXECUTABLE    -- [in] getenv(...)
3777 # ENV___PYVENV_LAUNCHER__ -- [in] getenv(...)
3778+# ENV_MSYSTEM             -- [in] getenv(...)
3779
3780 # ** Values calculated at runtime **
3781 # config            -- [in/out] dict of the PyConfig structure
3782@@ -185,8 +187,27 @@
3783     ZIP_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}{VERSION_MINOR}.zip'
3784     DELIM = ':'
3785     SEP = '/'
3786+    ALTSEP = None
3787
3788-elif os_name == 'nt':
3789+elif os_name == 'nt' and is_mingw:
3790+    BUILDDIR_TXT = 'pybuilddir.txt'
3791+    BUILD_LANDMARK = 'Modules/Setup.local'
3792+    DEFAULT_PROGRAM_NAME = f'python{VERSION_MAJOR}'
3793+    STDLIB_SUBDIR = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}'
3794+    STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}/os.py', f'{STDLIB_SUBDIR}/os.pyc']
3795+    PLATSTDLIB_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}/lib-dynload'
3796+    BUILDSTDLIB_LANDMARKS = ['Lib/os.py']
3797+    VENV_LANDMARK = 'pyvenv.cfg'
3798+    ZIP_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}{VERSION_MINOR}.zip'
3799+    DELIM = ';'
3800+    if ENV_MSYSTEM:
3801+        SEP = '/'
3802+        ALTSEP = '\\'
3803+    else:
3804+        SEP = '\\'
3805+        ALTSEP = '/'
3806+
3807+elif os_name == 'nt': # MSVC
3808     BUILDDIR_TXT = 'pybuilddir.txt'
3809     BUILD_LANDMARK = f'{VPATH}\\Modules\\Setup.local'
3810     DEFAULT_PROGRAM_NAME = f'python'
3811@@ -199,6 +220,7 @@
3812     WINREG_KEY = f'SOFTWARE\\Python\\PythonCore\\{PYWINVER}\\PythonPath'
3813     DELIM = ';'
3814     SEP = '\\'
3815+    ALTSEP = '/'
3816
3817
3818 # ******************************************************************************
3819@@ -211,6 +233,8 @@ def search_up(prefix, *landmarks, test=isfile):
3820             return prefix
3821         prefix = dirname(prefix)
3822
3823+def _normpath(p):
3824+    return normpath(p) if p is not None else None
3825
3826 # ******************************************************************************
3827 # READ VARIABLES FROM config
3828@@ -263,10 +287,10 @@ def search_up(prefix, *landmarks, test=isfile):
3829     if not executable:
3830         executable = real_executable
3831
3832-if not executable and SEP in program_name:
3833+if not executable and (SEP in program_name or
3834+                       (ALTSEP and ALTSEP in program_name)):
3835     # Resolve partial path program_name against current directory
3836     executable = abspath(program_name)
3837-
3838 if not executable:
3839     # All platforms default to real_executable if known at this
3840     # stage. POSIX does not set this value.
3841@@ -497,15 +521,15 @@ def search_up(prefix, *landmarks, test=isfile):
3842     except (FileNotFoundError, PermissionError):
3843         if isfile(joinpath(real_executable_dir, BUILD_LANDMARK)):
3844             build_prefix = joinpath(real_executable_dir, VPATH)
3845-            if os_name == 'nt':
3846+            if os_name == 'nt' and not is_mingw:
3847                 # QUIRK: Windows builds need platstdlib_dir to be the executable
3848                 # dir. Normally the builddir marker handles this, but in this
3849                 # case we need to correct manually.
3850                 platstdlib_dir = real_executable_dir
3851
3852     if build_prefix:
3853-        if os_name == 'nt':
3854-            # QUIRK: No searching for more landmarks on Windows
3855+        if os_name == 'nt' and not is_mingw:
3856+            # QUIRK: No searching for more landmarks on MSVC
3857             build_stdlib_prefix = build_prefix
3858         else:
3859             build_stdlib_prefix = search_up(build_prefix, *BUILDSTDLIB_LANDMARKS)
3860@@ -552,6 +576,9 @@ def search_up(prefix, *landmarks, test=isfile):
3861     # First try to detect prefix by looking alongside our runtime library, if known
3862     if library and not prefix:
3863         library_dir = dirname(library)
3864+        if os_name == 'nt' and is_mingw:
3865+            # QUIRK: On Windows, mingw Python DLLs are in the bin directory
3866+            library_dir = joinpath(library_dir, '..')
3867         if ZIP_LANDMARK:
3868             if os_name == 'nt':
3869                 # QUIRK: Windows does not search up for ZIP file
3870@@ -597,7 +624,7 @@ def search_up(prefix, *landmarks, test=isfile):
3871
3872     # Detect exec_prefix by searching from executable for the platstdlib_dir
3873     if PLATSTDLIB_LANDMARK and not exec_prefix:
3874-        if os_name == 'nt':
3875+        if os_name == 'nt' and (not is_mingw):
3876             # QUIRK: Windows always assumed these were the same
3877             # gh-100320: Our PYDs are assumed to be relative to the Lib directory
3878             # (that is, prefix) rather than the executable (that is, executable_dir)
3879@@ -607,7 +634,7 @@ def search_up(prefix, *landmarks, test=isfile):
3880         if not exec_prefix and EXEC_PREFIX:
3881             exec_prefix = EXEC_PREFIX
3882         if not exec_prefix or not isdir(joinpath(exec_prefix, PLATSTDLIB_LANDMARK)):
3883-            if os_name == 'nt':
3884+            if os_name == 'nt' and (not is_mingw):
3885                 # QUIRK: If DLLs is missing on Windows, don't warn, just assume
3886                 # that they're in exec_prefix
3887                 if not platstdlib_dir:
3888@@ -645,7 +672,7 @@ def search_up(prefix, *landmarks, test=isfile):
3889
3890 if py_setpath:
3891     # If Py_SetPath was called then it overrides any existing search path
3892-    config['module_search_paths'] = py_setpath.split(DELIM)
3893+    config['module_search_paths'] = [_normpath(p) for p in py_setpath.split(DELIM)]
3894     config['module_search_paths_set'] = 1
3895
3896 elif not pythonpath_was_set:
3897@@ -660,7 +687,7 @@ def search_up(prefix, *landmarks, test=isfile):
3898             pythonpath.append(abspath(p))
3899
3900     # Then add the default zip file
3901-    if os_name == 'nt':
3902+    if os_name == 'nt' and (not is_mingw):
3903         # QUIRK: Windows uses the library directory rather than the prefix
3904         if library:
3905             library_dir = dirname(library)
3906@@ -673,7 +700,7 @@ def search_up(prefix, *landmarks, test=isfile):
3907     else:
3908         pythonpath.append(joinpath(prefix, ZIP_LANDMARK))
3909
3910-    if os_name == 'nt' and use_environment and winreg:
3911+    if (not is_mingw) and os_name == 'nt' and use_environment and winreg:
3912         # QUIRK: Windows also lists paths in the registry. Paths are stored
3913         # as the default value of each subkey of
3914         # {HKCU,HKLM}\Software\Python\PythonCore\{winver}\PythonPath
3915@@ -714,7 +741,7 @@ def search_up(prefix, *landmarks, test=isfile):
3916     if not platstdlib_dir and exec_prefix:
3917         platstdlib_dir = joinpath(exec_prefix, PLATSTDLIB_LANDMARK)
3918
3919-    if os_name == 'nt':
3920+    if os_name == 'nt' and (not is_mingw):
3921         # QUIRK: Windows generates paths differently
3922         if platstdlib_dir:
3923             pythonpath.append(platstdlib_dir)
3924@@ -732,7 +759,7 @@ def search_up(prefix, *landmarks, test=isfile):
3925         if platstdlib_dir:
3926             pythonpath.append(platstdlib_dir)
3927
3928-    config['module_search_paths'] = pythonpath
3929+    config['module_search_paths'] = [_normpath(p) for p in pythonpath]
3930     config['module_search_paths_set'] = 1
3931
3932
3933@@ -742,8 +769,8 @@ def search_up(prefix, *landmarks, test=isfile):
3934
3935 # QUIRK: Non-Windows replaces prefix/exec_prefix with defaults when running
3936 # in build directory. This happens after pythonpath calculation.
3937-if os_name != 'nt' and build_prefix:
3938-    prefix = config.get('prefix') or PREFIX
3939+if (os_name != 'nt' or is_mingw) and build_prefix:
3940+    prefix = config.get('prefix') or abspath(PREFIX)
3941     exec_prefix = config.get('exec_prefix') or EXEC_PREFIX or prefix
3942
3943
3944@@ -767,23 +794,23 @@ def search_up(prefix, *landmarks, test=isfile):
3945             warn("unsupported 'import' line in ._pth file")
3946         else:
3947             pythonpath.append(joinpath(pth_dir, line))
3948-    config['module_search_paths'] = pythonpath
3949+    config['module_search_paths'] = [_normpath(p) for p in pythonpath]
3950     config['module_search_paths_set'] = 1
3951
3952 # ******************************************************************************
3953 # UPDATE config FROM CALCULATED VALUES
3954 # ******************************************************************************
3955
3956-config['program_name'] = program_name
3957-config['home'] = home
3958-config['executable'] = executable
3959-config['base_executable'] = base_executable
3960-config['prefix'] = prefix
3961-config['exec_prefix'] = exec_prefix
3962-config['base_prefix'] = base_prefix or prefix
3963-config['base_exec_prefix'] = base_exec_prefix or exec_prefix
3964+config['program_name'] = _normpath(program_name)
3965+config['home'] = _normpath(home)
3966+config['executable'] = _normpath(executable)
3967+config['base_executable'] = _normpath(base_executable)
3968+config['prefix'] = _normpath(prefix)
3969+config['exec_prefix'] = _normpath(exec_prefix)
3970+config['base_prefix'] = _normpath(base_prefix or prefix)
3971+config['base_exec_prefix'] = _normpath(base_exec_prefix or exec_prefix)
3972
3973-config['platlibdir'] = platlibdir
3974+config['platlibdir'] = _normpath(platlibdir)
3975 # test_embed expects empty strings, not None
3976-config['stdlib_dir'] = stdlib_dir or ''
3977-config['platstdlib_dir'] = platstdlib_dir or ''
3978+config['stdlib_dir'] = _normpath(stdlib_dir or '')
3979+config['platstdlib_dir'] = _normpath(platstdlib_dir or '')
3980diff --git a/Modules/main.c b/Modules/main.c
3981index 6904e3f..5c8708e 100644
3982--- a/Modules/main.c
3983+++ b/Modules/main.c
3984@@ -7,6 +7,7 @@
3985 #include "pycore_pathconfig.h"    // _PyPathConfig_ComputeSysPath0()
3986 #include "pycore_pylifecycle.h"   // _Py_PreInitializeFromPyArgv()
3987 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
3988+#include "iscygpty.h"
3989
3990 /* Includes for exit_sigint() */
3991 #include <stdio.h>                // perror()
3992@@ -92,7 +93,7 @@ static inline int config_run_code(const PyConfig *config)
3993 static int
3994 stdin_is_interactive(const PyConfig *config)
3995 {
3996-    return (isatty(fileno(stdin)) || config->interactive);
3997+    return (isatty(fileno(stdin)) || config->interactive || is_cygpty(fileno(stdin)));
3998 }
3999
4000
4001diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
4002index 8d09f54..cc668df 100644
4003--- a/Modules/posixmodule.c
4004+++ b/Modules/posixmodule.c
4005@@ -55,6 +55,7 @@
4006 #ifdef __ANDROID__
4007 #  undef HAVE_FACCESSAT
4008 #endif
4009+#include "iscygpty.h"
4010
4011 #include <stdio.h>                // ctermid()
4012 #include <stdlib.h>               // system()
4013@@ -355,6 +356,32 @@ corresponding Unix manual entries for more information on calls.");
4014 #    define HAVE_CWAIT      1
4015 #    define HAVE_FSYNC      1
4016 #    define fsync _commit
4017+#  elif defined(__MINGW32__)	/* GCC for windows hosts */
4018+/* getlogin is detected by configure on mingw-w64 */
4019+#    undef HAVE_GETLOGIN
4020+/* opendir is detected by configure on mingw-w64, and for some reason
4021+things don't work as expected. For example, os.listdir always returns
4022+the cwd's directory listing instead of the one specified. By
4023+un-defining, this, os.listdir will use the one which uses native
4024+windows API. */
4025+#    undef HAVE_OPENDIR
4026+/*#    define HAVE_GETCWD     1 - detected by configure*/
4027+#    define HAVE_GETPPID    1
4028+#    define HAVE_GETLOGIN   1
4029+#    define HAVE_SPAWNV     1
4030+#    define HAVE_WSPAWNV    1
4031+#    define HAVE_WEXECV     1
4032+/*#    define HAVE_EXECV	     1 - detected by configure*/
4033+#    define HAVE_PIPE	     1
4034+#    define HAVE_POPEN	     1
4035+#    define HAVE_SYSTEM	   1
4036+#    define HAVE_CWAIT      1
4037+#    define HAVE_FSYNC      1
4038+#    define fsync _commit
4039+#    include <winioctl.h>
4040+#    ifndef _MAX_ENV
4041+#      define _MAX_ENV	32767
4042+#    endif
4043 #  endif  /* _MSC_VER */
4044 #endif  /* ! __WATCOMC__ || __QNX__ */
4045
4046@@ -433,7 +460,7 @@ extern char        *ctermid_r(char *);
4047 #  endif
4048 #endif
4049
4050-#ifdef _MSC_VER
4051+#ifdef MS_WINDOWS
4052 #  ifdef HAVE_DIRECT_H
4053 #    include <direct.h>
4054 #  endif
4055@@ -444,7 +471,7 @@ extern char        *ctermid_r(char *);
4056 #    include <process.h>
4057 #  endif
4058 #  include <malloc.h>
4059-#endif /* _MSC_VER */
4060+#endif /* MS_WINDOWS */
4061
4062 #ifndef MAXPATHLEN
4063 #  if defined(PATH_MAX) && PATH_MAX > 1024
4064@@ -1598,9 +1625,9 @@ win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
4065 ** man environ(7).
4066 */
4067 #include <crt_externs.h>
4068-#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
4069+#elif !defined(MS_WINDOWS) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
4070 extern char **environ;
4071-#endif /* !_MSC_VER */
4072+#endif /* !MS_WINDOWS */
4073
4074 static PyObject *
4075 convertenviron(void)
4076@@ -3820,6 +3847,7 @@ posix_getcwd(int use_bytes)
4077         return PyErr_SetFromWindowsErr(0);
4078     }
4079
4080+    Py_NormalizeSepsW(wbuf2);
4081     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4082     if (wbuf2 != wbuf) {
4083         PyMem_RawFree(wbuf2);
4084@@ -4424,6 +4452,7 @@ os__getfinalpathname_impl(PyObject *module, path_t *path)
4085         target_path = tmp;
4086     }
4087
4088+    Py_NormalizeSepsW(target_path);
4089     result = PyUnicode_FromWideChar(target_path, result_length);
4090     if (result && path->narrow) {
4091         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4092@@ -5507,7 +5536,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
4093 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
4094 {
4095 #ifdef MS_WINDOWS
4096-    HANDLE hFile;
4097+    HANDLE hFile = 0;
4098     FILETIME atime, mtime;
4099 #else
4100     int result;
4101@@ -10234,7 +10263,7 @@ os_isatty_impl(PyObject *module, int fd)
4102     int return_value;
4103     Py_BEGIN_ALLOW_THREADS
4104     _Py_BEGIN_SUPPRESS_IPH
4105-    return_value = isatty(fd);
4106+    return_value = isatty(fd) || is_cygpty(fd);
4107     _Py_END_SUPPRESS_IPH
4108     Py_END_ALLOW_THREADS
4109     return return_value;
4110@@ -14722,7 +14751,7 @@ os__add_dll_directory_impl(PyObject *module, path_t *path)
4111        loaded. */
4112     Py_BEGIN_ALLOW_THREADS
4113     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
4114-        !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
4115+        !(AddDllDirectory = (PAddDllDirectory)(void *)GetProcAddress(
4116             hKernel32, "AddDllDirectory")) ||
4117         !(cookie = (*AddDllDirectory)(path->wide))) {
4118         err = GetLastError();
4119@@ -14772,7 +14801,7 @@ os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
4120        loaded. */
4121     Py_BEGIN_ALLOW_THREADS
4122     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
4123-        !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
4124+        !(RemoveDllDirectory = (PRemoveDllDirectory)(void *)GetProcAddress(
4125             hKernel32, "RemoveDllDirectory")) ||
4126         !(*RemoveDllDirectory)(cookieValue)) {
4127         err = GetLastError();
4128diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c
4129index 4eea928..6be3582 100644
4130--- a/Modules/selectmodule.c
4131+++ b/Modules/selectmodule.c
4132@@ -146,9 +146,9 @@ seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
4133         v = PyObject_AsFileDescriptor( o );
4134         if (v == -1) goto finally;
4135
4136-#if defined(_MSC_VER)
4137+#if defined(MS_WIN32)
4138         max = 0;                             /* not used for Win32 */
4139-#else  /* !_MSC_VER */
4140+#else  /* !MS_WIN32 */
4141         if (!_PyIsSelectable_fd(v)) {
4142             PyErr_SetString(PyExc_ValueError,
4143                         "filedescriptor out of range in select()");
4144@@ -156,7 +156,7 @@ seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
4145         }
4146         if (v > max)
4147             max = v;
4148-#endif /* _MSC_VER */
4149+#endif /* MS_WIN32 */
4150         FD_SET(v, set);
4151
4152         /* add object and its file descriptor to the list */
4153diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
4154index 65d0e10..d1bfe3d 100644
4155--- a/Modules/socketmodule.c
4156+++ b/Modules/socketmodule.c
4157@@ -274,7 +274,7 @@ shutdown(how) -- shut down traffic in one or both directions\n\
4158 # endif
4159
4160 /* Macros based on the IPPROTO enum, see: https://bugs.python.org/issue29515 */
4161-#ifdef MS_WINDOWS
4162+#ifdef _MSC_VER
4163 #define IPPROTO_ICMP IPPROTO_ICMP
4164 #define IPPROTO_IGMP IPPROTO_IGMP
4165 #define IPPROTO_GGP IPPROTO_GGP
4166@@ -305,7 +305,7 @@ shutdown(how) -- shut down traffic in one or both directions\n\
4167 #define IPPROTO_PGM IPPROTO_PGM  // WinSock2 only
4168 #define IPPROTO_L2TP IPPROTO_L2TP  // WinSock2 only
4169 #define IPPROTO_SCTP IPPROTO_SCTP  // WinSock2 only
4170-#endif /* MS_WINDOWS */
4171+#endif /* _MSC_VER */
4172
4173 /* Provides the IsWindows7SP1OrGreater() function */
4174 #include <versionhelpers.h>
4175@@ -404,6 +404,10 @@ remove_unusable_flags(PyObject *m)
4176   /* Do not include addrinfo.h for MSVC7 or greater. 'addrinfo' and
4177    * EAI_* constants are defined in (the already included) ws2tcpip.h.
4178    */
4179+#elif defined(__MINGW32__)
4180+  /* Do not include addrinfo.h as minimum supported version is
4181+   * _WIN32_WINNT >= WindowsXP(0x0501)
4182+   */
4183 #else
4184 #  include "addrinfo.h"
4185 #endif
4186diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
4187index 1b35b11..cff1f1d 100644
4188--- a/Modules/socketmodule.h
4189+++ b/Modules/socketmodule.h
4190@@ -68,8 +68,10 @@ struct SOCKADDR_BTH_REDEF {
4191  */
4192 # ifdef SIO_GET_MULTICAST_FILTER
4193 #  include <mstcpip.h> /* for SIO_RCVALL */
4194+#ifndef __MINGW32__ /* resolve by configure */
4195 #  define HAVE_ADDRINFO
4196 #  define HAVE_SOCKADDR_STORAGE
4197+#endif
4198 #  define HAVE_GETADDRINFO
4199 #  define HAVE_GETNAMEINFO
4200 #  define ENABLE_IPV6
4201diff --git a/Modules/timemodule.c b/Modules/timemodule.c
4202index 18f9ddb..4edc2e7 100644
4203--- a/Modules/timemodule.c
4204+++ b/Modules/timemodule.c
4205@@ -783,7 +783,7 @@ time_strftime(PyObject *module, PyObject *args)
4206         return NULL;
4207     }
4208
4209-#if defined(_MSC_VER) || (defined(__sun) && defined(__SVR4)) || defined(_AIX) || defined(__VXWORKS__)
4210+#if defined(MS_WINDOWS) || (defined(__sun) && defined(__SVR4)) || defined(_AIX) || defined(__VXWORKS__)
4211     if (buf.tm_year + 1900 < 1 || 9999 < buf.tm_year + 1900) {
4212         PyErr_SetString(PyExc_ValueError,
4213                         "strftime() requires year in [1; 9999]");
4214diff --git a/Objects/fileobject.c b/Objects/fileobject.c
4215index ffe55eb..1d73c09 100644
4216--- a/Objects/fileobject.c
4217+++ b/Objects/fileobject.c
4218@@ -3,6 +3,7 @@
4219 #define PY_SSIZE_T_CLEAN
4220 #include "Python.h"
4221 #include "pycore_call.h"          // _PyObject_CallNoArgs()
4222+#include "iscygpty.h"
4223 #include "pycore_runtime.h"       // _PyRuntime
4224
4225 #if defined(HAVE_GETC_UNLOCKED) && !defined(_Py_MEMORY_SANITIZER)
4226@@ -387,7 +388,7 @@ stdprinter_isatty(PyStdPrinter_Object *self, PyObject *Py_UNUSED(ignored))
4227     }
4228
4229     Py_BEGIN_ALLOW_THREADS
4230-    res = isatty(self->fd);
4231+    res = isatty(self->fd) || is_cygpty(self->fd);
4232     Py_END_ALLOW_THREADS
4233
4234     return PyBool_FromLong(res);
4235diff --git a/PC/_testconsole.c b/PC/_testconsole.c
4236index a830883..52aca33 100644
4237--- a/PC/_testconsole.c
4238+++ b/PC/_testconsole.c
4239@@ -10,7 +10,7 @@
4240 #ifdef MS_WINDOWS
4241
4242 #include "pycore_fileutils.h"     // _Py_get_osfhandle()
4243-#include "..\modules\_io\_iomodule.h"
4244+#include "../Modules/_io/_iomodule.h"
4245
4246 #define WIN32_LEAN_AND_MEAN
4247 #include <windows.h>
4248@@ -108,7 +108,7 @@ _testconsole_read_output_impl(PyObject *module, PyObject *file)
4249     Py_RETURN_NONE;
4250 }
4251
4252-#include "clinic\_testconsole.c.h"
4253+#include "clinic/_testconsole.c.h"
4254
4255 PyMethodDef testconsole_methods[] = {
4256     _TESTCONSOLE_WRITE_INPUT_METHODDEF
4257diff --git a/PC/launcher.c b/PC/launcher.c
4258index da566a1..09ac7d9 100644
4259--- a/PC/launcher.c
4260+++ b/PC/launcher.c
4261@@ -155,12 +155,12 @@ static wchar_t * get_env(wchar_t * key)
4262 #else
4263 #if defined(_WINDOWS)
4264
4265-#define PYTHON_EXECUTABLE L"pythonw.exe"
4266+#define PYTHON_EXECUTABLE PYTHON_EXECUTABLE_WITH_VERSION
4267 #define EXECUTABLEPATH_VALUE L"WindowedExecutablePath"
4268
4269 #else
4270
4271-#define PYTHON_EXECUTABLE L"python.exe"
4272+#define PYTHON_EXECUTABLE PYTHON_EXECUTABLE_WITH_VERSION
4273 #define EXECUTABLEPATH_VALUE L"ExecutablePath"
4274
4275 #endif
4276@@ -925,7 +925,7 @@ static COMMAND path_command;
4277 static COMMAND * find_on_path(wchar_t * name)
4278 {
4279     wchar_t * pathext;
4280-    size_t    varsize;
4281+    size_t    requiredSize;
4282     wchar_t * context = NULL;
4283     wchar_t * extension;
4284     COMMAND * result = NULL;
4285@@ -942,18 +942,23 @@ static COMMAND * find_on_path(wchar_t * name)
4286     }
4287     else {
4288         /* No extension - search using registered extensions. */
4289-        rc = _wdupenv_s(&pathext, &varsize, L"PATHEXT");
4290-        if (rc == 0) {
4291-            extension = wcstok_s(pathext, L";", &context);
4292-            while (extension) {
4293-                len = SearchPathW(NULL, name, extension, MSGSIZE, path_command.value, NULL);
4294-                if (len) {
4295-                    result = &path_command;
4296-                    break;
4297+        _wgetenv_s(&requiredSize, NULL, 0, L"PATHEXT");
4298+        if (requiredSize > 0) {
4299+            pathext = (wchar_t *)malloc(requiredSize * sizeof(wchar_t));
4300+            /* No extension - search using registered extensions. */
4301+            rc = _wgetenv_s(&requiredSize, pathext, requiredSize, L"PATHEXT");
4302+            if (rc == 0) {
4303+                extension = wcstok_s(pathext, L";", &context);
4304+                while (extension) {
4305+                    len = SearchPathW(NULL, name, extension, MSGSIZE, path_command.value, NULL);
4306+                    if (len) {
4307+                        result = &path_command;
4308+                        break;
4309+                    }
4310+                    extension = wcstok_s(NULL, L";", &context);
4311                 }
4312-                extension = wcstok_s(NULL, L";", &context);
4313+                free(pathext);
4314             }
4315-            free(pathext);
4316         }
4317     }
4318     return result;
4319@@ -1913,7 +1918,7 @@ process(int argc, wchar_t ** argv)
4320         if (_wfopen_s(&f, venv_cfg_path, L"r")) {
4321             error(RC_BAD_VENV_CFG, L"Cannot read '%ls'", venv_cfg_path);
4322         }
4323-        cb = fread_s(buffer, sizeof(buffer), sizeof(buffer[0]),
4324+        cb = fread(buffer, sizeof(buffer[0]),
4325                      sizeof(buffer) / sizeof(buffer[0]), f);
4326         fclose(f);
4327
4328diff --git a/PC/msvcrtmodule.c b/PC/msvcrtmodule.c
4329index 1f78d99..0f2da80 100644
4330--- a/PC/msvcrtmodule.c
4331+++ b/PC/msvcrtmodule.c
4332@@ -22,7 +22,9 @@
4333 #include <io.h>
4334 #include <conio.h>
4335 #include <sys/locking.h>
4336+#ifdef _DEBUG
4337 #include <crtdbg.h>
4338+#endif
4339 #include <windows.h>
4340
4341 #ifdef _MSC_VER
4342diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc
4343index 1186264..84b2917 100644
4344--- a/PC/pylauncher.rc
4345+++ b/PC/pylauncher.rc
4346@@ -12,17 +12,17 @@
4347 1 RT_MANIFEST "python.manifest"
4348
4349 #if defined(PY_ICON)
4350-1 ICON DISCARDABLE "icons\python.ico"
4351+1 ICON DISCARDABLE "icons/python.ico"
4352 #elif defined(PYW_ICON)
4353-1 ICON DISCARDABLE "icons\pythonw.ico"
4354+1 ICON DISCARDABLE "icons/pythonw.ico"
4355 #else
4356-1 ICON DISCARDABLE "icons\launcher.ico"
4357-2 ICON DISCARDABLE "icons\py.ico"
4358-3 ICON DISCARDABLE "icons\pyc.ico"
4359-4 ICON DISCARDABLE "icons\pyd.ico"
4360-5 ICON DISCARDABLE "icons\python.ico"
4361-6 ICON DISCARDABLE "icons\pythonw.ico"
4362-7 ICON DISCARDABLE "icons\setup.ico"
4363+1 ICON DISCARDABLE "icons/launcher.ico"
4364+2 ICON DISCARDABLE "icons/py.ico"
4365+3 ICON DISCARDABLE "icons/pyc.ico"
4366+4 ICON DISCARDABLE "icons/pyd.ico"
4367+5 ICON DISCARDABLE "icons/python.ico"
4368+6 ICON DISCARDABLE "icons/pythonw.ico"
4369+7 ICON DISCARDABLE "icons/setup.ico"
4370 #endif
4371
4372 1 USAGE "launcher-usage.txt"
4373@@ -64,4 +64,4 @@ BEGIN
4374     BEGIN
4375         VALUE "Translation", 0x0, 1200
4376     END
4377-END
4378\ No newline at end of file
4379+END
4380diff --git a/PC/python3dll.c b/PC/python3dll.c
4381index 50e7a96..8b524fd 100755
4382--- a/PC/python3dll.c
4383+++ b/PC/python3dll.c
4384@@ -3,6 +3,7 @@
4385
4386 /* Generated by Tools/scripts/stable_abi.py */
4387
4388+#ifdef _MSC_VER
4389 #ifdef _M_IX86
4390 #define DECORATE "_"
4391 #else
4392@@ -13,6 +14,13 @@
4393     __pragma(comment(linker, "/EXPORT:" DECORATE #name "=" PYTHON_DLL_NAME "." #name))
4394 #define EXPORT_DATA(name) \
4395     __pragma(comment(linker, "/EXPORT:" DECORATE #name "=" PYTHON_DLL_NAME "." #name ",DATA"))
4396+#else
4397+// XXX: Why do we need the .dll extension and no DECORATE compared to the MSVC case?
4398+#define EXPORT_FUNC(name) \
4399+    asm(".section .drectve\n\t.ascii \" -export:" #name "=\\\"" PYTHON_DLL_NAME "." #name "\\\" \"");
4400+#define EXPORT_DATA(name) \
4401+    asm(".section .drectve\n\t.ascii \" -export:" #name "=\\\"" PYTHON_DLL_NAME "." #name "\\\",DATA \"");
4402+#endif
4403
4404 EXPORT_FUNC(_Py_BuildValue_SizeT)
4405 EXPORT_FUNC(_Py_CheckRecursiveCall)
4406diff --git a/PC/python_exe.rc b/PC/python_exe.rc
4407index c3d3bff..dde0e53 100644
4408--- a/PC/python_exe.rc
4409+++ b/PC/python_exe.rc
4410@@ -12,7 +12,7 @@
4411 // current versions of Windows.
4412 1 RT_MANIFEST "python.manifest"
4413
4414-1 ICON DISCARDABLE "icons\python.ico"
4415+1 ICON DISCARDABLE "icons/python.ico"
4416
4417
4418 /////////////////////////////////////////////////////////////////////////////
4419diff --git a/PC/pythonw_exe.rc b/PC/pythonw_exe.rc
4420index 38570b7..7ce1043 100644
4421--- a/PC/pythonw_exe.rc
4422+++ b/PC/pythonw_exe.rc
4423@@ -12,7 +12,7 @@
4424 // current versions of Windows.
4425 1 RT_MANIFEST "python.manifest"
4426
4427-1 ICON DISCARDABLE "icons\pythonw.ico"
4428+1 ICON DISCARDABLE "icons/pythonw.ico"
4429
4430
4431 /////////////////////////////////////////////////////////////////////////////
4432diff --git a/PC/winreg.c b/PC/winreg.c
4433index f668cf3..08548a7 100644
4434--- a/PC/winreg.c
4435+++ b/PC/winreg.c
4436@@ -18,6 +18,25 @@
4437 #include "structmember.h"         // PyMemberDef
4438 #include <windows.h>
4439
4440+#ifndef SIZEOF_HKEY
4441+/* used only here */
4442+#if defined(MS_WIN64)
4443+#  define SIZEOF_HKEY 8
4444+#elif defined(MS_WIN32)
4445+#  define SIZEOF_HKEY 4
4446+#else
4447+#  error "SIZEOF_HKEY is not defined"
4448+#endif
4449+#endif
4450+
4451+#ifndef REG_LEGAL_CHANGE_FILTER
4452+#define REG_LEGAL_CHANGE_FILTER        (\
4453+          REG_NOTIFY_CHANGE_NAME       |\
4454+          REG_NOTIFY_CHANGE_ATTRIBUTES |\
4455+          REG_NOTIFY_CHANGE_LAST_SET   |\
4456+          REG_NOTIFY_CHANGE_SECURITY   )
4457+#endif
4458+
4459 static BOOL PyHKEY_AsHKEY(PyObject *ob, HKEY *pRes, BOOL bNoneOK);
4460 static BOOL clinic_HKEY_converter(PyObject *ob, void *p);
4461 static PyObject *PyHKEY_FromHKEY(HKEY h);
4462@@ -806,6 +825,7 @@ Reg2Py(BYTE *retDataBuf, DWORD retDataSize, DWORD typ)
4463         case REG_BINARY:
4464         /* ALSO handle ALL unknown data types here.  Even if we can't
4465            support it natively, we should handle the bits. */
4466+           /* fallthrough */
4467         default:
4468             if (retDataSize == 0) {
4469                 Py_INCREF(Py_None);
4470diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
4471index e20bd53..c035b6b 100644
4472--- a/Python/bltinmodule.c
4473+++ b/Python/bltinmodule.c
4474@@ -1,6 +1,7 @@
4475 /* Built-in functions */
4476
4477 #include "Python.h"
4478+#include "iscygpty.h"
4479 #include <ctype.h>
4480 #include "pycore_ast.h"           // _PyAST_Validate()
4481 #include "pycore_call.h"          // _PyObject_CallNoArgs()
4482@@ -2135,7 +2136,7 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
4483         Py_DECREF(tmp);
4484         if (fd < 0 && PyErr_Occurred())
4485             return NULL;
4486-        tty = fd == fileno(stdin) && isatty(fd);
4487+        tty = fd == fileno(stdin) && (isatty(fd) || is_cygpty(fd));
4488     }
4489     if (tty) {
4490         tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(fileno));
4491@@ -2148,7 +2149,7 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
4492             Py_DECREF(tmp);
4493             if (fd < 0 && PyErr_Occurred())
4494                 return NULL;
4495-            tty = fd == fileno(stdout) && isatty(fd);
4496+            tty = fd == fileno(stdout) && (isatty(fd) || is_cygpty(fd));
4497         }
4498     }
4499
4500diff --git a/Python/dynamic_annotations.c b/Python/dynamic_annotations.c
4501index 7febaa0..70d5b3d 100644
4502--- a/Python/dynamic_annotations.c
4503+++ b/Python/dynamic_annotations.c
4504@@ -27,7 +27,7 @@
4505  * Author: Kostya Serebryany
4506  */
4507
4508-#ifdef _MSC_VER
4509+#ifdef MS_WINDOWS
4510 # include <windows.h>
4511 #endif
4512
4513diff --git a/Python/dynload_win.c b/Python/dynload_win.c
4514index 5dc4095..fcb7321 100644
4515--- a/Python/dynload_win.c
4516+++ b/Python/dynload_win.c
4517@@ -4,6 +4,7 @@
4518 #include "Python.h"
4519 #include "pycore_fileutils.h"     // _Py_add_relfile()
4520 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
4521+#include "pycore_initconfig.h"
4522
4523 #ifdef HAVE_DIRECT_H
4524 #include <direct.h>
4525@@ -170,8 +171,7 @@ static char *GetPythonImport (HINSTANCE hModule)
4526    Return whether the DLL was found.
4527 */
4528 extern HMODULE PyWin_DLLhModule;
4529-static int
4530-_Py_CheckPython3(void)
4531+int _Py_CheckPython3(void)
4532 {
4533     static int python3_checked = 0;
4534     static HANDLE hPython3;
4535@@ -224,7 +224,21 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
4536     dl_funcptr p;
4537     char funcname[258], *import_python;
4538
4539-    _Py_CheckPython3();
4540+    int use_legacy = 0;
4541+    DWORD load_library_flags = 0;
4542+
4543+    _Py_get_env_flag(1, &use_legacy, "PYTHONLEGACYWINDOWSDLLLOADING");
4544+
4545+    if (use_legacy) {
4546+        load_library_flags = LOAD_WITH_ALTERED_SEARCH_PATH;
4547+    } else {
4548+        load_library_flags = LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
4549+                              LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
4550+    }
4551+
4552+#ifdef _MSC_VER
4553+    _Py_CheckPython3();
4554+#endif
4555
4556 #if USE_UNICODE_WCHAR_CACHE
4557     const wchar_t *wpathname = _PyUnicode_AsUnicode(pathname);
4558@@ -248,9 +262,7 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
4559            AddDllDirectory function. We add SEARCH_DLL_LOAD_DIR to
4560            ensure DLLs adjacent to the PYD are preferred. */
4561         Py_BEGIN_ALLOW_THREADS
4562-        hDLL = LoadLibraryExW(wpathname, NULL,
4563-                              LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
4564-                              LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
4565+        hDLL = LoadLibraryExW(wpathname, NULL, load_library_flags);
4566         Py_END_ALLOW_THREADS
4567 #if !USE_UNICODE_WCHAR_CACHE
4568         PyMem_Free(wpathname);
4569diff --git a/Python/fileutils.c b/Python/fileutils.c
4570index b310a6c..c575e5a 100644
4571--- a/Python/fileutils.c
4572+++ b/Python/fileutils.c
4573@@ -1,4 +1,5 @@
4574 #include "Python.h"
4575+#include "iscygpty.h"
4576 #include "pycore_fileutils.h"     // fileutils definitions
4577 #include "pycore_runtime.h"       // _PyRuntime
4578 #include "osdefs.h"               // SEP
4579@@ -71,7 +72,7 @@ _Py_device_encoding(int fd)
4580     int valid;
4581     Py_BEGIN_ALLOW_THREADS
4582     _Py_BEGIN_SUPPRESS_IPH
4583-    valid = isatty(fd);
4584+    valid = isatty(fd) || is_cygpty(fd);
4585     _Py_END_SUPPRESS_IPH
4586     Py_END_ALLOW_THREADS
4587     if (!valid)
4588@@ -1809,12 +1810,12 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
4589            depending on heap usage). */
4590         if (gil_held) {
4591             Py_BEGIN_ALLOW_THREADS
4592-            if (isatty(fd)) {
4593+            if (isatty(fd) || is_cygpty(fd)) {
4594                 count = 32767;
4595             }
4596             Py_END_ALLOW_THREADS
4597         } else {
4598-            if (isatty(fd)) {
4599+            if (isatty(fd) || is_cygpty(fd)) {
4600                 count = 32767;
4601             }
4602         }
4603@@ -2004,19 +2005,31 @@ int
4604 _Py_isabs(const wchar_t *path)
4605 {
4606 #ifdef MS_WINDOWS
4607+    // create a copy of path and replace all forward slashes with backslashes
4608+    // pathccskiproot does not handle forward slashes
4609+    wchar_t *path_copy = _wcsdup(path);
4610+    if (path_copy == NULL) {
4611+        return 0;
4612+    }
4613+    Py_NormalizeSepsPathcchW(path_copy);
4614+
4615     const wchar_t *tail;
4616-    HRESULT hr = PathCchSkipRoot(path, &tail);
4617-    if (FAILED(hr) || path == tail) {
4618+    HRESULT hr = PathCchSkipRoot(path_copy, &tail);
4619+    if (FAILED(hr) || path_copy == tail) {
4620+        free(path_copy);
4621         return 0;
4622     }
4623-    if (tail == &path[1] && (path[0] == SEP || path[0] == ALTSEP)) {
4624+    if (tail == &path_copy[1] && (path_copy[0] == SEP || path_copy[0] == ALTSEP)) {
4625         // Exclude paths with leading SEP
4626+        free(path_copy);
4627         return 0;
4628     }
4629-    if (tail == &path[2] && path[1] == L':') {
4630+    if (tail == &path_copy[2] && path_copy[1] == L':') {
4631         // Exclude drive-relative paths (e.g. C:filename.ext)
4632+        free(path_copy);
4633         return 0;
4634     }
4635+    free(path_copy);
4636     return 1;
4637 #else
4638     return (path[0] == SEP);
4639@@ -2049,7 +2062,11 @@ _Py_abspath(const wchar_t *path, wchar_t **abspath_p)
4640     }
4641
4642 #ifdef MS_WINDOWS
4643-    return _PyOS_getfullpathname(path, abspath_p);
4644+    if (_PyOS_getfullpathname(path, abspath_p) < 0){
4645+        return -1;
4646+    }
4647+    *abspath_p = _Py_normpath(*abspath_p, -1);
4648+    return 0;
4649 #else
4650     wchar_t cwd[MAXPATHLEN + 1];
4651     cwd[Py_ARRAY_LENGTH(cwd) - 1] = 0;
4652@@ -2093,6 +2110,8 @@ join_relfile(wchar_t *buffer, size_t bufsize,
4653              const wchar_t *dirname, const wchar_t *relfile)
4654 {
4655 #ifdef MS_WINDOWS
4656+    Py_NormalizeSepsPathcchW(dirname);
4657+    Py_NormalizeSepsPathcchW(relfile);
4658     if (FAILED(PathCchCombineEx(buffer, bufsize, dirname, relfile,
4659         PATHCCH_ALLOW_LONG_PATHS))) {
4660         return -1;
4661@@ -2195,11 +2214,16 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
4662     wchar_t *minP2 = path;  // the beginning of the destination range
4663     wchar_t lastC = L'\0';  // the last ljusted character, p2[-1] in most cases
4664
4665+    const wchar_t sep = Py_GetSepW(NULL);
4666+#ifdef ALTSEP
4667+    const wchar_t altsep = Py_GetAltSepW(NULL);
4668+#endif
4669+
4670 #define IS_END(x) (pEnd ? (x) == pEnd : !*(x))
4671 #ifdef ALTSEP
4672-#define IS_SEP(x) (*(x) == SEP || *(x) == ALTSEP)
4673+#define IS_SEP(x) (*(x) == sep || *(x) == altsep)
4674 #else
4675-#define IS_SEP(x) (*(x) == SEP)
4676+#define IS_SEP(x) (*(x) == sep)
4677 #endif
4678 #define SEP_OR_END(x) (IS_SEP(x) || IS_END(x))
4679
4680@@ -2210,7 +2234,7 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
4681             path++;
4682         }
4683         p1 = p2 = minP2 = path;
4684-        lastC = SEP;
4685+        lastC = sep;
4686     }
4687 #ifdef MS_WINDOWS
4688     // Skip past drive segment and update minP2
4689@@ -2224,13 +2248,13 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
4690     // and network paths, including the first segment.
4691     else if (IS_SEP(&p1[0]) && IS_SEP(&p1[1])) {
4692         int sepCount = 2;
4693-        *p2++ = SEP;
4694-        *p2++ = SEP;
4695+        *p2++ = sep;
4696+        *p2++ = sep;
4697         p1 += 2;
4698         for (; !IS_END(p1) && sepCount; ++p1) {
4699             if (IS_SEP(p1)) {
4700                 --sepCount;
4701-                *p2++ = lastC = SEP;
4702+                *p2++ = lastC = sep;
4703             } else {
4704                 *p2++ = lastC = *p1;
4705             }
4706@@ -2243,7 +2267,7 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
4707         *p2++ = *p1++;
4708         *p2++ = *p1++;
4709         minP2 = p2 - 1;  // Absolute path has SEP at minP2
4710-        lastC = SEP;
4711+        lastC = sep;
4712     }
4713 #endif /* MS_WINDOWS */
4714
4715@@ -2251,18 +2275,18 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
4716     for (; !IS_END(p1); ++p1) {
4717         wchar_t c = *p1;
4718 #ifdef ALTSEP
4719-        if (c == ALTSEP) {
4720-            c = SEP;
4721+        if (c == altsep) {
4722+            c = sep;
4723         }
4724 #endif
4725-        if (lastC == SEP) {
4726+        if (lastC == sep) {
4727             if (c == L'.') {
4728                 int sep_at_1 = SEP_OR_END(&p1[1]);
4729                 int sep_at_2 = !sep_at_1 && SEP_OR_END(&p1[2]);
4730                 if (sep_at_2 && p1[1] == L'.') {
4731                     wchar_t *p3 = p2;
4732-                    while (p3 != minP2 && *--p3 == SEP) { }
4733-                    while (p3 != minP2 && *(p3 - 1) != SEP) { --p3; }
4734+                    while (p3 != minP2 && *--p3 == sep) { }
4735+                    while (p3 != minP2 && *(p3 - 1) != sep) { --p3; }
4736                     if (p2 == minP2
4737                         || (p3[0] == L'.' && p3[1] == L'.' && IS_SEP(&p3[2])))
4738                     {
4739@@ -2271,7 +2295,7 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
4740                         *p2++ = L'.';
4741                         *p2++ = L'.';
4742                         lastC = L'.';
4743-                    } else if (p3[0] == SEP) {
4744+                    } else if (p3[0] == sep) {
4745                         // Absolute path, so absorb segment
4746                         p2 = p3 + 1;
4747                     } else {
4748@@ -2282,7 +2306,7 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
4749                 } else {
4750                     *p2++ = lastC = c;
4751                 }
4752-            } else if (c == SEP) {
4753+            } else if (c == sep) {
4754             } else {
4755                 *p2++ = lastC = c;
4756             }
4757@@ -2292,7 +2316,7 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
4758     }
4759     *p2 = L'\0';
4760     if (p2 != minP2) {
4761-        while (--p2 != minP2 && *p2 == SEP) {
4762+        while (--p2 != minP2 && *p2 == sep) {
4763             *p2 = L'\0';
4764         }
4765     } else {
4766diff --git a/Python/frozenmain.c b/Python/frozenmain.c
4767index 8743e08..c6f5f19 100644
4768--- a/Python/frozenmain.c
4769+++ b/Python/frozenmain.c
4770@@ -3,6 +3,7 @@
4771 #include "Python.h"
4772 #include "pycore_runtime.h"  // _PyRuntime_Initialize()
4773 #include <locale.h>
4774+#include "iscygpty.h"
4775
4776 #ifdef MS_WINDOWS
4777 extern void PyWinFreeze_ExeInit(void);
4778@@ -71,7 +72,7 @@ Py_FrozenMain(int argc, char **argv)
4779         sts = 0;
4780     }
4781
4782-    if (inspect && isatty((int)fileno(stdin))) {
4783+    if (inspect && (isatty((int)fileno(stdin)) || is_cygpty((int)fileno(stdin))))
4784         sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
4785     }
4786
4787diff --git a/Python/getcompiler.c b/Python/getcompiler.c
4788index a5d2623..4b0b9b3 100644
4789--- a/Python/getcompiler.c
4790+++ b/Python/getcompiler.c
4791@@ -7,10 +7,40 @@
4792
4793 // Note the __clang__ conditional has to come before the __GNUC__ one because
4794 // clang pretends to be GCC.
4795-#if defined(__clang__)
4796+#if defined(__clang__) && !defined(_WIN32)
4797 #define COMPILER "[Clang " __clang_version__ "]"
4798 #elif defined(__GNUC__)
4799-#define COMPILER "[GCC " __VERSION__ "]"
4800+/* To not break compatibility with things that determine
4801+   CPU arch by calling get_build_version in msvccompiler.py
4802+   (such as NumPy) add "32 bit" or "64 bit (AMD64)" on Windows
4803+   and also use a space as a separator rather than a newline. */
4804+#if defined(_WIN32)
4805+#define COMP_SEP " "
4806+#if defined(__x86_64__)
4807+#define ARCH_SUFFIX " 64 bit (AMD64)"
4808+#elif defined(__aarch64__)
4809+#define ARCH_SUFFIX " 64 bit (ARM64)"
4810+#elif defined(__arm__)
4811+#define ARCH_SUFFIX " 32 bit (ARM)"
4812+#else
4813+#define ARCH_SUFFIX " 32 bit"
4814+#endif
4815+#else
4816+#define COMP_SEP "\n"
4817+#define ARCH_SUFFIX ""
4818+#endif
4819+#if defined(__clang__)
4820+#define str(x) #x
4821+#define xstr(x) str(x)
4822+#define COMPILER COMP_SEP "[GCC Clang " xstr(__clang_major__) "." \
4823+        xstr(__clang_minor__) "." xstr(__clang_patchlevel__) ARCH_SUFFIX "]"
4824+#else
4825+#if defined(_UCRT)
4826+#define COMPILER COMP_SEP "[GCC UCRT " __VERSION__ ARCH_SUFFIX "]"
4827+#else
4828+#define COMPILER COMP_SEP "[GCC " __VERSION__ ARCH_SUFFIX "]"
4829+#endif
4830+#endif
4831 // Generic fallbacks.
4832 #elif defined(__cplusplus)
4833 #define COMPILER "[C++]"
4834diff --git a/Python/initconfig.c b/Python/initconfig.c
4835index d81cbaf..c54d238 100644
4836--- a/Python/initconfig.c
4837+++ b/Python/initconfig.c
4838@@ -176,7 +176,7 @@ static const char usage_envvars[] =
4839 "PYTHONVERBOSE           : trace import statements (-v)\n"
4840 "PYTHONWARNINGS=arg      : warning control (-W arg)\n";
4841
4842-#if defined(MS_WINDOWS)
4843+#if defined(_MSC_VER)
4844 #  define PYTHONHOMEHELP "<prefix>\\python{major}{minor}"
4845 #else
4846 #  define PYTHONHOMEHELP "<prefix>/lib/pythonX.X"
4847diff --git a/Python/iscygpty.c b/Python/iscygpty.c
4848new file mode 100644
4849index 0000000..722f88f
4850--- /dev/null
4851+++ b/Python/iscygpty.c
4852@@ -0,0 +1,185 @@
4853+/*
4854+ * iscygpty.c -- part of ptycheck
4855+ * https://github.com/k-takata/ptycheck
4856+ *
4857+ * Copyright (c) 2015-2017 K.Takata
4858+ *
4859+ * You can redistribute it and/or modify it under the terms of either
4860+ * the MIT license (as described below) or the Vim license.
4861+ *
4862+ * Permission is hereby granted, free of charge, to any person obtaining
4863+ * a copy of this software and associated documentation files (the
4864+ * "Software"), to deal in the Software without restriction, including
4865+ * without limitation the rights to use, copy, modify, merge, publish,
4866+ * distribute, sublicense, and/or sell copies of the Software, and to
4867+ * permit persons to whom the Software is furnished to do so, subject to
4868+ * the following conditions:
4869+ *
4870+ * The above copyright notice and this permission notice shall be
4871+ * included in all copies or substantial portions of the Software.
4872+ *
4873+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
4874+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4875+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
4876+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
4877+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
4878+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
4879+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4880+ */
4881+
4882+#ifdef _WIN32
4883+
4884+#include <ctype.h>
4885+#include <io.h>
4886+#include <wchar.h>
4887+#include <windows.h>
4888+
4889+#ifdef USE_FILEEXTD
4890+/* VC 7.1 or earlier doesn't support SAL. */
4891+# if !defined(_MSC_VER) || (_MSC_VER < 1400)
4892+#  define __out
4893+#  define __in
4894+#  define __in_opt
4895+# endif
4896+/* Win32 FileID API Library:
4897+ * http://www.microsoft.com/en-us/download/details.aspx?id=22599
4898+ * Needed for WinXP. */
4899+# include <fileextd.h>
4900+#else /* USE_FILEEXTD */
4901+/* VC 8 or earlier. */
4902+# if defined(_MSC_VER) && (_MSC_VER < 1500)
4903+#  ifdef ENABLE_STUB_IMPL
4904+#   define STUB_IMPL
4905+#  else
4906+#   error "Win32 FileID API Library is required for VC2005 or earlier."
4907+#  endif
4908+# endif
4909+#endif /* USE_FILEEXTD */
4910+
4911+
4912+#include "iscygpty.h"
4913+
4914+//#define USE_DYNFILEID
4915+#ifdef USE_DYNFILEID
4916+typedef BOOL (WINAPI *pfnGetFileInformationByHandleEx)(
4917+		HANDLE                    hFile,
4918+		FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
4919+		LPVOID                    lpFileInformation,
4920+		DWORD                     dwBufferSize
4921+);
4922+static pfnGetFileInformationByHandleEx pGetFileInformationByHandleEx = NULL;
4923+
4924+# ifndef USE_FILEEXTD
4925+static BOOL WINAPI stub_GetFileInformationByHandleEx(
4926+		HANDLE                    hFile,
4927+		FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
4928+		LPVOID                    lpFileInformation,
4929+		DWORD                     dwBufferSize
4930+		)
4931+{
4932+	return FALSE;
4933+}
4934+# endif
4935+
4936+static void setup_fileid_api(void)
4937+{
4938+	if (pGetFileInformationByHandleEx != NULL) {
4939+		return;
4940+	}
4941+	pGetFileInformationByHandleEx = (pfnGetFileInformationByHandleEx)
4942+		GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
4943+				"GetFileInformationByHandleEx");
4944+	if (pGetFileInformationByHandleEx == NULL) {
4945+# ifdef USE_FILEEXTD
4946+		pGetFileInformationByHandleEx = GetFileInformationByHandleEx;
4947+# else
4948+		pGetFileInformationByHandleEx = stub_GetFileInformationByHandleEx;
4949+# endif
4950+	}
4951+}
4952+#else
4953+# define pGetFileInformationByHandleEx	GetFileInformationByHandleEx
4954+# define setup_fileid_api()
4955+#endif
4956+
4957+
4958+#define is_wprefix(s, prefix) \
4959+	(wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
4960+
4961+/* Check if the fd is a cygwin/msys's pty. */
4962+int is_cygpty(int fd)
4963+{
4964+#ifdef STUB_IMPL
4965+	return 0;
4966+#else
4967+	HANDLE h;
4968+	int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * (MAX_PATH - 1);
4969+	FILE_NAME_INFO *nameinfo;
4970+	WCHAR *p = NULL;
4971+
4972+	setup_fileid_api();
4973+
4974+	h = (HANDLE) _get_osfhandle(fd);
4975+	if (h == INVALID_HANDLE_VALUE) {
4976+		return 0;
4977+	}
4978+	/* Cygwin/msys's pty is a pipe. */
4979+	if (GetFileType(h) != FILE_TYPE_PIPE) {
4980+		return 0;
4981+	}
4982+	nameinfo = malloc(size + sizeof(WCHAR));
4983+	if (nameinfo == NULL) {
4984+		return 0;
4985+	}
4986+	/* Check the name of the pipe:
4987+	 * '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master' */
4988+	if (pGetFileInformationByHandleEx(h, FileNameInfo, nameinfo, size)) {
4989+		nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
4990+		p = nameinfo->FileName;
4991+		if (is_wprefix(p, L"\\cygwin-")) {		/* Cygwin */
4992+			p += 8;
4993+		} else if (is_wprefix(p, L"\\msys-")) {	/* MSYS and MSYS2 */
4994+			p += 6;
4995+		} else {
4996+			p = NULL;
4997+		}
4998+		if (p != NULL) {
4999+			while (*p && isxdigit(*p))	/* Skip 16-digit hexadecimal. */
5000+				++p;
5001+			if (is_wprefix(p, L"-pty")) {
5002+				p += 4;
5003+			} else {
5004+				p = NULL;
5005+			}
5006+		}
5007+		if (p != NULL) {
5008+			while (*p && isdigit(*p))	/* Skip pty number. */
5009+				++p;
5010+			if (is_wprefix(p, L"-from-master")) {
5011+				//p += 12;
5012+			} else if (is_wprefix(p, L"-to-master")) {
5013+				//p += 10;
5014+			} else {
5015+				p = NULL;
5016+			}
5017+		}
5018+	}
5019+	free(nameinfo);
5020+	return (p != NULL);
5021+#endif /* STUB_IMPL */
5022+}
5023+
5024+/* Check if at least one cygwin/msys pty is used. */
5025+int is_cygpty_used(void)
5026+{
5027+	int fd, ret = 0;
5028+
5029+	for (fd = 0; fd < 3; fd++) {
5030+		ret |= is_cygpty(fd);
5031+	}
5032+	return ret;
5033+}
5034+
5035+#endif /* _WIN32 */
5036+
5037+/* vim: set ts=4 sw=4: */
5038diff --git a/Python/pathconfig.c b/Python/pathconfig.c
5039index be0f97c..7eb9006 100644
5040--- a/Python/pathconfig.c
5041+++ b/Python/pathconfig.c
5042@@ -2,7 +2,7 @@
5043
5044 #include "Python.h"
5045 #include "marshal.h"              // PyMarshal_ReadObjectFromString
5046-#include "osdefs.h"               // DELIM
5047+#include "osdefs.h"               // DELIM, SEP
5048 #include "pycore_initconfig.h"
5049 #include "pycore_fileutils.h"
5050 #include "pycore_pathconfig.h"
5051@@ -18,6 +18,158 @@
5052 extern "C" {
5053 #endif
5054
5055+#ifdef __MINGW32__
5056+#define wcstok  wcstok_s
5057+#include <windows.h>
5058+#endif
5059+
5060+static int
5061+Py_StartsWithA(const char * str, const char * prefix)
5062+{
5063+    while(*prefix)
5064+    {
5065+        if(*prefix++ != *str++)
5066+            return 0;
5067+    }
5068+
5069+    return 1;
5070+}
5071+
5072+static int
5073+Py_StartsWithW(const wchar_t * str, const wchar_t * prefix)
5074+{
5075+    while(*prefix)
5076+    {
5077+        if(*prefix++ != *str++)
5078+            return 0;
5079+    }
5080+
5081+    return 1;
5082+}
5083+
5084+char
5085+Py_GetSepA(const char *name)
5086+{
5087+    static char sep = '\0';
5088+#ifdef _WIN32
5089+    /* https://msdn.microsoft.com/en-gb/library/windows/desktop/aa365247%28v=vs.85%29.aspx
5090+     * The "\\?\" prefix .. indicate that the path should be passed to the system with minimal
5091+     * modification, which means that you cannot use forward slashes to represent path separators
5092+     */
5093+    if (name != NULL && Py_StartsWithA(name, "\\\\?\\") != 0)
5094+    {
5095+        return '\\';
5096+    }
5097+#endif
5098+    if (sep != '\0')
5099+        return sep;
5100+#if defined(__MINGW32__)
5101+    char* msystem = getenv("MSYSTEM");
5102+    if (msystem != NULL && strcmp(msystem, "") != 0)
5103+        sep = '/';
5104+    else
5105+        sep = '\\';
5106+#else
5107+    sep = SEP;
5108+#endif
5109+    return sep;
5110+}
5111+
5112+static char
5113+Py_GetAltSepA(const char *name)
5114+{
5115+    char sep = Py_GetSepA(name);
5116+    if (sep == '/')
5117+        return '\\';
5118+    return '/';
5119+}
5120+
5121+void
5122+Py_NormalizeSepsA(char *name)
5123+{
5124+    assert(name != NULL);
5125+    char sep = Py_GetSepA(name);
5126+    char altsep = Py_GetAltSepA(name);
5127+    char* seps;
5128+    if (name[0] != '\0' && name[1] == ':') {
5129+        name[0] = toupper(name[0]);
5130+    }
5131+    seps = strchr(name, altsep);
5132+    while(seps) {
5133+        *seps = sep;
5134+        seps = strchr(seps, altsep);
5135+    }
5136+}
5137+
5138+wchar_t
5139+Py_GetSepW(const wchar_t *name)
5140+{
5141+    static wchar_t sep = L'\0';
5142+#ifdef _WIN32
5143+    /* https://msdn.microsoft.com/en-gb/library/windows/desktop/aa365247%28v=vs.85%29.aspx
5144+     * The "\\?\" prefix .. indicate that the path should be passed to the system with minimal
5145+     * modification, which means that you cannot use forward slashes to represent path separators
5146+     */
5147+    if (name != NULL && Py_StartsWithW(name, L"\\\\?\\") != 0)
5148+    {
5149+        return L'\\';
5150+    }
5151+#endif
5152+    if (sep != L'\0')
5153+        return sep;
5154+#if defined(__MINGW32__)
5155+    char* msystem = getenv("MSYSTEM");
5156+    if (msystem != NULL && strcmp(msystem, "") != 0)
5157+        sep = L'/';
5158+    else
5159+        sep = L'\\';
5160+#else
5161+    sep = SEP;
5162+#endif
5163+    return sep;
5164+}
5165+
5166+wchar_t
5167+Py_GetAltSepW(const wchar_t *name)
5168+{
5169+    char sep = Py_GetSepW(name);
5170+    if (sep == L'/')
5171+        return L'\\';
5172+    return L'/';
5173+}
5174+
5175+void
5176+Py_NormalizeSepsW(wchar_t *name)
5177+{
5178+    assert(name != NULL);
5179+    wchar_t sep = Py_GetSepW(name);
5180+    wchar_t altsep = Py_GetAltSepW(name);
5181+    wchar_t* seps;
5182+    if (name[0] != L'\0' && name[1] == L':') {
5183+        name[0] = towupper(name[0]);
5184+    }
5185+    seps = wcschr(name, altsep);
5186+    while(seps) {
5187+        *seps = sep;
5188+        seps = wcschr(seps, altsep);
5189+    }
5190+}
5191+
5192+void
5193+Py_NormalizeSepsPathcchW(wchar_t *name)
5194+{
5195+#ifdef MS_WINDOWS
5196+    assert(name != NULL);
5197+    wchar_t sep = '\\';
5198+    wchar_t altsep = '/';
5199+    wchar_t* seps;
5200+    seps = wcschr(name, altsep);
5201+    while(seps) {
5202+        *seps = sep;
5203+        seps = wcschr(seps, altsep);
5204+    }
5205+#endif
5206+}
5207
5208 /* External interface */
5209
5210@@ -317,6 +469,7 @@ _Py_SetProgramFullPath(const wchar_t *program_full_path)
5211     if (has_value && _Py_path_config.program_full_path == NULL) {
5212         path_out_of_memory(__func__);
5213     }
5214+    Py_NormalizeSepsW(_Py_path_config.program_name);
5215 }
5216
5217
5218@@ -509,7 +662,7 @@ _PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
5219     }
5220 #endif /* All others */
5221
5222-    PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
5223+    PyObject *path0_obj = PyUnicode_FromWideChar(_Py_normpath(path0, -1), n);
5224     if (path0_obj == NULL) {
5225         return -1;
5226     }
5227diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
5228index 9248e97..1d53e12 100644
5229--- a/Python/pylifecycle.c
5230+++ b/Python/pylifecycle.c
5231@@ -31,6 +31,7 @@
5232
5233 extern void _PyIO_Fini(void);
5234
5235+#include "iscygpty.h"
5236 #include <locale.h>               // setlocale()
5237 #include <stdlib.h>               // getenv()
5238
5239@@ -2954,7 +2955,7 @@ Py_Exit(int sts)
5240 int
5241 Py_FdIsInteractive(FILE *fp, const char *filename)
5242 {
5243-    if (isatty((int)fileno(fp)))
5244+    if (isatty((int)fileno(fp)) || is_cygpty((int)fileno(fp)))
5245         return 1;
5246     if (!Py_InteractiveFlag)
5247         return 0;
5248@@ -2967,7 +2968,7 @@ Py_FdIsInteractive(FILE *fp, const char *filename)
5249 int
5250 _Py_FdIsInteractive(FILE *fp, PyObject *filename)
5251 {
5252-    if (isatty((int)fileno(fp))) {
5253+    if (isatty((int)fileno(fp)) || is_cygpty((int)fileno(fp))) {
5254         return 1;
5255     }
5256     if (!Py_InteractiveFlag) {
5257diff --git a/Python/sysmodule.c b/Python/sysmodule.c
5258index 8bab703..fed0adb 100644
5259--- a/Python/sysmodule.c
5260+++ b/Python/sysmodule.c
5261@@ -43,7 +43,7 @@ Data members:
5262 #include <windows.h>
5263 #endif /* MS_WINDOWS */
5264
5265-#ifdef MS_COREDLL
5266+#if defined(MS_WINDOWS) && defined(Py_ENABLE_SHARED)
5267 extern void *PyWin_DLLhModule;
5268 /* A string loaded from the DLL at startup: */
5269 extern const char *PyWin_DLLVersionString;
5270@@ -2923,7 +2923,7 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
5271     SET_SYS_FROM_STRING("byteorder", "little");
5272 #endif
5273
5274-#ifdef MS_COREDLL
5275+#if defined(MS_WINDOWS) && defined(Py_ENABLE_SHARED)
5276     SET_SYS("dllhandle", PyLong_FromVoidPtr(PyWin_DLLhModule));
5277     SET_SYS_FROM_STRING("winver", PyWin_DLLVersionString);
5278 #endif
5279diff --git a/Python/thread_nt.h b/Python/thread_nt.h
5280index 084bd58..f8a6765 100644
5281--- a/Python/thread_nt.h
5282+++ b/Python/thread_nt.h
5283@@ -360,8 +360,9 @@ PyThread_release_lock(PyThread_type_lock aLock)
5284 {
5285     dprintf(("%lu: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
5286
5287-    if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock)))
5288+    if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock))) {
5289         dprintf(("%lu: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError()));
5290+    }
5291 }
5292
5293 /* minimum/maximum thread stack sizes supported */
5294diff --git a/Python/traceback.c b/Python/traceback.c
5295index 7f47349..23fda62 100644
5296--- a/Python/traceback.c
5297+++ b/Python/traceback.c
5298@@ -323,7 +323,7 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *
5299     filepath = PyBytes_AS_STRING(filebytes);
5300
5301     /* Search tail of filename in sys.path before giving up */
5302-    tail = strrchr(filepath, SEP);
5303+    tail = strrchr(filepath, Py_GetSepA(filepath));
5304     if (tail == NULL)
5305         tail = filepath;
5306     else
5307diff --git a/configure.ac b/configure.ac
5308index 1c25abd..5cf7085 100644
5309--- a/configure.ac
5310+++ b/configure.ac
5311@@ -202,9 +202,11 @@ AC_SUBST([FREEZE_MODULE])
5312 AC_SUBST([FREEZE_MODULE_DEPS])
5313 AC_SUBST([PYTHON_FOR_BUILD_DEPS])
5314
5315+NATIVE_PYTHON_SEARCH_PATH_MINGW=`echo $host | grep -Eq 'mingw*' && echo "$MINGW_PREFIX/bin" || echo $PATH`
5316 AC_CHECK_PROGS([PYTHON_FOR_REGEN],
5317   [python$PACKAGE_VERSION python3.10 python3.9 python3.8 python3.7 python3.6 python3 python],
5318-  [python3])
5319+  [python3],
5320+  [$NATIVE_PYTHON_SEARCH_PATH_MINGW])
5321 AC_SUBST(PYTHON_FOR_REGEN)
5322
5323 AC_MSG_CHECKING([Python for regen version])
5324@@ -545,6 +547,9 @@ then
5325 	*-*-cygwin*)
5326 		ac_sys_system=Cygwin
5327 		;;
5328+	*-*-mingw*)
5329+		ac_sys_system=MINGW
5330+		;;
5331 	*-*-vxworks*)
5332 	    ac_sys_system=VxWorks
5333 	    ;;
5334@@ -580,6 +585,7 @@ then
5335 	linux*) MACHDEP="linux";;
5336 	cygwin*) MACHDEP="cygwin";;
5337 	darwin*) MACHDEP="darwin";;
5338+	mingw*) MACHDEP="win32";;
5339 	'')	MACHDEP="unknown";;
5340     esac
5341 fi
5342@@ -605,6 +611,9 @@ if test "$cross_compiling" = yes; then
5343 		;;
5344 	wasm32-*-* | wasm64-*-*)
5345 		_host_cpu=$host_cpu
5346+    ;;
5347+	*-*-mingw*)
5348+		_host_cpu=
5349 		;;
5350 	*)
5351 		# for now, limit cross builds to known configurations
5352@@ -612,6 +621,14 @@ if test "$cross_compiling" = yes; then
5353 		AC_MSG_ERROR([cross build not supported for $host])
5354 	esac
5355 	_PYTHON_HOST_PLATFORM="$MACHDEP${_host_cpu:+-$_host_cpu}"
5356+
5357+	case "$host_os" in
5358+	mingw*)
5359+	# As sys.platform() return 'win32' to build python and extantions
5360+	# we will use 'mingw' (in setup.py and etc.)
5361+	_PYTHON_HOST_PLATFORM=mingw
5362+	;;
5363+	esac
5364 fi
5365
5366 # Some systems cannot stand _XOPEN_SOURCE being defined at all; they
5367@@ -723,6 +740,65 @@ then
5368   AC_DEFINE(_INCLUDE__STDC_A1_SOURCE, 1, Define to include mbstate_t for mbrtowc)
5369 fi
5370
5371+# On 'semi-native' build systems (MSYS*/Cygwin targeting MinGW-w64)
5372+# _sysconfigdata.py will contain paths that are correct only in the
5373+# build environment. This means external modules will fail to build
5374+# without setting up the same env and also that the build of Python
5375+# itself will fail as the paths are not correct for the host tools.
5376+#
5377+# To work around these issues a set of _b2h variables are created:
5378+# prefix_b2h, srcdir_b2h, abs_srcdir_b2h
5379+# and abs_builddir_b2h
5380+# .. where b2h stands for build to host. sysconfig.py replaces path
5381+# prefixes matching the non-b2h versions with the b2h equivalents.
5382+#
5383+# (note this assumes the host compilers are native and *not* cross
5384+#  - in the 'semi-native' scenario only that is.)
5385+
5386+AC_DEFUN([ABS_PATH_HOST],
5387+[$1=$(cd $$2 && pwd)
5388+  case $build_os in
5389+    mingw*)
5390+      case $host_os in
5391+        mingw*) $1=$(cd $$2 && pwd -W) ;;
5392+        *) ;;
5393+      esac
5394+      ;;
5395+    cygwin*)
5396+      case $host_os in
5397+        mingw*) $1=$(cygpath -w -m $$2) ;;
5398+        *) ;;
5399+      esac
5400+      ;;
5401+  esac
5402+AC_SUBST([$1])
5403+])
5404+
5405+AC_MSG_CHECKING(absolute host location of prefix)
5406+ABS_PATH_HOST([prefix_b2h],[prefix])
5407+AC_MSG_RESULT([$prefix_b2h])
5408+
5409+AC_MSG_CHECKING(absolute host location of srcdir)
5410+ABS_PATH_HOST([srcdir_b2h],[srcdir])
5411+AC_MSG_RESULT([$srcdir_b2h])
5412+
5413+AC_MSG_CHECKING(absolute host location of abs_srcdir)
5414+ABS_PATH_HOST([abs_srcdir_b2h],[srcdir])
5415+AC_MSG_RESULT([$abs_srcdir_b2h])
5416+
5417+my_builddir=.
5418+AC_MSG_CHECKING(Absolute host location of abs_builddir)
5419+ABS_PATH_HOST([abs_builddir_b2h],[my_builddir])
5420+AC_MSG_RESULT([$abs_builddir_b2h])
5421+
5422+AC_MSG_CHECKING([for init system calls])
5423+AC_SUBST(INITSYS)
5424+case $host in
5425+  *-*-mingw*)	INITSYS=nt;;
5426+  *)		INITSYS=posix;;
5427+esac
5428+AC_MSG_RESULT([$INITSYS])
5429+
5430 # Record the configure-time value of MACOSX_DEPLOYMENT_TARGET,
5431 # it may influence the way we can build extensions, so distutils
5432 # needs to check it
5433@@ -1163,6 +1239,28 @@ AC_CACHE_CHECK([for -Wl,--no-as-needed], [ac_cv_wl_no_as_needed], [
5434 ])
5435 AC_SUBST(NO_AS_NEEDED)
5436
5437+# initialize default configuration
5438+py_config=
5439+case $host in
5440+  *-*-mingw*) py_config=mingw ;;
5441+esac
5442+if test -n "$py_config" ; then
5443+  AC_MSG_NOTICE([loading configure defaults from .../Misc/config_$py_config"])
5444+  . "$srcdir/Misc/config_$py_config"
5445+fi
5446+
5447+# initialize defaults for cross-builds
5448+if test "$cross_compiling" = yes; then
5449+  py_config=$host_os
5450+  case $py_config in
5451+    mingw32*) py_config=mingw32 ;;
5452+  esac
5453+  if test -f "$srcdir/Misc/cross_$py_config" ; then
5454+    AC_MSG_NOTICE([loading cross defaults from .../Misc/cross_$py_config"])
5455+    . "$srcdir/Misc/cross_$py_config"
5456+  fi
5457+fi
5458+
5459 AC_MSG_CHECKING([for the Android API level])
5460 cat > conftest.c <<EOF
5461 #ifdef __ANDROID__
5462@@ -1275,6 +1373,7 @@ AC_ARG_WITH([suffix],
5463     [Emscripten/browser*], [EXEEXT=.js],
5464     [Emscripten/node*], [EXEEXT=.js],
5465     [WASI/*], [EXEEXT=.wasm],
5466+    [MINGW*], [EXEEXT=.exe],
5467     [EXEEXT=]
5468   )
5469 ])
5470@@ -1298,6 +1397,10 @@ else
5471 fi
5472 rmdir CaseSensitiveTestDir
5473
5474+AS_CASE([$ac_sys_system],
5475+  [MINGW], [BUILDEXEEXT=".exe"]
5476+)
5477+
5478 case $ac_sys_system in
5479 hp*|HP*)
5480     case $CC in
5481@@ -1475,6 +1578,11 @@ if test $enable_shared = "yes"; then
5482           LDLIBRARY='libpython$(LDVERSION).dll.a'
5483           DLLLIBRARY='libpython$(LDVERSION).dll'
5484           ;;
5485+    MINGW*)
5486+          LDLIBRARY='libpython$(LDVERSION).dll.a'
5487+          DLLLIBRARY='libpython$(LDVERSION).dll'
5488+          BLDLIBRARY='-L. -lpython$(LDVERSION)'
5489+          ;;
5490     SunOS*)
5491 	  LDLIBRARY='libpython$(LDVERSION).so'
5492 	  BLDLIBRARY='-Wl,-R,$(LIBDIR) -L. -lpython$(LDVERSION)'
5493@@ -1525,6 +1633,9 @@ else # shared is disabled
5494           BLDLIBRARY='$(LIBRARY)'
5495           LDLIBRARY='libpython$(LDVERSION).dll.a'
5496           ;;
5497+    MINGW*)
5498+          LDLIBRARY='libpython$(LDVERSION).a'
5499+          ;;
5500   esac
5501 fi
5502
5503@@ -1618,6 +1729,10 @@ AC_SUBST(LINK_PYTHON_OBJS)
5504 AC_SUBST(AR)
5505 AC_CHECK_TOOLS(AR, ar aal, ar)
5506
5507+# windres program
5508+AC_SUBST(WINDRES)
5509+AC_CHECK_TOOL(WINDRES, windres)
5510+
5511 # tweak ARFLAGS only if the user didn't set it on the command line
5512 AC_SUBST(ARFLAGS)
5513 if test -z "$ARFLAGS"
5514@@ -2498,6 +2613,53 @@ then
5515 	BASECFLAGS="$BASECFLAGS $ac_arch_flags"
5516 fi
5517
5518+dnl NOTE:
5519+dnl - GCC 4.4+ for mingw* require and use posix threads(pthreads-w32)
5520+dnl - Host may contain installed pthreads-w32.
5521+dnl - On windows platform only NT-thread model is supported.
5522+dnl To avoid miss detection scipt first will check for NT-thread model
5523+dnl and if is not found will try to detect build options for pthread
5524+dnl model. Autodetection could be overiden if variable with_nt_threads
5525+dnl is set in "Site Configuration" (see autoconf manual).
5526+dnl If NT-thread model is enabled script skips some checks that
5527+dnl impact build process. When a new functionality is added, developers
5528+dnl are responsible to update configure script to avoid thread models
5529+dnl to be mixed.
5530+
5531+AC_MSG_CHECKING([for --with-nt-threads])
5532+AC_ARG_WITH(nt-threads,
5533+            AS_HELP_STRING([--with-nt-threads], [build with windows threads (default is system-dependent)]),
5534+[
5535+	case $withval in
5536+	no)	with_nt_threads=no;;
5537+	yes)	with_nt_threads=yes;;
5538+	*)	with_nt_threads=yes;;
5539+	esac
5540+], [
5541+	case $host in
5542+		*-*-mingw*) with_nt_threads=yes;;
5543+		*) with_nt_threads=no;;
5544+	esac
5545+])
5546+AC_MSG_RESULT([$with_nt_threads])
5547+
5548+if test $with_nt_threads = yes ; then
5549+AC_MSG_CHECKING([whether linking with nt-threads work])
5550+AC_LINK_IFELSE([
5551+    AC_LANG_PROGRAM([[#include <process.h>]],[[_beginthread(0, 0, 0);]])
5552+  ],
5553+  [AC_MSG_RESULT([yes])],
5554+  [AC_MSG_ERROR([failed to link with nt-threads])])
5555+fi
5556+
5557+if test $with_nt_threads = yes ; then
5558+  dnl temporary default flag to avoid additional pthread checks
5559+  dnl and initilize other ac..thread flags to no
5560+  ac_cv_pthread_is_default=no
5561+  ac_cv_kthread=no
5562+  ac_cv_pthread=no
5563+  dnl ac_cv_kpthread is set to no if default is yes (see below)
5564+else
5565 # On some compilers, pthreads are available without further options
5566 # (e.g. MacOS X). On some of these systems, the compiler will not
5567 # complain if unaccepted options are passed (e.g. gcc on Mac OS X).
5568@@ -2609,6 +2771,8 @@ int main(void){
5569 CC="$ac_save_cc"])
5570 fi
5571
5572+fi
5573+
5574 # If we have set a CC compiler flag for thread support then
5575 # check if it works for CXX, too.
5576 ac_cv_cxx_thread=no
5577@@ -2629,6 +2793,10 @@ elif test "$ac_cv_pthread" = "yes"
5578 then
5579   CXX="$CXX -pthread"
5580   ac_cv_cxx_thread=yes
5581+elif test $with_nt_threads = yes
5582+then
5583+  dnl set to always to skip extra pthread check below
5584+  ac_cv_cxx_thread=always
5585 fi
5586
5587 if test $ac_cv_cxx_thread = yes
5588@@ -2663,11 +2831,11 @@ AC_DEFINE(STDC_HEADERS, 1, [Define to 1 if you have the ANSI C header files.])
5589
5590 # checks for header files
5591 AC_CHECK_HEADERS([ \
5592-  alloca.h asm/types.h bluetooth.h conio.h crypt.h direct.h dlfcn.h endian.h errno.h fcntl.h grp.h \
5593+  alloca.h asm/types.h bluetooth.h conio.h crypt.h direct.h endian.h errno.h fcntl.h grp.h \
5594   ieeefp.h io.h langinfo.h libintl.h libutil.h linux/auxvec.h sys/auxv.h linux/memfd.h \
5595   linux/random.h linux/soundcard.h \
5596-  linux/tipc.h linux/wait.h netdb.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \
5597-  sched.h setjmp.h shadow.h signal.h spawn.h stropts.h sys/audioio.h sys/bsdtty.h sys/devpoll.h \
5598+  linux/tipc.h linux/wait.h netdb.h netinet/in.h netpacket/packet.h poll.h process.h pty.h \
5599+  setjmp.h shadow.h signal.h spawn.h stropts.h sys/audioio.h sys/bsdtty.h sys/devpoll.h \
5600   sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \
5601   sys/loadavg.h sys/lock.h sys/memfd.h sys/mkdev.h sys/mman.h sys/modem.h sys/param.h sys/poll.h \
5602   sys/random.h sys/resource.h sys/select.h sys/sendfile.h sys/socket.h sys/soundcard.h sys/stat.h \
5603@@ -2675,9 +2843,24 @@ AC_CHECK_HEADERS([ \
5604   sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h sys/xattr.h sysexits.h syslog.h \
5605   termios.h util.h utime.h utmp.h \
5606 ])
5607+
5608+case $host in
5609+  *-*-mingw*) ;;
5610+  *) AC_CHECK_HEADERS([dlfcn.h]);;
5611+esac
5612+
5613+
5614 AC_HEADER_DIRENT
5615 AC_HEADER_MAJOR
5616
5617+# If using nt threads, don't look for pthread.h or thread.h
5618+if test "x$with_nt_threads" = xno ; then
5619+AC_HEADER_STDC
5620+AC_CHECK_HEADERS(pthread.h sched.h thread.h)
5621+AC_HEADER_DIRENT
5622+AC_HEADER_MAJOR
5623+fi
5624+
5625 # bluetooth/bluetooth.h has been known to not compile with -std=c99.
5626 # http://permalink.gmane.org/gmane.linux.bluez.kernel/22294
5627 SAVE_CFLAGS=$CFLAGS
5628@@ -2852,6 +3035,10 @@ dnl LFS does not work with Emscripten 3.1
5629 AS_CASE([$ac_sys_system],
5630   [Emscripten], [have_largefile_support="no"]
5631 )
5632+dnl Activate on windows platforms (32&64-bit) where off_t(4) < fpos_t(8)
5633+AS_CASE([$ac_sys_system],
5634+  [MINGW], [have_largefile_support="yes"]
5635+)
5636 AS_VAR_IF([have_largefile_support], [yes], [
5637   AC_DEFINE(HAVE_LARGEFILE_SUPPORT, 1,
5638   [Defined to enable large file support when an off_t is bigger than a long
5639@@ -2882,6 +3069,10 @@ elif test "$ac_cv_pthread" = "yes"
5640 then CC="$CC -pthread"
5641 fi
5642
5643+if test $with_nt_threads = yes ; then
5644+  dnl skip check for pthread_t if NT-thread model is enabled
5645+  ac_cv_have_pthread_t=skip
5646+else
5647 AC_CACHE_CHECK([for pthread_t], [ac_cv_have_pthread_t], [
5648 AC_COMPILE_IFELSE([
5649   AC_LANG_PROGRAM([[#include <pthread.h>]], [[pthread_t x; x = *(pthread_t*)0;]])
5650@@ -2913,7 +3104,7 @@ AS_VAR_IF([ac_cv_pthread_key_t_is_arithmetic_type], [yes], [
5651     AC_DEFINE(PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT, 1,
5652               [Define if pthread_key_t is compatible with int.])
5653 ])
5654-
5655+fi
5656 CC="$ac_save_cc"
5657
5658 AC_SUBST(OTHER_LIBTOOL_OPT)
5659@@ -3089,6 +3280,9 @@ if test -z "$SHLIB_SUFFIX"; then
5660 	CYGWIN*)   SHLIB_SUFFIX=.dll;;
5661 	*)	   SHLIB_SUFFIX=.so;;
5662 	esac
5663+	case $host_os in
5664+	mingw*)    SHLIB_SUFFIX=.pyd;;
5665+	esac
5666 fi
5667 AC_MSG_RESULT($SHLIB_SUFFIX)
5668
5669@@ -3218,6 +3412,10 @@ then
5670 	CYGWIN*)
5671 		LDSHARED="gcc -shared -Wl,--enable-auto-image-base"
5672 		LDCXXSHARED="g++ -shared -Wl,--enable-auto-image-base";;
5673+  MINGW*)
5674+    LDSHARED='$(CC) -shared -Wl,--enable-auto-image-base'
5675+    LDCXXSHARED='$(CXX) -shared -Wl,--enable-auto-image-base'
5676+    ;;
5677 	*)	LDSHARED="ld";;
5678 	esac
5679 fi
5680@@ -3341,6 +3539,11 @@ then
5681 	VxWorks*)
5682 		LINKFORSHARED='-Wl,-export-dynamic';;
5683 	esac
5684+	case $host in
5685+	*-*-mingw*)
5686+		# for https://bugs.python.org/issue40458 on MINGW
5687+		LINKFORSHARED="-Wl,--stack,2000000";;
5688+	esac
5689 fi
5690 AC_MSG_RESULT($LINKFORSHARED)
5691
5692@@ -3385,7 +3588,12 @@ AC_MSG_RESULT($SHLIBS)
5693
5694 # checks for libraries
5695 AC_CHECK_LIB(sendfile, sendfile)
5696-AC_CHECK_LIB(dl, dlopen)	# Dynamic linking for SunOS/Solaris and SYSV
5697+
5698+case $host in
5699+  *-*-mingw*) ;;
5700+  *) AC_CHECK_LIB(dl, dlopen) ;;	# Dynamic linking for SunOS/Solaris and SYSV
5701+esac
5702+
5703 AC_CHECK_LIB(dld, shl_load)	# Dynamic linking for HP-UX
5704
5705
5706@@ -3448,16 +3656,30 @@ AS_VAR_IF([have_uuid], [missing], [
5707
5708 AS_VAR_IF([have_uuid], [missing], [have_uuid=no])
5709
5710+if test $with_nt_threads = yes ; then
5711+  dnl do not search for sem_init if NT-thread model is enabled
5712+  :
5713+else
5714 # 'Real Time' functions on Solaris
5715 # posix4 on Solaris 2.6
5716 # pthread (first!) on Linux
5717 AC_SEARCH_LIBS(sem_init, pthread rt posix4)
5718+fi
5719
5720 # check if we need libintl for locale functions
5721+case $host in
5722+  *-*-mingw*)
5723+  dnl Native windows build don't use libintl (see _localemodule.c).
5724+  dnl Also we don't like setup.py to add "intl" library to the list
5725+  dnl when build _locale module.
5726+  ;;
5727+  *)
5728 AC_CHECK_LIB(intl, textdomain,
5729 	[AC_DEFINE(WITH_LIBINTL, 1,
5730 	[Define to 1 if libintl is needed for locale functions.])
5731         LIBS="-lintl $LIBS"])
5732+  ;;
5733+esac
5734
5735 # checks for system dependent C++ extensions support
5736 case "$ac_sys_system" in
5737@@ -3645,7 +3867,7 @@ else
5738 fi
5739
5740 if test "$with_system_ffi" = "yes" && test -n "$PKG_CONFIG"; then
5741-    LIBFFI_INCLUDEDIR="`"$PKG_CONFIG" libffi --cflags-only-I 2>/dev/null | sed -e 's/^-I//;s/ *$//'`"
5742+    LIBFFI_INCLUDEDIR="`"$PKG_CONFIG" libffi --cflags-only-I 2>/dev/null | sed -e 's/^-I//;s/ .*$//'`"
5743 else
5744     LIBFFI_INCLUDEDIR=""
5745 fi
5746@@ -3780,6 +4002,12 @@ AS_CASE([$ac_sys_system],
5747   [OSSAUDIODEV_LIBS=""]
5748 )
5749
5750+dnl On MINGW, you need to link against ws2_32 and iphlpapi for sockets to work
5751+AS_CASE([$ac_sys_system],
5752+  [MINGW], [SOCKET_LIBS="-lws2_32 -liphlpapi"],
5753+  [SOCKET_LIBS=""]
5754+)
5755+
5756 dnl detect sqlite3 from Emscripten emport
5757 PY_CHECK_EMSCRIPTEN_PORT([LIBSQLITE3], [-sUSE_SQLITE3])
5758
5759@@ -4042,6 +4270,18 @@ AS_VAR_IF([with_dbmliborder], [error], [
5760 ])
5761 AC_MSG_RESULT($with_dbmliborder)
5762
5763+case $host in
5764+  *-*-mingw*)
5765+    CFLAGS_NODIST="$CFLAGS_NODIST -D_WIN32_WINNT=0x0602";;
5766+esac
5767+
5768+# Determine if windows modules should be used.
5769+AC_SUBST(USE_WIN32_MODULE)
5770+USE_WIN32_MODULE='#'
5771+case $host in
5772+  *-*-mingw*) USE_WIN32_MODULE=;;
5773+esac
5774+
5775 # Templates for things AC_DEFINEd more than once.
5776 # For a single AC_DEFINE, no template is needed.
5777 AH_TEMPLATE(_REENTRANT,
5778@@ -4076,6 +4316,11 @@ then
5779         CXX="$CXX -pthread"
5780     fi
5781     posix_threads=yes
5782+elif test $with_nt_threads = yes
5783+then
5784+    posix_threads=no
5785+    AC_DEFINE(NT_THREADS, 1,
5786+        [Define to 1 if you want to use native NT threads])
5787 else
5788     if test ! -z "$withval" -a -d "$withval"
5789     then LDFLAGS="$LDFLAGS -L$withval"
5790@@ -4450,11 +4695,14 @@ AC_MSG_RESULT($with_freelists)
5791 AC_MSG_CHECKING(for --with-c-locale-coercion)
5792 AC_ARG_WITH(c-locale-coercion,
5793             AS_HELP_STRING([--with-c-locale-coercion],
5794-              [enable C locale coercion to a UTF-8 based locale (default is yes)]))
5795+              [enable C locale coercion to a UTF-8 based locale (default is yes on Unix, no on Windows)]))
5796
5797 if test -z "$with_c_locale_coercion"
5798 then
5799-    with_c_locale_coercion="yes"
5800+    case $host in
5801+      *-*-mingw*) with_c_locale_coercion="no";;
5802+      *) with_c_locale_coercion="yes";;
5803+    esac
5804 fi
5805 if test "$with_c_locale_coercion" != "no"
5806 then
5807@@ -4555,12 +4803,36 @@ then
5808 	fi
5809 	;;
5810 	esac
5811+	case $host in
5812+	*-*-mingw*)
5813+    DYNLOADFILE="dynload_win.o"
5814+    extra_machdep_objs="$extra_machdep_objs PC/dl_nt.o"
5815+    CFLAGS_NODIST="$CFLAGS_NODIST -DPY3_DLLNAME='L\"$DLLLIBRARY\"'"
5816+    case $host in
5817+        i686*)
5818+                CFLAGS_NODIST="$CFLAGS_NODIST -DMS_DLL_ID='\"${VERSION}-32\"'"
5819+            ;;
5820+        armv7*)
5821+                CFLAGS_NODIST="$CFLAGS_NODIST -DMS_DLL_ID='\"${VERSION}-arm32\"'"
5822+            ;;
5823+        aarch64*)
5824+                CFLAGS_NODIST="$CFLAGS_NODIST -DMS_DLL_ID='\"${VERSION}-arm64\"'"
5825+            ;;
5826+            *)
5827+                CFLAGS_NODIST="$CFLAGS_NODIST -DMS_DLL_ID='\"$VERSION\"'"
5828+            ;;
5829+      esac
5830+    ;;
5831+	esac
5832 fi
5833 AC_MSG_RESULT($DYNLOADFILE)
5834 if test "$DYNLOADFILE" != "dynload_stub.o"
5835 then
5836+  have_dynamic_loading=yes
5837 	AC_DEFINE(HAVE_DYNAMIC_LOADING, 1,
5838         [Defined when any dynamic module loading is enabled.])
5839+else
5840+  have_dynamic_loading=no
5841 fi
5842
5843 # MACHDEP_OBJS can be set to platform-specific object files needed by Python
5844@@ -4580,13 +4852,22 @@ else
5845 fi
5846
5847 # checks for library functions
5848+if test $with_nt_threads = yes ; then
5849+  dnl GCC(mingw) 4.4+ require and use posix threads(pthreads-w32)
5850+  dnl and host may contain installed pthreads-w32.
5851+  dnl Skip checks for some functions declared in pthreads-w32 if
5852+  dnl NT-thread model is enabled.
5853+  ac_cv_func_pthread_kill=skip
5854+  ac_cv_func_sem_open=skip
5855+  ac_cv_func_sched_setscheduler=skip
5856+fi
5857 AC_CHECK_FUNCS([ \
5858   accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \
5859   copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \
5860   faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \
5861   fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \
5862   gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \
5863-  getgrnam_r getgrouplist getgroups gethostname getitimer getloadavg getlogin \
5864+  getgrnam_r getgrouplist getgroups getitimer getloadavg getlogin \
5865   getpeername getpgid getpid getppid getpriority _getpty \
5866   getpwent getpwnam_r getpwuid getpwuid_r getresgid getresuid getrusage getsid getspent \
5867   getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \
5868@@ -4599,7 +4880,7 @@ AC_CHECK_FUNCS([ \
5869   sched_setparam sched_setscheduler sem_clockwait sem_getvalue sem_open \
5870   sem_timedwait sem_unlink sendfile setegid seteuid setgid sethostname \
5871   setitimer setlocale setpgid setpgrp setpriority setregid setresgid \
5872-  setresuid setreuid setsid setuid setvbuf shutdown sigaction sigaltstack \
5873+  setresuid setreuid setsid setuid setvbuf sigaction sigaltstack \
5874   sigfillset siginterrupt sigpending sigrelse sigtimedwait sigwait \
5875   sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \
5876   sysconf system tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \
5877@@ -4829,7 +5110,13 @@ PKG_CHECK_MODULES([LIBLZMA], [liblzma], [have_liblzma=yes], [
5878 ])
5879
5880 dnl PY_CHECK_NETDB_FUNC(FUNCTION)
5881-AC_DEFUN([PY_CHECK_NETDB_FUNC], [PY_CHECK_FUNC([$1], [#include <netdb.h>])])
5882+AC_DEFUN([PY_CHECK_NETDB_FUNC], [PY_CHECK_FUNC([$1], [
5883+#ifdef _WIN32
5884+  #include <winsock.h>
5885+#else
5886+  #include <netdb.h>
5887+#endif
5888+])])
5889
5890 PY_CHECK_NETDB_FUNC([hstrerror])
5891 dnl not available in WASI yet
5892@@ -4838,13 +5125,19 @@ PY_CHECK_NETDB_FUNC([getservbyport])
5893 PY_CHECK_NETDB_FUNC([gethostbyname])
5894 PY_CHECK_NETDB_FUNC([gethostbyaddr])
5895 PY_CHECK_NETDB_FUNC([getprotobyname])
5896+PY_CHECK_NETDB_FUNC([gethostname])
5897+PY_CHECK_NETDB_FUNC([shutdown])
5898
5899 dnl PY_CHECK_SOCKET_FUNC(FUNCTION)
5900 AC_DEFUN([PY_CHECK_SOCKET_FUNC], [PY_CHECK_FUNC([$1], [
5901+#ifdef _WIN32
5902+#include <ws2tcpip.h>
5903+#else
5904 #include <sys/types.h>
5905 #include <sys/socket.h>
5906 #include <netinet/in.h>
5907 #include <arpa/inet.h>
5908+#endif
5909 ])])
5910
5911 PY_CHECK_SOCKET_FUNC([inet_aton])
5912@@ -4945,6 +5238,9 @@ WITH_SAVE_ENV([
5913   ])
5914 ])
5915
5916+case $host in
5917+  *-*-mingw*) ;;
5918+  *)
5919 AC_CHECK_FUNCS(clock_gettime, [], [
5920     AC_CHECK_LIB(rt, clock_gettime, [
5921         LIBS="$LIBS -lrt"
5922@@ -4965,6 +5261,8 @@ AC_CHECK_FUNCS(clock_settime, [], [
5923         AC_DEFINE(HAVE_CLOCK_SETTIME, 1)
5924     ])
5925 ])
5926+  ;;
5927+esac
5928
5929 AC_CHECK_FUNCS(clock_nanosleep, [], [
5930     AC_CHECK_LIB(rt, clock_nanosleep, [
5931@@ -5163,18 +5461,33 @@ if test $ac_cv_header_time_altzone = yes; then
5932   AC_DEFINE(HAVE_ALTZONE, 1, [Define this if your time.h defines altzone.])
5933 fi
5934
5935+AC_CHECK_HEADERS([ws2tcpip.h])
5936 AC_CACHE_CHECK([for addrinfo], [ac_cv_struct_addrinfo],
5937-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <netdb.h>]], [[struct addrinfo a]])],
5938+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
5939+#ifdef HAVE_WS2TCPIP_H
5940+#  include <ws2tcpip.h>
5941+#else
5942+#  include <netdb.h>
5943+#endif]],
5944+    [[struct addrinfo a]])],
5945   [ac_cv_struct_addrinfo=yes],
5946   [ac_cv_struct_addrinfo=no]))
5947 if test $ac_cv_struct_addrinfo = yes; then
5948-	AC_DEFINE(HAVE_ADDRINFO, 1, [struct addrinfo (netdb.h)])
5949+	AC_DEFINE(HAVE_ADDRINFO, 1, [struct addrinfo])
5950 fi
5951
5952 AC_CACHE_CHECK([for sockaddr_storage], [ac_cv_struct_sockaddr_storage],
5953 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
5954-#		include <sys/types.h>
5955-#		include <sys/socket.h>]], [[struct sockaddr_storage s]])],
5956+#ifdef HAVE_WS2TCPIP_H
5957+#include <ws2tcpip.h>
5958+#endif
5959+#ifdef HAVE_SYS_TYPES_H
5960+#include <sys/types.h>
5961+#endif
5962+#ifdef HAVE_SYS_SOCKET_H
5963+#include <sys/socket.h>
5964+#endif]],
5965+    [[struct sockaddr_storage s]])],
5966   [ac_cv_struct_sockaddr_storage=yes],
5967   [ac_cv_struct_sockaddr_storage=no]))
5968 if test $ac_cv_struct_sockaddr_storage = yes; then
5969@@ -5508,6 +5821,10 @@ dnl actually works.  For FreeBSD versions <= 7.2,
5970 dnl the kernel module that provides POSIX semaphores
5971 dnl isn't loaded by default, so an attempt to call
5972 dnl sem_open results in a 'Signal 12' error.
5973+if test $with_nt_threads = yes ; then
5974+  dnl skip posix semaphores test if NT-thread model is enabled
5975+  ac_cv_posix_semaphores_enabled=no
5976+fi
5977 AC_CACHE_CHECK([whether POSIX semaphores are enabled], [ac_cv_posix_semaphores_enabled],
5978   AC_RUN_IFELSE([
5979     AC_LANG_SOURCE([
5980@@ -5541,6 +5858,14 @@ AS_VAR_IF([ac_cv_posix_semaphores_enabled], [no], [
5981 ])
5982
5983 dnl Multiprocessing check for broken sem_getvalue
5984+if test $with_nt_threads = yes ; then
5985+  dnl Skip test if NT-thread model is enabled.
5986+  dnl NOTE the test case below fail for pthreads-w32 as:
5987+  dnl - SEM_FAILED is not defined;
5988+  dnl - sem_open is a stub;
5989+  dnl - sem_getvalue work(!).
5990+  ac_cv_broken_sem_getvalue=skip
5991+fi
5992 AC_CACHE_CHECK([for broken sem_getvalue], [ac_cv_broken_sem_getvalue],
5993   AC_RUN_IFELSE([
5994     AC_LANG_SOURCE([
5995@@ -5577,7 +5902,10 @@ AS_VAR_IF([ac_cv_broken_sem_getvalue], [yes], [
5996   )
5997 ])
5998
5999-AC_CHECK_DECLS([RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND, RTLD_MEMBER], [], [], [[#include <dlfcn.h>]])
6000+case $host in
6001+  *-*-mingw*) ;;
6002+  *) AC_CHECK_DECLS([RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND, RTLD_MEMBER], [], [], [[#include <dlfcn.h>]]);;
6003+esac
6004
6005 # determine what size digit to use for Python's longs
6006 AC_MSG_CHECKING([digit size for Python's longs])
6007@@ -5664,6 +5992,71 @@ esac
6008 # check for endianness
6009 AC_C_BIGENDIAN
6010
6011+AC_SUBST(PYD_PLATFORM_TAG)
6012+# Special case of PYD_PLATFORM_TAG with python build with mingw.
6013+# Python can with compiled with clang or gcc and linked
6014+# to msvcrt or ucrt. To avoid conflicts between them
6015+# we are selecting the extension as based on the compiler
6016+# and the runtime they link to
6017+#   gcc + x86_64 + msvcrt = cp{version number}-x86_64
6018+#   gcc + i686 + msvcrt = cp{version number}-i686
6019+#   gcc + x86_64 + ucrt = cp{version number}-x86_64-ucrt
6020+#   clang + x86_64 + ucrt = cp{version number}-x86_64-clang
6021+#   clang + i686 + ucrt = cp{version number}-i686-clang
6022+
6023+PYD_PLATFORM_TAG=""
6024+case $host in
6025+  *-*-mingw*)
6026+    # check if we are linking to ucrt
6027+    AC_MSG_CHECKING(whether linking to ucrt)
6028+    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
6029+    #include <stdio.h>
6030+    #ifndef _UCRT
6031+        #error no ucrt
6032+    #endif
6033+    int main(){ return 0; }
6034+    ]])],[linking_to_ucrt=yes],[linking_to_ucrt=no])
6035+    AC_MSG_RESULT($linking_to_ucrt)
6036+    ;;
6037+esac
6038+case $host_os in
6039+    mingw*)
6040+  AC_MSG_CHECKING(PYD_PLATFORM_TAG)
6041+  case $host in
6042+  i686-*-mingw*)
6043+    if test -n "${cc_is_clang}"; then
6044+      # it is CLANG32
6045+      PYD_PLATFORM_TAG="mingw_i686_clang"
6046+    else
6047+      if test $linking_to_ucrt = no; then
6048+        PYD_PLATFORM_TAG="mingw_i686"
6049+      else
6050+        PYD_PLATFORM_TAG="mingw_i686_ucrt"
6051+      fi
6052+    fi
6053+    ;;
6054+  x86_64-*-mingw*)
6055+    if test -n "${cc_is_clang}"; then
6056+      # it is CLANG64
6057+      PYD_PLATFORM_TAG="mingw_x86_64_clang"
6058+    else
6059+      if test $linking_to_ucrt = no; then
6060+        PYD_PLATFORM_TAG="mingw_x86_64"
6061+      else
6062+        PYD_PLATFORM_TAG="mingw_x86_64_ucrt"
6063+      fi
6064+    fi
6065+    ;;
6066+  aarch64-*-mingw*)
6067+    PYD_PLATFORM_TAG+="mingw_aarch64"
6068+    ;;
6069+  armv7-*-mingw*)
6070+    PYD_PLATFORM_TAG+="mingw_armv7"
6071+    ;;
6072+  esac
6073+  AC_MSG_RESULT($PYD_PLATFORM_TAG)
6074+esac
6075+
6076 # ABI version string for Python extension modules.  This appears between the
6077 # periods in shared library file names, e.g. foo.<SOABI>.so.  It is calculated
6078 # from the following attributes which affect the ABI of this Python build (in
6079@@ -5696,7 +6089,12 @@ if test "$Py_DEBUG" = 'true' -a "$with_trace_refs" != "yes"; then
6080 fi
6081
6082 AC_SUBST(EXT_SUFFIX)
6083-EXT_SUFFIX=.${SOABI}${SHLIB_SUFFIX}
6084+VERSION_NO_DOTS=$(echo $LDVERSION | tr -d .)
6085+if test -n "${PYD_PLATFORM_TAG}"; then
6086+  EXT_SUFFIX=".cp${VERSION_NO_DOTS}-${PYD_PLATFORM_TAG}${SHLIB_SUFFIX}"
6087+else
6088+  EXT_SUFFIX=.${SOABI}${SHLIB_SUFFIX}
6089+fi
6090
6091 AC_MSG_CHECKING(LDVERSION)
6092 LDVERSION='$(VERSION)$(ABIFLAGS)'
6093@@ -5704,7 +6102,7 @@ AC_MSG_RESULT($LDVERSION)
6094
6095 # On Android and Cygwin the shared libraries must be linked with libpython.
6096 AC_SUBST(LIBPYTHON)
6097-if test -n "$ANDROID_API_LEVEL" -o "$MACHDEP" = "cygwin"; then
6098+if test -n "$ANDROID_API_LEVEL" -o "$MACHDEP" = "cygwin" -o "$MACHDEP" = "win32"; then
6099   LIBPYTHON="-lpython${VERSION}${ABIFLAGS}"
6100 else
6101   LIBPYTHON=''
6102@@ -6073,11 +6471,16 @@ then
6103   [Define if you have struct stat.st_mtimensec])
6104 fi
6105
6106+if test -n "$PKG_CONFIG"; then
6107+    NCURSESW_INCLUDEDIR="`"$PKG_CONFIG" ncursesw --cflags-only-I 2>/dev/null | sed -e 's/^-I//;s/ .*$//'`"
6108+else
6109+    NCURSESW_INCLUDEDIR=""
6110+fi
6111+AC_SUBST(NCURSESW_INCLUDEDIR)
6112+
6113 # first curses header check
6114 ac_save_cppflags="$CPPFLAGS"
6115-if test "$cross_compiling" = no; then
6116-  CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw"
6117-fi
6118+CPPFLAGS="$CPPFLAGS -I$NCURSESW_INCLUDEDIR"
6119
6120 AC_CHECK_HEADERS(curses.h ncurses.h)
6121
6122@@ -6243,7 +6646,10 @@ fi
6123
6124 AC_CHECK_TYPE(socklen_t,,
6125   AC_DEFINE(socklen_t,int,
6126-            [Define to `int' if <sys/socket.h> does not define.]),[
6127+            [Define to `int' if <sys/socket.h> or <ws2tcpip.h> does not define.]),[
6128+#ifdef HAVE_WS2TCPIP_H
6129+#include <ws2tcpip.h>
6130+#endif
6131 #ifdef HAVE_SYS_TYPES_H
6132 #include <sys/types.h>
6133 #endif
6134@@ -6333,6 +6739,27 @@ do
6135   THREADHEADERS="$THREADHEADERS \$(srcdir)/$h"
6136 done
6137
6138+case $host in
6139+  *-*-mingw*)
6140+    dnl Required for windows builds as Objects/exceptions.c require
6141+    dnl "errmap.h" from $srcdir/PC.
6142+    dnl Note we cannot use BASECPPFLAGS as autogenerated pyconfig.h
6143+    dnl has to be before customized located in ../PC.
6144+    dnl (-I. at end is workaround for setup.py logic)
6145+    CPPFLAGS="-I\$(srcdir)/PC $CPPFLAGS -I."
6146+    ;;
6147+esac
6148+
6149+dnl Python interpreter main program for frozen scripts
6150+AC_SUBST(PYTHON_OBJS_FROZENMAIN)
6151+PYTHON_OBJS_FROZENMAIN="Python/frozenmain.o"
6152+case $host in
6153+  *-*-mingw*)
6154+    dnl 'PC/frozen_dllmain.c' - not yet
6155+    PYTHON_OBJS_FROZENMAIN=
6156+    ;;
6157+esac
6158+
6159 AC_SUBST(SRCDIRS)
6160 SRCDIRS="\
6161   Modules \
6162@@ -6354,6 +6781,10 @@ SRCDIRS="\
6163   Python \
6164   Python/frozen_modules \
6165   Python/deepfreeze"
6166+case $host in
6167+  *-*-mingw*) SRCDIRS="$SRCDIRS PC";;
6168+esac
6169+
6170 AC_MSG_CHECKING(for build directories)
6171 for dir in $SRCDIRS; do
6172     if test ! -d $dir; then
6173@@ -6362,6 +6793,38 @@ for dir in $SRCDIRS; do
6174 done
6175 AC_MSG_RESULT(done)
6176
6177+# For mingw build need additional library for linking
6178+case $host in
6179+  *-*-mingw*)
6180+    LIBS="$LIBS -lversion -lshlwapi -lpathcch -lbcrypt"
6181+    AC_PROG_AWK
6182+    if test "$AWK" = "gawk"; then
6183+      awk_extra_flag="--non-decimal-data"
6184+    fi
6185+    AC_MSG_CHECKING([FIELD3])
6186+    FIELD3=$($AWK $awk_extra_flag '\
6187+      /^#define PY_RELEASE_LEVEL_/             {levels[$2]=$3}    \
6188+      /^#define PY_MICRO_VERSION[[:space:]]+/  {micro=$3}         \
6189+      /^#define PY_RELEASE_LEVEL[[:space:]]+/  {level=levels[$3]} \
6190+      /^#define PY_RELEASE_SERIAL[[:space:]]+/ {serial=$3}        \
6191+      END {print micro * 1000 + level * 10 + serial}' \
6192+      $srcdir/Include/patchlevel.h
6193+    )
6194+
6195+    AC_MSG_RESULT([${FIELD3}])
6196+    RCFLAGS="$RCFLAGS -DFIELD3=$FIELD3 -O COFF"
6197+
6198+    case $host in
6199+      i686*)  RCFLAGS="$RCFLAGS --target=pe-i386" ;;
6200+      x86_64*)  RCFLAGS="$RCFLAGS --target=pe-x86-64" ;;
6201+      *) ;;
6202+    esac
6203+  ;;
6204+  *)
6205+  ;;
6206+esac
6207+AC_SUBST(RCFLAGS)
6208+
6209 # Availability of -O2:
6210 AC_CACHE_CHECK([for -O2], [ac_cv_compile_o2], [
6211 saved_cflags="$CFLAGS"
6212@@ -6971,7 +7434,6 @@ PY_STDLIB_MOD_SIMPLE([_json])
6213 PY_STDLIB_MOD_SIMPLE([_lsprof])
6214 PY_STDLIB_MOD_SIMPLE([_opcode])
6215 PY_STDLIB_MOD_SIMPLE([_pickle])
6216-PY_STDLIB_MOD_SIMPLE([_posixsubprocess])
6217 PY_STDLIB_MOD_SIMPLE([_queue])
6218 PY_STDLIB_MOD_SIMPLE([_random])
6219 PY_STDLIB_MOD_SIMPLE([select])
6220@@ -6982,7 +7444,7 @@ PY_STDLIB_MOD_SIMPLE([_zoneinfo])
6221
6222 dnl multiprocessing modules
6223 PY_STDLIB_MOD([_multiprocessing],
6224-  [], [test "$ac_cv_func_sem_unlink" = "yes"],
6225+  [], [test "$ac_cv_func_sem_unlink" = "yes" -o "$MACHDEP" = "win32"],
6226   [-I\$(srcdir)/Modules/_multiprocessing])
6227 PY_STDLIB_MOD([_posixshmem],
6228   [], [test "$have_posix_shmem" = "yes"],
6229@@ -7002,11 +7464,15 @@ PY_STDLIB_MOD([fcntl],
6230   [], [test "$ac_cv_header_sys_ioctl_h" = "yes" -a "$ac_cv_header_fcntl_h" = "yes"],
6231   [], [$FCNTL_LIBS])
6232 PY_STDLIB_MOD([mmap],
6233-  [], [test "$ac_cv_header_sys_mman_h" = "yes" -a "$ac_cv_header_sys_stat_h" = "yes"])
6234+  [], m4_flatten([test "$ac_cv_header_sys_mman_h" = "yes"
6235+                    -a "$ac_cv_header_sys_stat_h" = "yes"
6236+                    -o "$MACHDEP" = "win32"]))
6237 PY_STDLIB_MOD([_socket],
6238   [], m4_flatten([test "$ac_cv_header_sys_socket_h" = "yes"
6239                     -a "$ac_cv_header_sys_types_h" = "yes"
6240-                    -a "$ac_cv_header_netinet_in_h" = "yes"]))
6241+                    -a "$ac_cv_header_netinet_in_h" = "yes"
6242+                    -o "$MACHDEP" = "win32"]),
6243+  [], [$SOCKET_LIBS])
6244
6245 dnl platform specific extensions
6246 PY_STDLIB_MOD([grp], [], [test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes])
6247@@ -7021,6 +7487,7 @@ PY_STDLIB_MOD([_scproxy],
6248 PY_STDLIB_MOD([spwd], [], [test "$ac_cv_func_getspent" = yes -o "$ac_cv_func_getspnam" = yes])
6249 PY_STDLIB_MOD([syslog], [], [test "$ac_cv_header_syslog_h" = yes])
6250 PY_STDLIB_MOD([termios], [], [test "$ac_cv_header_termios_h" = yes])
6251+PY_STDLIB_MOD([_posixsubprocess], [], [test "$MACHDEP" != "win32"])
6252
6253 dnl _elementtree loads libexpat via CAPI hook in pyexpat
6254 PY_STDLIB_MOD([pyexpat], [], [], [$LIBEXPAT_CFLAGS], [$LIBEXPAT_LDFLAGS])
6255@@ -7083,25 +7550,35 @@ PY_STDLIB_MOD([_lzma], [], [test "$have_liblzma" = yes],
6256
6257 dnl OpenSSL bindings
6258 PY_STDLIB_MOD([_ssl], [], [test "$ac_cv_working_openssl_ssl" = yes],
6259-  [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $OPENSSL_LIBS])
6260+  [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $OPENSSL_LIBS -lws2_32])
6261 PY_STDLIB_MOD([_hashlib], [], [test "$ac_cv_working_openssl_hashlib" = yes],
6262   [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS])
6263
6264+dnl windows specific modules
6265+PY_STDLIB_MOD([msvcrt], [test "$MACHDEP" = "win32"])
6266+PY_STDLIB_MOD([_winapi], [test "$MACHDEP" = "win32"])
6267+PY_STDLIB_MOD([_msi], [test "$MACHDEP" = "win32"], [], [],
6268+  [-lmsi -lcabinet -lrpcrt4])
6269+PY_STDLIB_MOD([winsound], [test "$MACHDEP" = "win32"], [], [],
6270+  [-lwinmm])
6271+PY_STDLIB_MOD([_overlapped], [test "$MACHDEP" = "win32"], [], [],
6272+  [-lws2_32])
6273+
6274 dnl test modules
6275 PY_STDLIB_MOD([_testcapi], [test "$TEST_MODULES" = yes])
6276 PY_STDLIB_MOD([_testclinic], [test "$TEST_MODULES" = yes])
6277-PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes])
6278+PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes], [], [-DPY3_DLLNAME="\"$DLLLIBRARY\""], [])
6279 PY_STDLIB_MOD([_testbuffer], [test "$TEST_MODULES" = yes])
6280-PY_STDLIB_MOD([_testimportmultiple], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes])
6281-PY_STDLIB_MOD([_testmultiphase], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes])
6282+PY_STDLIB_MOD([_testimportmultiple], [test "$TEST_MODULES" = yes], [test "$have_dynamic_loading" = yes])
6283+PY_STDLIB_MOD([_testmultiphase], [test "$TEST_MODULES" = yes], [test "$have_dynamic_loading" = yes])
6284 PY_STDLIB_MOD([_xxtestfuzz], [test "$TEST_MODULES" = yes])
6285-PY_STDLIB_MOD([_ctypes_test], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes], [], [-lm])
6286+PY_STDLIB_MOD([_ctypes_test], [test "$TEST_MODULES" = yes], [test "$have_dynamic_loading" = yes], [], [-lm])
6287
6288 dnl Limited API template modules.
6289 dnl The limited C API is not compatible with the Py_TRACE_REFS macro.
6290 dnl Emscripten does not support shared libraries yet.
6291-PY_STDLIB_MOD([xxlimited], [test "$with_trace_refs" = "no"], [test "$ac_cv_func_dlopen" = yes])
6292-PY_STDLIB_MOD([xxlimited_35], [test "$with_trace_refs" = "no"], [test "$ac_cv_func_dlopen" = yes])
6293+PY_STDLIB_MOD([xxlimited], [test "$with_trace_refs" = "no"], [test "$have_dynamic_loading" = yes])
6294+PY_STDLIB_MOD([xxlimited_35], [test "$with_trace_refs" = "no"], [test "$have_dynamic_loading" = yes])
6295
6296 # substitute multiline block, must come after last PY_STDLIB_MOD()
6297 AC_SUBST([MODULE_BLOCK])
6298diff --git a/mingw_ignorefile.txt b/mingw_ignorefile.txt
6299new file mode 100644
6300index 0000000..54093f1
6301--- /dev/null
6302+++ b/mingw_ignorefile.txt
6303@@ -0,0 +1,42 @@
6304+ctypes.test.test_loading.LoaderTest.test_load_dll_with_flags
6305+distutils.tests.test_bdist_dumb.BuildDumbTestCase.test_simple_built
6306+distutils.tests.test_cygwinccompiler.CygwinCCompilerTestCase.test_get_versions
6307+distutils.tests.test_util.UtilTestCase.test_change_root
6308+test.datetimetester.TestLocalTimeDisambiguation_Fast.*
6309+test.datetimetester.TestLocalTimeDisambiguation_Pure.*
6310+test.test_cmath.CMathTests.test_specific_values
6311+test.test_cmd_line_script.CmdLineTest.test_consistent_sys_path_for_direct_execution
6312+test.test_compileall.CommandLineTestsNoSourceEpoch.*
6313+test.test_compileall.CommandLineTestsWithSourceEpoch.*
6314+test.test_compileall.CompileallTestsWithoutSourceEpoch.*
6315+test.test_compileall.CompileallTestsWithSourceEpoch.*
6316+test.test_import.ImportTests.test_dll_dependency_import
6317+test.test_math.MathTests.*
6318+test.test_ntpath.NtCommonTest.test_import
6319+test.test_os.StatAttributeTests.test_stat_block_device
6320+test.test_os.TestScandir.test_attributes
6321+test.test_os.UtimeTests.test_large_time
6322+test.test_platform.PlatformTest.test_architecture_via_symlink
6323+test.test_regrtest.ProgramsTestCase.test_pcbuild_rt
6324+test.test_regrtest.ProgramsTestCase.test_tools_buildbot_test
6325+test.test_site._pthFileTests.*
6326+test.test_site.HelperFunctionsTests.*
6327+test.test_site.StartupImportTests.*
6328+test.test_ssl.*
6329+test.test_strptime.CalculationTests.*
6330+test.test_strptime.StrptimeTests.test_weekday
6331+test.test_strptime.TimeRETests.test_compile
6332+test.test_tools.test_i18n.Test_pygettext.test_POT_Creation_Date
6333+test.test_venv.BasicTest.*
6334+test.test_venv.EnsurePipTest.*
6335+test.test_sysconfig.TestSysConfig.test_user_similar
6336+test.test_tcl.TclTest.testLoadWithUNC
6337+# flaky
6338+test.test__xxsubinterpreters.*
6339+test.test_asyncio.test_subprocess.SubprocessProactorTests.test_stdin_broken_pipe
6340+test.test_asynchat.TestAsynchat.test_line_terminator2
6341+test.test_asyncgen.AsyncGenAsyncioTest.test_async_gen_asyncio_gc_aclose_09
6342+test.test_concurrent_futures.ThreadPoolShutdownTest.test_interpreter_shutdown
6343+test.test_asynchat.TestNotConnected.test_disallow_negative_terminator
6344+test.test_logging.SysLogHandlerTest.*
6345+test.test_logging.IPv6SysLogHandlerTest.*
6346diff --git a/mingw_smoketests.py b/mingw_smoketests.py
6347new file mode 100644
6348index 0000000..ca1f652
6349--- /dev/null
6350+++ b/mingw_smoketests.py
6351@@ -0,0 +1,358 @@
6352+#!/usr/bin/env python3
6353+# Copyright 2017 Christoph Reiter
6354+#
6355+# Permission is hereby granted, free of charge, to any person obtaining
6356+# a copy of this software and associated documentation files (the
6357+# "Software"), to deal in the Software without restriction, including
6358+# without limitation the rights to use, copy, modify, merge, publish,
6359+# distribute, sublicense, and/or sell copies of the Software, and to
6360+# permit persons to whom the Software is furnished to do so, subject to
6361+# the following conditions:
6362+#
6363+# The above copyright notice and this permission notice shall be included
6364+# in all copies or substantial portions of the Software.
6365+#
6366+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
6367+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6368+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6369+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
6370+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
6371+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
6372+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6373+
6374+"""The goal of this test suite is collect tests for update regressions
6375+and to test msys2 related modifications like for path handling.
6376+Feel free to extend.
6377+"""
6378+
6379+import os
6380+import unittest
6381+import sysconfig
6382+
6383+if os.environ.get("MSYSTEM", ""):
6384+    SEP = "/"
6385+else:
6386+    SEP = "\\"
6387+
6388+if sysconfig.is_python_build():
6389+    os.environ["PYTHONLEGACYWINDOWSDLLLOADING"] = "1"
6390+
6391+_UCRT = sysconfig.get_platform() not in ('mingw_x86_64', 'mingw_i686')
6392+
6393+
6394+class Tests(unittest.TestCase):
6395+
6396+    def test_zoneinfo(self):
6397+        # https://github.com/msys2-contrib/cpython-mingw/issues/32
6398+        import zoneinfo
6399+        self.assertTrue(any(os.path.exists(p) for p in zoneinfo.TZPATH))
6400+        zoneinfo.ZoneInfo("America/Sao_Paulo")
6401+
6402+    def test_userdir_path_sep(self):
6403+        # Make sure os.path and pathlib use the same path separators
6404+        from unittest import mock
6405+        from os.path import expanduser
6406+        from pathlib import Path
6407+
6408+        profiles = ["C:\\foo", "C:/foo"]
6409+        for profile in profiles:
6410+            with mock.patch.dict(os.environ, {"USERPROFILE": profile}):
6411+                self.assertEqual(expanduser("~"), os.path.normpath(expanduser("~")))
6412+                self.assertEqual(str(Path("~").expanduser()), expanduser("~"))
6413+                self.assertEqual(str(Path.home()), expanduser("~"))
6414+
6415+    def test_sysconfig_schemes(self):
6416+        # https://github.com/msys2/MINGW-packages/issues/9319
6417+        import sysconfig
6418+        from distutils.dist import Distribution
6419+        from distutils.command.install import install
6420+
6421+        names = ['scripts', 'purelib', 'platlib', 'data', 'include']
6422+        for scheme in ["nt", "nt_user"]:
6423+            for name in names:
6424+                c = install(Distribution({"name": "foobar"}))
6425+                c.user = (scheme == "nt_user")
6426+                c.finalize_options()
6427+                if name == "include":
6428+                    dist_path = os.path.dirname(getattr(c, "install_" + "headers"))
6429+                else:
6430+                    dist_path = getattr(c, "install_" + name)
6431+                sys_path = sysconfig.get_path(name, scheme)
6432+                self.assertEqual(dist_path, sys_path, (scheme, name))
6433+
6434+    def test_ctypes_find_library(self):
6435+        from ctypes.util import find_library
6436+        from ctypes import cdll
6437+        self.assertTrue(cdll.msvcrt)
6438+        if _UCRT:
6439+            self.assertIsNone(find_library('c'))
6440+        else:
6441+            self.assertEqual(find_library('c'), 'msvcrt.dll')
6442+
6443+    def test_ctypes_dlopen(self):
6444+        import ctypes
6445+        import sys
6446+        self.assertEqual(ctypes.RTLD_GLOBAL, 0)
6447+        self.assertEqual(ctypes.RTLD_GLOBAL,  ctypes.RTLD_LOCAL)
6448+        self.assertFalse(hasattr(sys, 'setdlopenflags'))
6449+        self.assertFalse(hasattr(sys, 'getdlopenflags'))
6450+        self.assertFalse([n for n in dir(os) if n.startswith("RTLD_")])
6451+
6452+    def test_time_no_unix_stuff(self):
6453+        import time
6454+        self.assertFalse([n for n in dir(time) if n.startswith("clock_")])
6455+        self.assertFalse([n for n in dir(time) if n.startswith("CLOCK_")])
6456+        self.assertFalse([n for n in dir(time) if n.startswith("pthread_")])
6457+        self.assertFalse(hasattr(time, 'tzset'))
6458+
6459+    def test_strftime(self):
6460+        import time
6461+        with self.assertRaises(ValueError):
6462+            time.strftime('%Y', (12345,) + (0,) * 8)
6463+
6464+    def test_sep(self):
6465+        self.assertEqual(os.sep, SEP)
6466+
6467+    def test_module_file_path(self):
6468+        import asyncio
6469+        import zlib
6470+        self.assertEqual(zlib.__file__, os.path.normpath(zlib.__file__))
6471+        self.assertEqual(asyncio.__file__, os.path.normpath(asyncio.__file__))
6472+
6473+    def test_importlib_frozen_path_sep(self):
6474+        import importlib._bootstrap_external
6475+        self.assertEqual(importlib._bootstrap_external.path_sep, SEP)
6476+
6477+    def test_os_commonpath(self):
6478+        self.assertEqual(
6479+            os.path.commonpath(
6480+                [os.path.join("C:", os.sep, "foo", "bar"),
6481+                 os.path.join("C:", os.sep, "foo")]),
6482+                 os.path.join("C:", os.sep, "foo"))
6483+
6484+    def test_pathlib(self):
6485+        import pathlib
6486+
6487+        p = pathlib.Path("foo") / pathlib.Path("foo")
6488+        self.assertEqual(str(p), os.path.normpath(p))
6489+
6490+    def test_modules_import(self):
6491+        import sqlite3
6492+        import ssl
6493+        import ctypes
6494+        import curses
6495+
6496+    def test_c_modules_import(self):
6497+        import _decimal
6498+
6499+    def test_socket_inet_ntop(self):
6500+        import socket
6501+        self.assertTrue(hasattr(socket, "inet_ntop"))
6502+
6503+    def test_socket_inet_pton(self):
6504+        import socket
6505+        self.assertTrue(hasattr(socket, "inet_pton"))
6506+
6507+    def test_multiprocessing_queue(self):
6508+        from multiprocessing import Queue
6509+        Queue(0)
6510+
6511+    #def test_socket_timout_normal_error(self):
6512+    #    import urllib.request
6513+    #    from urllib.error import URLError
6514+
6515+    #    try:
6516+    #        urllib.request.urlopen(
6517+    #            'http://localhost', timeout=0.0001).close()
6518+    #    except URLError:
6519+    #        pass
6520+
6521+    def test_threads(self):
6522+        from concurrent.futures import ThreadPoolExecutor
6523+
6524+        with ThreadPoolExecutor(1) as pool:
6525+            for res in pool.map(lambda *x: None, range(10000)):
6526+                pass
6527+
6528+    def test_sysconfig(self):
6529+        import sysconfig
6530+        # This should be able to execute without exceptions
6531+        sysconfig.get_config_vars()
6532+
6533+    def test_sqlite_enable_load_extension(self):
6534+        # Make sure --enable-loadable-sqlite-extensions is used
6535+        import sqlite3
6536+        self.assertTrue(sqlite3.Connection.enable_load_extension)
6537+
6538+    def test_venv_creation(self):
6539+        import tempfile
6540+        import venv
6541+        import subprocess
6542+        import shutil
6543+        with tempfile.TemporaryDirectory() as tmp:
6544+            builder = venv.EnvBuilder()
6545+            builder.create(tmp)
6546+            assert os.path.exists(os.path.join(tmp, "bin", "activate"))
6547+            assert os.path.exists(os.path.join(tmp, "bin", "python.exe"))
6548+            assert os.path.exists(os.path.join(tmp, "bin", "python3.exe"))
6549+            subprocess.check_call([shutil.which("bash.exe"), os.path.join(tmp, "bin", "activate")])
6550+
6551+            # This will not work in in-tree build
6552+            if not sysconfig.is_python_build():
6553+                op = subprocess.check_output(
6554+                    [
6555+                        os.path.join(tmp, "bin", "python.exe"),
6556+                        "-c",
6557+                        "print('Hello World')"
6558+                    ],
6559+                    cwd=tmp,
6560+                )
6561+                assert op.decode().strip() == "Hello World"
6562+
6563+    def test_has_mktime(self):
6564+        from time import mktime, gmtime
6565+        mktime(gmtime())
6566+
6567+    def test_platform_things(self):
6568+        import sys
6569+        import sysconfig
6570+        import platform
6571+        import importlib.machinery
6572+        self.assertEqual(sys.implementation.name, "cpython")
6573+        self.assertEqual(sys.platform, "win32")
6574+        self.assertTrue(sysconfig.get_platform().startswith("mingw"))
6575+        self.assertTrue(sysconfig.get_config_var('SOABI').startswith("cpython-"))
6576+        ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')
6577+        self.assertTrue(ext_suffix.endswith(".pyd"))
6578+        self.assertTrue("mingw" in ext_suffix)
6579+        self.assertEqual(sysconfig.get_config_var('SHLIB_SUFFIX'), ".pyd")
6580+        ext_suffixes = importlib.machinery.EXTENSION_SUFFIXES
6581+        self.assertTrue(ext_suffix in ext_suffixes)
6582+        self.assertTrue(".pyd" in ext_suffixes)
6583+        if sysconfig.get_platform().startswith('mingw_i686'):
6584+             self.assertEqual(sys.winver, ".".join(map(str, sys.version_info[:2])) + '-32')
6585+        elif sysconfig.get_platform().startswith('mingw_aarch64'):
6586+            self.assertEqual(sys.winver, ".".join(map(str, sys.version_info[:2])) + '-arm64')
6587+        elif sysconfig.get_platform().startswith('mingw_armv7'):
6588+            self.assertEqual(sys.winver, ".".join(map(str, sys.version_info[:2])) + '-arm32')
6589+        else:
6590+            self.assertEqual(sys.winver, ".".join(map(str, sys.version_info[:2])))
6591+        self.assertEqual(platform.python_implementation(), "CPython")
6592+        self.assertEqual(platform.system(), "Windows")
6593+        self.assertTrue(isinstance(sys.api_version, int) and sys.api_version > 0)
6594+
6595+    def test_sys_getpath(self):
6596+        # everything sourced from getpath.py
6597+        import sys
6598+
6599+        def assertNormpath(path):
6600+            self.assertEqual(path, os.path.normpath(path))
6601+
6602+        assertNormpath(sys.executable)
6603+        assertNormpath(sys._base_executable)
6604+        assertNormpath(sys.prefix)
6605+        assertNormpath(sys.base_prefix)
6606+        assertNormpath(sys.exec_prefix)
6607+        assertNormpath(sys.base_exec_prefix)
6608+        assertNormpath(sys.platlibdir)
6609+        assertNormpath(sys._stdlib_dir)
6610+        for p in sys.path:
6611+            assertNormpath(p)
6612+
6613+    def test_site(self):
6614+        import site
6615+
6616+        self.assertEqual(len(site.getsitepackages()), 1)
6617+
6618+    def test_c_ext_build(self):
6619+        import tempfile
6620+        import sys
6621+        import subprocess
6622+        import textwrap
6623+        from pathlib import Path
6624+
6625+        with tempfile.TemporaryDirectory() as tmppro:
6626+            subprocess.check_call([sys.executable, "-m", "ensurepip", "--user"])
6627+            with Path(tmppro, "setup.py").open("w") as f:
6628+                f.write(
6629+                    textwrap.dedent(
6630+                        """\
6631+                                    from setuptools import setup, Extension
6632+
6633+                                    setup(
6634+                                        name='cwrapper',
6635+                                        version='1.0',
6636+                                        ext_modules=[
6637+                                            Extension(
6638+                                                'cwrapper',
6639+                                                sources=['cwrapper.c']),
6640+                                        ],
6641+                                    )
6642+                                """
6643+                    )
6644+                )
6645+            with Path(tmppro, "cwrapper.c").open("w") as f:
6646+                f.write(
6647+                    textwrap.dedent(
6648+                        """\
6649+                                    #include <Python.h>
6650+                                    static PyObject *
6651+                                    helloworld(PyObject *self, PyObject *args)
6652+                                    {
6653+                                        printf("Hello World\\n");
6654+                                        Py_RETURN_NONE;
6655+                                    }
6656+                                    static PyMethodDef
6657+                                    myMethods[] = {
6658+                                        { "helloworld", helloworld, METH_NOARGS, "Prints Hello World" },
6659+                                        { NULL, NULL, 0, NULL }
6660+                                    };
6661+                                    static struct PyModuleDef cwrapper = {
6662+                                        PyModuleDef_HEAD_INIT,
6663+                                        "cwrapper",
6664+                                        "Test Module",
6665+                                        -1,
6666+                                        myMethods
6667+                                    };
6668+
6669+                                    PyMODINIT_FUNC
6670+                                    PyInit_cwrapper(void)
6671+                                    {
6672+                                        return PyModule_Create(&cwrapper);
6673+                                    }
6674+                                """
6675+                    )
6676+                )
6677+            subprocess.check_call(
6678+                [sys.executable, "-c", "import struct"],
6679+            )
6680+            subprocess.check_call(
6681+                [
6682+                    sys.executable,
6683+                    "-m",
6684+                    "pip",
6685+                    "install",
6686+                    "wheel",
6687+                ],
6688+            )
6689+            subprocess.check_call(
6690+                [
6691+                    sys.executable,
6692+                    "-m",
6693+                    "pip",
6694+                    "install",
6695+                    tmppro,
6696+                ],
6697+            )
6698+            subprocess.check_call(
6699+                [sys.executable, "-c", "import cwrapper"],
6700+            )
6701+
6702+
6703+
6704+def suite():
6705+    return unittest.TestLoader().loadTestsFromName(__name__)
6706+
6707+
6708+if __name__ == '__main__':
6709+    unittest.main(defaultTest='suite')
6710diff --git a/pyconfig.h.in b/pyconfig.h.in
6711index 75f1d90..3b89b9e 100644
6712--- a/pyconfig.h.in
6713+++ b/pyconfig.h.in
6714@@ -60,7 +60,7 @@
6715 /* Define to 1 if you have the `acosh' function. */
6716 #undef HAVE_ACOSH
6717
6718-/* struct addrinfo (netdb.h) */
6719+/* struct addrinfo */
6720 #undef HAVE_ADDRINFO
6721
6722 /* Define to 1 if you have the `alarm' function. */
6723@@ -1521,6 +1521,9 @@
6724 /* Define if mvwdelch in curses.h is an expression. */
6725 #undef MVWDELCH_IS_EXPRESSION
6726
6727+/* Define to 1 if you want to use native NT threads */
6728+#undef NT_THREADS
6729+
6730 /* Define to the address where bug reports for this package should be sent. */
6731 #undef PACKAGE_BUGREPORT
6732
6733@@ -1836,7 +1839,7 @@
6734 /* Define to `unsigned int' if <sys/types.h> does not define. */
6735 #undef size_t
6736
6737-/* Define to `int' if <sys/socket.h> does not define. */
6738+/* Define to `int' if <sys/socket.h> or <ws2tcpip.h> does not define. */
6739 #undef socklen_t
6740
6741 /* Define to `int' if <sys/types.h> doesn't define. */
6742diff --git a/setup.py b/setup.py
6743index 4f122b6..e4f15d8 100644
6744--- a/setup.py
6745+++ b/setup.py
6746@@ -77,9 +77,24 @@ def get_platform():
6747     return sys.platform
6748
6749
6750+# On MSYS, os.system needs to be wrapped with sh.exe
6751+# as otherwise all the io redirection will fail.
6752+# Arguably, this could happen inside the real os.system
6753+# rather than this monkey patch.
6754+if sys.platform == "win32" and os.environ.get("MSYSTEM", ""):
6755+    os_system = os.system
6756+    def msys_system(command):
6757+        command_in_sh = 'sh.exe -c "%s"' % command.replace("\\", "\\\\")
6758+        return os_system(command_in_sh)
6759+    os.system = msys_system
6760+
6761+    # set PYTHONLEGACYWINDOWSDLLLOADING to 1 to load DLLs from PATH
6762+    # This is needed while building core extensions of Python
6763+    os.environ["PYTHONLEGACYWINDOWSDLLLOADING"] = "1"
6764+
6765 CROSS_COMPILING = ("_PYTHON_HOST_PLATFORM" in os.environ)
6766 HOST_PLATFORM = get_platform()
6767-MS_WINDOWS = (HOST_PLATFORM == 'win32')
6768+MS_WINDOWS = (HOST_PLATFORM == 'win32' or HOST_PLATFORM == 'mingw')
6769 CYGWIN = (HOST_PLATFORM == 'cygwin')
6770 MACOS = (HOST_PLATFORM == 'darwin')
6771 AIX = (HOST_PLATFORM.startswith('aix'))
6772@@ -687,7 +702,7 @@ def check_extension_import(self, ext):
6773     def add_multiarch_paths(self):
6774         # Debian/Ubuntu multiarch support.
6775         # https://wiki.ubuntu.com/MultiarchSpec
6776-        tmpfile = os.path.join(self.build_temp, 'multiarch')
6777+        tmpfile = os.path.join(self.build_temp, 'multiarch').replace('\\','/')
6778         if not os.path.exists(self.build_temp):
6779             os.makedirs(self.build_temp)
6780         ret = run_command(
6781@@ -712,7 +727,7 @@ def add_multiarch_paths(self):
6782         opt = ''
6783         if CROSS_COMPILING:
6784             opt = '-t' + sysconfig.get_config_var('HOST_GNU_TYPE')
6785-        tmpfile = os.path.join(self.build_temp, 'multiarch')
6786+        tmpfile = os.path.join(self.build_temp, 'multiarch').replace('\\','/')
6787         if not os.path.exists(self.build_temp):
6788             os.makedirs(self.build_temp)
6789         ret = run_command(
6790@@ -774,7 +789,7 @@ def add_search_path(line):
6791                 pass
6792
6793     def add_cross_compiling_paths(self):
6794-        tmpfile = os.path.join(self.build_temp, 'ccpaths')
6795+        tmpfile = os.path.join(self.build_temp, 'ccpaths').replace('\\','/')
6796         if not os.path.exists(self.build_temp):
6797             os.makedirs(self.build_temp)
6798         # bpo-38472: With a German locale, GCC returns "gcc-Version 9.1.0
6799@@ -796,14 +811,25 @@ def add_cross_compiling_paths(self):
6800                         elif line.startswith("End of search list"):
6801                             in_incdirs = False
6802                         elif (is_gcc or is_clang) and line.startswith("LIBRARY_PATH"):
6803-                            for d in line.strip().split("=")[1].split(":"):
6804+                            for d in line.strip().split("=")[1].split(os.pathsep):
6805                                 d = os.path.normpath(d)
6806-                                if '/gcc/' not in d:
6807+                                if '/gcc/' not in d and '/clang/' not in d:
6808                                     add_dir_to_list(self.compiler.library_dirs,
6809                                                     d)
6810                         elif (is_gcc or is_clang) and in_incdirs and '/gcc/' not in line and '/clang/' not in line:
6811                             add_dir_to_list(self.compiler.include_dirs,
6812                                             line.strip())
6813+            if is_clang:
6814+                ret = run_command('%s -print-search-dirs >%s' % (CC, tmpfile))
6815+                if ret == 0:
6816+                    with open(tmpfile) as fp:
6817+                        for line in fp.readlines():
6818+                            if line.startswith("libraries:"):
6819+                                for d in line.strip().split("=")[1].split(os.pathsep):
6820+                                    d = os.path.normpath(d)
6821+                                    if '/gcc/' not in d and '/clang/' not in d:
6822+                                        add_dir_to_list(self.compiler.library_dirs,
6823+                                                        d)
6824         finally:
6825             os.unlink(tmpfile)
6826
6827@@ -849,10 +875,10 @@ def configure_compiler(self):
6828         if not CROSS_COMPILING:
6829             add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
6830             add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
6831+            self.add_multiarch_paths()
6832         # only change this for cross builds for 3.3, issues on Mageia
6833         if CROSS_COMPILING:
6834             self.add_cross_compiling_paths()
6835-        self.add_multiarch_paths()
6836         self.add_ldflags_cppflags()
6837
6838     def init_inc_lib_dirs(self):
6839@@ -898,7 +924,7 @@ def init_inc_lib_dirs(self):
6840         if HOST_PLATFORM == 'hp-ux11':
6841             self.lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32']
6842
6843-        if MACOS:
6844+        if MACOS or MS_WINDOWS:
6845             # This should work on any unixy platform ;-)
6846             # If the user has bothered specifying additional -I and -L flags
6847             # in OPT and LDFLAGS we might as well use them here.
6848@@ -970,11 +996,15 @@ def detect_simple_extensions(self):
6849         # grp(3)
6850         self.addext(Extension('grp', ['grpmodule.c']))
6851
6852-        self.addext(Extension('_socket', ['socketmodule.c']))
6853+        self.addext(Extension(
6854+            '_socket', ['socketmodule.c'],
6855+            libraries=(['ws2_32', 'iphlpapi'] if MS_WINDOWS else None)))
6856         self.addext(Extension('spwd', ['spwdmodule.c']))
6857
6858         # select(2); not on ancient System V
6859-        self.addext(Extension('select', ['selectmodule.c']))
6860+        self.addext(Extension(
6861+            'select', ['selectmodule.c'],
6862+            libraries=(['ws2_32'] if MS_WINDOWS else None)))
6863
6864         # Memory-mapped files (also works on Win32).
6865         self.addext(Extension('mmap', ['mmapmodule.c']))
6866@@ -1033,12 +1063,15 @@ def detect_test_extensions(self):
6867             ['_xxtestfuzz/_xxtestfuzz.c', '_xxtestfuzz/fuzzer.c']
6868         ))
6869
6870+        if MS_WINDOWS:
6871+            self.add(Extension('_testconsole', ['../PC/_testconsole.c']))
6872+
6873     def detect_readline_curses(self):
6874         # readline
6875         readline_termcap_library = ""
6876         curses_library = ""
6877         # Cannot use os.popen here in py3k.
6878-        tmpfile = os.path.join(self.build_temp, 'readline_termcap_lib')
6879+        tmpfile = os.path.join(self.build_temp, 'readline_termcap_lib').replace('\\','/')
6880         if not os.path.exists(self.build_temp):
6881             os.makedirs(self.build_temp)
6882         # Determine if readline is already linked against curses or tinfo.
6883@@ -1101,6 +1134,8 @@ def detect_readline_curses(self):
6884                 # readline package
6885                 if find_file('readline/rlconf.h', self.inc_dirs, []) is None:
6886                     do_readline = False
6887+        if MS_WINDOWS:
6888+            do_readline = False
6889         if do_readline:
6890             readline_libs = [readline_lib]
6891             if readline_termcap_library:
6892@@ -1124,8 +1159,7 @@ def detect_readline_curses(self):
6893         panel_library = 'panel'
6894         if curses_library == 'ncursesw':
6895             curses_defines.append(('HAVE_NCURSESW', '1'))
6896-            if not CROSS_COMPILING:
6897-                curses_includes.append('/usr/include/ncursesw')
6898+            curses_includes.append(sysconfig.get_config_var("NCURSESW_INCLUDEDIR"))
6899             # Bug 1464056: If _curses.so links with ncursesw,
6900             # _curses_panel.so must link with panelw.
6901             panel_library = 'panelw'
6902@@ -1209,7 +1243,7 @@ def detect_dbm_gdbm(self):
6903             if dbm_args:
6904                 dbm_order = [arg.split('=')[-1] for arg in dbm_args][-1].split(":")
6905             else:
6906-                dbm_order = "gdbm:ndbm:bdb".split(":")
6907+                dbm_order = []
6908             dbmext = None
6909             for cand in dbm_order:
6910                 if cand == "ndbm":
6911@@ -1282,6 +1316,19 @@ def detect_platform_specific_exts(self):
6912         # macOS-only, needs SystemConfiguration and CoreFoundation framework
6913         self.addext(Extension('_scproxy', ['_scproxy.c']))
6914
6915+        # Windows-only modules
6916+        if MS_WINDOWS:
6917+            srcdir = sysconfig.get_config_var('srcdir')
6918+            pc_srcdir = os.path.abspath(os.path.join(srcdir, 'PC'))
6919+
6920+            self.addext(Extension('_msi',
6921+                                [os.path.join(pc_srcdir, '_msi.c')]))
6922+
6923+            self.addext(Extension('winsound',
6924+                                [os.path.join(pc_srcdir, 'winsound.c')]))
6925+
6926+            self.addext(Extension('_overlapped', ['overlapped.c']))
6927+
6928     def detect_compress_exts(self):
6929         # Andrew Kuchling's zlib module.
6930         self.addext(Extension('zlib', ['zlibmodule.c']))
6931@@ -1329,9 +1376,10 @@ def detect_multiprocessing(self):
6932         if (
6933             sysconfig.get_config_var('HAVE_SEM_OPEN') and not
6934             sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED')
6935-        ):
6936+        ) or MS_WINDOWS:
6937             multiprocessing_srcs.append('_multiprocessing/semaphore.c')
6938-        self.addext(Extension('_multiprocessing', multiprocessing_srcs))
6939+        self.addext(Extension('_multiprocessing', multiprocessing_srcs,
6940+                              libraries=(['ws2_32'] if MS_WINDOWS else None), include_dirs=["Modules/_multiprocessing"]))
6941         self.addext(Extension('_posixshmem', ['_multiprocessing/posixshmem.c']))
6942
6943     def detect_uuid(self):
6944@@ -1414,11 +1462,16 @@ def detect_ctypes(self):
6945                         include_dirs=include_dirs,
6946                         extra_compile_args=extra_compile_args,
6947                         extra_link_args=extra_link_args,
6948-                        libraries=[],
6949+                        libraries=(['ole32', 'oleaut32', 'uuid'] if MS_WINDOWS else []),
6950+                        export_symbols=(
6951+                            ['DllGetClassObject PRIVATE', 'DllCanUnloadNow PRIVATE']
6952+                            if MS_WINDOWS else None
6953+                        ),
6954                         sources=sources)
6955         self.add(ext)
6956         # function my_sqrt() needs libm for sqrt()
6957-        self.addext(Extension('_ctypes_test', ['_ctypes/_ctypes_test.c']))
6958+        self.addext(Extension('_ctypes_test', ['_ctypes/_ctypes_test.c'],
6959+                              libraries=(['oleaut32'] if MS_WINDOWS else [])))
6960
6961         ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR")
6962         ffi_lib = None
6963@@ -1568,7 +1621,7 @@ def copy_scripts(self):
6964             else:
6965                 newfilename = filename + minoronly
6966             log.info(f'renaming {filename} to {newfilename}')
6967-            os.rename(filename, newfilename)
6968+            os.replace(filename, newfilename)
6969             newoutfiles.append(newfilename)
6970             if filename in updated_files:
6971                 newupdated_files.append(newfilename)
6972