diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e319e063..5d402c797 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -277,6 +277,32 @@ 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-latest: + # try latest version to see if it works with a later version of Windows SDK + runs-on: windows-2025 + strategy: + fail-fast: false + matrix: + arch: [x86, x64] + permissions: + id-token: write # This is required for requesting the JWT + steps: + - uses: actions/setup-python@v5 + id: python38 + with: + python-version: '3.8.10' + architecture: ${{ matrix.arch }} + - uses: ilammy/setup-nasm@v1 + - 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.python38.outputs.python-path }}" + macos: runs-on: macos-14 # latest permissions: diff --git a/setup.py b/setup.py index 68e0f617b..80f688a1b 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ # This is the minimum version of the Windows SDK needed for schannel.h with SCH_CREDENTIALS and # TLS_PARAMETERS. These are required to build Windows Binaries with TLS 1.3 support. -WINDOWS_SDK_VERSION_TLS1_3_SUPPORT = "10.0.17763.0" +WINDOWS_SDK_MIN_VERSION_TLS1_3_SUPPORT = "10.0.17763.0" def parse_version(version_string): @@ -88,6 +88,76 @@ def determine_cross_compile_args(): return [] +def get_windows_sdk_versions(): + """Return a list of installed Windows SDK versions, sorted from newest to oldest. + + Uses the Windows registry to find the SDK installation path. + """ + if sys.platform != 'win32': + return [] + + import winreg + + sdk_versions = [] + sdk_paths = [] + + # Try to get SDK path from registry + try: + with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, + r"SOFTWARE\Microsoft\Windows Kits\Installed Roots") as key: + sdk_root = winreg.QueryValueEx(key, "KitsRoot10")[0] + sdk_paths.append(os.path.join(sdk_root, "Include")) + except (OSError, FileNotFoundError): + # Registry key not found, fall back to common installation paths + sdk_paths = [ + os.path.join(os.environ.get('ProgramFiles(x86)', 'C:\\Program Files (x86)'), + 'Windows Kits', '10', 'Include'), + os.path.join(os.environ.get('ProgramFiles', 'C:\\Program Files'), + 'Windows Kits', '10', 'Include'), + ] + + for sdk_path in sdk_paths: + if os.path.exists(sdk_path): + try: + for entry in os.listdir(sdk_path): + # SDK version directories look like "10.0.17763.0" + if entry.startswith('10.0.') and os.path.isdir(os.path.join(sdk_path, entry)): + if entry not in sdk_versions: + sdk_versions.append(entry) + except OSError: + continue + + # Sort versions from newest to oldest + sdk_versions.sort(key=parse_version, reverse=True) + return sdk_versions + + +def get_best_windows_sdk_version(): + """Return the best Windows SDK version to use for TLS 1.3 support. + + Returns the latest installed SDK version that is >= WINDOWS_SDK_MIN_VERSION_TLS1_3_SUPPORT. + Raises RuntimeError if no suitable SDK is found. + """ + min_version = parse_version(WINDOWS_SDK_MIN_VERSION_TLS1_3_SUPPORT) + installed_versions = get_windows_sdk_versions() + + for version in installed_versions: + if parse_version(version) >= min_version: + print(f"Found Windows SDK {version} (>= {WINDOWS_SDK_MIN_VERSION_TLS1_3_SUPPORT} required for TLS 1.3)") + return version + + # No suitable SDK found + if installed_versions: + raise RuntimeError( + f"No Windows SDK >= {WINDOWS_SDK_MIN_VERSION_TLS1_3_SUPPORT} found. " + f"Installed versions: {', '.join(installed_versions)}. " + f"Please install Windows SDK {WINDOWS_SDK_MIN_VERSION_TLS1_3_SUPPORT} or later for TLS 1.3 support.") + else: + raise RuntimeError( + f"No Windows SDK found. " + f"Please install Windows SDK {WINDOWS_SDK_MIN_VERSION_TLS1_3_SUPPORT} or later for TLS 1.3 support.") + + def determine_generator_args(cmake_version=None, windows_sdk_version=None): if sys.platform == 'win32': try: @@ -272,7 +342,7 @@ def _build_dependencies_impl(self, build_dir, install_path, osx_arch=None): if sys.platform == 'win32': windows_sdk_version = os.getenv('AWS_CRT_WINDOWS_SDK_VERSION') if windows_sdk_version is None: - windows_sdk_version = WINDOWS_SDK_VERSION_TLS1_3_SUPPORT + windows_sdk_version = get_best_windows_sdk_version() cmake_version = get_cmake_version()