# DP: backport issue #13150: sysconfig no longer parses the Makefile and config.h
# DP: files when imported, instead doing it at build time.  This makes importing
# DP: sysconfig faster and reduces Python startup time by 20%.

Index: b/Lib/sysconfig.py
===================================================================
--- a/Lib/sysconfig.py
+++ b/Lib/sysconfig.py
@@ -345,9 +345,10 @@
                         'config-{}{}'.format(_PY_VERSION_SHORT, sys.abiflags),
                         'Makefile')
 
-
-def _init_posix(vars):
-    """Initialize the module as appropriate for POSIX systems."""
+def _generate_posix_vars():
+    """Generate the Python module containing build-time variables."""
+    import pprint
+    vars = {}
     # load the installed Makefile:
     makefile = get_makefile_filename()
     try:
@@ -373,6 +374,19 @@
     if _PYTHON_BUILD:
         vars['LDSHARED'] = vars['BLDSHARED']
 
+    destfile = '_sysconfigdata.py'
+    with open(destfile, 'w', encoding='utf8') as f:
+        f.write('# system configuration generated and used by'
+                ' the sysconfig module\n')
+        f.write('build_time_vars = ')
+        pprint.pprint(vars, stream=f)
+
+def _init_posix(vars):
+    """Initialize the module as appropriate for POSIX systems."""
+    # _sysconfigdata is generated at build time, see _generate_posix_vars()
+    from _sysconfigdata import build_time_vars
+    vars.update(build_time_vars)
+
 def _init_non_posix(vars):
     """Initialize the module as appropriate for NT"""
     # set basic install directories
@@ -777,6 +791,9 @@
 
 def _main():
     """Display all information sysconfig detains."""
+    if '--generate-posix-vars' in sys.argv:
+        _generate_posix_vars()
+        return
     print('Platform: "{0}"'.format(get_platform()))
     print('Python version: "{0}"'.format(get_python_version()))
     print('Current installation scheme: "{0}"'.format(_get_default_scheme()))
Index: b/Makefile.pre.in
===================================================================
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -380,6 +380,7 @@
 		Objects/unicodectype.o \
 		Objects/weakrefobject.o
 
+SYSCONFIGDATA=_sysconfigdata.py
 
 ##########################################################################
 # objects that get linked into the Python library
@@ -397,7 +398,7 @@
 
 # Default target
 all:		build_all
-build_all:	$(BUILDPYTHON) oldsharedmods sharedmods gdbhooks Modules/_testembed
+build_all:	$(BUILDPYTHON) $(SYSCONFIGDATA) oldsharedmods sharedmods gdbhooks Modules/_testembed
 
 # Compile a binary with gcc profile guided optimization.
 profile-opt:
@@ -430,14 +431,20 @@
 $(BUILDPYTHON):	Modules/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
 	$(LINKCC) $(PY_LDFLAGS) $(PY_CFLAGS) $(LINKFORSHARED) -o $@ Modules/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
 
-platform: $(BUILDPYTHON)
+platform: $(BUILDPYTHON) $(SYSCONFIGDATA)
 	$(RUNSHARED) ./$(BUILDPYTHON) -E -c 'import sys ; from sysconfig import get_platform ; print(get_platform()+"-"+sys.version[0:3])' >platform
 
+# Generate the sysconfig build-time data
+$(SYSCONFIGDATA): $(BUILDPYTHON)
+	$(RUNSHARED) ./$(BUILDPYTHON) -SE -m sysconfig --generate-posix-vars
+	$(RUNSHARED) ./$(BUILDPYTHON) -S -c 'import os,sys ; from distutils.util import get_platform ; d=os.path.join("build", "lib."+get_platform()+"-"+sys.version[0:3]+("-pydebug" if hasattr(sys, "gettotalrefcount") else "")); print(d, end="")' > pybuilddir.txt
+	mkdir -p `cat pybuilddir.txt`
+	cp $(SYSCONFIGDATA) `cat pybuilddir.txt`/.
 
 # Build the shared modules
 # MAKEFLAGS are sorted and normalized. Under GNU make the 's' for
 # -s, --silent or --quiet is always the first char.
-sharedmods: $(BUILDPYTHON)
+sharedmods: $(BUILDPYTHON) $(SYSCONFIGDATA)
 	@case "$$MAKEFLAGS" in \
 	    s*) quiet="-q";; \
 	    *) quiet="";; \
@@ -962,7 +969,7 @@
 		else	true; \
 		fi; \
 	done
-	@for i in $(srcdir)/Lib/*.py $(srcdir)/Lib/*.egg-info ; \
+	@for i in $(srcdir)/Lib/*.py $(SYSCONFIGDATA) $(srcdir)/Lib/*.egg-info ; \
 	do \
 		if test -x $$i; then \
 			$(INSTALL_SCRIPT) $$i $(DESTDIR)$(LIBDEST); \
Index: b/setup.py
===================================================================
--- a/setup.py
+++ b/setup.py
@@ -23,10 +23,6 @@
 # This global variable is used to hold the list of modules to be disabled.
 disabled_module_list = []
 
-# File which contains the directory for shared mods (for sys.path fixup
-# when running from the build dir, see Modules/getpath.c)
-_BUILDDIR_COOKIE = "pybuilddir.txt"
-
 def add_dir_to_list(dirlist, dir):
     """Add the directory 'dir' to the list 'dirlist' (after any relative
     directories) if:
@@ -246,12 +242,9 @@
             args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags
         self.compiler.set_executables(**args)
 
-        # Not only do we write the builddir cookie, but we manually install
-        # the shared modules directory if it isn't already in sys.path.
-        # Otherwise trying to import the extensions after building them
-        # will fail.
-        with open(_BUILDDIR_COOKIE, "wb") as f:
-            f.write(self.build_lib.encode('utf-8', 'surrogateescape'))
+        # We manually install the shared modules directory if it isn't
+        # already in sys.path.  Otherwise trying to import the
+        # extensions after building them will fail.
         abs_build_lib = os.path.join(os.getcwd(), self.build_lib)
         if abs_build_lib not in sys.path:
             sys.path.append(abs_build_lib)
