88using System . Globalization ;
99using System . IO ;
1010using System . Linq ;
11+ using System . Reflection ;
1112using System . Xml ;
1213using UnityEditor ;
1314using UnityEngine ;
@@ -51,6 +52,8 @@ public class BuildInfo
5152
5253 public WSASDK ? WSASdk { get ; set ; }
5354
55+ public string WsaUwpSdk { get ; set ; }
56+
5457 public WSAUWPBuildType ? WSAUWPBuildType { get ; set ; }
5558
5659 public Boolean ? WSAGenerateReferenceProjects { get ; set ; }
@@ -66,53 +69,80 @@ public BuildInfo()
6669
6770 public void AppendSymbols ( params string [ ] symbol )
6871 {
69- AppendSymbols ( ( IEnumerable < string > ) symbol ) ;
72+ this . AppendSymbols ( ( IEnumerable < string > ) symbol ) ;
7073 }
7174
7275 public void AppendSymbols ( IEnumerable < string > symbols )
7376 {
74- string [ ] toAdd = symbols . Except ( BuildSymbols . Split ( ';' ) )
77+ string [ ] toAdd = symbols . Except ( this . BuildSymbols . Split ( ';' ) )
7578 . Where ( sym => ! string . IsNullOrEmpty ( sym ) ) . ToArray ( ) ;
7679
7780 if ( ! toAdd . Any ( ) )
7881 {
7982 return ;
8083 }
8184
82- if ( ! String . IsNullOrEmpty ( BuildSymbols ) )
85+ if ( ! String . IsNullOrEmpty ( this . BuildSymbols ) )
8386 {
84- BuildSymbols += ";" ;
87+ this . BuildSymbols += ";" ;
8588 }
8689
87- BuildSymbols += String . Join ( ";" , toAdd ) ;
90+ this . BuildSymbols += String . Join ( ";" , toAdd ) ;
8891 }
8992
9093 public bool HasAnySymbols ( params string [ ] symbols )
9194 {
92- return BuildSymbols . Split ( ';' ) . Intersect ( symbols ) . Any ( ) ;
95+ return this . BuildSymbols . Split ( ';' ) . Intersect ( symbols ) . Any ( ) ;
9396 }
9497
9598 public bool HasConfigurationSymbol ( )
9699 {
97100 return HasAnySymbols (
98- BuildSymbolDebug ,
99- BuildSymbolRelease ,
100- BuildSymbolMaster ) ;
101+ BuildSLNUtilities . BuildSymbolDebug ,
102+ BuildSLNUtilities . BuildSymbolRelease ,
103+ BuildSLNUtilities . BuildSymbolMaster ) ;
101104 }
102105
103106 public static IEnumerable < string > RemoveConfigurationSymbols ( string symbolstring )
104107 {
105108 return symbolstring . Split ( ';' ) . Except ( new [ ]
106109 {
107- BuildSymbolDebug ,
108- BuildSymbolRelease ,
109- BuildSymbolMaster
110+ BuildSLNUtilities . BuildSymbolDebug ,
111+ BuildSLNUtilities . BuildSymbolRelease ,
112+ BuildSLNUtilities . BuildSymbolMaster
110113 } ) ;
111114 }
112115
113116 public bool HasAnySymbols ( IEnumerable < string > symbols )
114117 {
115- return BuildSymbols . Split ( ';' ) . Intersect ( symbols ) . Any ( ) ;
118+ return this . BuildSymbols . Split ( ';' ) . Intersect ( symbols ) . Any ( ) ;
119+ }
120+ }
121+
122+ /// <summary>
123+ /// A method capable of configuring <see cref="BuildInfo"/> settings.
124+ /// </summary>
125+ /// <param name="toConfigure">The settings to configure.</param>
126+ public delegate void BuildInfoConfigurationMethod ( ref BuildInfo toConfigure ) ;
127+
128+ /// <summary>
129+ /// Add a handler to this event to override <see cref="BuildInfo"/> defaults before a build.
130+ /// </summary>
131+ /// <seealso cref="RaiseOverrideBuildDefaults"/>
132+ public static event BuildInfoConfigurationMethod OverrideBuildDefaults ;
133+
134+ /// <summary>
135+ /// Call this method to give other code an opportunity to override <see cref="BuildInfo"/> defaults.
136+ /// </summary>
137+ /// <param name="toConfigure">>The settings to configure.</param>
138+ /// <seealso cref="OverrideBuildDefaults"/>
139+ public static void RaiseOverrideBuildDefaults ( ref BuildInfo toConfigure )
140+ {
141+ var handlers = OverrideBuildDefaults ;
142+
143+ if ( handlers != null )
144+ {
145+ handlers ( ref toConfigure ) ;
116146 }
117147 }
118148
@@ -151,37 +181,39 @@ public static void PerformBuild(BuildInfo buildInfo)
151181 {
152182 if ( ! buildInfo . HasConfigurationSymbol ( ) )
153183 {
154- buildInfo . AppendSymbols ( BuildSymbolDebug ) ;
184+ buildInfo . AppendSymbols ( BuildSLNUtilities . BuildSymbolDebug ) ;
155185 }
156186 }
157187
158- if ( buildInfo . HasAnySymbols ( BuildSymbolDebug ) )
188+ if ( buildInfo . HasAnySymbols ( BuildSLNUtilities . BuildSymbolDebug ) )
159189 {
160190 buildInfo . BuildOptions |= BuildOptions . Development | BuildOptions . AllowDebugging ;
161191 }
162192
163- if ( buildInfo . HasAnySymbols ( BuildSymbolRelease ) )
193+ if ( buildInfo . HasAnySymbols ( BuildSLNUtilities . BuildSymbolRelease ) )
164194 {
165195 //Unity automatically adds the DEBUG symbol if the BuildOptions.Development flag is
166196 //specified. In order to have debug symbols and the RELEASE symbole we have to
167197 //inject the symbol Unity relies on to enable the /debug+ flag of csc.exe which is "DEVELOPMENT_BUILD"
168198 buildInfo . AppendSymbols ( "DEVELOPMENT_BUILD" ) ;
169199 }
170200
171- BuildTarget oldBuildTarget = EditorUserBuildSettings . activeBuildTarget ;
172- BuildTargetGroup oldBuildTargetGroup = GetGroup ( oldBuildTarget ) ;
173-
174- EditorUserBuildSettings . SwitchActiveBuildTarget ( buildTargetGroup , buildInfo . BuildTarget ) ;
201+ var oldBuildTarget = EditorUserBuildSettings . activeBuildTarget ;
202+ EditorUserBuildSettings . SwitchActiveBuildTarget ( buildInfo . BuildTarget ) ;
175203
176204 var oldWSASDK = EditorUserBuildSettings . wsaSDK ;
177205 if ( buildInfo . WSASdk . HasValue )
178206 {
179207 EditorUserBuildSettings . wsaSDK = buildInfo . WSASdk . Value ;
180208 }
181209
210+ string oldWsaUwpSdk = null ;
182211 WSAUWPBuildType ? oldWSAUWPBuildType = null ;
183212 if ( EditorUserBuildSettings . wsaSDK == WSASDK . UWP )
184213 {
214+ oldWsaUwpSdk = EditorUserBuildSettings . wsaUWPSDK ;
215+ EditorUserBuildSettings . wsaUWPSDK = buildInfo . WsaUwpSdk ;
216+
185217 oldWSAUWPBuildType = EditorUserBuildSettings . wsaUWPBuildType ;
186218 if ( buildInfo . WSAUWPBuildType . HasValue )
187219 {
@@ -209,6 +241,11 @@ public static void PerformBuild(BuildInfo buildInfo)
209241 string buildError = "Error" ;
210242 try
211243 {
244+ if ( EditorUserBuildSettings . wsaSDK == WSASDK . UWP )
245+ {
246+ VerifyWsaUwpSdkIsInstalled ( EditorUserBuildSettings . wsaUWPSDK ) ;
247+ }
248+
212249 // For the WSA player, Unity builds into a target directory.
213250 // For other players, the OutputPath parameter indicates the
214251 // path to the target executable to build.
@@ -233,25 +270,84 @@ public static void PerformBuild(BuildInfo buildInfo)
233270 {
234271 OnPostProcessBuild ( buildInfo , buildError ) ;
235272
273+ if ( buildInfo . BuildTarget == BuildTarget . WSAPlayer && EditorUserBuildSettings . wsaGenerateReferenceProjects )
274+ {
275+ UwpProjectPostProcess . Execute ( buildInfo . OutputDirectory ) ;
276+ }
277+
236278 PlayerSettings . colorSpace = oldColorSpace ;
237279 PlayerSettings . SetScriptingDefineSymbolsForGroup ( buildTargetGroup , oldBuildSymbols ) ;
238280
239- EditorUserBuildSettings . wsaSDK = oldWSASDK ;
240-
241- if ( oldWSAUWPBuildType . HasValue )
281+ if ( EditorUserBuildSettings . wsaSDK == WSASDK . UWP )
242282 {
283+ EditorUserBuildSettings . wsaUWPSDK = oldWsaUwpSdk ;
243284 EditorUserBuildSettings . wsaUWPBuildType = oldWSAUWPBuildType . Value ;
244285 }
286+ EditorUserBuildSettings . wsaSDK = oldWSASDK ;
245287
246288 EditorUserBuildSettings . wsaGenerateReferenceProjects = oldWSAGenerateReferenceProjects ;
247289
248- EditorUserBuildSettings . SwitchActiveBuildTarget ( oldBuildTargetGroup , oldBuildTarget ) ;
290+ EditorUserBuildSettings . SwitchActiveBuildTarget ( oldBuildTarget ) ;
291+ }
292+ }
293+
294+ private static void VerifyWsaUwpSdkIsInstalled ( string wsaUwpSdk )
295+ {
296+ if ( string . IsNullOrEmpty ( wsaUwpSdk ) )
297+ {
298+ // Unity uses a null or empty string to mean "use the latest sdk that's installed", so we don't need to
299+ // verify any particular version.
300+ return ;
301+ }
302+
303+
304+ IEnumerable < Version > uwpSdksAvailable ;
305+ try
306+ {
307+ // In order to get the same list of SDKs that the Unity build settings "UWP SDK" box has, we call into an
308+ // internal Unity function. If Unity changes how its internals work, we'll need to update this code.
309+
310+ Type uwpReferencesType = typeof ( UnityEditor . Editor ) . Assembly
311+ . GetType ( "UnityEditor.Scripting.Compilers.UWPReferences" , throwOnError : false ) ;
312+
313+ MethodInfo uwpReferencesMethod = ( uwpReferencesType == null )
314+ ? null
315+ : uwpReferencesType . GetMethod ( "GetInstalledSDKVersions" ) ;
316+
317+ uwpSdksAvailable = ( uwpReferencesMethod == null )
318+ ? null
319+ : ( uwpReferencesMethod . Invoke ( obj : null , parameters : null ) as IEnumerable < Version > ) ;
320+ }
321+ catch
322+ {
323+ uwpSdksAvailable = null ;
324+ }
325+
326+
327+ if ( uwpSdksAvailable == null )
328+ {
329+ Debug . LogWarningFormat ( "Couldn't verify that UWP SDK \" {0}\" is installed. You better make sure it's installed"
330+ + " and available in your Unity Build settings menu, or you may get unexpected build breaks or runtime"
331+ + " behavior." ,
332+ wsaUwpSdk
333+ ) ;
334+ }
335+ else if ( ! uwpSdksAvailable . Select ( version => version . ToString ( ) ) . Contains ( wsaUwpSdk ) )
336+ {
337+ throw new Exception ( string . Format ( "UWP SDK \" {0}\" is not installed. Please install it and try building again. If"
338+ + " you really want to build without that SDK, build directly from Unity's Build settings menu instead." ,
339+ wsaUwpSdk
340+ ) ) ;
341+ }
342+ else
343+ {
344+ // The SDK is verified installed. All is right with the world!
249345 }
250346 }
251347
252348 public static void ParseBuildCommandLine ( ref BuildInfo buildInfo )
253349 {
254- string [ ] arguments = Environment . GetCommandLineArgs ( ) ;
350+ string [ ] arguments = System . Environment . GetCommandLineArgs ( ) ;
255351
256352 buildInfo . IsCommandLine = true ;
257353
@@ -268,6 +364,10 @@ public static void ParseBuildCommandLine(ref BuildInfo buildInfo)
268364
269365 buildInfo . WSASdk = ( WSASDK ) Enum . Parse ( typeof ( WSASDK ) , wsaSdkArg ) ;
270366 }
367+ else if ( string . Equals ( arguments [ i ] , "-wsaUwpSdk" , StringComparison . InvariantCultureIgnoreCase ) )
368+ {
369+ buildInfo . WsaUwpSdk = arguments [ ++ i ] ;
370+ }
271371 else if ( string . Equals ( arguments [ i ] , "-wsaUWPBuildType" , StringComparison . InvariantCultureIgnoreCase ) )
272372 {
273373
@@ -295,12 +395,12 @@ public static void ParseBuildCommandLine(ref BuildInfo buildInfo)
295395
296396 public static void PerformBuild_CommandLine ( )
297397 {
298- BuildInfo buildInfo = new BuildInfo
398+ BuildInfo buildInfo = new BuildInfo ( )
299399 {
300- // Use scenes from the editor build settings.
301- Scenes = EditorBuildSettings . scenes . Where ( scene => scene . enabled ) . Select ( scene => scene . path )
400+ Scenes = EditorBuildSettings . scenes . Where ( scene => scene . enabled ) . Select ( scene => scene . path ) , // Use scenes from the editor build settings.
302401 } ;
303402
403+ RaiseOverrideBuildDefaults ( ref buildInfo ) ;
304404 ParseBuildCommandLine ( ref buildInfo ) ;
305405
306406 PerformBuild ( buildInfo ) ;
@@ -405,7 +505,7 @@ private static IEnumerable<CopyDirectoryInfo> ReadCopyList(XmlTextReader reader)
405505 }
406506 else if ( string . Equals ( reader . Name , "Recursive" , StringComparison . InvariantCultureIgnoreCase ) )
407507 {
408- recursive = Convert . ToBoolean ( reader . Value ) ;
508+ recursive = System . Convert . ToBoolean ( reader . Value ) ;
409509 }
410510 else if ( string . Equals ( reader . Name , "Filter" , StringComparison . InvariantCultureIgnoreCase ) )
411511 {
@@ -511,7 +611,7 @@ private static void OnPostProcessBuild(BuildInfo buildInfo, string buildError)
511611 }
512612 }
513613
514- private static string GetProjectPath ( )
614+ public static string GetProjectPath ( )
515615 {
516616 return Path . GetDirectoryName ( Path . GetFullPath ( Application . dataPath ) ) ;
517617 }
0 commit comments