Skip to content

gh-148690: Build abi3t-compat\python3.dll on Windows#148912

Open
encukou wants to merge 12 commits intopython:mainfrom
encukou:windows-abi3t-compat
Open

gh-148690: Build abi3t-compat\python3.dll on Windows#148912
encukou wants to merge 12 commits intopython:mainfrom
encukou:windows-abi3t-compat

Conversation

@encukou
Copy link
Copy Markdown
Member

@encukou encukou commented Apr 23, 2026

Per discussion in #146636 (comment), this adds abi3t-compat\python3.dll to Windows builds.

And to the WiX installer, though I haven't managed to test this.

Copy link
Copy Markdown
Contributor

@clin1234 clin1234 left a comment

Choose a reason for hiding this comment

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

Looks congruent to me

@zooba
Copy link
Copy Markdown
Member

zooba commented Apr 23, 2026

Looks like a solid change, but probably simpler to just create a python3t.vcxproj and put the python3t.dll in the default location, which will remove a lot of the modifications (and can simplify things you didn't even add, since we'll just build it twice and python3.dll and python3t.dll are now both constants). We rearrange output files as part of building the installer, so that's where the directory should come into it.

It won't work so nicely for dev/in-tree builds, but I'm not so concerned about that. We probably need to choose an entirely new output directory for free-threaded builds, but that's going to break all sorts of stuff that assumes directory names in a build, so probably best to just say "ABI3 will get weird in dev builds if you don't clean before switching kind of build". I expect anyone trying to work on both simultaneously has separate clones anyway.

@chris-eibl
Copy link
Copy Markdown
Member

I've tried to build the installer using your branch and get the same error as CI:

error CNDL0027: The File/@Name attribute's value, 'abi3t-compat\python3t.dll', is not a valid long name because it contains illegal characters.

Changing to

            <Component Id="python_abi3tcompat.dll" Directory="abi3t_compat" Guid="*">
                <File Id="python_abi3tcompat.dll" Name="python$(var.MajorVersionNumber)t.dll" KeyPath="yes" />
            </Component>

and adding the directory to Tools/msi/common.wxs:

    <Fragment>
        <DirectoryRef Id="InstallDirectory">
            <Directory Id="abi3t_compat" Name="abi3t-compat" />
        </DirectoryRef>
    </Fragment>

Note Id="abi3t_compat" is chosen, because - is not allowed in an identifier.

As Steve mentions

put the python3t.dll in the default location,

then the above did work for me (when manually copying the dll just to try it out).

Otherwise, you'd have to add a Source in

<File Id="python_abi3tcompat.dll" Name="python$(var.MajorVersionNumber)t.dll" KeyPath="yes" />

But this is all new to me as well ...

@chris-eibl
Copy link
Copy Markdown
Member

Adding

        <LinkerBindInputPaths Include="$(BuildPath)">
            <BindName>build</BindName>
        </LinkerBindInputPaths>

to Tools\msi\msi.props and using

<File Id="python_abi3tcompat.dll" Name="python$(var.MajorVersionNumber)t.dll" Source="!(bindpath.build)\abi3t-compat\python$(var.MajorVersionNumber)t.dll" KeyPath="yes" />

did work for me using your current layout.

@chris-eibl
Copy link
Copy Markdown
Member

And IMHO we should bundle python3t_d.dll in the installer as well.

@zooba
Copy link
Copy Markdown
Member

zooba commented Apr 24, 2026

Changing to

            <Component Id="python_abi3tcompat.dll" Directory="abi3t_compat" Guid="*">
                <File Id="python_abi3tcompat.dll" Name="python$(var.MajorVersionNumber)t.dll" KeyPath="yes" />
            </Component>

and adding the directory to Tools/msi/common.wxs:

    <Fragment>
        <DirectoryRef Id="InstallDirectory">
            <Directory Id="abi3t_compat" Name="abi3t-compat" />
        </DirectoryRef>
    </Fragment>

This is the way.

this is all new to me as well ...

In two more weeks we get to never touch this MSI again :)

@encukou
Copy link
Copy Markdown
Member Author

encukou commented Apr 28, 2026

Thanks for the pointers!

This is how far I got in another day: python3dll and python3tdll with fixed names.
Further pointers would be appreciated again :)
I got it to build on CI, and on my machine once, but now Tools\msi\build.bat -x64 is giving me:

Build FAILED.

"C:\Users\encukou\dev\cpython\Tools\msi\bundle\snapshot.wixproj" (default target) (1) ->
"C:\Users\encukou\dev\cpython\Tools\msi\doc\doc.wixproj" (Build target) (7) ->
(Link target) ->
  C:\Users\encukou\dev\cpython\Tools\msi\doc\doc.wxs(12): error LGHT0094: Unresolved reference to symbol 'WixComponen 
tGroup:doc_html' in section 'Product:*'. [C:\Users\encukou\dev\cpython\Tools\msi\doc\doc.wixproj]
  C:\Users\encukou\dev\cpython\Tools\msi\doc\doc.wxs(27): error LGHT0094: Unresolved reference to symbol 'WixComponen 
tGroup:doc_html' in section 'Product:*'. [C:\Users\encukou\dev\cpython\Tools\msi\doc\doc.wixproj]

I'll continue tomorrow.

@zooba
Copy link
Copy Markdown
Member

zooba commented Apr 28, 2026

I think you need to build docs manually for the installer? I remember cutting a corner in the msi/build.bat that I regretted, but solved it by basically never using that script again... buildrelease.bat should do it all.

Couple of other comments/concerns coming on the changes.

@ngoldbaum
Copy link
Copy Markdown
Contributor

ngoldbaum commented Apr 28, 2026

I built an installer based on this branch, but am seeing issues caused by the python3t.dll produced being self-referential:

C:\Users\goldbaum\AppData\Local\Programs\Python\Python315>dumpbin /exports abi3t-compat\python3t.dll
Microsoft (R) COFF/PE Dumper Version 14.44.35226.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file abi3t-compat\python3t.dll

File Type: DLL

  Section contains the following exports for python3t.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
         948 number of functions
         948 number of names

    ordinal hint RVA      name

          1    0          PyABIInfo_Check (forwarded to python3t.PyABIInfo_Check)
          2    1          PyAIter_Check (forwarded to python3t.PyAIter_Check)
          3    2          PyArg_Parse (forwarded to python3t.PyArg_Parse)
          4    3          PyArg_ParseTuple (forwarded to python3t.PyArg_ParseTuple)
          5    4          PyArg_ParseTupleAndKeywords (forwarded to python3t.PyArg_ParseTupleAndKeywords)

In this output we should be seeing e.g. PyABIInfo_Check re-exporting from python315.dll, but it's re-exporting from itself.

@ngoldbaum
Copy link
Copy Markdown
Contributor

I think you need to build docs manually for the installer?

Yeah, all the CI jobs pass --doc, so building without it seems to have broken at some point.

I have a (claude-suggested) fix for the issue I described in my last comment that I'm testing out. Sadly each build takes about a half hour end-to-end, including the Maturin and PyO3 builds needed in the stable-abi-testing repo to run end-to-end tests.

Copy link
Copy Markdown
Member

@zooba zooba left a comment

Choose a reason for hiding this comment

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

The other place that will need changing is the script under PC/layout, which is the "new" install creator (essentially it's the make install command). That just has to copy in the right file if it's been built, without the subdirectory.

Comment thread PCbuild/_remote_debugging.vcxproj Outdated
Comment thread PCbuild/pcbuild.proj Outdated
Comment thread Tools/msi/core/core_files.wxs Outdated
Comment thread Python/dynload_win.c
}
#endif

wcscpy(p + 1, PY3_DLLNAME);
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.

We also want to search for the compatibility DLL name without the extra directory, but only if the one with the directory doesn't exist. That will be the long-term (post 3.15) path, and also used by the PyManager package straight away (which doesn't do overlapping installs).

@zooba
Copy link
Copy Markdown
Member

zooba commented Apr 28, 2026

caused by the python3t.dll produced being self-referential

This will be a typo in the script that generates the .def file. I missed it when reviewing, but I assume it's just a wrong variable that'll be easy to spot (for Petr, who has worked on this generator a lot).

Copy link
Copy Markdown
Contributor

@ngoldbaum ngoldbaum left a comment

Choose a reason for hiding this comment

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

With the suggested changes I'm able to run the tests in the stable-abi-testing repo on the GIL-enabled and free-threaded builds and don't see any issues. There are two failures on the GIL-enabled build for the meson-python tests, but fixing those will require updating @mgorny's meson-python branch we use in the stable-abi-testing repo or adjusting the tests in the stable-abi-testing repo.

I also manually verified using my maturin and PyO3 branches for abi3t support that a wheel built with either build is installable and importable by both builds.

Not sure how well these suggestions play with @zooba's suggestions to leave things unconditional. Hopefully there's a straightforward way to integrate my suggestions with his.

Comment thread PCbuild/python3tdll.vcxproj Outdated
Comment thread PCbuild/python3dll.vcxproj Outdated
Comment thread PCbuild/python3tdll.vcxproj
Comment thread Tools/msi/core/core_files.wxs Outdated
<Fragment>
<ComponentGroup Id="core_dll">
<Component Id="python_abi3tcompat.dll" Directory="abi3t_compat" Guid="*">
<File Id="python_abi3tcompat.dll" Name="python$(var.MajorVersionNumber)t.dll" Source="python$(var.MajorVersionNumber)t.dll" KeyPath="yes" />
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
<File Id="python_abi3tcompat.dll" Name="python$(var.MajorVersionNumber)t.dll" Source="python$(var.MajorVersionNumber)t.dll" KeyPath="yes" />
<File Id="python_abi3tcompat.dll" Name="python$(var.MajorVersionNumber)t.dll" Source="abi3t-compat\python$(var.MajorVersionNumber)t.dll" KeyPath="yes" />

Copy link
Copy Markdown
Member Author

@encukou encukou left a comment

Choose a reason for hiding this comment

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

Thanks! I'll start today with these suggestions.

Comment thread PCbuild/_remote_debugging.vcxproj Outdated
Co-authored-by: Steve Dower <steve.dower@microsoft.com>
Co-authored-by: Nathan Goldbaum <nathan.goldbaum@gmail.com>
@read-the-docs-community
Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #32462471 | 📁 Comparing 3dc7bc1 against main (d71e3bc)

  🔍 Preview build  

6 files changed · ± 6 modified

± Modified

@zooba
Copy link
Copy Markdown
Member

zooba commented Apr 29, 2026

I looked at the error message in the installer build and immediately thought "that'll be @hugovk's fault" and one git log Doc\make.bat later I see I was right 😆

Maybe we shouldn't be assuming that every dependency (pip, in this case) is forcibly updated on every build? That's actually bad policy (you should use a lockfile to pin to a known good version, which might be a little older 😉 )

@hugovk
Copy link
Copy Markdown
Member

hugovk commented Apr 29, 2026

It looks like currently we're using whatever pip is in the CI runner?

Short term, we can either require newer pip or revert the make.bat change, so docs' deps are installed from requirements.txt instead of pylock.toml.

And/or we can start pinning pip to a certain version. We should then decide when/how to upgrade that. Easiest would be via Dependabot.

Which do you prefer?

@ngoldbaum
Copy link
Copy Markdown
Contributor

I tried re-doing my testing from yesterday but hit a segfault. See this crash report from WinDbg using the stable-abi-testing maturin/rust example:

https://gist.github.com/ngoldbaum/7f277b39f8c054959c47a96e4ec5c228

Or this crash using the setuptools/c example:

https://gist.github.com/ngoldbaum/fa31157e5839c8425bdd6626d0d8ef3d

It's possible that this is caused by other changes that were recently merged into CPython main that somehow broke my WIP branch for PyO3 PEP 803 support. Let me try again with the branch I got to successfully work yesterday and see what's different in that version of things.

@ngoldbaum
Copy link
Copy Markdown
Contributor

I think I see the issue - the free-threaded python3t.dll is clobbering the python3t.dll that gets produced in the first build pass for the GIL-enabled build, so the abi3t_compat\python3t.dll that ends up installed re-exports from the wrong dll, and we get crashes because sizeof(PyObject) is wrong:

C:\Users\goldbaum\AppData\Local\Programs\Python\Python315>dumpbin /exports abi3t-compat\python3t.dll
Microsoft (R) COFF/PE Dumper Version 14.44.35226.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file abi3t-compat\python3t.dll

File Type: DLL

  Section contains the following exports for python3t.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
         948 number of functions
         948 number of names

    ordinal hint RVA      name

          1    0          PyABIInfo_Check (forwarded to python315t.PyABIInfo_Check)
          2    1          PyAIter_Check (forwarded to python315t.PyAIter_Check)
          3    2          PyArg_Parse (forwarded to python315t.PyArg_Parse)
          4    3          PyArg_ParseTuple (forwarded to python315t.PyArg_ParseTuple)
          5    4          PyArg_ParseTupleAndKeywords (forwarded to python315t.PyArg_ParseTupleAndKeywords)

All the forwards above should be from python315, not python315t.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants