build-scripts/winrtbuild.ps1
author Cameron Gutman <aicommander@gmail.com>
Sun, 28 Apr 2019 17:37:49 -0700
changeset 12746 132a2af7edac
parent 12229 2fb171be56e0
permissions -rw-r--r--
Fix use-after-free when pumping the event loop after SDL_DestroyWindow()

Closing the window is asynchronous, but we free the window data immediately,
so we can get an updateLayer callback before the window is really destroyed which
will cause us to access the freed memory.

Clearing the content view will cause it to be immediately released, so no further
updateLayer callbacks will occur.
     1 #
     2 # winrtbuild.ps1 -- A Powershell script to build all SDL/WinRT variants,
     3 #    across all WinRT platforms, in all of their supported, CPU architectures.
     4 #
     5 # Initial version written by David Ludwig <dludwig@pobox.com>
     6 #
     7 # This script can be launched from Windows Explorer by double-clicking
     8 # on winrtbuild.bat
     9 #
    10 # Output will be placed in the following subdirectories of the SDL source
    11 # tree:
    12 #   * VisualC-WinRT\lib\  -- final .dll, .lib, and .pdb files
    13 #   * VisualC-WinRT\obj\  -- intermediate build files
    14 #
    15 # Recommended Dependencies:
    16 #   * Windows 8.1 or higher
    17 #   * Powershell 4.0 or higher (included as part of Windows 8.1)
    18 #   * Visual C++ 2012, for building Windows 8.0 and Windows Phone 8.0 binaries.
    19 #   * Visual C++ 2013, for building Windows 8.1 and Windows Phone 8.1 binaries
    20 #   * SDKs for Windows 8.0, Windows 8.1, Windows Phone 8.0, and
    21 #     Windows Phone 8.1, as needed
    22 #
    23 # Commom parameters/variables may include, but aren't strictly limited to:
    24 #   * PlatformToolset: the name of one of Visual Studio's build platforms.
    25 #     Different PlatformToolsets output different binaries.  One
    26 #     PlatformToolset exists for each WinRT platform.  Possible values
    27 #     may include:
    28 #       - "v110": Visual Studio 2012 build tools, plus the Windows 8.0 SDK
    29 #       - "v110_wp80": Visual Studio 2012 build tools, plus the Windows Phone 8.0 SDK
    30 #       - "v120": Visual Studio 2013 build tools, plus the Windows 8.1 SDK
    31 #       - "v120_wp81": Visual Studio 2013 build tools, plus the Windows Phone 8.1 SDK
    32 #   * VSProjectPath: the full path to a Visual Studio or Visual C++ project file
    33 #   * VSProjectName: the internal name of a Visual Studio or Visual C++ project
    34 #     file.  Some of Visual Studio's own build tools use this name when
    35 #     calculating paths for build-output.
    36 #   * Platform: a Visual Studio platform name, which often maps to a CPU
    37 #     CPU architecture.  Possible values may include: "Win32" (for 32-bit x86),
    38 #     "ARM", or "x64" (for 64-bit x86).
    39 #
    40 
    41 # Base version of SDL, used for packaging purposes
    42 $SDLVersion = "2.0.9"
    43 
    44 # Gets the .bat file that sets up an MSBuild environment, given one of
    45 # Visual Studio's, "PlatformToolset"s.
    46 function Get-MSBuild-Env-Launcher
    47 {
    48     param(
    49         [Parameter(Mandatory=$true,Position=1)][string]$PlatformToolset
    50     )
    51 
    52     if ($PlatformToolset -eq "v110") {      # Windows 8.0 (not Windows Phone), via VS 2012
    53         return "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"
    54     }
    55     if ($PlatformToolset -eq "v110_wp80") { # Windows Phone 8.0, via VS 2012
    56         return "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\WPSDK\WP80\vcvarsphoneall.bat"
    57     }
    58     if ($PlatformToolset -eq "v120") {      # Windows 8.1 (not Windows Phone), via VS 2013
    59         return "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
    60     }
    61     if ($PlatformToolset -eq "v120_wp81") { # Windows Phone 8.1, via VS 2013
    62         return "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
    63     }
    64     if ($PlatformToolset -eq "v140") {      # Windows 10, via VS 2015
    65         return "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
    66     }
    67     return ""
    68 }
    69 
    70 # Gets a string that identifies the build-variant of SDL/WinRT that is specific
    71 # to a particular Visual Studio PlatformToolset.
    72 function Get-SDL-WinRT-Variant-Name
    73 {
    74     param(
    75         [Parameter(Mandatory=$true,Position=1)][string]$PlatformToolset,
    76 
    77         # If true, append a string to this function's output, identifying the
    78         # build-variant's minimum-supported version of Visual Studio.
    79         [switch]$IncludeVSSuffix = $false
    80     )
    81 
    82     if ($PlatformToolset -eq "v110") {      # Windows 8.0 (not Windows Phone), via VS 2012 project files
    83         if ($IncludeVSSuffix) {
    84             return "WinRT80_VS2012"
    85         } else {
    86             return "WinRT80"
    87         }
    88     }
    89     if ($PlatformToolset -eq "v110_wp80") { # Windows Phone 8.0, via VS 2012 project files
    90         if ($IncludeVSSuffix) {
    91             return "WinPhone80_VS2012"
    92         } else {
    93             return "WinPhone80"
    94         }
    95     }
    96     if ($PlatformToolset -eq "v120") {      # Windows 8.1 (not Windows Phone), via VS 2013 project files
    97         if ($IncludeVSSuffix) {
    98             return "WinRT81_VS2013"
    99         } else {
   100             return "WinRT81"
   101         }
   102     }
   103     if ($PlatformToolset -eq "v120_wp81") { # Windows Phone 8.1, via VS 2013 project files
   104         if ($IncludeVSSuffix) {
   105             return "WinPhone81_VS2013"
   106         } else {
   107             return "WinPhone81"
   108         }
   109     }
   110     if ($PlatformToolset -eq "v140") {      # Windows 10, via VS 2015 project files
   111         if ($IncludeVSSuffix) {
   112             return "UWP_VS2015"
   113         } else {
   114             return "UWP"
   115         }
   116     }
   117     return ""
   118 }
   119 
   120 # Returns the internal name of a Visual Studio Project.
   121 #
   122 # The internal name of a VS Project is encoded inside the project file
   123 # itself, inside a set of <ProjectName></ProjectName> XML tags.
   124 function Get-VS-ProjectName
   125 {
   126     param(
   127         [Parameter(Mandatory=$true,Position=1)]$VSProjectPath
   128     )
   129 
   130     # For now, just do a regex for the project name:
   131     $matches = (Get-Content $VSProjectPath | Select-String -Pattern ".*<ProjectName>([^<]+)<.*").Matches
   132     foreach ($match in $matches) {
   133         if ($match.Groups.Count -ge 1) {
   134             return $match.Groups[1].Value
   135         }
   136     }
   137     return $null
   138 }
   139 
   140 # Build a specific variant of SDL/WinRT
   141 function Build-SDL-WinRT-Variant
   142 {
   143     #
   144     # Read in arguments:
   145     #
   146     param (
   147         # name of an SDL project file, minus extensions and
   148         # platform-identifying suffixes
   149         [Parameter(Mandatory=$true,Position=1)][string]$SDLProjectName,
   150 
   151         [Parameter(Mandatory=$true,Position=2)][string]$PlatformToolset,
   152 
   153         [Parameter(Mandatory=$true,Position=3)][string]$Platform
   154     )
   155 
   156     #
   157     # Derive other properties from read-in arguments:
   158     #
   159 
   160     # The .bat file to setup a platform-appropriate MSBuild environment:
   161     $BatchFileForMSBuildEnv = Get-MSBuild-Env-Launcher $PlatformToolset
   162 
   163     # The full path to the VS Project that'll be built:
   164     $VSProjectPath = "$PSScriptRoot\..\VisualC-WinRT\$(Get-SDL-WinRT-Variant-Name $PlatformToolset -IncludeVSSuffix)\$SDLProjectName-$(Get-SDL-WinRT-Variant-Name $PlatformToolset).vcxproj"
   165 
   166     # The internal name of the VS Project, used in some post-build steps:
   167     $VSProjectName = Get-VS-ProjectName $VSProjectPath
   168 
   169     # Where to place output binaries (.dll, .lib, and .pdb files):
   170     $OutDir = "$PSScriptRoot\..\VisualC-WinRT\lib\$(Get-SDL-WinRT-Variant-Name $PlatformToolset)\$Platform"
   171 
   172     # Where to place intermediate build files:
   173     $IntermediateDir = "$PSScriptRoot\..\VisualC-WinRT\obj\$SDLProjectName-$(Get-SDL-WinRT-Variant-Name $PlatformToolset)\$Platform"
   174 
   175     #
   176     # Build the VS Project:
   177     #
   178     cmd.exe /c " ""$BatchFileForMSBuildEnv"" x86 & msbuild ""$VSProjectPath"" /p:Configuration=Release /p:Platform=$Platform /p:OutDir=""$OutDir\\"" /p:IntDir=""$IntermediateDir\\""" | Out-Host
   179     $BuildResult = $?
   180 
   181     #
   182     # Move .dll files into place.  This fixes a problem whereby MSBuild may
   183     # put output files into a sub-directory of $OutDir, rather than $OutDir
   184     # itself.
   185     #
   186     if (Test-Path "$OutDir\$VSProjectName\") {
   187         Move-Item -Force "$OutDir\$VSProjectName\*" "$OutDir"
   188     }
   189 
   190     #
   191     # Clean up unneeded files in $OutDir:
   192     #
   193     if (Test-Path "$OutDir\$VSProjectName\") {
   194         Remove-Item -Recurse "$OutDir\$VSProjectName"
   195     }
   196     Remove-Item "$OutDir\*.exp"
   197     Remove-Item "$OutDir\*.ilk"
   198     Remove-Item "$OutDir\*.pri"
   199 
   200     #
   201     # All done.  Indicate success, or failure, to the caller:
   202     #
   203     #echo "RESULT: $BuildResult" | Out-Host
   204     return $BuildResult
   205 }
   206 
   207 
   208 #
   209 # Build each variant, with corresponding .dll, .lib, and .pdb files:
   210 #
   211 $DidAnyDLLBuildFail = $false
   212 $DidAnyNugetBuildFail = $false
   213 
   214 # Ryan disabled WP8.0, because it doesn't appear to have mmdeviceapi.h that SDL_wasapi needs.
   215 # My assumption is that no one will miss this, but send patches otherwise!  --ryan.
   216 # Build for Windows Phone 8.0, via VC++ 2012:
   217 #if ( ! (Build-SDL-WinRT-Variant "SDL" "v110_wp80" "ARM"))   { $DidAnyDLLBuildFail = $true }
   218 #if ( ! (Build-SDL-WinRT-Variant "SDL" "v110_wp80" "Win32")) { $DidAnyDLLBuildFail = $true }
   219 
   220 # Build for Windows Phone 8.1, via VC++ 2013:
   221 if ( ! (Build-SDL-WinRT-Variant "SDL" "v120_wp81" "ARM"))   { $DidAnyDLLBuildFail = $true }
   222 if ( ! (Build-SDL-WinRT-Variant "SDL" "v120_wp81" "Win32")) { $DidAnyDLLBuildFail = $true }
   223 
   224 # Build for Windows 8.0 and Windows RT 8.0, via VC++ 2012:
   225 #
   226 # Win 8.0 auto-building was disabled on 2017-Feb-25, by David Ludwig <dludwig@pobox.com>.
   227 # Steam's OS-usage surveys indicate that Windows 8.0 use is pretty much nil, plus
   228 # Microsoft hasn't supported Windows 8.0 development for a few years now.
   229 # The commented-out lines below may still work on some systems, though.
   230 # 
   231 #if ( ! (Build-SDL-WinRT-Variant "SDL" "v110" "ARM"))        { $DidAnyDLLBuildFail = $true }
   232 #if ( ! (Build-SDL-WinRT-Variant "SDL" "v110" "Win32"))      { $DidAnyDLLBuildFail = $true }
   233 #if ( ! (Build-SDL-WinRT-Variant "SDL" "v110" "x64"))        { $DidAnyDLLBuildFail = $true }
   234 
   235 # Build for Windows 8.1 and Windows RT 8.1, via VC++ 2013:
   236 if ( ! (Build-SDL-WinRT-Variant "SDL" "v120" "ARM"))        { $DidAnyDLLBuildFail = $true }
   237 if ( ! (Build-SDL-WinRT-Variant "SDL" "v120" "Win32"))      { $DidAnyDLLBuildFail = $true }
   238 if ( ! (Build-SDL-WinRT-Variant "SDL" "v120" "x64"))        { $DidAnyDLLBuildFail = $true }
   239 
   240 # Build for Windows 10, via VC++ 2015
   241 if ( ! (Build-SDL-WinRT-Variant "SDL" "v140" "ARM"))        { $DidAnyDLLBuildFail = $true }
   242 if ( ! (Build-SDL-WinRT-Variant "SDL" "v140" "Win32"))      { $DidAnyDLLBuildFail = $true }
   243 if ( ! (Build-SDL-WinRT-Variant "SDL" "v140" "x64"))        { $DidAnyDLLBuildFail = $true }
   244 
   245 # Build NuGet packages, if possible
   246 if ($DidAnyDLLBuildFail -eq $true) {
   247     Write-Warning -Message "Unable to build all variants.  NuGet packages will not be built."
   248     $DidAnyNugetBuildFail = $true
   249 } else {
   250     $NugetPath = (Get-Command -CommandType Application nuget.exe | %{$_.Path}) 2> $null
   251     if ("$NugetPath" -eq "") {
   252         Write-Warning -Message "Unable to find nuget.exe.  NuGet packages will not be built."
   253         $DidAnyNugetBuildFail = $true
   254     } else {
   255         Write-Host -ForegroundColor Cyan "Building SDL2 NuGet packages..."
   256         Write-Host -ForegroundColor Cyan "... via NuGet install: $NugetPath"
   257         $NugetOutputDir = "$PSScriptRoot\..\VisualC-WinRT\lib\nuget"
   258         Write-Host -ForegroundColor Cyan "...  output directory: $NugetOutputDir"
   259         $SDLHGRevision = $($(hg log -l 1 --repository "$PSScriptRoot\.." | select-string "changeset") -Replace "changeset:\W*(\d+).*",'$1') 2>$null
   260         Write-Host -ForegroundColor Cyan "...       HG Revision: $SDLHGRevision"
   261 
   262         # Base options to nuget.exe
   263         $NugetOptions = @("pack", "PACKAGE_NAME_WILL_GO_HERE", "-Output", "$NugetOutputDir")
   264 
   265         # Try attaching hg revision to NuGet package:
   266         $NugetOptions += "-Version"
   267         if ("$SDLHGRevision" -eq "") {
   268             Write-Warning -Message "Unable to find the Mercurial revision (maybe hg.exe can't be found?).  NuGet packages will not have this attached to their name."
   269             $NugetOptions += "$SDLVersion-Unofficial"
   270         } else {
   271             $NugetOptions += "$SDLVersion.$SDLHGRevision-Unofficial"
   272         }
   273 
   274         # Create NuGet output dir, if not yet created:
   275         if ($(Test-Path "$NugetOutputDir") -eq $false) {
   276             New-Item "$NugetOutputDir" -type directory
   277         }
   278 
   279         # Package SDL2:
   280         $NugetOptions[1] = "$PSScriptRoot\..\VisualC-WinRT\SDL2-WinRT.nuspec"
   281         &"$NugetPath" $NugetOptions -Symbols
   282         if ( ! $? ) { $DidAnyNugetBuildFail = $true }
   283 
   284         # Package SDL2main:
   285         $NugetOptions[1] = "$PSScriptRoot\..\VisualC-WinRT\SDL2main-WinRT-NonXAML.nuspec"
   286         &"$NugetPath" $NugetOptions
   287         if ( ! $? ) { $DidAnyNugetBuildFail = $true }
   288     }
   289 }
   290 
   291 
   292 # Let the script's caller know whether or not any errors occurred.
   293 # Exit codes compatible with Buildbot are used (1 for error, 0 for success).
   294 if ($DidAnyDLLBuildFail -eq $true) {
   295     Write-Error -Message "Unable to build all known variants of SDL2 for WinRT"
   296     exit 1
   297 } elseif ($DidAnyNugetBuildFail -eq $true) {
   298     Write-Warning -Message "Unable to build NuGet packages"
   299     exit 0  # Should NuGet package build failure lead to a non-failing result code instead?
   300 } else {
   301     exit 0
   302 }