iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
💪

The Complete Guide to Setting Up Python and Azure SDK on Windows ARM64 (Copilot+ PC)

に公開

Introduction

Windows machines equipped with ARM64 processors (Snapdragon X Elite / Plus), such as the Surface Pro X, Copilot+ PC, and Surface Pro 11, are spreading rapidly. They are attractive as development machines because they have long battery life and are fanless and quiet, but when you try to do Azure development with Python, you will immediately run into a wall.

Why is being able to use the Azure SDK great?

By using the Azure SDK (azure-identity, azure-storage-blob, azure-cosmos, etc.), you can operate Azure resources from Python safely and easily.

# With the Azure SDK, you can upload files to Blob Storage in just a few lines
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient

credential = DefaultAzureCredential()  # Authentication is automatic!
client = BlobServiceClient(
    account_url="https://myaccount.blob.core.windows.net",
    credential=credential
)
blob_client = client.get_blob_client("my-container", "report.pdf")
with open("report.pdf", "rb") as f:
    blob_client.upload_blob(f, overwrite=True)

Particularly important is DefaultAzureCredential. This class automatically determines the execution environment and switches between using az login authentication locally and Managed Identity on Azure. In other words, you can write an app that runs on both local and cloud environments without changing a single line of code.

Without the Azure SDK, you would need tedious code like calling the REST API directly and manually calculating the HMAC-SHA256 signature of the access key.

Why does the cryptography package become an issue?

cryptography is a cryptographic library for Python. It handles the core of security, such as SSL/TLS communication, certificate verification, and digital signatures. Even if you don't use it directly, azure-identity in the Azure SDK depends on it internally, so if this cannot be installed, the Azure SDK itself will not work.

The problem is that this package is written in three languages—Python + C + Rust—and requires native binaries during pip install. Usually, pre-built binaries (wheels) are published on PyPI, but wheels for Windows ARM64 simply do not exist. Therefore, it is necessary to build it from the source code.

Errors encountered

ERROR: Failed building wheel for cryptography
ImportError: DLL load failed while importing _rust: The specified procedure could not be found.

Workaround: WSL2 is also an option

As a quick workaround, there is WSL2 (Windows Subsystem for Linux). Since Linux ARM64 wheels are available on Ubuntu in WSL2, pip install azure-identity works in a single shot.

However, native Windows development is necessary in the following cases:

  • You want to combine it with PowerShell scripts.
  • You want to fully utilize native VS Code Python extensions.
  • Projects using Windows-specific APIs (COM, Win32).
  • You want to execute and debug directly locally without using Docker.

In this article, I will carefully explain the procedure for setting up the Azure SDK in a Windows ARM64 native environment without relying on WSL2, including background knowledge.

What you can solve in this article

Issue Solution
pip install azure-identity fails Build cryptography from source
Cannot import due to DLL load failed Control DLL loading order with sitecustomize.py
Cannot access Azure resources from local Configure DefaultAzureCredential + RBAC

Background: Why is this procedure necessary?

Wheel availability

Pre-built wheels for major platforms are published on PyPI for cryptography, but not all are supported:

OS Architecture Wheel Availability
Windows x64 ✅ Available
Windows ARM64 None
macOS ARM64 (Apple Silicon) ✅ Available
Linux x64 ✅ Available
Linux ARM64 ✅ Available

Windows ARM64 is the only one left behind. Therefore, you need to build it from source code yourself.

What is needed for source build

Because cryptography is written in three languages, the build requires three toolchains:

cryptography source code
├── Python part → Handled by pip (no additional tools needed)
├── C part      → MSVC (Microsoft Visual C++) required
└── Rust part   → Rust compiler (rustc) required
        └── Link to OpenSSL → OpenSSL development libraries required

Furthermore, to create a .pyd (Python extension module) for ARM64, each tool must be able to output with ARM64 as the target.


Terminology

Before getting into the setup steps, let's summarize the terms that will appear.

Rust

A systems programming language developed by Mozilla. It balances memory safety and high performance. Since version 35, the cryptography package has implemented some of its cryptographic processes in Rust. Therefore, the Rust compiler (rustc) is required for the source build.

MSVC (Microsoft Visual C++)

A set of Microsoft's C/C++ compiler and linker. It is included in the Visual Studio Build Tools. Since cryptography also has parts written in C, the MSVC linker (link.exe) is required.

The important thing is that to create an ARM64 executable, you need the linker and libraries for ARM64. By default, only the ones for x64 are installed, so you must explicitly add the ARM64 components.

OpenSSL

The de facto standard library for encrypted communications. It is used for TLS/SSL connections, certificate verification, and more. The cryptography package links to OpenSSL to perform cryptographic operations, so OpenSSL header files (.h) and libraries (.lib) are required at build time.

DefaultAzureCredential

The authentication class for the Azure SDK introduced in the "Introduction". It automatically selects the optimal authentication method based on the execution environment:

Execution Environment Authentication Method Used
Azure App Service Managed Identity
Local (after az login) Azure CLI credentials
GitHub Actions Federated identity tokens

The goal of this article is to get this DefaultAzureCredential working in a local environment.

RBAC (Role-Based Access Control)

A mechanism for controlling "who" can do "what" to Azure resources using roles. For example, assigning the Storage Blob Data Contributor role allows reading, writing, and deleting blobs. To access Azure resources from a local environment using DefaultAzureCredential, you need to assign the appropriate roles to the az login user.

sitecustomize.py

A file that Python automatically loads upon startup. When placed in the site-packages/ directory, it is automatically executed first whenever any Python script is run. In this article, we use it to control the loading order of OpenSSL DLLs.


Prerequisites

  • Windows 11 ARM64 (Surface Pro X / Copilot+ PC / Dev Kit, etc.)
  • Python 3.12+ (Native ARM64 version)
  • winget command available
  • Azure CLI installed and logged in with az login (when accessing Azure resources)

Verification command:

# Check if Python is the ARM64 version
python -c "import platform; print(platform.machine())"
# → OK if "ARM64" is displayed (if "x86_64", it's the x64 emulation version)

Setup Procedure

Step 1. Installing the Rust Compiler

It is necessary for compiling the Rust code included in the cryptography source code.

winget install Rustlang.Rustup
rustup default stable
rustc --version
# → OK if rustc 1.xx.x (aarch64-pc-windows-msvc) is displayed

If aarch64-pc-windows-msvc is displayed, the Rust compiler for ARM64 is correctly installed.

Step 2. Installing Visual Studio Build Tools 2022

This is the MSVC toolchain required for compiling and linking C/C++ code.

winget install Microsoft.VisualStudio.2022.BuildTools `
  --override "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --passive"

Adding ARM64 Components (⚠️ Administrator privileges required):

By default, only the linker and libraries for x64 are installed. To build for ARM64, you must explicitly add the ARM64 components.

$installer = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vs_installer.exe"
Start-Process -Verb RunAs -FilePath $installer -ArgumentList @(
    "modify",
    "--installPath", "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2022\BuildTools",
    "--add", "Microsoft.VisualStudio.Component.VC.Tools.ARM64",
    "--passive"
) -Wait

Verification (OK if True is returned):

Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\*\lib\arm64"

Step 3. Installing OpenSSL ARM64 Development Libraries

This is the cryptographic library that cryptography links to. Since both header files (.h) and static libraries (.lib) are required, install the Dev version.

winget install ShiningLight.OpenSSL.Dev
# → Installed to C:\Program Files\OpenSSL-Win64-ARM

Step 4. Creating a Virtual Environment

Create an isolated Python environment for each project.

python -m venv .venv
.\.venv\Scripts\Activate.ps1

Step 5. Building cryptography from Source

This is the most complex part of the procedure. To tell the build system where MSVC and OpenSSL are located, you need to set several environment variables before running pip install.

# --- Resolve MSVC location ---
$msvcVer = (Get-ChildItem "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC" |
            Sort-Object Name -Descending | Select-Object -First 1).Name
$msvcBase = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\$msvcVer"

# --- Resolve Windows SDK location ---
$sdkVer = (Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\10\Include" |
           Where-Object { $_.Name -match '^\d+\.' } |
           Sort-Object Name -Descending | Select-Object -First 1).Name

# --- Set environment variables ---
# PATH: Use ARM64 native link.exe (Hostarm64\arm64)
$env:PATH = "$msvcBase\bin\Hostarm64\arm64;$env:PATH"

# INCLUDE: Where the compiler looks for header files
$env:INCLUDE = "$msvcBase\include;" + `
  "${env:ProgramFiles(x86)}\Windows Kits\10\Include\$sdkVer\ucrt;" + `
  "${env:ProgramFiles(x86)}\Windows Kits\10\Include\$sdkVer\shared;" + `
  "${env:ProgramFiles(x86)}\Windows Kits\10\Include\$sdkVer\um"

# LIB: Where the linker looks for libraries (specify the arm64 subfolder)
$env:LIB = "$msvcBase\lib\arm64;" + `
  "${env:ProgramFiles(x86)}\Windows Kits\10\Lib\$sdkVer\ucrt\arm64;" + `
  "${env:ProgramFiles(x86)}\Windows Kits\10\Lib\$sdkVer\um\arm64"

# --- Specify OpenSSL location ---
$env:OPENSSL_DIR = "C:\Program Files\OpenSSL-Win64-ARM"
# ⚠️ Libraries are in lib\VC\arm64\MD\, not directly under lib\
$env:OPENSSL_LIB_DIR = "C:\Program Files\OpenSSL-Win64-ARM\lib\VC\arm64\MD"
$env:OPENSSL_INCLUDE_DIR = "C:\Program Files\OpenSSL-Win64-ARM\include"

# --- Build & Install ---
pip install cryptography --no-binary cryptography
Meaning of each environment variable
Environment Variable Setting Why is it necessary?
PATH Directory containing MSVC's ARM64 link.exe ARM64 binaries cannot be created if x64 link.exe is used
INCLUDE MSVC headers + Windows SDK headers (ucrt, shared, um) For the C compiler to resolve #include
LIB MSVC lib + Windows SDK lib (arm64 subfolder) For the linker to find .lib files
OPENSSL_DIR OpenSSL root directory Referenced by the cryptography build script
OPENSSL_LIB_DIR Location of OpenSSL .lib files Explicitly specified as they aren't directly under lib\
OPENSSL_INCLUDE_DIR Location of OpenSSL header files To resolve #include <openssl/ssl.h>

Step 6. Avoiding Runtime DLL Conflicts

Even if the build is successful, you might encounter this error during import (though it may not occur in all environments):

ImportError: DLL load failed while importing _rust: The specified procedure could not be found.

Cause: The Rust extension of the built cryptography (_rust.pyd) requires OpenSSL DLLs at runtime. However, OpenSSL DLLs might also exist in C:\Windows\System32, and Python may load those first. Since they differ in version or export symbols from the OpenSSL used during the build, the loading fails.

Search order:
  1. C:\Windows\System32\libcrypto-3.dll  ← ❌ Wrong version
  2. C:\Program Files\OpenSSL-Win64-ARM\bin\libcrypto-3-arm64.dll  ← ✅ Correct version

Solution: Create sitecustomize.py within the venv to load the correct DLL first upon Python startup. Even if you don't see this error, it is recommended to set this up as a preventive measure.

sitecustomize.py
# .venv/Lib/site-packages/sitecustomize.py
"""
OpenSSL DLL Preloading for Windows ARM64
To avoid conflicts with OpenSSL DLLs in System32,
load the OpenSSL DLLs used during the build first.
"""
import os
import sys

if sys.platform == "win32":
    _openssl_bin = r"C:\Program Files\OpenSSL-Win64-ARM\bin"
    if os.path.isdir(_openssl_bin):
        os.add_dll_directory(_openssl_bin)
        import ctypes
        try:
            ctypes.WinDLL(os.path.join(_openssl_bin, "libcrypto-3-arm64.dll"))
            ctypes.WinDLL(os.path.join(_openssl_bin, "libssl-3-arm64.dll"))
        except OSError:
            pass  # OpenSSL not installed — fall through

Step 7. Installing the Azure SDK

Now that cryptography is working, you can install the Azure SDK as usual.

If you want to install all the packages used in your project at once, it is a best practice to organize them in a requirements.txt file:

requirements.txt
# requirements.txt
azure-identity            # Authentication (DefaultAzureCredential) — almost essential
azure-storage-blob        # Blob Storage
azure-cosmos              # Cosmos DB
azure-ai-documentintelligence  # Document Intelligence (AI)
openai                    # Azure OpenAI
azure-mgmt-resource       # Azure Resource Manager (Resource Management)
azure-monitor-opentelemetry    # Application Insights (Monitoring)
pip install -r requirements.txt

If you are just getting started with the basics, you only need the authentication package plus the service you want to use:

# Example: When using Blob Storage
pip install azure-identity azure-storage-blob

Step 8. Verification

python -c "from azure.identity import DefaultAzureCredential; print('azure-identity OK')"
python -c "from azure.storage.blob import BlobServiceClient; print('azure-storage-blob OK')"

If both display OK, the setup is complete! 🎉


(Optional) Accessing Azure Resources from Local

To use DefaultAzureCredential locally, you need to grant the az login user access rights to the Azure resources.

For Blob Storage

# Get your own object ID
$objectId = (az ad signed-in-user show --query id -o tsv)

# Grant read/write permissions to Blob Storage
az role assignment create `
  --assignee-object-id $objectId `
  --assignee-principal-type User `
  --role "Storage Blob Data Contributor" `
  --scope "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RG>/providers/Microsoft.Storage/storageAccounts/<ACCOUNT>"

For Cosmos DB

az cosmosdb sql role assignment create `
  --account-name <ACCOUNT> `
  --resource-group <RG> `
  --role-definition-name "Cosmos DB Built-in Data Contributor" `
  --principal-id $objectId `
  --scope "/"

Verification (Blob Example)

from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient

credential = DefaultAzureCredential()
client = BlobServiceClient(
    account_url="https://<ACCOUNT>.blob.core.windows.net",
    credential=credential
)

# List containers
for container in client.list_containers():
    print(container["name"])

Troubleshooting

Error Cause Action
link.exe not found MSVC PATH is not set Check the $env:PATH setting in Step 5
LNK4272: library machine type 'x64' conflicts with target 'ARM64' ARM64 MSVC components not installed Perform the ARM64 addition in Step 2
Could not find OpenSSL OpenSSL environment variables not set Check the 3 OPENSSL_* variables in Step 5
OpenSSL library not found at lib OPENSSL_LIB_DIR is incorrect Specify lib\VC\arm64\MD (not directly under lib)
DLL load failed: The specified procedure could not be found OpenSSL in System32 is loaded first Set up sitecustomize.py in Step 6
AuthorizationPermissionMismatch RBAC role not granted or waiting for propagation Set up RBAC and wait a few minutes before retrying
OpenSSL 3's legacy provider failed to load Warning only. No impact on operation You can ignore it
error: can't find Rust compiler Rust not installed or PATH not set Perform Step 1 and restart the terminal

FAQ

Q. Is this procedure necessary when deploying to Azure App Service?

No, it is not. Python on Azure App Service typically runs on Linux (x64 / ARM64), so pre-built wheels are automatically installed from PyPI. Even for Windows App Service, wheels are available since it is an x64 environment. This procedure is only necessary for local development on Windows ARM64.

Q. If I close the terminal after building, do I have to rebuild next time?

No, it is not. The built wheel is saved in the pip cache. The next time you run pip install cryptography, it will be retrieved from the cache, so there is no need to rebuild the environment.

# Check the cache
pip cache list cryptography

Q. What happens if I create a new venv?

Building is not required as it will be retrieved from the cache with pip install cryptography. However, sitecustomize.py needs to be created for each venv.

Q. Can I avoid this procedure by using WSL2?

Yes. As mentioned in the "Introduction," Linux ARM64 wheels are available on Ubuntu in WSL2. If WSL2 is suitable for your use case, it is the simplest option. If you need PowerShell or a Windows native environment, please set it up using the procedure in this article.

Q. Will this become unnecessary if a Windows ARM64 wheel is added to PyPI for cryptography?

Yes. Once the cryptography team officially releases a Windows ARM64 wheel, this procedure will be completely unnecessary. This is being discussed in the pyca/cryptography GitHub Issues.


Summary

To use Python + Azure SDK on Windows ARM64, the following three steps are required:

  1. Prepare build tools (Rust + MSVC ARM64 + OpenSSL)
  2. Build cryptography from source (Set environment variables → pip install --no-binary)
  3. Avoid DLL conflicts (Place sitecustomize.py)

Once set up, the cache takes over, so subsequent pip install runs will work as usual.

With the spread of Copilot+ PCs, the number of developers on Windows ARM64 is expected to increase. I hope this article helps you overcome the hurdles of setting up your environment.


Verification Environment

Item Version
Verification Date 2026-02-14
OS Windows 11 ARM64 (24H2)
Python 3.12.10 (ARM64)
cryptography 46.0.5 (Source build)
Rust 1.93.1 (aarch64-pc-windows-msvc)
MSVC 14.44.35207
OpenSSL 3.6.1 (ShiningLight ARM64 Dev)
azure-identity 1.25.2
azure-storage-blob 12.28.0
GitHubで編集を提案

Discussion