From 3d7bf40b19274c652a87123161f4ac396450d5cb Mon Sep 17 00:00:00 2001 From: ssss141414 Date: Fri, 21 Aug 2026 16:56:10 +0800 Subject: [PATCH 01/18] Add Windows ARM64 wheel support --- .github/workflows/ci.yml | 62 +++++++++++++++++++ continuous-delivery/build-wheels-winarm64.bat | 36 +++++++++++ setup.py | 28 +++++++++ 3 files changed, 126 insertions(+) create mode 100644 continuous-delivery/build-wheels-winarm64.bat diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77e98ae8e..5451dce6d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -308,6 +308,68 @@ jobs: python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" python builder.pyz build -p ${{ env.PACKAGE_NAME }} --python "${{ steps.python38.outputs.python-path }}" + windows-arm64: + runs-on: windows-11-arm + strategy: + fail-fast: false + matrix: + include: + - build-python: '3.11' + test-python: '3.11' + - build-python: '3.11' + test-python: '3.12' + - build-python: '3.13' + test-python: '3.13' + - build-python: '3.13' + test-python: '3.14' + - build-python: '3.13t' + test-python: '3.13t' + - build-python: '3.14t' + test-python: '3.14t' + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.build-python }} + architecture: arm64 + - uses: ilammy/msvc-dev-cmd@v1 + with: + arch: arm64 + - name: Build Windows ARM64 wheel + shell: pwsh + run: | + python -m pip install --upgrade build + python -m build --wheel + $wheel = @(Get-Item dist\*win_arm64.whl) + if ($wheel.Count -ne 1) { + throw 'Expected exactly one win_arm64 wheel' + } + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.test-python }} + architecture: arm64 + - name: Test installed wheel + shell: pwsh + env: + AWS_TEST_LOCALHOST: '1' + run: | + python -m venv ..\awscrt-test + $wheel = @(Get-Item dist\*win_arm64.whl) + if ($wheel.Count -ne 1) { + throw 'Expected exactly one win_arm64 wheel' + } + ..\awscrt-test\Scripts\python.exe -m pip install $wheel[0].FullName + ..\awscrt-test\Scripts\python.exe -m pip install 'websockets>=13.1' 'h2==4.1.0' + Copy-Item test "$env:RUNNER_TEMP\test" -Recurse + Push-Location $env:RUNNER_TEMP + try { + & "$env:GITHUB_WORKSPACE\..\awscrt-test\Scripts\python.exe" -m unittest discover --failfast --verbose + } finally { + Pop-Location + } + macos: runs-on: macos-14 # latest permissions: diff --git a/continuous-delivery/build-wheels-winarm64.bat b/continuous-delivery/build-wheels-winarm64.bat new file mode 100644 index 000000000..3b96f9f83 --- /dev/null +++ b/continuous-delivery/build-wheels-winarm64.bat @@ -0,0 +1,36 @@ +@echo off + +if not defined PYTHON311_ARM64 goto missing_python +if not defined PYTHON313_ARM64 goto missing_python +if not defined PYTHON313T_ARM64 goto missing_python +if not defined PYTHON314T_ARM64 goto missing_python + +for %%P in ("%PYTHON311_ARM64%" "%PYTHON313_ARM64%" "%PYTHON313T_ARM64%" "%PYTHON314T_ARM64%") do ( + "%%~P" -c "import sysconfig; raise SystemExit(0 if sysconfig.get_platform() == 'win-arm64' else 1)" || goto wrong_architecture +) + +"%PYTHON313_ARM64%" continuous-delivery\update-version.py || goto error + +:: The 3.11 stable ABI wheel also supports Python 3.12. +"%PYTHON311_ARM64%" -m build || goto error + +:: Use the 3.13 stable ABI from 3.13 onwards because of deprecated functions. +"%PYTHON313_ARM64%" -m build || goto error + +:: Free-threaded builds do not support the Limited C API or stable ABI. +"%PYTHON313T_ARM64%" -m build || goto error +"%PYTHON314T_ARM64%" -m build || goto error + +goto :EOF + +:missing_python +echo PYTHON311_ARM64, PYTHON313_ARM64, PYTHON313T_ARM64, and PYTHON314T_ARM64 must point to native ARM64 Python executables. +exit /b 1 + +:wrong_architecture +echo All configured Python executables must target win-arm64. +exit /b 1 + +:error +echo Failed with error #%errorlevel%. +exit /b %errorlevel% \ No newline at end of file diff --git a/setup.py b/setup.py index bcf0b0456..7a1e28809 100644 --- a/setup.py +++ b/setup.py @@ -48,6 +48,10 @@ def is_32bit(): return is_64bit() == False +def is_windows_arm64(): + return sys.platform == 'win32' and sysconfig.get_platform() == 'win-arm64' + + # TODO: Fix this. Since adding pyproject.toml, it always returns False def is_development_mode(): """Return whether we're building in Development Mode (a.k.a. “Editable Installs”). @@ -196,6 +200,20 @@ def determine_generator_args(cmake_version=None, windows_sdk_version=None): print('Using Visual Studio', vs_version, vs_year) + if is_windows_arm64(): + if not shutil.which('clang-cl'): + raise RuntimeError('clang-cl is required to build for Windows ARM64') + print('Using Ninja and clang-cl for Windows ARM64') + return [ + '-G', 'Ninja', + f'-DCMAKE_SYSTEM_VERSION={windows_sdk_version}', + '-DCMAKE_C_COMPILER=clang-cl', + '-DCMAKE_CXX_COMPILER=clang-cl', + '-DCMAKE_ASM_COMPILER=clang-cl', + # The optimized ARM checksum sources do not compile with clang-cl. + '-DUSE_CPU_EXTENSIONS=OFF', + ] + if vs_year <= 2017: # For VS2017 and earlier, architecture goes at end of generator string if is_64bit(): @@ -325,6 +343,16 @@ def __init__(self, name, extra_cmake_args=[], libname=None): class awscrt_build_ext(setuptools.command.build_ext.build_ext): + def build_extensions(self): + if is_windows_arm64(): + if not self.compiler.initialized: + self.compiler.initialize() + clang_cl = shutil.which('clang-cl') + if not clang_cl: + raise RuntimeError('clang-cl is required to build for Windows ARM64') + self.compiler.cc = clang_cl + super().build_extensions() + def _build_dependencies_impl(self, build_dir, install_path, osx_arch=None): cmake = get_cmake_path() From cca25c3b83afc7946ad594937b4c61e1a92628cc Mon Sep 17 00:00:00 2001 From: ssss141414 Date: Fri, 21 Aug 2026 17:03:57 +0800 Subject: [PATCH 02/18] Stage HTTP test server for ARM64 CI --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5451dce6d..b2b1891e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -363,6 +363,10 @@ jobs: ..\awscrt-test\Scripts\python.exe -m pip install $wheel[0].FullName ..\awscrt-test\Scripts\python.exe -m pip install 'websockets>=13.1' 'h2==4.1.0' Copy-Item test "$env:RUNNER_TEMP\test" -Recurse + $httpTests = "$env:RUNNER_TEMP\crt\aws-c-http\tests" + New-Item $httpTests -ItemType Directory -Force | Out-Null + Copy-Item crt\aws-c-http\tests\mock_server $httpTests -Recurse + Copy-Item crt\aws-c-http\tests\resources $httpTests -Recurse Push-Location $env:RUNNER_TEMP try { & "$env:GITHUB_WORKSPACE\..\awscrt-test\Scripts\python.exe" -m unittest discover --failfast --verbose From 29b62b6e3521c91f8135a08424f39fa49f0d5c13 Mon Sep 17 00:00:00 2001 From: ssss141414 Date: Fri, 21 Aug 2026 17:13:17 +0800 Subject: [PATCH 03/18] Isolate unavailable httpbin test in ARM64 CI --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2b1891e9..1d34428cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -361,7 +361,7 @@ jobs: throw 'Expected exactly one win_arm64 wheel' } ..\awscrt-test\Scripts\python.exe -m pip install $wheel[0].FullName - ..\awscrt-test\Scripts\python.exe -m pip install 'websockets>=13.1' 'h2==4.1.0' + ..\awscrt-test\Scripts\python.exe -m pip install 'websockets>=13.1' 'h2==4.1.0' 'pytest>=8.4' Copy-Item test "$env:RUNNER_TEMP\test" -Recurse $httpTests = "$env:RUNNER_TEMP\crt\aws-c-http\tests" New-Item $httpTests -ItemType Directory -Force | Out-Null @@ -369,7 +369,8 @@ jobs: Copy-Item crt\aws-c-http\tests\resources $httpTests -Recurse Push-Location $env:RUNNER_TEMP try { - & "$env:GITHUB_WORKSPACE\..\awscrt-test\Scripts\python.exe" -m unittest discover --failfast --verbose + # This test depends on httpbin.org returning 404, but the service currently returns 503. + & "$env:GITHUB_WORKSPACE\..\awscrt-test\Scripts\python.exe" -m pytest test --maxfail=1 --verbose -k 'not test_h2_remote_end_stream_ordering' } finally { Pop-Location } From 69bbcffd9e1d26e461983bf460e4594831e2ef89 Mon Sep 17 00:00:00 2001 From: ssss141414 Date: Fri, 21 Aug 2026 17:20:21 +0800 Subject: [PATCH 04/18] Run filtered ARM64 tests with unittest --- .github/workflows/ci.yml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d34428cd..4e083a24f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -361,7 +361,7 @@ jobs: throw 'Expected exactly one win_arm64 wheel' } ..\awscrt-test\Scripts\python.exe -m pip install $wheel[0].FullName - ..\awscrt-test\Scripts\python.exe -m pip install 'websockets>=13.1' 'h2==4.1.0' 'pytest>=8.4' + ..\awscrt-test\Scripts\python.exe -m pip install 'websockets>=13.1' 'h2==4.1.0' Copy-Item test "$env:RUNNER_TEMP\test" -Recurse $httpTests = "$env:RUNNER_TEMP\crt\aws-c-http\tests" New-Item $httpTests -ItemType Directory -Force | Out-Null @@ -370,7 +370,24 @@ jobs: Push-Location $env:RUNNER_TEMP try { # This test depends on httpbin.org returning 404, but the service currently returns 503. - & "$env:GITHUB_WORKSPACE\..\awscrt-test\Scripts\python.exe" -m pytest test --maxfail=1 --verbose -k 'not test_h2_remote_end_stream_ordering' + @' + import unittest + + excluded = 'test.test_aiohttp_client.AIOHttp2RemoteEndStreamTest.test_h2_remote_end_stream_ordering' + discovered = unittest.defaultTestLoader.discover('test') + filtered = unittest.TestSuite() + + def add_tests(suite): + for test in suite: + if isinstance(test, unittest.TestSuite): + add_tests(test) + elif test.id() != excluded: + filtered.addTest(test) + + add_tests(discovered) + result = unittest.TextTestRunner(verbosity=2, failfast=True).run(filtered) + raise SystemExit(0 if result.wasSuccessful() else 1) + '@ | & "$env:GITHUB_WORKSPACE\..\awscrt-test\Scripts\python.exe" - } finally { Pop-Location } From 6d9c7f21ad32a15ce1671df34287bba3b19a7de6 Mon Sep 17 00:00:00 2001 From: ssss141414 Date: Fri, 21 Aug 2026 17:26:54 +0800 Subject: [PATCH 05/18] Avoid here-string indentation in ARM64 CI --- .github/workflows/ci.yml | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e083a24f..e77c72175 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -370,24 +370,22 @@ jobs: Push-Location $env:RUNNER_TEMP try { # This test depends on httpbin.org returning 404, but the service currently returns 503. - @' - import unittest - - excluded = 'test.test_aiohttp_client.AIOHttp2RemoteEndStreamTest.test_h2_remote_end_stream_ordering' - discovered = unittest.defaultTestLoader.discover('test') - filtered = unittest.TestSuite() - - def add_tests(suite): - for test in suite: - if isinstance(test, unittest.TestSuite): - add_tests(test) - elif test.id() != excluded: - filtered.addTest(test) - - add_tests(discovered) - result = unittest.TextTestRunner(verbosity=2, failfast=True).run(filtered) - raise SystemExit(0 if result.wasSuccessful() else 1) - '@ | & "$env:GITHUB_WORKSPACE\..\awscrt-test\Scripts\python.exe" - + $testScript = @( + 'import unittest' + "excluded = 'test.test_aiohttp_client.AIOHttp2RemoteEndStreamTest.test_h2_remote_end_stream_ordering'" + "discovered = unittest.defaultTestLoader.discover('test')" + 'filtered = unittest.TestSuite()' + 'def add_tests(suite):' + ' for test in suite:' + ' if isinstance(test, unittest.TestSuite):' + ' add_tests(test)' + ' elif test.id() != excluded:' + ' filtered.addTest(test)' + 'add_tests(discovered)' + 'result = unittest.TextTestRunner(verbosity=2, failfast=True).run(filtered)' + 'raise SystemExit(0 if result.wasSuccessful() else 1)' + ) -join "`n" + & "$env:GITHUB_WORKSPACE\..\awscrt-test\Scripts\python.exe" -c $testScript } finally { Pop-Location } From 4995f43c47b4fa0624c6600e622a261cfd5bd267 Mon Sep 17 00:00:00 2001 From: ssss141414 Date: Fri, 21 Aug 2026 17:35:27 +0800 Subject: [PATCH 06/18] Match isolated HTTP test ID --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e77c72175..c29819d47 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -372,14 +372,14 @@ jobs: # This test depends on httpbin.org returning 404, but the service currently returns 503. $testScript = @( 'import unittest' - "excluded = 'test.test_aiohttp_client.AIOHttp2RemoteEndStreamTest.test_h2_remote_end_stream_ordering'" + "excluded = '.AIOHttp2RemoteEndStreamTest.test_h2_remote_end_stream_ordering'" "discovered = unittest.defaultTestLoader.discover('test')" 'filtered = unittest.TestSuite()' 'def add_tests(suite):' ' for test in suite:' ' if isinstance(test, unittest.TestSuite):' ' add_tests(test)' - ' elif test.id() != excluded:' + ' elif not test.id().endswith(excluded):' ' filtered.addTest(test)' 'add_tests(discovered)' 'result = unittest.TextTestRunner(verbosity=2, failfast=True).run(filtered)' From 46c0b26d476b782623775ae95be2f878faf6d258 Mon Sep 17 00:00:00 2001 From: ssss141414 Date: Fri, 21 Aug 2026 17:44:39 +0800 Subject: [PATCH 07/18] Exclude both unavailable httpbin tests --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c29819d47..7f4d8e6f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -369,17 +369,17 @@ jobs: Copy-Item crt\aws-c-http\tests\resources $httpTests -Recurse Push-Location $env:RUNNER_TEMP try { - # This test depends on httpbin.org returning 404, but the service currently returns 503. + # These tests depend on httpbin.org returning 404, but the service currently returns 503. $testScript = @( 'import unittest' - "excluded = '.AIOHttp2RemoteEndStreamTest.test_h2_remote_end_stream_ordering'" + "excluded = ('.AIOHttp2RemoteEndStreamTest.test_h2_remote_end_stream_ordering', '.Http2RemoteEndStreamTest.test_h2_remote_end_stream_ordering')" "discovered = unittest.defaultTestLoader.discover('test')" 'filtered = unittest.TestSuite()' 'def add_tests(suite):' ' for test in suite:' ' if isinstance(test, unittest.TestSuite):' ' add_tests(test)' - ' elif not test.id().endswith(excluded):' + ' elif not any(test.id().endswith(test_id) for test_id in excluded):' ' filtered.addTest(test)' 'add_tests(discovered)' 'result = unittest.TextTestRunner(verbosity=2, failfast=True).run(filtered)' From ef45c356a7e8970eed3aa85306bf738150075b07 Mon Sep 17 00:00:00 2001 From: ssss141414 Date: Fri, 21 Aug 2026 17:55:47 +0800 Subject: [PATCH 08/18] Harden ARM64 wheel validation --- .github/workflows/ci.yml | 27 ++++++++++++++----- continuous-delivery/build-wheels-winarm64.bat | 11 ++++---- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f4d8e6f3..df35b5191 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -316,16 +316,22 @@ jobs: include: - build-python: '3.11' test-python: '3.11' + expected-tag: 'cp311-abi3-win_arm64' - build-python: '3.11' test-python: '3.12' + expected-tag: 'cp311-abi3-win_arm64' - build-python: '3.13' test-python: '3.13' + expected-tag: 'cp313-abi3-win_arm64' - build-python: '3.13' test-python: '3.14' + expected-tag: 'cp313-abi3-win_arm64' - build-python: '3.13t' test-python: '3.13t' + expected-tag: 'cp313-cp313t-win_arm64' - build-python: '3.14t' test-python: '3.14t' + expected-tag: 'cp314-cp314t-win_arm64' steps: - uses: actions/checkout@v4 with: @@ -342,10 +348,12 @@ jobs: run: | python -m pip install --upgrade build python -m build --wheel - $wheel = @(Get-Item dist\*win_arm64.whl) - if ($wheel.Count -ne 1) { - throw 'Expected exactly one win_arm64 wheel' + $wheel = @(Get-Item "dist\awscrt-*-${{ matrix.expected-tag }}.whl") + $allWheels = @(Get-Item dist\*.whl) + if ($wheel.Count -ne 1 -or $allWheels.Count -ne 1) { + throw 'Expected exactly one wheel with tag ${{ matrix.expected-tag }}' } + python -c "import sys, zipfile; p=sys.argv[1]; expected='Tag: ' + sys.argv[2]; z=zipfile.ZipFile(p); wheel=z.read(next(n for n in z.namelist() if n.endswith('.dist-info/WHEEL'))).decode().splitlines(); assert expected in wheel, (expected, wheel)" $wheel[0].FullName '${{ matrix.expected-tag }}' - uses: actions/setup-python@v5 with: python-version: ${{ matrix.test-python }} @@ -356,9 +364,9 @@ jobs: AWS_TEST_LOCALHOST: '1' run: | python -m venv ..\awscrt-test - $wheel = @(Get-Item dist\*win_arm64.whl) + $wheel = @(Get-Item "dist\awscrt-*-${{ matrix.expected-tag }}.whl") if ($wheel.Count -ne 1) { - throw 'Expected exactly one win_arm64 wheel' + throw 'Expected exactly one wheel with tag ${{ matrix.expected-tag }}' } ..\awscrt-test\Scripts\python.exe -m pip install $wheel[0].FullName ..\awscrt-test\Scripts\python.exe -m pip install 'websockets>=13.1' 'h2==4.1.0' @@ -372,16 +380,21 @@ jobs: # These tests depend on httpbin.org returning 404, but the service currently returns 503. $testScript = @( 'import unittest' - "excluded = ('.AIOHttp2RemoteEndStreamTest.test_h2_remote_end_stream_ordering', '.Http2RemoteEndStreamTest.test_h2_remote_end_stream_ordering')" + "excluded = {'test_aiohttp_client.AIOHttp2RemoteEndStreamTest.test_h2_remote_end_stream_ordering', 'test_http_client.Http2RemoteEndStreamTest.test_h2_remote_end_stream_ordering'}" + 'excluded_found = set()' "discovered = unittest.defaultTestLoader.discover('test')" 'filtered = unittest.TestSuite()' 'def add_tests(suite):' ' for test in suite:' ' if isinstance(test, unittest.TestSuite):' ' add_tests(test)' - ' elif not any(test.id().endswith(test_id) for test_id in excluded):' + ' elif test.id() in excluded:' + ' excluded_found.add(test.id())' + ' else:' ' filtered.addTest(test)' 'add_tests(discovered)' + "if excluded_found != excluded: raise RuntimeError(f'Expected exclusions {excluded}, found {excluded_found}')" + "if filtered.countTestCases() == 0: raise RuntimeError('No tests discovered')" 'result = unittest.TextTestRunner(verbosity=2, failfast=True).run(filtered)' 'raise SystemExit(0 if result.wasSuccessful() else 1)' ) -join "`n" diff --git a/continuous-delivery/build-wheels-winarm64.bat b/continuous-delivery/build-wheels-winarm64.bat index 3b96f9f83..cff24192d 100644 --- a/continuous-delivery/build-wheels-winarm64.bat +++ b/continuous-delivery/build-wheels-winarm64.bat @@ -5,9 +5,10 @@ if not defined PYTHON313_ARM64 goto missing_python if not defined PYTHON313T_ARM64 goto missing_python if not defined PYTHON314T_ARM64 goto missing_python -for %%P in ("%PYTHON311_ARM64%" "%PYTHON313_ARM64%" "%PYTHON313T_ARM64%" "%PYTHON314T_ARM64%") do ( - "%%~P" -c "import sysconfig; raise SystemExit(0 if sysconfig.get_platform() == 'win-arm64' else 1)" || goto wrong_architecture -) +"%PYTHON311_ARM64%" -c "import sys, sysconfig; raise SystemExit(0 if sys.version_info[:2] == (3, 11) and sysconfig.get_platform() == 'win-arm64' and not sysconfig.get_config_var('Py_GIL_DISABLED') else 1)" || goto wrong_python +"%PYTHON313_ARM64%" -c "import sys, sysconfig; raise SystemExit(0 if sys.version_info[:2] == (3, 13) and sysconfig.get_platform() == 'win-arm64' and not sysconfig.get_config_var('Py_GIL_DISABLED') else 1)" || goto wrong_python +"%PYTHON313T_ARM64%" -c "import sys, sysconfig; raise SystemExit(0 if sys.version_info[:2] == (3, 13) and sysconfig.get_platform() == 'win-arm64' and sysconfig.get_config_var('Py_GIL_DISABLED') else 1)" || goto wrong_python +"%PYTHON314T_ARM64%" -c "import sys, sysconfig; raise SystemExit(0 if sys.version_info[:2] == (3, 14) and sysconfig.get_platform() == 'win-arm64' and sysconfig.get_config_var('Py_GIL_DISABLED') else 1)" || goto wrong_python "%PYTHON313_ARM64%" continuous-delivery\update-version.py || goto error @@ -27,8 +28,8 @@ goto :EOF echo PYTHON311_ARM64, PYTHON313_ARM64, PYTHON313T_ARM64, and PYTHON314T_ARM64 must point to native ARM64 Python executables. exit /b 1 -:wrong_architecture -echo All configured Python executables must target win-arm64. +:wrong_python +echo Configured Python executables must have the expected version, win-arm64 platform, and free-threaded status. exit /b 1 :error From 222403715e26284c1a2da24f4510eb64a5ca71e1 Mon Sep 17 00:00:00 2001 From: Krish Date: Wed, 16 Sep 2026 22:41:51 +0000 Subject: [PATCH 09/18] Standardize Windows ARM64 CI --- .github/workflows/ci.yml | 95 ++++++++----------- continuous-delivery/build-wheels-winarm64.bat | 37 -------- 2 files changed, 37 insertions(+), 95 deletions(-) delete mode 100644 continuous-delivery/build-wheels-winarm64.bat diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df35b5191..ba6132172 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -309,20 +309,40 @@ jobs: python builder.pyz build -p ${{ env.PACKAGE_NAME }} --python "${{ steps.python38.outputs.python-path }}" windows-arm64: + runs-on: windows-11-arm + strategy: + fail-fast: false + matrix: + python: ['3.11', '3.13'] + permissions: + id-token: write # This is required for requesting the JWT + steps: + - uses: actions/setup-python@v5 + id: python + with: + python-version: ${{ matrix.python }} + architecture: arm64 + - name: configure AWS credentials (containers) + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + - name: Build ${{ env.PACKAGE_NAME }} + consumers + run: | + python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" + python builder.pyz build -p ${{ env.PACKAGE_NAME }} --python "${{ steps.python.outputs.python-path }}" + + windows-arm64-wheel: + # Verify the wheel we'd ship is tagged for win_arm64, and that an abi3 wheel + # built on one python installs and imports on a newer one. runs-on: windows-11-arm strategy: fail-fast: false matrix: include: - - build-python: '3.11' - test-python: '3.11' - expected-tag: 'cp311-abi3-win_arm64' - build-python: '3.11' test-python: '3.12' expected-tag: 'cp311-abi3-win_arm64' - - build-python: '3.13' - test-python: '3.13' - expected-tag: 'cp313-abi3-win_arm64' - build-python: '3.13' test-python: '3.14' expected-tag: 'cp313-abi3-win_arm64' @@ -340,68 +360,27 @@ jobs: with: python-version: ${{ matrix.build-python }} architecture: arm64 - - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: arm64 - - name: Build Windows ARM64 wheel + - name: Build wheel shell: pwsh run: | python -m pip install --upgrade build python -m build --wheel - $wheel = @(Get-Item "dist\awscrt-*-${{ matrix.expected-tag }}.whl") - $allWheels = @(Get-Item dist\*.whl) - if ($wheel.Count -ne 1 -or $allWheels.Count -ne 1) { - throw 'Expected exactly one wheel with tag ${{ matrix.expected-tag }}' - } - python -c "import sys, zipfile; p=sys.argv[1]; expected='Tag: ' + sys.argv[2]; z=zipfile.ZipFile(p); wheel=z.read(next(n for n in z.namelist() if n.endswith('.dist-info/WHEEL'))).decode().splitlines(); assert expected in wheel, (expected, wheel)" $wheel[0].FullName '${{ matrix.expected-tag }}' + $wheels = @(Get-Item dist\*.whl) + if ($wheels.Count -ne 1) { throw "Expected exactly one wheel, got $($wheels.Count)" } + $expected = 'Tag: ${{ matrix.expected-tag }}' + python -c "import sys, zipfile; z=zipfile.ZipFile(sys.argv[1]); w=z.read(next(n for n in z.namelist() if n.endswith('.dist-info/WHEEL'))).decode().splitlines(); assert sys.argv[2] in w, (sys.argv[2], w)" $wheels[0].FullName $expected - uses: actions/setup-python@v5 with: python-version: ${{ matrix.test-python }} architecture: arm64 - - name: Test installed wheel + - name: Install wheel and import shell: pwsh - env: - AWS_TEST_LOCALHOST: '1' run: | - python -m venv ..\awscrt-test - $wheel = @(Get-Item "dist\awscrt-*-${{ matrix.expected-tag }}.whl") - if ($wheel.Count -ne 1) { - throw 'Expected exactly one wheel with tag ${{ matrix.expected-tag }}' - } - ..\awscrt-test\Scripts\python.exe -m pip install $wheel[0].FullName - ..\awscrt-test\Scripts\python.exe -m pip install 'websockets>=13.1' 'h2==4.1.0' - Copy-Item test "$env:RUNNER_TEMP\test" -Recurse - $httpTests = "$env:RUNNER_TEMP\crt\aws-c-http\tests" - New-Item $httpTests -ItemType Directory -Force | Out-Null - Copy-Item crt\aws-c-http\tests\mock_server $httpTests -Recurse - Copy-Item crt\aws-c-http\tests\resources $httpTests -Recurse - Push-Location $env:RUNNER_TEMP - try { - # These tests depend on httpbin.org returning 404, but the service currently returns 503. - $testScript = @( - 'import unittest' - "excluded = {'test_aiohttp_client.AIOHttp2RemoteEndStreamTest.test_h2_remote_end_stream_ordering', 'test_http_client.Http2RemoteEndStreamTest.test_h2_remote_end_stream_ordering'}" - 'excluded_found = set()' - "discovered = unittest.defaultTestLoader.discover('test')" - 'filtered = unittest.TestSuite()' - 'def add_tests(suite):' - ' for test in suite:' - ' if isinstance(test, unittest.TestSuite):' - ' add_tests(test)' - ' elif test.id() in excluded:' - ' excluded_found.add(test.id())' - ' else:' - ' filtered.addTest(test)' - 'add_tests(discovered)' - "if excluded_found != excluded: raise RuntimeError(f'Expected exclusions {excluded}, found {excluded_found}')" - "if filtered.countTestCases() == 0: raise RuntimeError('No tests discovered')" - 'result = unittest.TextTestRunner(verbosity=2, failfast=True).run(filtered)' - 'raise SystemExit(0 if result.wasSuccessful() else 1)' - ) -join "`n" - & "$env:GITHUB_WORKSPACE\..\awscrt-test\Scripts\python.exe" -c $testScript - } finally { - Pop-Location - } + python -m venv ${{ runner.temp }}\venv + $py = "${{ runner.temp }}\venv\Scripts\python.exe" + & $py -m pip install @(Get-Item dist\*.whl)[0].FullName + & $py -c "import awscrt.io, awscrt.http, awscrt.s3; print(awscrt.__version__)" + macos: runs-on: macos-14 # latest diff --git a/continuous-delivery/build-wheels-winarm64.bat b/continuous-delivery/build-wheels-winarm64.bat deleted file mode 100644 index cff24192d..000000000 --- a/continuous-delivery/build-wheels-winarm64.bat +++ /dev/null @@ -1,37 +0,0 @@ -@echo off - -if not defined PYTHON311_ARM64 goto missing_python -if not defined PYTHON313_ARM64 goto missing_python -if not defined PYTHON313T_ARM64 goto missing_python -if not defined PYTHON314T_ARM64 goto missing_python - -"%PYTHON311_ARM64%" -c "import sys, sysconfig; raise SystemExit(0 if sys.version_info[:2] == (3, 11) and sysconfig.get_platform() == 'win-arm64' and not sysconfig.get_config_var('Py_GIL_DISABLED') else 1)" || goto wrong_python -"%PYTHON313_ARM64%" -c "import sys, sysconfig; raise SystemExit(0 if sys.version_info[:2] == (3, 13) and sysconfig.get_platform() == 'win-arm64' and not sysconfig.get_config_var('Py_GIL_DISABLED') else 1)" || goto wrong_python -"%PYTHON313T_ARM64%" -c "import sys, sysconfig; raise SystemExit(0 if sys.version_info[:2] == (3, 13) and sysconfig.get_platform() == 'win-arm64' and sysconfig.get_config_var('Py_GIL_DISABLED') else 1)" || goto wrong_python -"%PYTHON314T_ARM64%" -c "import sys, sysconfig; raise SystemExit(0 if sys.version_info[:2] == (3, 14) and sysconfig.get_platform() == 'win-arm64' and sysconfig.get_config_var('Py_GIL_DISABLED') else 1)" || goto wrong_python - -"%PYTHON313_ARM64%" continuous-delivery\update-version.py || goto error - -:: The 3.11 stable ABI wheel also supports Python 3.12. -"%PYTHON311_ARM64%" -m build || goto error - -:: Use the 3.13 stable ABI from 3.13 onwards because of deprecated functions. -"%PYTHON313_ARM64%" -m build || goto error - -:: Free-threaded builds do not support the Limited C API or stable ABI. -"%PYTHON313T_ARM64%" -m build || goto error -"%PYTHON314T_ARM64%" -m build || goto error - -goto :EOF - -:missing_python -echo PYTHON311_ARM64, PYTHON313_ARM64, PYTHON313T_ARM64, and PYTHON314T_ARM64 must point to native ARM64 Python executables. -exit /b 1 - -:wrong_python -echo Configured Python executables must have the expected version, win-arm64 platform, and free-threaded status. -exit /b 1 - -:error -echo Failed with error #%errorlevel%. -exit /b %errorlevel% \ No newline at end of file From 2a028fc0c1491dd312389af10d8362e54e06ef4b Mon Sep 17 00:00:00 2001 From: Krish Date: Thu, 17 Sep 2026 21:09:15 +0000 Subject: [PATCH 10/18] Suppress unused clang-cl flags --- setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setup.py b/setup.py index 7a1e28809..573ba7537 100644 --- a/setup.py +++ b/setup.py @@ -568,6 +568,12 @@ def awscrt_ext(): extra_compile_args += ['/Z7'] extra_link_args += ['/DEBUG'] + if is_windows_arm64(): + # We compile the extension with clang-cl (see awscrt_build_ext), but + # distutils still hands it MSVC's default "/O2 /W3 /GL /DNDEBUG /MD", + # and clang-cl does not implement /GL. + extra_compile_args += ['-Wno-unused-command-line-argument'] + elif sys.platform == 'darwin': extra_link_args += ['-framework', 'Security'] From 2ca3261184be34aa15d2f1b6361570020e04e2ce Mon Sep 17 00:00:00 2001 From: Krish Date: Thu, 17 Sep 2026 21:09:15 +0000 Subject: [PATCH 11/18] Shorten ARM64 wheel job names --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba6132172..deba4a4b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -335,6 +335,7 @@ jobs: windows-arm64-wheel: # Verify the wheel we'd ship is tagged for win_arm64, and that an abi3 wheel # built on one python installs and imports on a newer one. + name: windows-arm64-wheel (${{ matrix.build-python }} → ${{ matrix.test-python }}) runs-on: windows-11-arm strategy: fail-fast: false From 3f9e6a64c1941437c03b27e0ecb018557e8ec924 Mon Sep 17 00:00:00 2001 From: Krish Date: Thu, 17 Sep 2026 21:21:23 +0000 Subject: [PATCH 12/18] Test unreleased submodule fixes --- crt/aws-c-common | 2 +- crt/aws-c-io | 2 +- crt/aws-c-mqtt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crt/aws-c-common b/crt/aws-c-common index 3a5e638ae..0b414a6eb 160000 --- a/crt/aws-c-common +++ b/crt/aws-c-common @@ -1 +1 @@ -Subproject commit 3a5e638aee99c9f1d65696f7df8c4e5d3dc5805c +Subproject commit 0b414a6eb6c5da9ae591fe6d72779c3062b2e973 diff --git a/crt/aws-c-io b/crt/aws-c-io index 28e4eb351..54a2ceff4 160000 --- a/crt/aws-c-io +++ b/crt/aws-c-io @@ -1 +1 @@ -Subproject commit 28e4eb351a536daf1627bf69279e50671f7729b5 +Subproject commit 54a2ceff4d011e8306684dd6f8cf00c2e2509937 diff --git a/crt/aws-c-mqtt b/crt/aws-c-mqtt index e35b9ca3f..ea8311cf0 160000 --- a/crt/aws-c-mqtt +++ b/crt/aws-c-mqtt @@ -1 +1 @@ -Subproject commit e35b9ca3f9fcbf1a972c831c5e79046ce56959d1 +Subproject commit ea8311cf014718a0b332b38ad0ee85de97bf3e0a From e19bdfc4b7191ff573dab4acaeb52a038150dc74 Mon Sep 17 00:00:00 2001 From: Krish Date: Fri, 18 Sep 2026 21:42:36 +0000 Subject: [PATCH 13/18] Pin submodules to latest releases --- crt/aws-c-auth | 2 +- crt/aws-c-cal | 2 +- crt/aws-c-common | 2 +- crt/aws-c-compression | 2 +- crt/aws-c-event-stream | 2 +- crt/aws-c-http | 2 +- crt/aws-c-io | 2 +- crt/aws-c-mqtt | 2 +- crt/aws-c-s3 | 2 +- crt/aws-c-sdkutils | 2 +- crt/aws-checksums | 2 +- crt/aws-lc | 2 +- crt/s2n | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/crt/aws-c-auth b/crt/aws-c-auth index 4b5d524bf..055e822f0 160000 --- a/crt/aws-c-auth +++ b/crt/aws-c-auth @@ -1 +1 @@ -Subproject commit 4b5d524bf1a511b05e0fffe5bdc51800770b9427 +Subproject commit 055e822f021d1cab11d608b94ac34de250986134 diff --git a/crt/aws-c-cal b/crt/aws-c-cal index 8aa2a48a0..2441187f3 160000 --- a/crt/aws-c-cal +++ b/crt/aws-c-cal @@ -1 +1 @@ -Subproject commit 8aa2a48a09f93c65d4cf06388e143a6584de6321 +Subproject commit 2441187f3bdbe0f0fe7fa5dd1736be98227ad556 diff --git a/crt/aws-c-common b/crt/aws-c-common index 0b414a6eb..3d274e1af 160000 --- a/crt/aws-c-common +++ b/crt/aws-c-common @@ -1 +1 @@ -Subproject commit 0b414a6eb6c5da9ae591fe6d72779c3062b2e973 +Subproject commit 3d274e1af954592b344a33fdf042af37b936f3d5 diff --git a/crt/aws-c-compression b/crt/aws-c-compression index d8264e64f..891312c05 160000 --- a/crt/aws-c-compression +++ b/crt/aws-c-compression @@ -1 +1 @@ -Subproject commit d8264e64f698341eb03039b96b4f44702a9b3f83 +Subproject commit 891312c058e69a4d55f569f79dde1ee221982532 diff --git a/crt/aws-c-event-stream b/crt/aws-c-event-stream index 51bef3c44..d32600bfe 160000 --- a/crt/aws-c-event-stream +++ b/crt/aws-c-event-stream @@ -1 +1 @@ -Subproject commit 51bef3c44e1058b1689751539170b2e0f589ccdb +Subproject commit d32600bfecc6616cab0c478f96ea5a779f03e05e diff --git a/crt/aws-c-http b/crt/aws-c-http index 8aefd899f..2b563f8a7 160000 --- a/crt/aws-c-http +++ b/crt/aws-c-http @@ -1 +1 @@ -Subproject commit 8aefd899fc3210bfd0e3fd414011a3cb708bf6e4 +Subproject commit 2b563f8a7bd67a902a8b558bb44113748045877c diff --git a/crt/aws-c-io b/crt/aws-c-io index 54a2ceff4..1685abcd3 160000 --- a/crt/aws-c-io +++ b/crt/aws-c-io @@ -1 +1 @@ -Subproject commit 54a2ceff4d011e8306684dd6f8cf00c2e2509937 +Subproject commit 1685abcd331dcced3da63b8d4cd3ced38a8bb14a diff --git a/crt/aws-c-mqtt b/crt/aws-c-mqtt index ea8311cf0..f51046577 160000 --- a/crt/aws-c-mqtt +++ b/crt/aws-c-mqtt @@ -1 +1 @@ -Subproject commit ea8311cf014718a0b332b38ad0ee85de97bf3e0a +Subproject commit f510465775dcce35be8a5cea1aec26893b8c975a diff --git a/crt/aws-c-s3 b/crt/aws-c-s3 index 226c3e693..4edf76c24 160000 --- a/crt/aws-c-s3 +++ b/crt/aws-c-s3 @@ -1 +1 @@ -Subproject commit 226c3e6937e3d5f7db9e10651f7bd20575e98187 +Subproject commit 4edf76c24c810ef2fce1f791358df729245e81e1 diff --git a/crt/aws-c-sdkutils b/crt/aws-c-sdkutils index a1cc19f53..de0fbe807 160000 --- a/crt/aws-c-sdkutils +++ b/crt/aws-c-sdkutils @@ -1 +1 @@ -Subproject commit a1cc19f53b63658f1b1400b36f199eafeeb895a6 +Subproject commit de0fbe807a409158c3fa285bafb88120c8989609 diff --git a/crt/aws-checksums b/crt/aws-checksums index 1d5f2f1f3..ee7c435de 160000 --- a/crt/aws-checksums +++ b/crt/aws-checksums @@ -1 +1 @@ -Subproject commit 1d5f2f1f3e5d013aae8810878ceb5b3f6f258c4e +Subproject commit ee7c435de1677754c14e488aab699ed603ae552e diff --git a/crt/aws-lc b/crt/aws-lc index 6f246af4c..a3d1e6855 160000 --- a/crt/aws-lc +++ b/crt/aws-lc @@ -1 +1 @@ -Subproject commit 6f246af4cd1de8cee8c62d76139bcda299c1aa00 +Subproject commit a3d1e685552f05a9ad04a2946962c03e97bdecac diff --git a/crt/s2n b/crt/s2n index 853d1943b..bce022f41 160000 --- a/crt/s2n +++ b/crt/s2n @@ -1 +1 @@ -Subproject commit 853d1943bbbd7f782a159e77830cdaaf520d68ed +Subproject commit bce022f4195c290175b70e925e08a458221608f0 From 94122cbf573ad9c42983ff56bc95e6ad830ddc7b Mon Sep 17 00:00:00 2001 From: Krish Date: Fri, 18 Sep 2026 22:02:46 +0000 Subject: [PATCH 14/18] Silence clang-cl /MP warning --- setup.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/setup.py b/setup.py index 573ba7537..16129b604 100644 --- a/setup.py +++ b/setup.py @@ -212,6 +212,13 @@ def determine_generator_args(cmake_version=None, windows_sdk_version=None): '-DCMAKE_ASM_COMPILER=clang-cl', # The optimized ARM checksum sources do not compile with clang-cl. '-DUSE_CPU_EXTENSIONS=OFF', + # The CRT's CMake adds /MP (parallel compilation), which clang-cl + # accepts and ignores, warning once per translation unit. + # This lands ahead of the /W4 that aws_set_common_properties() adds, + # which is fine: /W4 maps to -Wall -Wextra, and neither of those + # groups includes -Wunused-command-line-argument, so they do not + # turn it back on. + '-DCMAKE_C_FLAGS=-Wno-unused-command-line-argument', ] if vs_year <= 2017: From fa6e41d9b6c239607436507896942ef618e29b9a Mon Sep 17 00:00:00 2001 From: Krish Date: Mon, 21 Sep 2026 22:14:38 +0000 Subject: [PATCH 15/18] Honor CFLAGS in ARM64 build --- setup.py | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/setup.py b/setup.py index 16129b604..1e7162ac1 100644 --- a/setup.py +++ b/setup.py @@ -35,6 +35,23 @@ # Regex to match a Windows SDK version directory name in the format of major.minor.build.revision SDK_VERSION_RE = re.compile(r'^(\d+)\.(\d+)\.(\d+)\.(\d+)$') +# On Windows ARM64 we build with clang-cl, which accepts MSVC-only flags and then +# ignores them, warning once per translation unit. We get /MP from the CRT's CMake +# and /GL from distutils. Those are two independent compiler invocations that share +# no configuration, so these have to be passed to each of them separately. +# +# Keep this a list, one flag per entry: extra_compile_args entries each become a +# single argv element, so "-Wa -Wb" in one entry reaches clang-cl as one unknown +# option and is silently ignored. +# +# Note these only reach the CRT build via CMAKE_C_FLAGS, which CMake emits *before* +# a target's own options. So a flag here cannot turn off anything the CRT's /W4 +# re-enables (i.e. anything in -Wall or -Wextra) -- that has to be fixed in +# aws-c-common's AwsCFlags.cmake instead. +CLANG_CL_IGNORED_FLAG_WARNINGS = [ + '-Wno-unused-command-line-argument', +] + def parse_version(version_string): return tuple(int(x) for x in version_string.split(".")) @@ -212,13 +229,14 @@ def determine_generator_args(cmake_version=None, windows_sdk_version=None): '-DCMAKE_ASM_COMPILER=clang-cl', # The optimized ARM checksum sources do not compile with clang-cl. '-DUSE_CPU_EXTENSIONS=OFF', - # The CRT's CMake adds /MP (parallel compilation), which clang-cl - # accepts and ignores, warning once per translation unit. - # This lands ahead of the /W4 that aws_set_common_properties() adds, - # which is fine: /W4 maps to -Wall -Wextra, and neither of those - # groups includes -Wunused-command-line-argument, so they do not - # turn it back on. - '-DCMAKE_C_FLAGS=-Wno-unused-command-line-argument', + # Silences /MP, which the CRT's CMake adds. This lands ahead of the + # /W4 that aws_set_common_properties() adds, which is fine: /W4 maps + # to -Wall -Wextra, and neither group includes this warning, so they + # do not turn it back on. + # Appends to, rather than replaces, what CMake would have taken from + # the CFLAGS env var -- an explicit -D on the command line wins over + # that, and the extension half already honors CFLAGS (see awscrt_ext). + '-DCMAKE_C_FLAGS=' + ' '.join([os.environ.get('CFLAGS', '')] + CLANG_CL_IGNORED_FLAG_WARNINGS).strip(), ] if vs_year <= 2017: @@ -576,10 +594,10 @@ def awscrt_ext(): extra_link_args += ['/DEBUG'] if is_windows_arm64(): - # We compile the extension with clang-cl (see awscrt_build_ext), but - # distutils still hands it MSVC's default "/O2 /W3 /GL /DNDEBUG /MD", - # and clang-cl does not implement /GL. - extra_compile_args += ['-Wno-unused-command-line-argument'] + # Silences /GL, which distutils hardcodes into its MSVC defaults + # ("/O2 /W3 /GL /DNDEBUG /MD"). This is a separate compiler invocation + # from the CMake one above, so it needs the flag of its own. + extra_compile_args += CLANG_CL_IGNORED_FLAG_WARNINGS elif sys.platform == 'darwin': extra_link_args += ['-framework', 'Security'] From 3d4d7f43ed1930618b7cb65828ab68d54143019b Mon Sep 17 00:00:00 2001 From: Krish Date: Mon, 21 Sep 2026 22:14:38 +0000 Subject: [PATCH 16/18] Harden ARM64 wheel job --- .github/workflows/ci.yml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index deba4a4b6..8cb922dbb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -337,6 +337,8 @@ jobs: # built on one python installs and imports on a newer one. name: windows-arm64-wheel (${{ matrix.build-python }} → ${{ matrix.test-python }}) runs-on: windows-11-arm + permissions: + contents: read # only needs to check out the source; no AWS creds, no OIDC strategy: fail-fast: false matrix: @@ -365,7 +367,13 @@ jobs: shell: pwsh run: | python -m pip install --upgrade build - python -m build --wheel + # Bare "-m build", matching what the release scripts run, rather than + # --wheel: it builds the sdist, extracts it, and builds the wheel from + # the extraction, so an sdist missing files the ARM64 build needs (e.g. + # aws-lc's generated-src/win-aarch64 assembly) fails here instead of at + # release time. The Linux package-source job cannot catch that, since it + # only ever compiles generated-src/linux-x86_64. + python -m build $wheels = @(Get-Item dist\*.whl) if ($wheels.Count -ne 1) { throw "Expected exactly one wheel, got $($wheels.Count)" } $expected = 'Tag: ${{ matrix.expected-tag }}' @@ -379,8 +387,20 @@ jobs: run: | python -m venv ${{ runner.temp }}\venv $py = "${{ runner.temp }}\venv\Scripts\python.exe" - & $py -m pip install @(Get-Item dist\*.whl)[0].FullName - & $py -c "import awscrt.io, awscrt.http, awscrt.s3; print(awscrt.__version__)" + $wheel = @(Get-Item dist\*.whl)[0].FullName + & $py -m pip install $wheel + if ($LASTEXITCODE -ne 0) { throw 'pip install of the wheel failed' } + # Run from outside the checkout. "python -c" puts the working directory + # first on sys.path, so from the repo root "import awscrt" would resolve + # the source tree and only _awscrt would come from the wheel -- which + # would still pass if the wheel shipped none of awscrt's python files. + Push-Location ${{ runner.temp }} + try { + & $py -c "import awscrt, awscrt.io, awscrt.http, awscrt.s3; print(awscrt.__version__, awscrt.__file__)" + if ($LASTEXITCODE -ne 0) { throw 'importing the installed wheel failed' } + } finally { + Pop-Location + } macos: From 268f76b312063863a0727207ac6d3269f03dd10b Mon Sep 17 00:00:00 2001 From: Krish Date: Mon, 21 Sep 2026 22:39:08 +0000 Subject: [PATCH 17/18] Trim ARM64 wheel job checks --- .github/workflows/ci.yml | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8cb922dbb..d91b97520 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -367,12 +367,8 @@ jobs: shell: pwsh run: | python -m pip install --upgrade build - # Bare "-m build", matching what the release scripts run, rather than - # --wheel: it builds the sdist, extracts it, and builds the wheel from - # the extraction, so an sdist missing files the ARM64 build needs (e.g. - # aws-lc's generated-src/win-aarch64 assembly) fails here instead of at - # release time. The Linux package-source job cannot catch that, since it - # only ever compiles generated-src/linux-x86_64. + # Bare "-m build" (not --wheel) builds the wheel from an extracted sdist, + # so it also proves the sdist carries the files the ARM64 build needs. python -m build $wheels = @(Get-Item dist\*.whl) if ($wheels.Count -ne 1) { throw "Expected exactly one wheel, got $($wheels.Count)" } @@ -387,17 +383,12 @@ jobs: run: | python -m venv ${{ runner.temp }}\venv $py = "${{ runner.temp }}\venv\Scripts\python.exe" - $wheel = @(Get-Item dist\*.whl)[0].FullName - & $py -m pip install $wheel - if ($LASTEXITCODE -ne 0) { throw 'pip install of the wheel failed' } - # Run from outside the checkout. "python -c" puts the working directory - # first on sys.path, so from the repo root "import awscrt" would resolve - # the source tree and only _awscrt would come from the wheel -- which - # would still pass if the wheel shipped none of awscrt's python files. + & $py -m pip install @(Get-Item dist\*.whl)[0].FullName + # Import from outside the checkout, else "python -c" resolves awscrt's + # python files from the source tree instead of the installed wheel. Push-Location ${{ runner.temp }} try { - & $py -c "import awscrt, awscrt.io, awscrt.http, awscrt.s3; print(awscrt.__version__, awscrt.__file__)" - if ($LASTEXITCODE -ne 0) { throw 'importing the installed wheel failed' } + & $py -c "import awscrt, awscrt.io, awscrt.http, awscrt.s3, awscrt.aio, awscrt.eventstream; print(awscrt.__version__, awscrt.__file__)" } finally { Pop-Location } From 20fff7f21db5326d98312dd1eea394635cf091b0 Mon Sep 17 00:00:00 2001 From: Krish Date: Mon, 21 Sep 2026 23:10:57 +0000 Subject: [PATCH 18/18] Build wheel only in wheel job --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d91b97520..a431138eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -367,9 +367,7 @@ jobs: shell: pwsh run: | python -m pip install --upgrade build - # Bare "-m build" (not --wheel) builds the wheel from an extracted sdist, - # so it also proves the sdist carries the files the ARM64 build needs. - python -m build + python -m build --wheel $wheels = @(Get-Item dist\*.whl) if ($wheels.Count -ne 1) { throw "Expected exactly one wheel, got $($wheels.Count)" } $expected = 'Tag: ${{ matrix.expected-tag }}'