build-scripts/winrtbuild.ps1
author Sylvain Becker <sylvain.becker@gmail.com>
Mon, 19 Aug 2019 21:23:47 +0200
changeset 13027 69cc269eec53
parent 12869 2b56cef46971
permissions -rw-r--r--
Fix audio conversion U16_to_F32_SSE2 (bug 4186)
     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.10"
    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 }