Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 26 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
74 changes: 72 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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)):
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it make more sense to regexp split into (\d+).(\d+).(\d+).(\d+) and check the capture groups? There will undoubtedly be kernel versions past 10.0

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:
Expand Down Expand Up @@ -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()

Expand Down