diff --git a/Misc/NEWS.d/next/Build/2021-09-14-00-47-57.bpo-45188.MNbo_T.rst b/Misc/NEWS.d/next/Build/2021-09-14-00-47-57.bpo-45188.MNbo_T.rst
new file mode 100644
index 00000000000..df470e8eeb3
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2021-09-14-00-47-57.bpo-45188.MNbo_T.rst
@@ -0,0 +1,3 @@
+Windows builds now regenerate frozen modules as the first part of the build.
+Previously the regeneration was later in the build, which would require it
+to be restarted if any modules had changed.
diff --git a/PC/config_minimal.c b/PC/config_minimal.c
new file mode 100644
index 00000000000..adb1c44a724
--- /dev/null
+++ b/PC/config_minimal.c
@@ -0,0 +1,53 @@
+/* Module configuration */
+
+/* This file contains the table of built-in modules.
+ See create_builtin() in import.c. */
+
+#include "Python.h"
+
+extern PyObject* PyInit_faulthandler(void);
+extern PyObject* PyInit__tracemalloc(void);
+extern PyObject* PyInit_gc(void);
+extern PyObject* PyInit_nt(void);
+extern PyObject* PyInit__signal(void);
+extern PyObject* PyInit_winreg(void);
+
+extern PyObject* PyInit__ast(void);
+extern PyObject* PyInit__io(void);
+extern PyObject* PyInit_atexit(void);
+extern PyObject* _PyWarnings_Init(void);
+extern PyObject* PyInit__string(void);
+extern PyObject* PyInit__tokenize(void);
+
+extern PyObject* PyMarshal_Init(void);
+extern PyObject* PyInit__imp(void);
+
+struct _inittab _PyImport_Inittab[] = {
+ {"_ast", PyInit__ast},
+ {"faulthandler", PyInit_faulthandler},
+ {"gc", PyInit_gc},
+ {"nt", PyInit_nt}, /* Use the NT os functions, not posix */
+ {"_signal", PyInit__signal},
+ {"_tokenize", PyInit__tokenize},
+ {"_tracemalloc", PyInit__tracemalloc},
+
+ {"winreg", PyInit_winreg},
+
+ /* This module "lives in" with marshal.c */
+ {"marshal", PyMarshal_Init},
+
+ /* This lives it with import.c */
+ {"_imp", PyInit__imp},
+
+ /* These entries are here for sys.builtin_module_names */
+ {"builtins", NULL},
+ {"sys", NULL},
+ {"_warnings", _PyWarnings_Init},
+ {"_string", PyInit__string},
+
+ {"_io", PyInit__io},
+ {"atexit", PyInit_atexit},
+
+ /* Sentinel */
+ {0, 0}
+};
diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj
index a0bedf49e69..a87dca75c34 100644
--- a/PCbuild/_freeze_module.vcxproj
+++ b/PCbuild/_freeze_module.vcxproj
@@ -88,24 +88,145 @@
- _CONSOLE;%(PreprocessorDefinitions)
+ Py_NO_ENABLE_SHARED;Py_BUILD_CORE;_CONSOLE;%(PreprocessorDefinitions)
Console
+ version.lib;shlwapi.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies)
+
-
- {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}
- true
- true
- false
- true
- false
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -126,7 +247,7 @@
hello
- $(IntDir)ello.g.h
+ $(IntDir)hello.g.h
$(PySourcePath)Python\frozen_modules\hello.h
@@ -134,9 +255,9 @@
-
+
-
+
@@ -145,18 +266,8 @@
-
-
-
-
-
-
-
+
diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj
index f464ad3b18e..b3cbd471c66 100644
--- a/PCbuild/pcbuild.proj
+++ b/PCbuild/pcbuild.proj
@@ -14,6 +14,18 @@
+
+ $(Platform)
+ Win32
+ x64
+ $(Configuration)
+ Release
+
+ Build
+ Clean
+ CleanAll
+ false
+
$(Platform)
$(Configuration)
@@ -73,7 +85,7 @@
-
+
@@ -82,6 +94,11 @@
+
'
else:
- source = os.path.relpath(self.pyfile, ROOT_DIR)
+ source = relpath_for_posix_display(self.pyfile, ROOT_DIR)
return {
'module': self.name,
'ispkg': self.ispkg,
@@ -397,7 +432,7 @@ def replace_block(lines, start_marker, end_marker, replacements, file):
raise Exception(f"End marker {end_marker!r} "
f"occurs before start marker {start_marker!r} "
f"in file {file}")
- replacements = [line.rstrip() + os.linesep for line in replacements]
+ replacements = [line.rstrip() + '\n' for line in replacements]
return lines[:start_pos + 1] + replacements + lines[end_pos:]
@@ -446,7 +481,7 @@ def regen_frozen(modules):
for src in _iter_sources(modules):
# Adding a comment to separate sections here doesn't add much,
# so we don't.
- header = os.path.relpath(src.frozenfile, parentdir)
+ header = relpath_for_posix_display(src.frozenfile, parentdir)
headerlines.append(f'#include "{header}"')
deflines = []
@@ -503,11 +538,10 @@ def regen_makefile(modules):
frozenfiles = []
rules = ['']
for src in _iter_sources(modules):
- header = os.path.relpath(src.frozenfile, ROOT_DIR)
- relfile = header.replace('\\', '/')
- frozenfiles.append(f'\t\t$(srcdir)/{relfile} \\')
+ header = relpath_for_posix_display(src.frozenfile, ROOT_DIR)
+ frozenfiles.append(f'\t\t$(srcdir)/{header} \\')
- pyfile = os.path.relpath(src.pyfile, ROOT_DIR)
+ pyfile = relpath_for_posix_display(src.pyfile, ROOT_DIR)
# Note that we freeze the module to the target .h file
# instead of going through an intermediate file like we used to.
rules.append(f'{header}: Programs/_freeze_module {pyfile}')
@@ -546,9 +580,9 @@ def regen_pcbuild(modules):
# See bpo-45186 and bpo-45188.
if src.id not in ESSENTIAL and src.id != 'hello':
continue
- pyfile = os.path.relpath(src.pyfile, ROOT_DIR).replace('/', '\\')
- header = os.path.relpath(src.frozenfile, ROOT_DIR).replace('/', '\\')
- intfile = header.split('\\')[-1].strip('.h') + '.g.h'
+ pyfile = relpath_for_windows_display(src.pyfile, ROOT_DIR)
+ header = relpath_for_windows_display(src.frozenfile, ROOT_DIR)
+ intfile = ntpath.splitext(ntpath.basename(header))[0] + '.g.h'
projlines.append(f' ')
projlines.append(f' {src.frozenid}')
projlines.append(f' $(IntDir){intfile}')
@@ -600,7 +634,7 @@ def _freeze_module(frozenid, pyfile, frozenfile):
print('#', ' '.join(os.path.relpath(a) for a in argv), flush=True)
try:
subprocess.run(argv, check=True)
- except subprocess.CalledProcessError:
+ except (FileNotFoundError, subprocess.CalledProcessError):
if not os.path.exists(TOOL):
sys.exit(f'ERROR: missing {TOOL}; you need to run "make regen-frozen"')
raise # re-raise