Skip to content

Commit ab41a34

Browse files
encukouvstinner
andauthored
gh-146636: Improve ABI/feature selection, add new header for it (GH-148302)
Improve ABI/feature selection, add new header for it. Add a test that Python headers themselves don't use Py_GIL_DISABLED in abi3t: abi3 and abi3t ought to be the same except the _Py_OPAQUE_PYOBJECT differences. This is done using the GCC-only poison pragma. Co-authored-by: Victor Stinner <[email protected]>
1 parent 3b93979 commit ab41a34

10 files changed

Lines changed: 148 additions & 82 deletions

File tree

Include/Python.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
// is not needed.
1010

1111

12-
// Include Python header files
13-
#include "patchlevel.h"
14-
#include "pyconfig.h"
15-
#include "pymacconfig.h"
12+
// Include Python configuration headers
13+
#include "patchlevel.h" // the Python version
14+
#include "pyconfig.h" // information from configure
15+
#include "pymacconfig.h" // overrides for pyconfig
16+
#include "pyabi.h" // feature/ABI selection
1617

1718

1819
// Include standard header files
@@ -46,13 +47,11 @@
4647
# endif
4748
#endif
4849

49-
#if defined(Py_GIL_DISABLED)
50-
# if defined(_MSC_VER)
51-
# include <intrin.h> // __readgsqword()
52-
# endif
53-
54-
# if defined(__MINGW32__)
55-
# include <intrin.h> // __readgsqword()
50+
#if !defined(Py_LIMITED_API)
51+
# if defined(Py_GIL_DISABLED)
52+
# if defined(_MSC_VER) || defined(__MINGW32__)
53+
# include <intrin.h> // __readgsqword()
54+
# endif
5655
# endif
5756
#endif // Py_GIL_DISABLED
5857

@@ -67,6 +66,7 @@ __pragma(warning(disable: 4201))
6766

6867
// Include Python header files
6968
#include "pyport.h"
69+
#include "exports.h"
7070
#include "pymacro.h"
7171
#include "pymath.h"
7272
#include "pymem.h"

Include/exports.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#define Py_LOCAL_SYMBOL
3737
#endif
3838
/* module init functions outside the core must be exported */
39-
#if defined(Py_BUILD_CORE)
39+
#if defined(_PyEXPORTS_CORE)
4040
#define _PyINIT_EXPORTED_SYMBOL Py_EXPORTED_SYMBOL
4141
#else
4242
#define _PyINIT_EXPORTED_SYMBOL __declspec(dllexport)
@@ -64,13 +64,13 @@
6464
/* only get special linkage if built as shared or platform is Cygwin */
6565
#if defined(Py_ENABLE_SHARED) || defined(__CYGWIN__)
6666
# if defined(HAVE_DECLSPEC_DLL)
67-
# if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
67+
# if defined(_PyEXPORTS_CORE) && !defined(_PyEXPORTS_CORE_MODULE)
6868
/* module init functions inside the core need no external linkage */
6969
/* except for Cygwin to handle embedding */
7070
# if !defined(__CYGWIN__)
7171
# define _PyINIT_FUNC_DECLSPEC
7272
# endif /* __CYGWIN__ */
73-
# else /* Py_BUILD_CORE */
73+
# else /* _PyEXPORTS_CORE */
7474
/* Building an extension module, or an embedded situation */
7575
/* public Python functions and data are imported */
7676
/* Under Cygwin, auto-import functions to prevent compilation */
@@ -80,7 +80,7 @@
8080
# define PyAPI_FUNC(RTYPE) Py_IMPORTED_SYMBOL RTYPE
8181
# endif /* !__CYGWIN__ */
8282
# define PyAPI_DATA(RTYPE) extern Py_IMPORTED_SYMBOL RTYPE
83-
# endif /* Py_BUILD_CORE */
83+
# endif /* _PyEXPORTS_CORE */
8484
# endif /* HAVE_DECLSPEC_DLL */
8585
#endif /* Py_ENABLE_SHARED */
8686

Include/patchlevel.h

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -61,32 +61,4 @@
6161
#define PYTHON_ABI_VERSION 3
6262
#define PYTHON_ABI_STRING "3"
6363

64-
65-
/* Stable ABI for free-threaded builds (introduced in PEP 803)
66-
is enabled by one of:
67-
- Py_TARGET_ABI3T, or
68-
- Py_LIMITED_API and Py_GIL_DISABLED.
69-
"Output" macros to be used internally:
70-
- Py_LIMITED_API (defines the subset of API we expose)
71-
- _Py_OPAQUE_PYOBJECT (additionally hides what's ABI-incompatible between
72-
free-threaded & GIL)
73-
(Don't use Py_TARGET_ABI3T directly: it's currently only used to set these
74-
2 macros. It's also available for users' convenience.)
75-
*/
76-
#if defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) \
77-
&& !defined(Py_TARGET_ABI3T)
78-
# define Py_TARGET_ABI3T Py_LIMITED_API
79-
#endif
80-
#if defined(Py_TARGET_ABI3T)
81-
# define _Py_OPAQUE_PYOBJECT
82-
# if !defined(Py_LIMITED_API)
83-
# define Py_LIMITED_API Py_TARGET_ABI3T
84-
# elif Py_LIMITED_API > Py_TARGET_ABI3T
85-
// if both are defined, use the *lower* version,
86-
// i.e. maximum compatibility
87-
# undef Py_LIMITED_API
88-
# define Py_LIMITED_API Py_TARGET_ABI3T
89-
# endif
90-
#endif
91-
9264
#endif //_Py_PATCHLEVEL_H

Include/pyabi.h

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/* Macros that restrict available definitions and select implementations
2+
* to match an ABI stability promise:
3+
*
4+
* - internal API/ABI (may change at any time) -- Py_BUILD_CORE*
5+
* - general CPython API/ABI (may change in 3.x.0) -- default
6+
* - Stable ABI: abi3, abi3t (long-term stable) -- Py_LIMITED_API,
7+
* Py_TARGET_ABI3T, _Py_OPAQUE_PYOBJECT
8+
* - Free-threading (incompatible with non-free-threading builds)
9+
* -- Py_GIL_DISABLED
10+
*/
11+
12+
#ifndef _Py_PYABI_H
13+
#define _Py_PYABI_H
14+
15+
/* Defines to build Python and its standard library:
16+
*
17+
* - Py_BUILD_CORE: Build Python core. Gives access to Python internals; should
18+
* not be used by third-party modules.
19+
* - Py_BUILD_CORE_BUILTIN: Build a Python stdlib module as a built-in module.
20+
* - Py_BUILD_CORE_MODULE: Build a Python stdlib module as a dynamic library.
21+
*
22+
* Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE imply Py_BUILD_CORE.
23+
*
24+
* On Windows, Py_BUILD_CORE_MODULE exports "PyInit_xxx" symbol, whereas
25+
* Py_BUILD_CORE_BUILTIN does not.
26+
*/
27+
#if defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE)
28+
# define Py_BUILD_CORE
29+
#endif
30+
#if defined(Py_BUILD_CORE_MODULE) && !defined(Py_BUILD_CORE)
31+
# define Py_BUILD_CORE
32+
#endif
33+
34+
/* Check valid values for target ABI macros.
35+
*/
36+
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 3
37+
// Empty Py_LIMITED_API used to work; redefine to
38+
// Python 3.2 to be explicit.
39+
# undef Py_LIMITED_API
40+
# define Py_LIMITED_API 0x03020000
41+
#endif
42+
#if defined(Py_TARGET_ABI3T) && Py_TARGET_ABI3T+0 < 0x030f0000
43+
# error "Py_TARGET_ABI3T must be 0x030f0000 (3.15) or above"
44+
#endif
45+
46+
/* Stable ABI for free-threaded builds (abi3t, introduced in PEP 803)
47+
* is enabled by one of:
48+
* - Py_TARGET_ABI3T, or
49+
* - Py_LIMITED_API and Py_GIL_DISABLED.
50+
*
51+
* These affect set the following, which Python.h should use internally:
52+
* - Py_LIMITED_API (defines the subset of API we expose)
53+
* - _Py_OPAQUE_PYOBJECT (additionally hides what's ABI-incompatible between
54+
* free-threaded & GIL)
55+
*
56+
* (Don't use Py_TARGET_ABI3T directly. It's currently only used to set these
57+
* 2 macros, and defined for users' convenience.)
58+
*/
59+
#if defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) \
60+
&& !defined(Py_TARGET_ABI3T)
61+
# define Py_TARGET_ABI3T Py_LIMITED_API
62+
#endif
63+
#if defined(Py_TARGET_ABI3T)
64+
# define _Py_OPAQUE_PYOBJECT
65+
# if !defined(Py_LIMITED_API)
66+
# define Py_LIMITED_API Py_TARGET_ABI3T
67+
# elif Py_LIMITED_API > Py_TARGET_ABI3T
68+
// if both are defined, use the *lower* version,
69+
// i.e. maximum compatibility
70+
# undef Py_LIMITED_API
71+
# define Py_LIMITED_API Py_TARGET_ABI3T
72+
# endif
73+
#else
74+
# ifdef _Py_OPAQUE_PYOBJECT
75+
// _Py_OPAQUE_PYOBJECT is a private macro; do not define it directly.
76+
# error "Define Py_TARGET_ABI3T to target abi3t."
77+
# endif
78+
#endif
79+
80+
#if defined(Py_TARGET_ABI3T)
81+
# if !defined(Py_GIL_DISABLED)
82+
// Define Py_GIL_DISABLED for users' needs. Users check this macro to see
83+
// whether they need extra synchronization.
84+
# define Py_GIL_DISABLED
85+
# endif
86+
# if defined(_Py_IS_TESTCEXT)
87+
// When compiling for abi3t, contents of Python.h should not depend
88+
// on Py_GIL_DISABLED.
89+
// We ask GCC to error if it sees the macro from this point on.
90+
// Since users are free to the macro, and there's no way to undo the
91+
// poisoning at the end of Python.h, we only do this in a test module
92+
// (test_cext).
93+
//
94+
// Clang's poisoning is stricter than GCC's: it looks in `#elif`
95+
// expressions after matching `#if`s. We disable it for now.
96+
// We also provide an undocumented, unsupported opt-out macro to help
97+
// porting to other compilers. Consider reaching out if you use it.
98+
# if defined(__GNUC__) && !defined(__clang__) && !defined(_Py_NO_GCC_POISON)
99+
# undef Py_GIL_DISABLED
100+
# pragma GCC poison Py_GIL_DISABLED
101+
# endif
102+
# endif
103+
#endif
104+
105+
/* The internal C API must not be used with the limited C API: make sure
106+
* that Py_BUILD_CORE* macros are not defined in this case.
107+
* But, keep the "original" values, under different names, for "exports.h"
108+
*/
109+
#ifdef Py_BUILD_CORE
110+
# define _PyEXPORTS_CORE
111+
#endif
112+
#ifdef Py_BUILD_CORE_MODULE
113+
# define _PyEXPORTS_CORE_MODULE
114+
#endif
115+
#ifdef Py_LIMITED_API
116+
# undef Py_BUILD_CORE
117+
# undef Py_BUILD_CORE_BUILTIN
118+
# undef Py_BUILD_CORE_MODULE
119+
#endif
120+
121+
#endif // _Py_PYABI_H

Include/pyport.h

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -58,34 +58,6 @@
5858
#endif
5959

6060

61-
/* Defines to build Python and its standard library:
62-
*
63-
* - Py_BUILD_CORE: Build Python core. Give access to Python internals, but
64-
* should not be used by third-party modules.
65-
* - Py_BUILD_CORE_BUILTIN: Build a Python stdlib module as a built-in module.
66-
* - Py_BUILD_CORE_MODULE: Build a Python stdlib module as a dynamic library.
67-
*
68-
* Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE imply Py_BUILD_CORE.
69-
*
70-
* On Windows, Py_BUILD_CORE_MODULE exports "PyInit_xxx" symbol, whereas
71-
* Py_BUILD_CORE_BUILTIN does not.
72-
*/
73-
#if defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE)
74-
# define Py_BUILD_CORE
75-
#endif
76-
#if defined(Py_BUILD_CORE_MODULE) && !defined(Py_BUILD_CORE)
77-
# define Py_BUILD_CORE
78-
#endif
79-
80-
#if defined(Py_TARGET_ABI3T)
81-
# if !defined(Py_GIL_DISABLED)
82-
// Define Py_GIL_DISABLED for users' needs. This macro is used to enable
83-
// locking needed in for free-threaded interpreters builds.
84-
# define Py_GIL_DISABLED
85-
# endif
86-
#endif
87-
88-
8961
/**************************************************************************
9062
Symbols and macros to supply platform-independent interfaces to basic
9163
C language & library operations whose spellings vary across platforms.
@@ -393,17 +365,6 @@ extern "C" {
393365
# define Py_NO_INLINE
394366
#endif
395367

396-
#include "exports.h"
397-
398-
#ifdef Py_LIMITED_API
399-
// The internal C API must not be used with the limited C API: make sure
400-
// that Py_BUILD_CORE macro is not defined in this case. These 3 macros are
401-
// used by exports.h, so only undefine them afterwards.
402-
# undef Py_BUILD_CORE
403-
# undef Py_BUILD_CORE_BUILTIN
404-
# undef Py_BUILD_CORE_MODULE
405-
#endif
406-
407368
/* limits.h constants that may be missing */
408369

409370
#ifndef INT_MAX

Lib/test/test_cext/setup.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
# The purpose of test_cext extension is to check that building a C
1919
# extension using the Python C API does not emit C compiler warnings.
2020
'-Werror',
21+
# Enable extra checks for header files, which:
22+
# - need to be enabled somewhere inside Python headers (rather than
23+
# before including Python.h)
24+
# - should not be checked for user code
25+
'-D_Py_IS_TESTCEXT',
2126
]
2227

2328
# C compiler flags for GCC and clang

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,7 @@ PYTHON_HEADERS= \
12141214
$(srcdir)/Include/osdefs.h \
12151215
$(srcdir)/Include/osmodule.h \
12161216
$(srcdir)/Include/patchlevel.h \
1217+
$(srcdir)/Include/pyabi.h \
12171218
$(srcdir)/Include/pyatomic.h \
12181219
$(srcdir)/Include/pybuffer.h \
12191220
$(srcdir)/Include/pycapsule.h \
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Using :c:macro:`Py_LIMITED_API` on a non-Windows free-threaded build no
2+
longer needs an extra :c:macro:`Py_GIL_DISABLED`.

PCbuild/pythoncore.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@
359359
<ClInclude Include="..\Include\osmodule.h" />
360360
<ClInclude Include="..\Include\patchlevel.h" />
361361
<ClInclude Include="..\Include\py_curses.h" />
362+
<ClInclude Include="..\Include\pyabi.h" />
362363
<ClInclude Include="..\Include\pyatomic.h" />
363364
<ClInclude Include="..\Include\pybuffer.h" />
364365
<ClInclude Include="..\Include\pycapsule.h" />

PCbuild/pythoncore.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@
156156
<ClInclude Include="..\Include\py_curses.h">
157157
<Filter>Include</Filter>
158158
</ClInclude>
159+
<ClInclude Include="..\Include\pyabi.h">
160+
<Filter>Include</Filter>
161+
</ClInclude>
159162
<ClInclude Include="..\Include\pyatomic.h">
160163
<Filter>Include</Filter>
161164
</ClInclude>

0 commit comments

Comments
 (0)