Skip to content

Conversation

@encukou
Copy link
Contributor

@encukou encukou commented Jan 13, 2026

Since PEP 793, it's valid for modules to not have a PyInit function. Telling MSVC to export a nonexistent function will make it fail.

The function should be exported in code, using PyMODINIT_FUNC (which adds __declspec(dllexport), which is preferred over /EXPORT according to Microsoft docs.)

Fixes: #387

Since PEP 793, it's valid for modules to not have a PyInit function.
Telling MSVC to export a nonexistent function will make it fail.

The function should be exported in code, using `PyMODINIT_FUNC`
(which adds `__declspec(dllexport)`, which is preferred over
`/EXPORT` according to [Microsoft docs].)

Microsoft docs: https://learn.microsoft.com/en-us/cpp/build/reference/export-exports-a-function?view=msvc-170
Copy link

@rgommers rgommers left a comment

Choose a reason for hiding this comment

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

This implementation looks good to me, for now I only have a few very small suggestions for the docstring. I still need to do some testing with a few real-world packages.

For other reviewers: this relies on python/cpython#141672, which was merged only last week.

import hook function.
Since Python 3.15, don't add anything.
An export directive should be in the code itself.

Choose a reason for hiding this comment

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

The original could possibly confuse the reader, since it could be read as
the package author having to do something - so try to rephrase:

Suggested change
An export directive should be in the code itself.
An export directive was added to the "PyMODINIT_FUNC" implementation
for Python 3.15, which is all that is needed.

export. This returns, and possibly updates, 'ext.export_symbols'.
On Python 3.14 and below (that is, before a new export hook name was added),
it adds "PyInit_" + module_name 'ext.export_symbols'.

Choose a reason for hiding this comment

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

Suggested change
it adds "PyInit_" + module_name 'ext.export_symbols'.
it adds "PyInit_" + module_name to 'ext.export_symbols'.

@rgommers
Copy link

I tested this change with the setuptools/c test case in https://github.com/Quansight-Labs/stable-abi-testing (side note: not yet fully polished, but it's usable enough to derive test cases from now; it contains test packages in a build-backends x binding-generators matrix).

With the latest released version of setuptools, that test package fails to build with 3.15.0a3 - which is the most recent build available in GHA's setup-python - with (CI log):

LINK : error LNK2001: unresolved external symbol PyInit_limited

After applying the patch in this PR to setuptools._distutils, that error goes away and the package builds and passes its tests (CI log).

That repo uses test packages with PyMODEXPORT_FUNC rather than PyMODINIT_FUNC, so that does not yet prove that this also works with the latter.

I then started with psutil, tested the patch with its existing wheel build CI matrix for completeness - that passed of course, since 3.15 wheels are not included yet (no cibuildwheel support), and this PR is a no-op on older Python versions.

I then also added a new psutil CI job for 3.15, before figuring out that psutil depends on pywin32 which doesn't have an sdist and doesn't build from source. So that's where I gave up.

Testing on 3.15-alpha is pretty cumbersome given the many packaging components and packages that don't yet support 3.15. That said, I'm confident that this PR works, and the testing I was able to do all worked as expected - so I'm +1 for merging this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Avoid passing /EXPORT:PyInit_* to MSVC for Python 3.15+ (PEP 793)

2 participants