diff --git a/Lib/test/test_importlib/test_windows.py b/Lib/test/test_importlib/test_windows.py
index 46e23beae75..c893bcf565e 100644
--- a/Lib/test/test_importlib/test_windows.py
+++ b/Lib/test/test_importlib/test_windows.py
@@ -2,9 +2,11 @@ from . import util as test_util
machinery = test_util.import_importlib('importlib.machinery')
import os
+import re
import sys
import unittest
from test import support
+from distutils.util import get_platform
from contextlib import contextmanager
from .util import temp_module
@@ -83,3 +85,25 @@ class WindowsRegistryFinderTests:
(Frozen_WindowsRegistryFinderTests,
Source_WindowsRegistryFinderTests
) = test_util.test_both(WindowsRegistryFinderTests, machinery=machinery)
+
+@unittest.skipUnless(sys.platform.startswith('win'), 'requires Windows')
+class WindowsExtensionSuffixTests:
+ def test_tagged_suffix(self):
+ suffixes = self.machinery.EXTENSION_SUFFIXES
+ expected_tag = ".cp{0.major}{0.minor}-{1}.pyd".format(sys.version_info,
+ re.sub('[^a-zA-Z0-9]', '_', get_platform()))
+ try:
+ untagged_i = suffixes.index(".pyd")
+ except ValueError:
+ untagged_i = suffixes.index("_d.pyd")
+ expected_tag = "_d" + expected_tag
+
+ self.assertIn(expected_tag, suffixes)
+
+ # Ensure the tags are in the correct order
+ tagged_i = suffixes.index(expected_tag)
+ self.assertLess(tagged_i, untagged_i)
+
+(Frozen_WindowsExtensionSuffixTests,
+ Source_WindowsExtensionSuffixTests
+ ) = test_util.test_both(WindowsExtensionSuffixTests, machinery=machinery)
diff --git a/Misc/NEWS b/Misc/NEWS
index 295995ec49d..903331e604b 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -1584,6 +1584,9 @@ Windows
- Issue #10747: Use versioned labels in the Windows start menu.
Patch by Olive Kilburn.
+- Issue #22980: .pyd files with a version and platform tag (for example,
+ ".cp35-win32.pyd") will now be loaded in preference to those without tags.
+
What's New in Python 3.4.0?
===========================
diff --git a/PC/pyconfig.h b/PC/pyconfig.h
index bd8844f5b42..328be0f362e 100644
--- a/PC/pyconfig.h
+++ b/PC/pyconfig.h
@@ -145,9 +145,11 @@ WIN32 is still required for the locale module.
#if defined(_M_IA64)
#define COMPILER _Py_PASTE_VERSION("64 bit (Itanium)")
#define MS_WINI64
+#define PYD_PLATFORM_TAG "win_ia64"
#elif defined(_M_X64) || defined(_M_AMD64)
#define COMPILER _Py_PASTE_VERSION("64 bit (AMD64)")
#define MS_WINX64
+#define PYD_PLATFORM_TAG "win_amd64"
#else
#define COMPILER _Py_PASTE_VERSION("64 bit (Unknown)")
#endif
@@ -193,8 +195,10 @@ typedef _W64 int ssize_t;
#if defined(MS_WIN32) && !defined(MS_WIN64)
#if defined(_M_IX86)
#define COMPILER _Py_PASTE_VERSION("32 bit (Intel)")
+#define PYD_PLATFORM_TAG "win32"
#elif defined(_M_ARM)
#define COMPILER _Py_PASTE_VERSION("32 bit (ARM)")
+#define PYD_PLATFORM_TAG "win_arm"
#else
#define COMPILER _Py_PASTE_VERSION("32 bit (Unknown)")
#endif
diff --git a/PCbuild/python.props b/PCbuild/python.props
index 3dbc8065dac..99eebf0fe28 100644
--- a/PCbuild/python.props
+++ b/PCbuild/python.props
@@ -96,6 +96,10 @@
python$(MajorVersionNumber)$(MinorVersionNumber)$(PyDebugExt)
+
+
+ .cp$(MajorVersionNumber)$(MinorVersionNumber)-win32
+ .cp$(MajorVersionNumber)$(MinorVersionNumber)-win_amd64
diff --git a/Python/dynload_win.c b/Python/dynload_win.c
index ffcf0ee1d73..9ed9eea3337 100644
--- a/Python/dynload_win.c
+++ b/Python/dynload_win.c
@@ -9,6 +9,7 @@
#include
#include "importdl.h"
+#include "patchlevel.h"
#include
// "activation context" magic - see dl_nt.c...
@@ -17,16 +18,28 @@ extern ULONG_PTR _Py_ActivateActCtx();
void _Py_DeactivateActCtx(ULONG_PTR cookie);
#endif
-const char *_PyImport_DynLoadFiletab[] = {
#ifdef _DEBUG
- "_d.pyd",
+#define PYD_DEBUG_SUFFIX "_d"
#else
- ".pyd",
+#define PYD_DEBUG_SUFFIX ""
#endif
+
+#define STRINGIZE2(x) #x
+#define STRINGIZE(x) STRINGIZE2(x)
+#ifdef PYD_PLATFORM_TAG
+#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX ".cp" STRINGIZE(PY_MAJOR_VERSION) STRINGIZE(PY_MINOR_VERSION) "-" PYD_PLATFORM_TAG ".pyd"
+#else
+#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX ".cp" STRINGIZE(PY_MAJOR_VERSION) STRINGIZE(PY_MINOR_VERSION) ".pyd"
+#endif
+
+#define PYD_UNTAGGED_SUFFIX PYD_DEBUG_SUFFIX ".pyd"
+
+const char *_PyImport_DynLoadFiletab[] = {
+ PYD_TAGGED_SUFFIX,
+ PYD_UNTAGGED_SUFFIX,
NULL
};
-
/* Case insensitive string compare, to avoid any dependencies on particular
C RTL implementations */