Skip to content

Commit cf6f23b

Browse files
colesburyFFY00
andauthored
gh-88402: Add new sysconfig variables on Windows (GH-110049)
Co-authored-by: Filipe Laíns <filipe.lains@gmail.com>
1 parent 80dc39e commit cf6f23b

20 files changed

+231
-70
lines changed

Include/internal/pycore_importdl.h

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#ifndef Py_INTERNAL_IMPORTDL_H
2+
#define Py_INTERNAL_IMPORTDL_H
3+
4+
#include "patchlevel.h" // PY_MAJOR_VERSION
5+
6+
#ifdef __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
#ifndef Py_BUILD_CORE
11+
# error "this header requires Py_BUILD_CORE define"
12+
#endif
13+
14+
15+
extern const char *_PyImport_DynLoadFiletab[];
16+
17+
extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *);
18+
19+
typedef PyObject *(*PyModInitFunction)(void);
20+
21+
/* Max length of module suffix searched for -- accommodates "module.slb" */
22+
#define MAXSUFFIXSIZE 12
23+
24+
#ifdef MS_WINDOWS
25+
#include <windows.h>
26+
typedef FARPROC dl_funcptr;
27+
28+
#ifdef _DEBUG
29+
# define PYD_DEBUG_SUFFIX "_d"
30+
#else
31+
# define PYD_DEBUG_SUFFIX ""
32+
#endif
33+
34+
#ifdef Py_NOGIL
35+
# define PYD_THREADING_TAG "t"
36+
#else
37+
# define PYD_THREADING_TAG ""
38+
#endif
39+
40+
#ifdef PYD_PLATFORM_TAG
41+
# define PYD_SOABI "cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) PYD_THREADING_TAG "-" PYD_PLATFORM_TAG
42+
#else
43+
# define PYD_SOABI "cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) PYD_THREADING_TAG
44+
#endif
45+
46+
#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX "." PYD_SOABI ".pyd"
47+
#define PYD_UNTAGGED_SUFFIX PYD_DEBUG_SUFFIX ".pyd"
48+
49+
#else
50+
typedef void (*dl_funcptr)(void);
51+
#endif
52+
53+
54+
#ifdef __cplusplus
55+
}
56+
#endif
57+
#endif /* !Py_INTERNAL_IMPORTDL_H */

Lib/sysconfig.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -544,16 +544,20 @@ def _init_posix(vars):
544544
def _init_non_posix(vars):
545545
"""Initialize the module as appropriate for NT"""
546546
# set basic install directories
547-
import _imp
547+
import _winapi
548+
import _sysconfig
548549
vars['LIBDEST'] = get_path('stdlib')
549550
vars['BINLIBDEST'] = get_path('platstdlib')
550551
vars['INCLUDEPY'] = get_path('include')
551-
try:
552-
# GH-99201: _imp.extension_suffixes may be empty when
553-
# HAVE_DYNAMIC_LOADING is not set. In this case, don't set EXT_SUFFIX.
554-
vars['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
555-
except IndexError:
556-
pass
552+
553+
# Add EXT_SUFFIX, SOABI, and Py_NOGIL
554+
vars.update(_sysconfig.config_vars())
555+
556+
vars['LIBDIR'] = _safe_realpath(os.path.join(get_config_var('installed_base'), 'libs'))
557+
if hasattr(sys, 'dllhandle'):
558+
dllhandle = _winapi.GetModuleFileName(sys.dllhandle)
559+
vars['LIBRARY'] = os.path.basename(_safe_realpath(dllhandle))
560+
vars['LDLIBRARY'] = vars['LIBRARY']
557561
vars['EXE'] = '.exe'
558562
vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
559563
vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))

Lib/test/test_sysconfig.py

+21-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
get_path, get_path_names, _INSTALL_SCHEMES,
1818
get_default_scheme, get_scheme_names, get_config_var,
1919
_expand_vars, _get_preferred_schemes, _main)
20+
import _imp
2021
import _osx_support
22+
import _sysconfig
2123

2224

2325
HAS_USER_BASE = sysconfig._HAS_USER_BASE
@@ -394,6 +396,24 @@ def test_ldshared_value(self):
394396

395397
self.assertIn(ldflags, ldshared)
396398

399+
@unittest.skipIf(not _imp.extension_suffixes(), "stub loader has no suffixes")
400+
def test_soabi(self):
401+
soabi = sysconfig.get_config_var('SOABI')
402+
self.assertIn(soabi, _imp.extension_suffixes()[0])
403+
404+
def test_library(self):
405+
library = sysconfig.get_config_var('LIBRARY')
406+
ldlibrary = sysconfig.get_config_var('LDLIBRARY')
407+
major, minor = sys.version_info[:2]
408+
if sys.platform == 'win32':
409+
self.assertTrue(library.startswith(f'python{major}{minor}'))
410+
self.assertTrue(library.endswith('.dll'))
411+
self.assertEqual(library, ldlibrary)
412+
else:
413+
self.assertTrue(library.startswith(f'libpython{major}.{minor}'))
414+
self.assertTrue(library.endswith('.a'))
415+
self.assertTrue(ldlibrary.startswith(f'libpython{major}.{minor}'))
416+
397417
@unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX")
398418
@requires_subprocess()
399419
def test_platform_in_subprocess(self):
@@ -472,10 +492,8 @@ def test_srcdir_independent_of_cwd(self):
472492

473493
@unittest.skipIf(sysconfig.get_config_var('EXT_SUFFIX') is None,
474494
'EXT_SUFFIX required for this test')
495+
@unittest.skipIf(not _imp.extension_suffixes(), "stub loader has no suffixes")
475496
def test_EXT_SUFFIX_in_vars(self):
476-
import _imp
477-
if not _imp.extension_suffixes():
478-
self.skipTest("stub loader has no suffixes")
479497
vars = sysconfig.get_config_vars()
480498
self.assertEqual(vars['EXT_SUFFIX'], _imp.extension_suffixes()[0])
481499

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add new variables to :py:meth:`sysconfig.get_config_vars` on Windows:
2+
``LIBRARY``, ``LDLIBRARY``, ``LIBDIR``, ``SOABI``, and ``Py_NOGIL``.

Modules/Setup

+1
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ PYTHONPATH=$(COREPYTHONPATH)
155155
#math mathmodule.c
156156
#mmap mmapmodule.c
157157
#select selectmodule.c
158+
#_sysconfig _sysconfig.c
158159

159160
# XML
160161
#_elementtree _elementtree.c

Modules/Setup.bootstrap.in

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ errno errnomodule.c
1919
_io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c
2020
itertools itertoolsmodule.c
2121
_sre _sre/sre.c
22+
_sysconfig _sysconfig.c
2223
_thread _threadmodule.c
2324
time timemodule.c
2425
_typing _typingmodule.c

Modules/_sysconfig.c

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// _sysconfig provides data for the Python sysconfig module
2+
3+
#ifndef Py_BUILD_CORE_BUILTIN
4+
# define Py_BUILD_CORE_MODULE 1
5+
#endif
6+
7+
#include "Python.h"
8+
9+
#include "pycore_importdl.h" // _PyImport_DynLoadFiletab
10+
#include "pycore_long.h" // _PyLong_GetZero, _PyLong_GetOne
11+
12+
13+
/*[clinic input]
14+
module _sysconfig
15+
[clinic start generated code]*/
16+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=0a7c02d3e212ac97]*/
17+
18+
#include "clinic/_sysconfig.c.h"
19+
20+
#ifdef MS_WINDOWS
21+
static int
22+
add_string_value(PyObject *dict, const char *key, const char *str_value)
23+
{
24+
PyObject *value = PyUnicode_FromString(str_value);
25+
if (value == NULL) {
26+
return -1;
27+
}
28+
int err = PyDict_SetItemString(dict, key, value);
29+
Py_DECREF(value);
30+
return err;
31+
}
32+
#endif
33+
34+
/*[clinic input]
35+
_sysconfig.config_vars
36+
37+
Returns a dictionary containing build variables intended to be exposed by sysconfig.
38+
[clinic start generated code]*/
39+
40+
static PyObject *
41+
_sysconfig_config_vars_impl(PyObject *module)
42+
/*[clinic end generated code: output=9c41cdee63ea9487 input=391ff42f3af57d01]*/
43+
{
44+
PyObject *config = PyDict_New();
45+
if (config == NULL) {
46+
return NULL;
47+
}
48+
49+
#ifdef MS_WINDOWS
50+
if (add_string_value(config, "EXT_SUFFIX", PYD_TAGGED_SUFFIX) < 0) {
51+
Py_DECREF(config);
52+
return NULL;
53+
}
54+
if (add_string_value(config, "SOABI", PYD_SOABI) < 0) {
55+
Py_DECREF(config);
56+
return NULL;
57+
}
58+
#endif
59+
60+
#ifdef Py_NOGIL
61+
PyObject *py_nogil = _PyLong_GetOne();
62+
#else
63+
PyObject *py_nogil = _PyLong_GetZero();
64+
#endif
65+
if (PyDict_SetItemString(config, "Py_NOGIL", py_nogil) < 0) {
66+
Py_DECREF(config);
67+
return NULL;
68+
}
69+
70+
return config;
71+
}
72+
73+
PyDoc_STRVAR(sysconfig__doc__,
74+
"A helper for the sysconfig module.");
75+
76+
static struct PyMethodDef sysconfig_methods[] = {
77+
_SYSCONFIG_CONFIG_VARS_METHODDEF
78+
{NULL, NULL}
79+
};
80+
81+
static PyModuleDef_Slot sysconfig_slots[] = {
82+
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
83+
{0, NULL}
84+
};
85+
86+
static PyModuleDef sysconfig_module = {
87+
.m_base = PyModuleDef_HEAD_INIT,
88+
.m_name = "_sysconfig",
89+
.m_doc = sysconfig__doc__,
90+
.m_methods = sysconfig_methods,
91+
.m_slots = sysconfig_slots,
92+
};
93+
94+
PyMODINIT_FUNC
95+
PyInit__sysconfig(void)
96+
{
97+
return PyModuleDef_Init(&sysconfig_module);
98+
}

Modules/clinic/_sysconfig.c.h

+22
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

PC/config.c

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ extern PyObject* PyInit__sha1(void);
2222
extern PyObject* PyInit__sha2(void);
2323
extern PyObject* PyInit__sha3(void);
2424
extern PyObject* PyInit__statistics(void);
25+
extern PyObject* PyInit__sysconfig(void);
2526
extern PyObject* PyInit__typing(void);
2627
extern PyObject* PyInit__blake2(void);
2728
extern PyObject* PyInit_time(void);
@@ -102,6 +103,7 @@ struct _inittab _PyImport_Inittab[] = {
102103
{"_sha2", PyInit__sha2},
103104
{"_sha3", PyInit__sha3},
104105
{"_blake2", PyInit__blake2},
106+
{"_sysconfig", PyInit__sysconfig},
105107
{"time", PyInit_time},
106108
{"_thread", PyInit__thread},
107109
{"_tokenize", PyInit__tokenize},

PCbuild/pythoncore.vcxproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@
240240
<ClInclude Include="..\Include\internal\pycore_hashtable.h" />
241241
<ClInclude Include="..\Include\internal\pycore_identifier.h" />
242242
<ClInclude Include="..\Include\internal\pycore_import.h" />
243+
<ClInclude Include="..\Include\internal\pycore_importdl.h" />
243244
<ClInclude Include="..\Include\internal\pycore_initconfig.h" />
244245
<ClInclude Include="..\Include\internal\pycore_interp.h" />
245246
<ClInclude Include="..\Include\internal\pycore_intrinsics.h" />
@@ -367,7 +368,6 @@
367368
<ClInclude Include="..\PC\errmap.h" />
368369
<ClInclude Include="..\PC\pyconfig.h" />
369370
<ClInclude Include="..\Python\condvar.h" />
370-
<ClInclude Include="..\Python\importdl.h" />
371371
<ClInclude Include="..\Python\stdlib_module_names.h" />
372372
<ClInclude Include="..\Python\thread_nt.h" />
373373
</ItemGroup>
@@ -438,6 +438,7 @@
438438
<ClCompile Include="..\Modules\signalmodule.c" />
439439
<ClCompile Include="..\Modules\_statisticsmodule.c" />
440440
<ClCompile Include="..\Modules\symtablemodule.c" />
441+
<ClCompile Include="..\Modules\_sysconfig.c" />
441442
<ClCompile Include="..\Modules\_threadmodule.c" />
442443
<ClCompile Include="..\Modules\_tracemalloc.c" />
443444
<ClCompile Include="..\Modules\_typingmodule.c" />

PCbuild/pythoncore.vcxproj.filters

+6-3
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,6 @@
300300
<ClInclude Include="..\PC\pyconfig.h">
301301
<Filter>PC</Filter>
302302
</ClInclude>
303-
<ClInclude Include="..\Python\importdl.h">
304-
<Filter>Python</Filter>
305-
</ClInclude>
306303
<ClInclude Include="..\Python\stdlib_module_names.h">
307304
<Filter>Python</Filter>
308305
</ClInclude>
@@ -633,6 +630,9 @@
633630
<ClInclude Include="..\Include\internal\pycore_import.h">
634631
<Filter>Include\internal</Filter>
635632
</ClInclude>
633+
<ClInclude Include="..\Include\internal\pycore_importdl.h">
634+
<Filter>Include\internal</Filter>
635+
</ClInclude>
636636
<ClInclude Include="..\Include\internal\pycore_initconfig.h">
637637
<Filter>Include\internal</Filter>
638638
</ClInclude>
@@ -959,6 +959,9 @@
959959
<ClCompile Include="..\Modules\symtablemodule.c">
960960
<Filter>Modules</Filter>
961961
</ClCompile>
962+
<ClCompile Include="..\Modules\_sysconfig.c">
963+
<Filter>Modules</Filter>
964+
</ClCompile>
962965
<ClCompile Include="..\Modules\_threadmodule.c">
963966
<Filter>Modules</Filter>
964967
</ClCompile>

Python/dynload_hpux.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <errno.h>
66

77
#include "Python.h"
8-
#include "importdl.h"
8+
#include "pycore_importdl.h"
99

1010
#if defined(__hp9000s300)
1111
#define FUNCNAME_PATTERN "_%.20s_%.200s"

Python/dynload_shlib.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "Python.h"
55
#include "pycore_interp.h" // _PyInterpreterState.dlopenflags
66
#include "pycore_pystate.h" // _PyInterpreterState_GET()
7-
#include "importdl.h"
7+
#include "pycore_importdl.h"
88

99
#include <sys/types.h>
1010
#include <sys/stat.h>

Python/dynload_stub.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
not present. */
44

55
#include "Python.h"
6-
#include "importdl.h"
6+
#include "pycore_importdl.h"
77

88

99
const char *_PyImport_DynLoadFiletab[] = {NULL};

0 commit comments

Comments
 (0)