2 # winrtbuild.ps1 -- A Powershell script to build all SDL/WinRT variants,
3 # across all WinRT platforms, in all of their supported, CPU architectures.
5 # Initial version written by David Ludwig <dludwig@pobox.com>
7 # This script can be launched from Windows Explorer by double-clicking
10 # Output will be placed in the following subdirectories of the SDL source
12 # * VisualC-WinRT\lib\ -- final .dll, .lib, and .pdb files
13 # * VisualC-WinRT\obj\ -- intermediate build files
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
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
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).
41 # Base version of SDL, used for packaging purposes
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
49 [Parameter(Mandatory=$true,Position=1)][string]$PlatformToolset
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"
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"
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"
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"
64 if ($PlatformToolset -eq "v140") { # Windows 10, via VS 2015
65 return "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
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
75 [Parameter(Mandatory=$true,Position=1)][string]$PlatformToolset,
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
82 if ($PlatformToolset -eq "v110") { # Windows 8.0 (not Windows Phone), via VS 2012 project files
83 if ($IncludeVSSuffix) {
84 return "WinRT80_VS2012"
89 if ($PlatformToolset -eq "v110_wp80") { # Windows Phone 8.0, via VS 2012 project files
90 if ($IncludeVSSuffix) {
91 return "WinPhone80_VS2012"
96 if ($PlatformToolset -eq "v120") { # Windows 8.1 (not Windows Phone), via VS 2013 project files
97 if ($IncludeVSSuffix) {
98 return "WinRT81_VS2013"
103 if ($PlatformToolset -eq "v120_wp81") { # Windows Phone 8.1, via VS 2013 project files
104 if ($IncludeVSSuffix) {
105 return "WinPhone81_VS2013"
110 if ($PlatformToolset -eq "v140") { # Windows 10, via VS 2015 project files
111 if ($IncludeVSSuffix) {
120 # Returns the internal name of a Visual Studio Project.
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
127 [Parameter(Mandatory=$true,Position=1)]$VSProjectPath
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
140 # Build a specific variant of SDL/WinRT
141 function Build-SDL-WinRT-Variant
147 # name of an SDL project file, minus extensions and
148 # platform-identifying suffixes
149 [Parameter(Mandatory=$true,Position=1)][string]$SDLProjectName,
151 [Parameter(Mandatory=$true,Position=2)][string]$PlatformToolset,
153 [Parameter(Mandatory=$true,Position=3)][string]$Platform
157 # Derive other properties from read-in arguments:
160 # The .bat file to setup a platform-appropriate MSBuild environment:
161 $BatchFileForMSBuildEnv = Get-MSBuild-Env-Launcher $PlatformToolset
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"
166 # The internal name of the VS Project, used in some post-build steps:
167 $VSProjectName = Get-VS-ProjectName $VSProjectPath
169 # Where to place output binaries (.dll, .lib, and .pdb files):
170 $OutDir = "$PSScriptRoot\..\VisualC-WinRT\lib\$(Get-SDL-WinRT-Variant-Name $PlatformToolset)\$Platform"
172 # Where to place intermediate build files:
173 $IntermediateDir = "$PSScriptRoot\..\VisualC-WinRT\obj\$SDLProjectName-$(Get-SDL-WinRT-Variant-Name $PlatformToolset)\$Platform"
176 # Build the VS Project:
178 cmd.exe /c " ""$BatchFileForMSBuildEnv"" x86 & msbuild ""$VSProjectPath"" /p:Configuration=Release /p:Platform=$Platform /p:OutDir=""$OutDir\\"" /p:IntDir=""$IntermediateDir\\""" | Out-Host
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
186 if (Test-Path "$OutDir\$VSProjectName\") {
187 Move-Item -Force "$OutDir\$VSProjectName\*" "$OutDir"
191 # Clean up unneeded files in $OutDir:
193 if (Test-Path "$OutDir\$VSProjectName\") {
194 Remove-Item -Recurse "$OutDir\$VSProjectName"
196 Remove-Item "$OutDir\*.exp"
197 Remove-Item "$OutDir\*.ilk"
198 Remove-Item "$OutDir\*.pri"
201 # All done. Indicate success, or failure, to the caller:
203 #echo "RESULT: $BuildResult" | Out-Host
209 # Build each variant, with corresponding .dll, .lib, and .pdb files:
211 $DidAnyDLLBuildFail = $false
212 $DidAnyNugetBuildFail = $false
214 # Build for Windows Phone 8.0, via VC++ 2012:
215 if ( ! (Build-SDL-WinRT-Variant "SDL" "v110_wp80" "ARM")) { $DidAnyDLLBuildFail = $true }
216 if ( ! (Build-SDL-WinRT-Variant "SDL" "v110_wp80" "Win32")) { $DidAnyDLLBuildFail = $true }
218 # Build for Windows Phone 8.1, via VC++ 2013:
219 if ( ! (Build-SDL-WinRT-Variant "SDL" "v120_wp81" "ARM")) { $DidAnyDLLBuildFail = $true }
220 if ( ! (Build-SDL-WinRT-Variant "SDL" "v120_wp81" "Win32")) { $DidAnyDLLBuildFail = $true }
222 # Build for Windows 8.0 and Windows RT 8.0, via VC++ 2012:
224 # Win 8.0 auto-building was disabled on 2017-Feb-25, by David Ludwig <dludwig@pobox.com>.
225 # Steam's OS-usage surveys indicate that Windows 8.0 use is pretty much nil, plus
226 # Microsoft hasn't supported Windows 8.0 development for a few years now.
227 # The commented-out lines below may still work on some systems, though.
229 #if ( ! (Build-SDL-WinRT-Variant "SDL" "v110" "ARM")) { $DidAnyDLLBuildFail = $true }
230 #if ( ! (Build-SDL-WinRT-Variant "SDL" "v110" "Win32")) { $DidAnyDLLBuildFail = $true }
231 #if ( ! (Build-SDL-WinRT-Variant "SDL" "v110" "x64")) { $DidAnyDLLBuildFail = $true }
233 # Build for Windows 8.1 and Windows RT 8.1, via VC++ 2013:
234 if ( ! (Build-SDL-WinRT-Variant "SDL" "v120" "ARM")) { $DidAnyDLLBuildFail = $true }
235 if ( ! (Build-SDL-WinRT-Variant "SDL" "v120" "Win32")) { $DidAnyDLLBuildFail = $true }
236 if ( ! (Build-SDL-WinRT-Variant "SDL" "v120" "x64")) { $DidAnyDLLBuildFail = $true }
238 # Build for Windows 10, via VC++ 2015
239 if ( ! (Build-SDL-WinRT-Variant "SDL" "v140" "ARM")) { $DidAnyDLLBuildFail = $true }
240 if ( ! (Build-SDL-WinRT-Variant "SDL" "v140" "Win32")) { $DidAnyDLLBuildFail = $true }
241 if ( ! (Build-SDL-WinRT-Variant "SDL" "v140" "x64")) { $DidAnyDLLBuildFail = $true }
243 # Build NuGet packages, if possible
244 if ($DidAnyDLLBuildFail -eq $true) {
245 Write-Warning -Message "Unable to build all variants. NuGet packages will not be built."
246 $DidAnyNugetBuildFail = $true
248 $NugetPath = (Get-Command -CommandType Application nuget.exe | %{$_.Path}) 2> $null
249 if ("$NugetPath" -eq "") {
250 Write-Warning -Message "Unable to find nuget.exe. NuGet packages will not be built."
251 $DidAnyNugetBuildFail = $true
253 Write-Host -ForegroundColor Cyan "Building SDL2 NuGet packages..."
254 Write-Host -ForegroundColor Cyan "... via NuGet install: $NugetPath"
255 $NugetOutputDir = "$PSScriptRoot\..\VisualC-WinRT\lib\nuget"
256 Write-Host -ForegroundColor Cyan "... output directory: $NugetOutputDir"
257 $SDLHGRevision = $($(hg log -l 1 --repository "$PSScriptRoot\.." | select-string "changeset") -Replace "changeset:\W*(\d+).*",'$1') 2>$null
258 Write-Host -ForegroundColor Cyan "... HG Revision: $SDLHGRevision"
260 # Base options to nuget.exe
261 $NugetOptions = @("pack", "PACKAGE_NAME_WILL_GO_HERE", "-Output", "$NugetOutputDir")
263 # Try attaching hg revision to NuGet package:
264 $NugetOptions += "-Version"
265 if ("$SDLHGRevision" -eq "") {
266 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."
267 $NugetOptions += "$SDLVersion-Unofficial"
269 $NugetOptions += "$SDLVersion.$SDLHGRevision-Unofficial"
272 # Create NuGet output dir, if not yet created:
273 if ($(Test-Path "$NugetOutputDir") -eq $false) {
274 New-Item "$NugetOutputDir" -type directory
278 $NugetOptions[1] = "$PSScriptRoot\..\VisualC-WinRT\SDL2-WinRT.nuspec"
279 &"$NugetPath" $NugetOptions -Symbols
280 if ( ! $? ) { $DidAnyNugetBuildFail = $true }
283 $NugetOptions[1] = "$PSScriptRoot\..\VisualC-WinRT\SDL2main-WinRT-NonXAML.nuspec"
284 &"$NugetPath" $NugetOptions
285 if ( ! $? ) { $DidAnyNugetBuildFail = $true }
290 # Let the script's caller know whether or not any errors occurred.
291 # Exit codes compatible with Buildbot are used (1 for error, 0 for success).
292 if ($DidAnyDLLBuildFail -eq $true) {
293 Write-Error -Message "Unable to build all known variants of SDL2 for WinRT"
295 } elseif ($DidAnyNugetBuildFail -eq $true) {
296 Write-Warning -Message "Unable to build NuGet packages"
297 exit 0 # Should NuGet package build failure lead to a non-failing result code instead?