Hash :
a70b6f56
        
        Author :
  
        
        Date :
2024-01-26T20:37:07
        
      
Add support for WinUI3/Windows App SDK Adds the necessary build args and code changes to support building ANGLE for WinUI 3 (aka Windows App SDK). To reduce the set of changes, and because it is functionally the same, a Windows App SDK build is basically a UWP build, but with an extra define so that the code can make a few changes to the namespaces and includes used. The main changes to the code are: - ICoreWindow is no longer used - Dispatcher has a few changes in naming and args - ISwapChainPanel is now in a different namespace Bug: angleproject:8490 Change-Id: Ibb298e3e86e8298dac12c2019eac7996a8185c51 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5230637 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
#!/usr/bin/python3
#
# Copyright 2024 The ANGLE Project Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# winappsdk_setup.py:
#   Downloads and processes a specific version of Windows App SDK
#   for use when building ANGLE for WinUI 3 apps.
#
# Usage:
#   python3 winappsdk_setup.py [--version <package-version>] [--output /path/to/dest] [--force]
import argparse
import fnmatch
import io
import os
import subprocess
import urllib.request
import zipfile
package_id = "Microsoft.WindowsAppSDK"
uap_version = "10.0.18362"
default_version = "1.3.230724000"
default_output = "third_party\WindowsAppSDK"
def download_and_extract_nuget_package(force, version, output_path):
    # first check if the last download was successful
    stamp = os.path.join(output_path, f"{version}.stamp")
    if os.path.exists(stamp) and not force:
        return
    # download the package
    nuget_url = f"https://www.nuget.org/api/v2/package/{package_id}/{version}"
    with urllib.request.urlopen(nuget_url) as response:
        if response.status == 200:
            package_bytes = io.BytesIO(response.read())
            # extract
            os.makedirs(output_path, exist_ok=True)
            with zipfile.ZipFile(package_bytes, 'r') as zip_ref:
                zip_ref.extractall(output_path)
            # make a stamp to avoid re-downloading
            with open(stamp, 'w') as file:
                pass
        else:
            print(
                f"Failed to download the {package_id} NuGet package. Status code: {response.status}"
            )
            sys.exit(1)
def get_win_sdk():
    p = os.getenv("ProgramFiles(x86)", "C:\\Program Files (x86)")
    win_sdk = os.getenv("WindowsSdkDir")
    if not win_sdk:
        win_sdk = os.path.join(p, "Windows Kits", "10")
        print("%WindowsSdkDir% not set. Defaulting to", win_sdk)
        print("You might want to run this from a Visual Studio cmd prompt.")
    return win_sdk
def get_latest_sdk_version(win_sdk):
    files = os.listdir(os.path.join(win_sdk, "bin"))
    filtered_files = fnmatch.filter(files, "10.0.*")
    sorted_files = sorted(filtered_files, reverse=True)
    return sorted_files[0]
def run_winmdidl(force, win_sdk_bin, output_path, winmd, stamp_filename=None):
    include = os.path.join(output_path, "include")
    lib = os.path.join(output_path, "lib")
    if stamp_filename:
        stamp = os.path.join(include, stamp_filename)
    else:
        no_ext = os.path.splitext(os.path.basename(winmd))[0]
        stamp = os.path.join(include, no_ext + ".idl")
    if os.path.exists(stamp) and not force:
        return
    winmdidl = os.path.join(win_sdk_bin, "winmdidl.exe")
    command = [
        winmdidl,
        os.path.join(lib, winmd), "/metadata_dir:C:\\Windows\\System32\\WinMetadata",
        "/metadata_dir:" + os.path.join(lib, f"uap{uap_version}"),
        "/metadata_dir:" + os.path.join(lib, "uap10.0"), "/outdir:" + include, "/nologo"
    ]
    subprocess.run(command, check=True, cwd=include)
def run_midlrt(force, win_sdk_bin, output_path, idl):
    include = os.path.join(output_path, "include")
    lib = os.path.join(output_path, "lib")
    no_ext = os.path.splitext(os.path.basename(idl))[0]
    stamp = os.path.join(include, no_ext + ".h")
    if os.path.exists(stamp) and not force:
        return
    midlrt = os.path.join(win_sdk_bin, "midlrt.exe")
    command = [
        midlrt,
        os.path.join(include, idl), "/metadata_dir", "C:\\Windows\\System32\\WinMetadata",
        "/ns_prefix", "/nomidl", "/nologo"
    ]
    subprocess.run(command, check=True, cwd=include)
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Setup the Windows App SDK.")
    parser.add_argument(
        "--version", default=default_version, help="the package version to download")
    parser.add_argument(
        "--output", default=default_output, help="the destination path for extracted contents")
    parser.add_argument(
        "--force", action="store_true", help="ignore existing files and re-download")
    args = parser.parse_args()
    if os.path.isabs(args.output):
        output_path = args.output
    else:
        output_path = os.path.join(os.getcwd(), args.output)
    win_sdk = get_win_sdk()
    latest_sdk = get_latest_sdk_version(win_sdk)
    arch = "x64"
    win_sdk_bin = os.path.join(win_sdk, "bin", latest_sdk, arch)
    winmd_files = {
        f"uap{uap_version}\\Microsoft.Foundation.winmd": None,
        f"uap{uap_version}\\Microsoft.Graphics.winmd": "Microsoft.Graphics.DirectX.idl",
        f"uap{uap_version}\\Microsoft.UI.winmd": None,
        "uap10.0\\Microsoft.UI.Text.winmd": None,
        "uap10.0\\Microsoft.UI.Xaml.winmd": None,
        "uap10.0\\Microsoft.Web.WebView2.Core.winmd": None,
    }
    idl_files = [
        "Microsoft.Foundation.idl",
        "Microsoft.Graphics.DirectX.idl",
        "Microsoft.UI.Composition.idl",
        "Microsoft.UI.Composition.SystemBackdrops.idl",
        "Microsoft.UI.Dispatching.idl",
        "Microsoft.UI.idl",
        "Microsoft.UI.Input.idl",
        "Microsoft.UI.Text.idl",
        "Microsoft.UI.Windowing.idl",
        "Microsoft.UI.Xaml.Automation.idl",
        "Microsoft.UI.Xaml.Automation.Peers.idl",
        "Microsoft.UI.Xaml.Automation.Provider.idl",
        "Microsoft.UI.Xaml.Automation.Text.idl",
        "Microsoft.UI.Xaml.Controls.idl",
        "Microsoft.UI.Xaml.Controls.Primitives.idl",
        "Microsoft.UI.Xaml.Data.idl",
        "Microsoft.UI.Xaml.Documents.idl",
        "Microsoft.UI.Xaml.idl",
        "Microsoft.UI.Xaml.Input.idl",
        "Microsoft.UI.Xaml.Interop.idl",
        "Microsoft.UI.Xaml.Media.Animation.idl",
        "Microsoft.UI.Xaml.Media.idl",
        "Microsoft.UI.Xaml.Media.Imaging.idl",
        "Microsoft.UI.Xaml.Media.Media3D.idl",
        "Microsoft.UI.Xaml.Navigation.idl",
        "Microsoft.Web.WebView2.Core.idl",
    ]
    progress = 1
    total = len(winmd_files) + len(idl_files) + 1
    # Download the NuGet package that contains all the files we need
    print(
        f"[{progress}/{total}] Downloading {package_id} NuGet package version {args.version} to {output_path}..."
    )
    download_and_extract_nuget_package(args.force, args.version, output_path)
    # Generate .idl files from the .winmd files
    for winmd, header in winmd_files.items():
        progress += 1
        print(f"[{progress}/{total}] Processing WINMD {winmd}...")
        run_winmdidl(args.force, win_sdk_bin, output_path, winmd, header)
    # Generate all the C++ headers and related files from the .idl files
    for idl in idl_files:
        progress += 1
        print(f"[{progress}/{total}] Processing IDL {idl}...")
        run_midlrt(args.force, win_sdk_bin, output_path, idl)
    print("Setup is complete.")
    print("")
    print(f"Pass winappsdk_dir=\"{output_path}\" to gn gen or ninja.")