Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
22b2594
Native ARM64 CI tests and wheels
Avasam Apr 27, 2025
2fb45fd
Shorten ` --config-setting=--build-option` commands
Avasam Apr 27, 2025
acf0700
Merge branch 'try-shorten-cross-compile-command' into Native-ARM64-CI…
Avasam Apr 27, 2025
f25248d
try specify arm64
Avasam Apr 27, 2025
25b8caa
Try with wheel specified
Avasam Apr 27, 2025
7d7e3a8
Work around missing pythonarm64 NuGet downloads for older Python vers…
Avasam Apr 27, 2025
eca016f
Reuse setuptools' logic for plat_dir
Avasam Apr 27, 2025
99110ce
Don't even need _vcvars_names
Avasam Apr 27, 2025
a99d812
rename plat_dir to target_machine
Avasam Apr 27, 2025
96ea6bf
Updated matrix to request native Python below 3.11
Avasam Apr 27, 2025
bc8b19e
typo
Avasam Apr 27, 2025
4d5147f
Merge branch 'main' into Native-ARM64-CI-wheels
Avasam Apr 27, 2025
46f931f
Try fix matrix
Avasam Apr 28, 2025
b80db64
Discard changes to setup.py
Avasam Apr 28, 2025
6f1162c
reverted setup.py
Avasam Apr 28, 2025
9c2d3e7
Remove other comment
Avasam Apr 28, 2025
4e923cf
Flip includes
Avasam Apr 28, 2025
fca0484
Apply "Fix user Scripts missing from PATH" to arm64 as well
Avasam Apr 28, 2025
e701123
Maybe fix tests
Avasam Apr 30, 2025
b13c85e
Merge branch 'main' of https://github.com/mhammond/pywin32 into Nativ…
Avasam Apr 30, 2025
686fafb
Merge branch 'main' of https://github.com/mhammond/pywin32 into Nativ…
Avasam May 30, 2025
332635f
Merge branch 'main' of https://github.com/mhammond/pywin32 into Nativ…
Avasam Jun 14, 2025
b89fcd3
Merge branch 'main' of https://github.com/mhammond/pywin32 into Nativ…
Avasam Jul 24, 2025
f525b4b
Try always install non ARM64 ATL
Avasam Jul 24, 2025
391e958
Try just ARM just to see
Avasam Jul 24, 2025
a7efed7
Merge branch 'main' of https://github.com/mhammond/pywin32 into Nativ…
Avasam Sep 27, 2025
ca2ec6f
Apply the same retargetting as #2655
Avasam Sep 27, 2025
000a137
Merge branch 'main' into Native-ARM64-CI-wheels
Avasam Sep 27, 2025
1bc0daf
Merge branch 'main' into Native-ARM64-CI-wheels
Avasam Sep 29, 2025
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
9 changes: 6 additions & 3 deletions .github/workflows/install-vs-components.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@
text=True,
shell=True,
).strip()
components_to_add = (
["Microsoft.VisualStudio.Component.VC.14.29.16.11.ATL.ARM64"]
components_to_add = ["Microsoft.VisualStudio.Component.VC.14.29.16.11.ATL"] + (
[
"Microsoft.VisualStudio.Component.VC.14.29.16.11.ATL.ARM",
"Microsoft.VisualStudio.Component.VC.14.29.16.11.ATL.ARM64",
]
if platform.machine() == "ARM64"
else ["Microsoft.VisualStudio.Component.VC.14.29.16.11.ATL"]
else []
)
args = (
"vs_installer.exe",
Expand Down
37 changes: 24 additions & 13 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,25 @@ concurrency:
jobs:
test:
name: Build and test
runs-on: windows-2022
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
architecture: [x64, x86]
python-architecture: [x64, x86, arm64]
include:
- os: windows-2022
- python-architecture: arm64
os: windows-11-arm
exclude:
# actions/setup-python does not provide prebuilt arm64 Python before 3.11
- python-architecture: arm64
python-version: "3.8"
- python-architecture: arm64
python-version: "3.9"
- python-architecture: arm64
python-version: "3.10"
env:
# TODO: We can't yet run tests with PYTHONDEVMODE=1, let's emulated it as much as we can
# https://docs.python.org/3/library/devmode.html#effects-of-the-python-development-mode
Expand All @@ -37,7 +49,7 @@ jobs:
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.architecture }}
architecture: ${{ matrix.python-architecture }}
cache: pip
cache-dependency-path: .github/workflows/main.yml
check-latest: true
Expand Down Expand Up @@ -83,21 +95,20 @@ jobs:
# Upload artifacts even if tests fail
if: ${{ always() }}
with:
name: artifacts-${{ matrix.python-version }}-${{ matrix.architecture }}
name: artifacts-${{ matrix.python-version }}-${{ matrix.python-architecture }}
path: dist/*.whl
if-no-files-found: error

# We cannot build and test on ARM64, so we cross-compile.
# Later, when available, we can add tests using this wheel on ARM64 VMs
build_arm64:
name: Cross-compile ARM
# actions/setup-python does not provide prebuilt arm64 Python before 3.11, so we cross-compile.
cross_compile_arm64:
name: Cross-compile ARM64
runs-on: windows-2022
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
# pythonarm64 NuGet's has no download for Python ~=3.9.11
python-version: ["3.9.10", "3.10", "3.11", "3.12", "3.13", "3.14"]
# pythonarm64 NuGet has no download for Python 3.8 and Python ~=3.9.11
python-version: ["3.9.10", "3.10"]
steps:
- uses: actions/checkout@v4

Expand All @@ -115,10 +126,10 @@ jobs:
run: pip install --upgrade build

- name: Obtain ARM64 library files
run: python .github\workflows\download-arm64-libs.py .\arm64libs
run: python .github\workflows\download-arm64-libs.py ./arm64libs

- name: Build wheels
run: python -m build --wheel --config-setting=--build-option=build_ext --config-setting=--build-option=-L.\arm64libs --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=build --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=bdist_wheel --config-setting=--build-option=--plat-name=win-arm64
run: python -m build --wheel --config-setting=--build-option="build_ext -L./arm64libs --plat-name=win-arm64 build --plat-name=win-arm64 bdist_wheel --plat-name=win-arm64"

- uses: actions/upload-artifact@v4
with:
Expand All @@ -128,7 +139,7 @@ jobs:

merge:
runs-on: windows-latest
needs: [test, build_arm64]
needs: [test, cross_compile_arm64]
steps:
- name: Merge Artifacts
uses: actions/upload-artifact/merge@v4
Expand Down
9 changes: 4 additions & 5 deletions build_env.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,12 @@ configuration, please [open an issue](https://github.com/mhammond/pywin32/issues
- Follow the `For Visual Studio XXXX` instructions above and pick the optional ARM64 build tools

- Download prebuilt Python ARM64 binaries to a temporary location on your machine. You will need this location in a later step.
- This script downloads a Python ARM64 build [from NuGet](https://www.nuget.org/packages/pythonarm64/#versions-tab) that matches the version you used to run it.

```shell
python .github\workflows\download-arm64-libraries.py "<temporary path>"
python .github\workflows\download-arm64-libs.py ./arm64libs
```

- This script downloads a Python ARM64 build [from NuGet](https://www.nuget.org/packages/pythonarm64/#versions-tab) that matches the version you used to run it.
- Setup the cross-compilation environment:

```shell
Expand All @@ -156,13 +156,12 @@ configuration, please [open an issue](https://github.com/mhammond/pywin32/issues
```

- Build the extensions, passing the directory from earlier. You may optionally add the `bdist_wheel` command to generate a wheel.
- If you are not using an initialized build environment, you will need to specify the `build_ext`, `build` and `bdist_wheel` commands and pass `--plat-name win-arm64` to *each* of them separately. Otherwise you may get a mixed platform build and/or linker errors.

```shell
python -m build --wheel --config-setting=--build-option=build_ext --config-setting=--build-option=-L.\arm64libs --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=bdist_wheel --config-setting=--build-option=--plat-name=win-arm64
python -m build --wheel --config-setting=--build-option="build_ext -L./arm64libs --plat-name=win-arm64 bdist_wheel --plat-name=win-arm64"
```

- If you are not using an initialized build environment, you will need to specify the `build_ext`, `build` and `bdist_wheel` commands and pass `--plat-name win-arm64` to *each* of them separately. Otherwise you may get a mixed platform build and/or linker errors.

- Copy the built wheel to the target machine and install directly:

```shell
Expand Down
27 changes: 19 additions & 8 deletions com/win32com/test/testPyComTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import datetime
import decimal
import os
import platform
import time
from unittest import SkipTest

import pythoncom
import win32com
Expand All @@ -25,6 +27,7 @@
gencache,
register_record_class,
)
from win32com.universal import RegisterInterfaces
from win32process import GetProcessMemoryInfo

# This test uses a Python implemented COM server - ensure correctly registered.
Expand All @@ -46,10 +49,6 @@
print(f"The PyCOMTest module can not be located or generated.\n{importMsg}\n")
raise RuntimeError(importMsg) from error

# We had a bg where RegisterInterfaces would fail if gencache had
# already been run - exercise that here
universal.RegisterInterfaces("{6BCDCB60-5605-11D0-AE5F-CADD4C000000}", 0, 1, 1)

verbose = 0


Expand Down Expand Up @@ -910,15 +909,27 @@ def TestQueryInterface(long_lived_server=0, iterations=5):


class Tester(win32com.test.util.TestCase):
def testVTableInProc(self):
def testRegisterInterfacesAfterGencache(self) -> None:
# We had a bug where RegisterInterfaces would fail if gencache had
# already been run - exercise that here
try:
RegisterInterfaces("{6BCDCB60-5605-11D0-AE5F-CADD4C000000}", 0, 1, 1)
except NotImplementedError:
if platform.machine() == "ARM64":
raise SkipTest(
"`win32com.universal.RegisterInterfaces` doesn't support ARM64 yet"
)
raise
Comment on lines +917 to +922
Copy link
Collaborator Author

@Avasam Avasam May 1, 2025

Choose a reason for hiding this comment

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

I carved this very specific exception so that if support is added (or attempted) and the error changes or disappears, this will have to be updated accordingly (hopefully by removing the try-except entirely)


def testVTableInProc(self) -> None:
# We used to crash running this the second time - do it a few times
for i in range(3):
progress("Testing VTables in-process #%d..." % (i + 1))
progress(f"Testing VTables in-process #{(i + 1)}...")
TestVTable(pythoncom.CLSCTX_INPROC_SERVER)

def testVTableLocalServer(self):
def testVTableLocalServer(self) -> None:
for i in range(3):
progress("Testing VTables out-of-process #%d..." % (i + 1))
progress(f"Testing VTables out-of-process #{(i + 1)}...")
TestVTable(pythoncom.CLSCTX_LOCAL_SERVER)

def testVTable2(self):
Expand Down
12 changes: 6 additions & 6 deletions make_all.bat
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ py -3.13 -m build --wheel
py -3.14-32 -m build --wheel
py -3.14 -m build --wheel

rem Check /build_env.md#build-environment to make sure you have all the required ARM64 components installed
py -3.10 -m build --wheel --config-setting=--build-option=build_ext --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=build --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=bdist_wheel --config-setting=--build-option=--plat-name=win-arm64
py -3.11 -m build --wheel --config-setting=--build-option=build_ext --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=build --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=bdist_wheel --config-setting=--build-option=--plat-name=win-arm64
py -3.12 -m build --wheel --config-setting=--build-option=build_ext --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=build --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=bdist_wheel --config-setting=--build-option=--plat-name=win-arm64
py -3.13 -m build --wheel --config-setting=--build-option=build_ext --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=build --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=bdist_wheel --config-setting=--build-option=--plat-name=win-arm64
py -3.14 -m build --wheel --config-setting=--build-option=build_ext --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=build --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=bdist_wheel --config-setting=--build-option=--plat-name=win-arm64
rem Check /build_env.md#cross-compiling-for-arm64-microsoft-visual-c-141-and-up to make sure you have all the required ARM64 components installed
py -3.10 -m build --wheel --config-setting=--build-option="build_ext --plat-name=win-arm64 build --plat-name=win-arm64 bdist_wheel --plat-name=win-arm64"
py -3.11 -m build --wheel --config-setting=--build-option="build_ext --plat-name=win-arm64 build --plat-name=win-arm64 bdist_wheel --plat-name=win-arm64"
py -3.12 -m build --wheel --config-setting=--build-option="build_ext --plat-name=win-arm64 build --plat-name=win-arm64 bdist_wheel --plat-name=win-arm64"
py -3.13 -m build --wheel --config-setting=--build-option="build_ext --plat-name=win-arm64 build --plat-name=win-arm64 bdist_wheel --plat-name=win-arm64"
py -3.14 -m build --wheel --config-setting=--build-option="build_ext --plat-name=win-arm64 build --plat-name=win-arm64 bdist_wheel --plat-name=win-arm64"

@goto xit
:couldnt_rm
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

For a debug (_d) version, you need a local debug build of Python, but must use
the release version executable for the build. eg:
pip install . -v --config-setting=--build-option=build --config-setting=--build-option=--debug
pip install . -v --config-setting=--build-option="build --debug"

Cross-compilation from x86 to ARM is well supported (assuming installed vs tools etc) - eg:
python -m build --wheel --config-setting=--build-option=build_ext --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=build --config-setting=--build-option=--plat-name=win-arm64 --config-setting=--build-option=bdist_wheel --config-setting=--build-option=--plat-name=win-arm64
python -m build --wheel --config-setting=--build-option="build_ext --plat-name=win-arm64 build --plat-name=win-arm64 bdist_wheel --plat-name=win-arm64"

Some modules require special SDKs or toolkits to build (eg, mapi/exchange),
which often aren't available in CI. The build process treats them as optional -
Expand Down
Loading