Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions Include/Python.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
// is not needed.


// Include Python header files
#include "patchlevel.h"
#include "pyconfig.h"
#include "pymacconfig.h"
// Include Python configuration headers
#include "patchlevel.h" // the Python version
#include "pyconfig.h" // information from configure
#include "pymacconfig.h" // overrides for pyconfig
#include "pyabi.h" // feature/ABI selection


// Include standard header files
Expand Down Expand Up @@ -46,13 +47,11 @@
# endif
#endif

#if defined(Py_GIL_DISABLED)
# if defined(_MSC_VER)
# include <intrin.h> // __readgsqword()
# endif

# if defined(__MINGW32__)
# include <intrin.h> // __readgsqword()
#if !defined(Py_LIMITED_API)
# if defined(Py_GIL_DISABLED)
# if defined(_MSC_VER) || defined(__MINGW32__)
# include <intrin.h> // __readgsqword()
# endif
# endif
#endif // Py_GIL_DISABLED

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

// Include Python header files
#include "pyport.h"
#include "exports.h"
#include "pymacro.h"
#include "pymath.h"
#include "pymem.h"
Expand Down
8 changes: 4 additions & 4 deletions Include/exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#define Py_LOCAL_SYMBOL
#endif
/* module init functions outside the core must be exported */
#if defined(Py_BUILD_CORE)
#if defined(_PyEXPORTS_CORE)
#define _PyINIT_EXPORTED_SYMBOL Py_EXPORTED_SYMBOL
#else
#define _PyINIT_EXPORTED_SYMBOL __declspec(dllexport)
Expand Down Expand Up @@ -64,13 +64,13 @@
/* only get special linkage if built as shared or platform is Cygwin */
#if defined(Py_ENABLE_SHARED) || defined(__CYGWIN__)
# if defined(HAVE_DECLSPEC_DLL)
# if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# if defined(_PyEXPORTS_CORE) && !defined(_PyEXPORTS_CORE_MODULE)
/* module init functions inside the core need no external linkage */
/* except for Cygwin to handle embedding */
# if !defined(__CYGWIN__)
# define _PyINIT_FUNC_DECLSPEC
# endif /* __CYGWIN__ */
# else /* Py_BUILD_CORE */
# else /* _PyEXPORTS_CORE */
/* Building an extension module, or an embedded situation */
/* public Python functions and data are imported */
/* Under Cygwin, auto-import functions to prevent compilation */
Expand All @@ -80,7 +80,7 @@
# define PyAPI_FUNC(RTYPE) Py_IMPORTED_SYMBOL RTYPE
# endif /* !__CYGWIN__ */
# define PyAPI_DATA(RTYPE) extern Py_IMPORTED_SYMBOL RTYPE
# endif /* Py_BUILD_CORE */
# endif /* _PyEXPORTS_CORE */
# endif /* HAVE_DECLSPEC_DLL */
#endif /* Py_ENABLE_SHARED */

Expand Down
28 changes: 0 additions & 28 deletions Include/patchlevel.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,32 +61,4 @@
#define PYTHON_ABI_VERSION 3
#define PYTHON_ABI_STRING "3"


/* Stable ABI for free-threaded builds (introduced in PEP 803)
is enabled by one of:
- Py_TARGET_ABI3T, or
- Py_LIMITED_API and Py_GIL_DISABLED.
"Output" macros to be used internally:
- Py_LIMITED_API (defines the subset of API we expose)
- _Py_OPAQUE_PYOBJECT (additionally hides what's ABI-incompatible between
free-threaded & GIL)
(Don't use Py_TARGET_ABI3T directly: it's currently only used to set these
2 macros. It's also available for users' convenience.)
*/
#if defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) \
&& !defined(Py_TARGET_ABI3T)
# define Py_TARGET_ABI3T Py_LIMITED_API
#endif
#if defined(Py_TARGET_ABI3T)
# define _Py_OPAQUE_PYOBJECT
# if !defined(Py_LIMITED_API)
# define Py_LIMITED_API Py_TARGET_ABI3T
# elif Py_LIMITED_API > Py_TARGET_ABI3T
// if both are defined, use the *lower* version,
// i.e. maximum compatibility
# undef Py_LIMITED_API
# define Py_LIMITED_API Py_TARGET_ABI3T
# endif
#endif

#endif //_Py_PATCHLEVEL_H
99 changes: 99 additions & 0 deletions Include/pyabi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/* Macros that restrict available definitions and select implementations
* to match an ABI stability promise:
*
* - internal API/ABI (may change at any time) -- Py_BUILD_CORE*
* - general CPython API/ABI (may change in 3.x.0) -- default
* - Stable ABI: abi3, abi3t (long-term stable) -- Py_LIMITED_API,
* Py_TARGET_ABI3T, _Py_OPAQUE_PYOBJECT
* - Free-threading (incompatible with non-free-threading builds)
* -- Py_GIL_DISABLED
*/

#ifndef _Py_PYABI_H
#define _Py_PYABI_H

/* Defines to build Python and its standard library:
*
* - Py_BUILD_CORE: Build Python core. Gives access to Python internals; should
* not be used by third-party modules.
* - Py_BUILD_CORE_BUILTIN: Build a Python stdlib module as a built-in module.
* - Py_BUILD_CORE_MODULE: Build a Python stdlib module as a dynamic library.
*
* Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE imply Py_BUILD_CORE.
*
* On Windows, Py_BUILD_CORE_MODULE exports "PyInit_xxx" symbol, whereas
* Py_BUILD_CORE_BUILTIN does not.
*/
#if defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE)
# define Py_BUILD_CORE
#endif
#if defined(Py_BUILD_CORE_MODULE) && !defined(Py_BUILD_CORE)
# define Py_BUILD_CORE
#endif

/* Stable ABI for free-threaded builds (abi3t, introduced in PEP 803)
* is enabled by one of:
* - Py_TARGET_ABI3T, or
* - Py_LIMITED_API and Py_GIL_DISABLED.
*
* These affect set the following, which Python.h should use internally:
* - Py_LIMITED_API (defines the subset of API we expose)
* - _Py_OPAQUE_PYOBJECT (additionally hides what's ABI-incompatible between
* free-threaded & GIL)
*
* (Don't use Py_TARGET_ABI3T directly. It's currently only used to set these
* 2 macros, and defined for users' convenience.)
*/
#if defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) \
&& !defined(Py_TARGET_ABI3T)
# define Py_TARGET_ABI3T Py_LIMITED_API
#endif
#if defined(Py_TARGET_ABI3T)
# define _Py_OPAQUE_PYOBJECT
# if !defined(Py_LIMITED_API)
# define Py_LIMITED_API Py_TARGET_ABI3T
# elif Py_LIMITED_API > Py_TARGET_ABI3T
// if both are defined, use the *lower* version,
// i.e. maximum compatibility
# undef Py_LIMITED_API
# define Py_LIMITED_API Py_TARGET_ABI3T
# endif
#endif

#if defined(Py_TARGET_ABI3T)
# if !defined(Py_GIL_DISABLED)
// Define Py_GIL_DISABLED for users' needs. Users check this macro to see
// whether they need extra synchronization.
# define Py_GIL_DISABLED
# endif
# if defined(_Py_IS_TESTCEXT)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may move #ifdef __GNUC__ here:

Suggested change
# if defined(_Py_IS_TESTCEXT)
# if defined(_Py_IS_TESTCEXT) && defined(__GNUC__)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This subtle style detail is intentional: I'm inviting #elifs for other compilers.

// When compiling for abi3t, contents of Python.h should not depend
// on Py_GIL_DISABLED.
// We ask GCC to error if it sees the macro from this point on.
// Since users are free to the macro, and there's no way to undo the
// poisoning at the end of Python.h, we only do this in a test module
// (test_cext).
# ifdef __GNUC__
# undef Py_GIL_DISABLED
# pragma GCC poison Py_GIL_DISABLED
# endif
# endif
#endif

/* The internal C API must not be used with the limited C API: make sure
* that Py_BUILD_CORE* macros are not defined in this case.
* But, keep the "original" values, under different names, for "exports.h"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's surprising that _PyEXPORTS_CORE and _PyEXPORTS_CORE_MODULE are defined even if Py_LIMITED_API is defined. I tried to undefine Py_BUILD_CORE if Py_LIMITED_API is defined before _PyEXPORTS_CORE code, but I got linker errors on Windows. Examples:

LINK : warning LNK4217: symbol 'PyType_GetFlags' defined in 'typeobject.obj' is imported by '_stat.obj' in fu 
nction '_PyLong_AsMode_t' [C:\victor\python\main\PCbuild\pythoncore.vcxproj]
LINK : warning LNK4217: symbol '_Py_DecRef' defined in 'object.obj' is imported by '_stat.obj' in function '_ 
PyLong_AsMode_t' [C:\victor\python\main\PCbuild\pythoncore.vcxproj]
LINK : warning LNK4286: symbol '_Py_DecRef' defined in 'object.obj' is imported by 'errnomodule.obj' [C:\vict 
or\python\main\PCbuild\pythoncore.vcxproj]
LINK : warning LNK4217: symbol 'PyUnicode_FromStringAndSize' defined in 'unicodeobject.obj' is imported by '_ 
stat.obj' in function 'stat_filemode' [C:\victor\python\main\PCbuild\pythoncore.vcxproj]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes; these select whether PyAPI_FUNC sumbols are exported or imported. Anything compiled into the main binary needs to be exported, regardless of the API it uses.

(This is currently done by including "exports.h" in the middle of pyport.h, right before Py_BUILD_CORE is undefined -- which is IMO confusing, as it makes the meaning of Py_BUILD_CORE depend on where you are in the header.)

*/
#ifdef Py_BUILD_CORE
# define _PyEXPORTS_CORE
#endif
#ifdef Py_BUILD_CORE_MODULE
# define _PyEXPORTS_CORE_MODULE
#endif
#ifdef Py_LIMITED_API
# undef Py_BUILD_CORE
# undef Py_BUILD_CORE_BUILTIN
# undef Py_BUILD_CORE_MODULE
#endif

#endif // _Py_PYABI_H
39 changes: 0 additions & 39 deletions Include/pyport.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,34 +58,6 @@
#endif


/* Defines to build Python and its standard library:
*
* - Py_BUILD_CORE: Build Python core. Give access to Python internals, but
* should not be used by third-party modules.
* - Py_BUILD_CORE_BUILTIN: Build a Python stdlib module as a built-in module.
* - Py_BUILD_CORE_MODULE: Build a Python stdlib module as a dynamic library.
*
* Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE imply Py_BUILD_CORE.
*
* On Windows, Py_BUILD_CORE_MODULE exports "PyInit_xxx" symbol, whereas
* Py_BUILD_CORE_BUILTIN does not.
*/
#if defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE)
# define Py_BUILD_CORE
#endif
#if defined(Py_BUILD_CORE_MODULE) && !defined(Py_BUILD_CORE)
# define Py_BUILD_CORE
#endif

#if defined(Py_TARGET_ABI3T)
# if !defined(Py_GIL_DISABLED)
// Define Py_GIL_DISABLED for users' needs. This macro is used to enable
// locking needed in for free-threaded interpreters builds.
# define Py_GIL_DISABLED
# endif
#endif


/**************************************************************************
Symbols and macros to supply platform-independent interfaces to basic
C language & library operations whose spellings vary across platforms.
Expand Down Expand Up @@ -393,17 +365,6 @@ extern "C" {
# define Py_NO_INLINE
#endif

#include "exports.h"

#ifdef Py_LIMITED_API
// The internal C API must not be used with the limited C API: make sure
// that Py_BUILD_CORE macro is not defined in this case. These 3 macros are
// used by exports.h, so only undefine them afterwards.
# undef Py_BUILD_CORE
# undef Py_BUILD_CORE_BUILTIN
# undef Py_BUILD_CORE_MODULE
#endif

/* limits.h constants that may be missing */

#ifndef INT_MAX
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_cext/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
# The purpose of test_cext extension is to check that building a C
# extension using the Python C API does not emit C compiler warnings.
'-Werror',
# Enable extra checks for header files, which:
# - need to be enabled somewhere inside Python headers (rather than
# before including Python.h)
# - should not be checked for user code
'-D_Py_IS_TESTCEXT',
]

# C compiler flags for GCC and clang
Expand Down
1 change: 1 addition & 0 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/osdefs.h \
$(srcdir)/Include/osmodule.h \
$(srcdir)/Include/patchlevel.h \
$(srcdir)/Include/pyabi.h \
$(srcdir)/Include/pyatomic.h \
$(srcdir)/Include/pybuffer.h \
$(srcdir)/Include/pycapsule.h \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Using :c:macro:`Py_LIMITED_API` on a non-Windows free-threaded build no
longer needs an extra :c:macro:`Py_GIL_DISABLED`.
1 change: 1 addition & 0 deletions PCbuild/pythoncore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@
<ClInclude Include="..\Include\osmodule.h" />
<ClInclude Include="..\Include\patchlevel.h" />
<ClInclude Include="..\Include\py_curses.h" />
<ClInclude Include="..\Include\pyabi.h" />
<ClInclude Include="..\Include\pyatomic.h" />
<ClInclude Include="..\Include\pybuffer.h" />
<ClInclude Include="..\Include\pycapsule.h" />
Expand Down
3 changes: 3 additions & 0 deletions PCbuild/pythoncore.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@
<ClInclude Include="..\Include\py_curses.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\pyabi.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\pyatomic.h">
<Filter>Include</Filter>
</ClInclude>
Expand Down
Loading