EDK2 PyTool Extensions
EDK2 PyTool Extensions is a collection of Python-based tools designed to support the development of UEFI EDK2 firmware. It orchestrates common build tasks, manages external dependencies, and provides a programmatic interface for EDK2 builds. The current version is 0.31.0, with an active development cadence featuring frequent updates and bug fixes.
Common errors
-
EDK2_PATH environment variable not set or invalid.
cause The `EDK2_PATH` (and usually `WORKSPACE`) environment variable is either not defined or points to a directory that doesn't contain a valid EDK2 source tree as expected by the tools.fixSet the `EDK2_PATH` and `WORKSPACE` environment variables to the root directory of your EDK2 source code before running any EDK2-PyTool-Extensions commands or scripts. Example: `export EDK2_PATH=/path/to/edk2/source` and `export WORKSPACE=/path/to/edk2/source` (Linux/macOS) or `set EDK2_PATH=C:\path\to\edk2\source` (Windows). -
FileNotFoundError: [Errno 2] No such file or directory: 'nasm'
cause The EDK2 build process, orchestrated by this library, requires external executables (like `nasm`, `cl.exe`, `gcc`, `iasl`) that are not found in your system's PATH.fixInstall the necessary EDK2 toolchain components (e.g., NASM assembler, Visual Studio Build Tools for MSVC, or GCC for GCC toolchain) and ensure their installation directory is added to your system's PATH environment variable. -
AttributeError: module 'edk2toolext' has no attribute 'invocables'
cause This usually means you're trying to directly import a submodule like `edk2toolext.invocables.edk2_setup` programmatically when it's primarily designed for command-line invocation via `python -m`.fixFor tools like `edk2_setup`, use the `python -m` command-line invocation (e.g., `python -m edk2toolext.invocables.edk2_setup`). For programmatic access, ensure you are importing specific classes like `UefiBuilder` from their correct paths (`from edk2toolext.environment.uefi_build import UefiBuilder`).
Warnings
- gotcha EDK2-PyTool-Extensions relies heavily on specific environment variables (e.g., `WORKSPACE`, `EDK2_PATH`) to locate your EDK2 source tree and associated packages. Incorrect or unset variables are a primary cause of build failures.
- gotcha Building EDK2 firmware requires a complete external toolchain (e.g., NASM, MSVC/GCC, IASL, etc.) to be discoverable in your system's PATH. The Python library orchestrates these tools but does not provide them.
- breaking As a pre-1.0 library (currently 0.x.x), API interfaces and internal behaviors may change between minor versions without explicit deprecation warnings, potentially requiring code adjustments.
Install
-
pip install edk2-pytool-extensions
Imports
- UefiBuilder
from edk2toolext.environment.uefi_build import UefiBuilder
- edk2_setup (command-line)
from edk2toolext.invocables import edk2_setup
python -m edk2toolext.invocables.edk2_setup
Quickstart
import os
import tempfile
import shutil
from pathlib import Path
import subprocess
import sys
# --- Create a dummy EDK2 environment for demonstration ---
# In a real scenario, EDK2_PATH and WORKSPACE would point to
# your actual EDK2 source code and build workspace.
temp_dir = Path(tempfile.mkdtemp())
edk2_path = temp_dir / "edk2"
workspace_path = temp_dir / "MyWorkspace"
edk2_path.mkdir(exist_ok=True)
workspace_path.mkdir(exist_ok=True)
# Simulate minimal EDK2 structure needed for some checks
(edk2_path / "MdePkg").mkdir(exist_ok=True)
(edk2_path / "MdePkg" / "MdePkg.dsc").write_text("# Dummy DSC file")
(workspace_path / "MyPlatformPkg").mkdir(exist_ok=True)
(workspace_path / "MyPlatformPkg" / "MyPlatform.dsc").write_text("# Dummy Platform DSC file")
os.environ['EDK2_PATH'] = str(edk2_path)
os.environ['WORKSPACE'] = str(workspace_path)
try:
# --- 1. Demonstrate using the EDK2 setup tool (command-line) ---
# This tool helps download external dependencies for EDK2 builds.
print("\n--- Running EDK2 Setup Tool (displaying help) ---")
setup_result = subprocess.run(
[sys.executable, "-m", "edk2toolext.invocables.edk2_setup", "--help"],
capture_output=True, text=True, check=False
)
print("EDK2 Setup Tool Help Output (truncated):\n" + setup_result.stdout[:500] + "...")
if setup_result.returncode != 0:
print(f"Error running setup tool help: {setup_result.stderr}")
# --- 2. Demonstrate programmatic use of UefiBuilder ---
# UefiBuilder is a core class for orchestrating EDK2 builds.
print("\n--- Demonstrating programmatic import of UefiBuilder ---")
from edk2toolext.environment.uefi_build import UefiBuilder
builder_instance = UefiBuilder()
print(f"Successfully instantiated UefiBuilder: {builder_instance.__class__.__name__}")
print("Note: A real build would require valid EDK2 source, toolchains, ")
print("and potentially specific platform configuration files, which are ")
print("outside the scope of this minimal quickstart example.")
except ImportError as e:
print(f"Error importing EDK2 PyTool Extensions. Ensure it's installed: {e}")
except Exception as e:
print(f"An unexpected error occurred during quickstart: {e}")
finally:
# Clean up dummy environment
if temp_dir.exists():
shutil.rmtree(temp_dir)
print("\n--- Quickstart demonstration complete. --- ")