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