]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-88402: Add new sysconfig variables on Windows (GH-110049) 110252/head
authorSam Gross <colesbury@gmail.com>
Wed, 4 Oct 2023 22:50:29 +0000 (22:50 +0000)
committerGitHub <noreply@github.com>
Wed, 4 Oct 2023 22:50:29 +0000 (22:50 +0000)
Co-authored-by: Filipe LaĆ­ns <filipe.lains@gmail.com>
20 files changed:
Include/internal/pycore_importdl.h [new file with mode: 0644]
Lib/sysconfig.py
Lib/test/test_sysconfig.py
Misc/NEWS.d/next/Library/2023-09-28-12-32-57.gh-issue-88402.hoa3Gx.rst [new file with mode: 0644]
Modules/Setup
Modules/Setup.bootstrap.in
Modules/_sysconfig.c [new file with mode: 0644]
Modules/clinic/_sysconfig.c.h [new file with mode: 0644]
PC/config.c
PCbuild/pythoncore.vcxproj
PCbuild/pythoncore.vcxproj.filters
Python/dynload_hpux.c
Python/dynload_shlib.c
Python/dynload_stub.c
Python/dynload_win.c
Python/import.c
Python/importdl.c
Python/importdl.h [deleted file]
Python/stdlib_module_names.h
Tools/c-analyzer/cpython/ignored.tsv

diff --git a/Include/internal/pycore_importdl.h b/Include/internal/pycore_importdl.h
new file mode 100644 (file)
index 0000000..dee6424
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef Py_INTERNAL_IMPORTDL_H
+#define Py_INTERNAL_IMPORTDL_H
+
+#include "patchlevel.h"           // PY_MAJOR_VERSION
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+#  error "this header requires Py_BUILD_CORE define"
+#endif
+
+
+extern const char *_PyImport_DynLoadFiletab[];
+
+extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *);
+
+typedef PyObject *(*PyModInitFunction)(void);
+
+/* Max length of module suffix searched for -- accommodates "module.slb" */
+#define MAXSUFFIXSIZE 12
+
+#ifdef MS_WINDOWS
+#include <windows.h>
+typedef FARPROC dl_funcptr;
+
+#ifdef _DEBUG
+#  define PYD_DEBUG_SUFFIX "_d"
+#else
+#  define PYD_DEBUG_SUFFIX ""
+#endif
+
+#ifdef Py_NOGIL
+#  define PYD_THREADING_TAG "t"
+#else
+#  define PYD_THREADING_TAG ""
+#endif
+
+#ifdef PYD_PLATFORM_TAG
+#  define PYD_SOABI "cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) PYD_THREADING_TAG "-" PYD_PLATFORM_TAG
+#else
+#  define PYD_SOABI "cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) PYD_THREADING_TAG
+#endif
+
+#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX "." PYD_SOABI ".pyd"
+#define PYD_UNTAGGED_SUFFIX PYD_DEBUG_SUFFIX ".pyd"
+
+#else
+typedef void (*dl_funcptr)(void);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_IMPORTDL_H */
index a8b5c5f7dfba5ba21c134f93db37137583694071..edfe451a86bfd0ba14dabc1d8eef702418bff69a 100644 (file)
@@ -544,16 +544,20 @@ def _init_posix(vars):
 def _init_non_posix(vars):
     """Initialize the module as appropriate for NT"""
     # set basic install directories
-    import _imp
+    import _winapi
+    import _sysconfig
     vars['LIBDEST'] = get_path('stdlib')
     vars['BINLIBDEST'] = get_path('platstdlib')
     vars['INCLUDEPY'] = get_path('include')
-    try:
-        # GH-99201: _imp.extension_suffixes may be empty when
-        # HAVE_DYNAMIC_LOADING is not set. In this case, don't set EXT_SUFFIX.
-        vars['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
-    except IndexError:
-        pass
+
+    # Add EXT_SUFFIX, SOABI, and Py_NOGIL
+    vars.update(_sysconfig.config_vars())
+
+    vars['LIBDIR'] = _safe_realpath(os.path.join(get_config_var('installed_base'), 'libs'))
+    if hasattr(sys, 'dllhandle'):
+        dllhandle = _winapi.GetModuleFileName(sys.dllhandle)
+        vars['LIBRARY'] = os.path.basename(_safe_realpath(dllhandle))
+        vars['LDLIBRARY'] = vars['LIBRARY']
     vars['EXE'] = '.exe'
     vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
     vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
index b6dbf3d52cb4c30f24e1fd12463ee2d54b6309a5..a077ac5349fdc6d57ac88ca56d0efe01e081ed96 100644 (file)
@@ -17,7 +17,9 @@ from sysconfig import (get_paths, get_platform, get_config_vars,
                        get_path, get_path_names, _INSTALL_SCHEMES,
                        get_default_scheme, get_scheme_names, get_config_var,
                        _expand_vars, _get_preferred_schemes, _main)
+import _imp
 import _osx_support
+import _sysconfig
 
 
 HAS_USER_BASE = sysconfig._HAS_USER_BASE
@@ -394,6 +396,24 @@ class TestSysConfig(unittest.TestCase):
 
         self.assertIn(ldflags, ldshared)
 
+    @unittest.skipIf(not _imp.extension_suffixes(), "stub loader has no suffixes")
+    def test_soabi(self):
+        soabi = sysconfig.get_config_var('SOABI')
+        self.assertIn(soabi, _imp.extension_suffixes()[0])
+
+    def test_library(self):
+        library = sysconfig.get_config_var('LIBRARY')
+        ldlibrary = sysconfig.get_config_var('LDLIBRARY')
+        major, minor = sys.version_info[:2]
+        if sys.platform == 'win32':
+            self.assertTrue(library.startswith(f'python{major}{minor}'))
+            self.assertTrue(library.endswith('.dll'))
+            self.assertEqual(library, ldlibrary)
+        else:
+            self.assertTrue(library.startswith(f'libpython{major}.{minor}'))
+            self.assertTrue(library.endswith('.a'))
+            self.assertTrue(ldlibrary.startswith(f'libpython{major}.{minor}'))
+
     @unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX")
     @requires_subprocess()
     def test_platform_in_subprocess(self):
@@ -472,10 +492,8 @@ class TestSysConfig(unittest.TestCase):
 
     @unittest.skipIf(sysconfig.get_config_var('EXT_SUFFIX') is None,
                      'EXT_SUFFIX required for this test')
+    @unittest.skipIf(not _imp.extension_suffixes(), "stub loader has no suffixes")
     def test_EXT_SUFFIX_in_vars(self):
-        import _imp
-        if not _imp.extension_suffixes():
-            self.skipTest("stub loader has no suffixes")
         vars = sysconfig.get_config_vars()
         self.assertEqual(vars['EXT_SUFFIX'], _imp.extension_suffixes()[0])
 
diff --git a/Misc/NEWS.d/next/Library/2023-09-28-12-32-57.gh-issue-88402.hoa3Gx.rst b/Misc/NEWS.d/next/Library/2023-09-28-12-32-57.gh-issue-88402.hoa3Gx.rst
new file mode 100644 (file)
index 0000000..80ec650
--- /dev/null
@@ -0,0 +1,2 @@
+Add new variables to :py:meth:`sysconfig.get_config_vars` on Windows:
+``LIBRARY``, ``LDLIBRARY``, ``LIBDIR``, ``SOABI``, and ``Py_NOGIL``.
index 8676f9ddce48418ef2d4e72548677cc2729c8ad7..1367f0ef4fa54a348de174aa4dfb67dbda5de1ec 100644 (file)
@@ -155,6 +155,7 @@ PYTHONPATH=$(COREPYTHONPATH)
 #math mathmodule.c
 #mmap mmapmodule.c
 #select selectmodule.c
+#_sysconfig _sysconfig.c
 
 # XML
 #_elementtree _elementtree.c
index 8ef0f203a82a8ee347bdfa2fb78e7a3dd3b1fdf6..cd12c1bd0df8f9050fc814b8857cf1bdebca8a9e 100644 (file)
@@ -19,6 +19,7 @@ errno errnomodule.c
 _io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c
 itertools itertoolsmodule.c
 _sre _sre/sre.c
+_sysconfig _sysconfig.c
 _thread _threadmodule.c
 time timemodule.c
 _typing _typingmodule.c
diff --git a/Modules/_sysconfig.c b/Modules/_sysconfig.c
new file mode 100644 (file)
index 0000000..6f1cc16
--- /dev/null
@@ -0,0 +1,98 @@
+// _sysconfig provides data for the Python sysconfig module
+
+#ifndef Py_BUILD_CORE_BUILTIN
+#  define Py_BUILD_CORE_MODULE 1
+#endif
+
+#include "Python.h"
+
+#include "pycore_importdl.h"   // _PyImport_DynLoadFiletab
+#include "pycore_long.h"       // _PyLong_GetZero, _PyLong_GetOne
+
+
+/*[clinic input]
+module _sysconfig
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=0a7c02d3e212ac97]*/
+
+#include "clinic/_sysconfig.c.h"
+
+#ifdef MS_WINDOWS
+static int
+add_string_value(PyObject *dict, const char *key, const char *str_value)
+{
+    PyObject *value = PyUnicode_FromString(str_value);
+    if (value == NULL) {
+        return -1;
+    }
+    int err = PyDict_SetItemString(dict, key, value);
+    Py_DECREF(value);
+    return err;
+}
+#endif
+
+/*[clinic input]
+_sysconfig.config_vars
+
+Returns a dictionary containing build variables intended to be exposed by sysconfig.
+[clinic start generated code]*/
+
+static PyObject *
+_sysconfig_config_vars_impl(PyObject *module)
+/*[clinic end generated code: output=9c41cdee63ea9487 input=391ff42f3af57d01]*/
+{
+    PyObject *config = PyDict_New();
+    if (config == NULL) {
+        return NULL;
+    }
+
+#ifdef MS_WINDOWS
+    if (add_string_value(config, "EXT_SUFFIX", PYD_TAGGED_SUFFIX) < 0) {
+        Py_DECREF(config);
+        return NULL;
+    }
+    if (add_string_value(config, "SOABI", PYD_SOABI) < 0) {
+        Py_DECREF(config);
+        return NULL;
+    }
+#endif
+
+#ifdef Py_NOGIL
+    PyObject *py_nogil = _PyLong_GetOne();
+#else
+    PyObject *py_nogil = _PyLong_GetZero();
+#endif
+    if (PyDict_SetItemString(config, "Py_NOGIL", py_nogil) < 0) {
+        Py_DECREF(config);
+        return NULL;
+    }
+
+    return config;
+}
+
+PyDoc_STRVAR(sysconfig__doc__,
+"A helper for the sysconfig module.");
+
+static struct PyMethodDef sysconfig_methods[] = {
+    _SYSCONFIG_CONFIG_VARS_METHODDEF
+    {NULL, NULL}
+};
+
+static PyModuleDef_Slot sysconfig_slots[] = {
+    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
+    {0, NULL}
+};
+
+static PyModuleDef sysconfig_module = {
+    .m_base = PyModuleDef_HEAD_INIT,
+    .m_name = "_sysconfig",
+    .m_doc = sysconfig__doc__,
+    .m_methods = sysconfig_methods,
+    .m_slots = sysconfig_slots,
+};
+
+PyMODINIT_FUNC
+PyInit__sysconfig(void)
+{
+    return PyModuleDef_Init(&sysconfig_module);
+}
diff --git a/Modules/clinic/_sysconfig.c.h b/Modules/clinic/_sysconfig.c.h
new file mode 100644 (file)
index 0000000..eb3d396
--- /dev/null
@@ -0,0 +1,22 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(_sysconfig_config_vars__doc__,
+"config_vars($module, /)\n"
+"--\n"
+"\n"
+"Returns a dictionary containing build variables intended to be exposed by sysconfig.");
+
+#define _SYSCONFIG_CONFIG_VARS_METHODDEF    \
+    {"config_vars", (PyCFunction)_sysconfig_config_vars, METH_NOARGS, _sysconfig_config_vars__doc__},
+
+static PyObject *
+_sysconfig_config_vars_impl(PyObject *module);
+
+static PyObject *
+_sysconfig_config_vars(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+    return _sysconfig_config_vars_impl(module);
+}
+/*[clinic end generated code: output=25d395cf02eced1f input=a9049054013a1b77]*/
index 88f69758aac7644410512607c0549c24222aa84b..da2bde640961e0bb8aa69cfa24790b7947f7d97b 100644 (file)
@@ -22,6 +22,7 @@ extern PyObject* PyInit__sha1(void);
 extern PyObject* PyInit__sha2(void);
 extern PyObject* PyInit__sha3(void);
 extern PyObject* PyInit__statistics(void);
+extern PyObject* PyInit__sysconfig(void);
 extern PyObject* PyInit__typing(void);
 extern PyObject* PyInit__blake2(void);
 extern PyObject* PyInit_time(void);
@@ -102,6 +103,7 @@ struct _inittab _PyImport_Inittab[] = {
     {"_sha2", PyInit__sha2},
     {"_sha3", PyInit__sha3},
     {"_blake2", PyInit__blake2},
+    {"_sysconfig", PyInit__sysconfig},
     {"time", PyInit_time},
     {"_thread", PyInit__thread},
     {"_tokenize", PyInit__tokenize},
index 1ec106777db56d77d501e3ecd1a226c3bdc50a06..43a79fd5938486c8599d5a0093beebe3203b38ca 100644 (file)
     <ClInclude Include="..\Include\internal\pycore_hashtable.h" />
     <ClInclude Include="..\Include\internal\pycore_identifier.h" />
     <ClInclude Include="..\Include\internal\pycore_import.h" />
+    <ClInclude Include="..\Include\internal\pycore_importdl.h" />
     <ClInclude Include="..\Include\internal\pycore_initconfig.h" />
     <ClInclude Include="..\Include\internal\pycore_interp.h" />
     <ClInclude Include="..\Include\internal\pycore_intrinsics.h" />
     <ClInclude Include="..\PC\errmap.h" />
     <ClInclude Include="..\PC\pyconfig.h" />
     <ClInclude Include="..\Python\condvar.h" />
-    <ClInclude Include="..\Python\importdl.h" />
     <ClInclude Include="..\Python\stdlib_module_names.h" />
     <ClInclude Include="..\Python\thread_nt.h" />
   </ItemGroup>
     <ClCompile Include="..\Modules\signalmodule.c" />
     <ClCompile Include="..\Modules\_statisticsmodule.c" />
     <ClCompile Include="..\Modules\symtablemodule.c" />
+    <ClCompile Include="..\Modules\_sysconfig.c" />
     <ClCompile Include="..\Modules\_threadmodule.c" />
     <ClCompile Include="..\Modules\_tracemalloc.c" />
     <ClCompile Include="..\Modules\_typingmodule.c" />
index f381120c9b035ac0098ac6b5bddca05586890b14..59159ed609968b84e09523049c64bc43a0629718 100644 (file)
     <ClInclude Include="..\PC\pyconfig.h">
       <Filter>PC</Filter>
     </ClInclude>
-    <ClInclude Include="..\Python\importdl.h">
-      <Filter>Python</Filter>
-    </ClInclude>
     <ClInclude Include="..\Python\stdlib_module_names.h">
       <Filter>Python</Filter>
     </ClInclude>
     <ClInclude Include="..\Include\internal\pycore_import.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
+    <ClInclude Include="..\Include\internal\pycore_importdl.h">
+      <Filter>Include\internal</Filter>
+    </ClInclude>
     <ClInclude Include="..\Include\internal\pycore_initconfig.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
     <ClCompile Include="..\Modules\symtablemodule.c">
       <Filter>Modules</Filter>
     </ClCompile>
+    <ClCompile Include="..\Modules\_sysconfig.c">
+      <Filter>Modules</Filter>
+    </ClCompile>
     <ClCompile Include="..\Modules\_threadmodule.c">
       <Filter>Modules</Filter>
     </ClCompile>
index a53373038ed85988233c7d74db9a83a8ad93b17f..1c44722ff9a2d015c799b2defa56d0b752f50d07 100644 (file)
@@ -5,7 +5,7 @@
 #include <errno.h>
 
 #include "Python.h"
-#include "importdl.h"
+#include "pycore_importdl.h"
 
 #if defined(__hp9000s300)
 #define FUNCNAME_PATTERN "_%.20s_%.200s"
index 6761bba457983bd215e3d5055f4966572d1a951e..5a37a83805ba7895b02bf18b0a984522a2580184 100644 (file)
@@ -4,7 +4,7 @@
 #include "Python.h"
 #include "pycore_interp.h"    // _PyInterpreterState.dlopenflags
 #include "pycore_pystate.h"   // _PyInterpreterState_GET()
-#include "importdl.h"
+#include "pycore_importdl.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
index 59160483caa448bc9f2cba9d59b86ba8a8500ad1..11f7e5f643f79e5a350102308c9bc8080f113cb1 100644 (file)
@@ -3,7 +3,7 @@
    not present. */
 
 #include "Python.h"
-#include "importdl.h"
+#include "pycore_importdl.h"
 
 
 const char *_PyImport_DynLoadFiletab[] = {NULL};
index fcb3cb744047ce3dc651cf5c88732c96073704ad..a0ac31c80a5f6e33088c8f25f82f071a8eebee67 100644 (file)
@@ -5,30 +5,10 @@
 #include "pycore_fileutils.h"     // _Py_add_relfile()
 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
 
-#include "importdl.h"             // dl_funcptr
+#include "pycore_importdl.h"      // dl_funcptr
 #include "patchlevel.h"           // PY_MAJOR_VERSION
 #include <windows.h>
 
-#ifdef _DEBUG
-#define PYD_DEBUG_SUFFIX "_d"
-#else
-#define PYD_DEBUG_SUFFIX ""
-#endif
-
-#ifdef Py_NOGIL
-#  define PYD_THREADING_TAG "t"
-#else
-#  define PYD_THREADING_TAG ""
-#endif
-
-#ifdef PYD_PLATFORM_TAG
-#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX ".cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) PYD_THREADING_TAG "-" PYD_PLATFORM_TAG ".pyd"
-#else
-#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX ".cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) PYD_THREADING_TAG ".pyd"
-#endif
-
-#define PYD_UNTAGGED_SUFFIX PYD_DEBUG_SUFFIX ".pyd"
-
 const char *_PyImport_DynLoadFiletab[] = {
     PYD_TAGGED_SUFFIX,
     PYD_UNTAGGED_SUFFIX,
index 5636968ed9e63bdfe5757ec2b3d60452d4e0b785..cafdd834502224b03f30f9220fa3a60fce1724ef 100644 (file)
@@ -17,7 +17,7 @@
 #include "pycore_weakref.h"       // _PyWeakref_GET_REF()
 
 #include "marshal.h"              // PyMarshal_ReadObjectFromString()
-#include "importdl.h"             // _PyImport_DynLoadFiletab
+#include "pycore_importdl.h"      // _PyImport_DynLoadFiletab
 #include "pydtrace.h"             // PyDTrace_IMPORT_FIND_LOAD_START_ENABLED()
 #include <stdbool.h>              // bool
 
index 9ab0a5ad33aaaceaf10133ba8a93b789c16381ad..7dfd301d77efb494926770a62a723cd0cd7114cf 100644 (file)
@@ -15,7 +15,7 @@
 */
 #ifdef HAVE_DYNAMIC_LOADING
 
-#include "importdl.h"
+#include "pycore_importdl.h"
 
 #ifdef MS_WINDOWS
 extern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
diff --git a/Python/importdl.h b/Python/importdl.h
deleted file mode 100644 (file)
index 9171adc..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef Py_IMPORTDL_H
-#define Py_IMPORTDL_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-extern const char *_PyImport_DynLoadFiletab[];
-
-extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *);
-
-typedef PyObject *(*PyModInitFunction)(void);
-
-/* Max length of module suffix searched for -- accommodates "module.slb" */
-#define MAXSUFFIXSIZE 12
-
-#ifdef MS_WINDOWS
-#include <windows.h>
-typedef FARPROC dl_funcptr;
-#else
-typedef void (*dl_funcptr)(void);
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* !Py_IMPORTDL_H */
index 13b1764f0886d1cbffcb69090eb5242f0cbb9380..701bfc35cc81822dc573bb76b8890bbff2c7c45e 100644 (file)
@@ -77,6 +77,7 @@ static const char* _Py_stdlib_module_names[] = {
 "_strptime",
 "_struct",
 "_symtable",
+"_sysconfig",
 "_thread",
 "_threading_local",
 "_tkinter",
index c6c69a3e222f0729a5cac9989146ebe4fb3a7954..f9911643332b5e474d17eafb3a369fccde8bf71a 100644 (file)
@@ -607,6 +607,7 @@ Modules/_xxtestfuzz/fuzzer.c        LLVMFuzzerTestOneInput  AST_LITERAL_EVAL_INITIALIZED
 # XXX Fix the analyzer.
 
 ## forward/extern references
+Include/internal/pycore_importdl.h     -       _PyImport_DynLoadFiletab        -
 Include/py_curses.h    -       PyCurses_API    -
 Include/pydecimal.h    -       _decimal_api    -
 Modules/_blake2/blake2module.c -       blake2b_type_spec       -
@@ -668,7 +669,6 @@ Objects/object.c    -       _PyLineIterator -
 Objects/object.c       -       _PyPositionsIterator    -
 Python/perf_trampoline.c       -       _Py_trampoline_func_start       -
 Python/perf_trampoline.c       -       _Py_trampoline_func_end -
-Python/importdl.h      -       _PyImport_DynLoadFiletab        -
 Modules/expat/xmlrole.c        -       prolog0 -
 Modules/expat/xmlrole.c        -       prolog1 -
 Modules/expat/xmlrole.c        -       prolog2 -