Advertisement
vexe

Manual Compilation in Unity3D

Jun 20th, 2014
454
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.32 KB | None | 0 0
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Linq;
  4. using System;
  5. using System.Reflection;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. using System.Diagnostics;
  9. using Object = UnityEngine.Object;
  10. using Debug = UnityEngine.Debug;
  11.  
  12. public abstract class Compiler
  13. {
  14.     private const string BooCompilerName = "BooCompiler";
  15.     private const string JSCompilerName = "UnityScriptCompiler";
  16.     private const string CSCompilerName = "MonoCSharpCompiler";
  17.  
  18.     public BuildTarget BuildTarget { get; set; }
  19.     public string Profile { get; set; }
  20.     public string[] SourceFiles { get; set; }
  21.     public string[] References { get; set; }
  22.     public string[] Defines { get; set; }
  23.     public string Output { get; set; }
  24.  
  25.     protected abstract Type CompilerType { get; }
  26.  
  27.     public void Compile()
  28.     {
  29.         Defines = Defines ?? new string[0];
  30.         Profile = Profile ?? "2.0";
  31.  
  32.         var island = Activator.CreateInstance(Cache.MonoIslandType, BuildTarget, Profile, SourceFiles, References, Defines, Output);
  33.         var compiler = Activator.CreateInstance(CompilerType, island);
  34.         var w = Stopwatch.StartNew();
  35.         var program = Cache.StartCompilerMethod.Invoke(compiler, null);
  36.         w.Stop();
  37.         PrintCompiledFiles();
  38.         Debug.Log("Time took to compile: " + w.ElapsedMilliseconds + " ms");
  39.         var errors = Cache.GetErrorOutputMethod.Invoke(program, null);
  40.         var std = Cache.GetStdOutputMethod.Invoke(program, null);
  41.  
  42.         // Sometimes in JS compilation errors are not displayed in the error output, but instead in the GetAllOutput
  43.         // so you might want to uncomment the next line, or even put some debug points and see for your self when things are not compiling
  44.         // var all = program.GetType().GetMethod("GetAllOutput", BindingFlags.Instance | BindingFlags.Public).Invoke(program, null);
  45.         // Debug.Log(all);
  46.  
  47.         Foreach((errors as IEnumerable<string>), Debug.LogError);
  48.         Foreach((std as IEnumerable<string>), Debug.Log);
  49.  
  50.         // A lot of the times this doesn't really do what it should so you have to lose focus from Unity, and focus again...
  51.         EditorApplication.delayCall += () =>
  52.         {
  53.             AssetDatabase.ImportAsset(Output);
  54.             ProjectWindowUtil.ShowCreatedAsset(AssetDatabase.LoadAssetAtPath(Output, typeof(Object)));
  55.             AssetDatabase.Refresh();
  56.         };
  57.     }
  58.  
  59.     private void PrintCompiledFiles()
  60.     {
  61.         Debug.Log("Compiled the following files:");
  62.         string files = "";
  63.         Foreach(SourceFiles, f => files += (f + ", "));
  64.         files = files.Remove(files.LastIndexOf(','));
  65.         Debug.Log(files);
  66.     }
  67.  
  68.     public static T Create<T>(BuildTarget target, string profile, string[] sourceFiles, string[] references, string[] defines, string output) where T : Compiler, new()
  69.     {
  70.         return new T() { BuildTarget = target, Profile = profile, SourceFiles = sourceFiles, References = references, Defines = defines, Output = output };
  71.     }
  72.  
  73.     public static T Create<T>(BuildTarget target, string[] sourceFiles, string[] references, string[] defines, string output) where T : Compiler, new()
  74.     {
  75.         return Create<T>(target, "2.0", sourceFiles, references, defines, output);
  76.     }
  77.  
  78.     public static T Create<T>(BuildTarget target, string[] sourceFiles, string[] references, string output) where T : Compiler, new()
  79.     {
  80.         return Create<T>(target, sourceFiles, references, new string[0], output);
  81.     }
  82.  
  83.     private static void Foreach<T>(IEnumerable<T> e, Action<T> act)
  84.     {
  85.         foreach (var item in e) act(item);
  86.     }
  87.  
  88.     protected static class Cache
  89.     {
  90.         public static Assembly EditorAsm { get { return AssignIfNull(ref editorAsm, () => typeof(Editor).Assembly); } }
  91.         public static Type[] EditorTypes { get { return AssignIfNull(ref editorTypes, () => EditorAsm.GetTypes()); } }
  92.         public static Type MonoIslandType { get { return AssignIfNull(ref monoIslandType, () => EditorTypes.First(t => t.Name == "MonoIsland")); } }
  93.         public static Type CsCompilerType { get { return AssignIfNull(ref csCompilerType, () => EditorTypes.First(t => t.Name == CSCompilerName)); } }
  94.         public static Type JsCompilerType { get { return AssignIfNull(ref jsCompilerType, () => EditorTypes.First(t => t.Name == JSCompilerName)); } }
  95.         public static Type BooCompilerType { get { return AssignIfNull(ref booCompilerType, () => EditorTypes.First(t => t.Name == BooCompilerName)); } }
  96.         public static Type ProgramType { get { return AssignIfNull(ref programType, () => programType = EditorTypes.First(t => t.Name == "Program")); } }
  97.         public static MethodInfo StartCompilerMethod { get { return AssignIfNull(ref startCompilerMethod, () => EditorTypes.First(t => t.Name == "ScriptCompilerBase").GetMethod("StartCompiler", BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null)); } }
  98.         public static MethodInfo GetErrorOutputMethod { get { return AssignIfNull(ref getErrorOutputMethod, () => ProgramType.GetMethod("GetErrorOutput", BindingFlags.Instance | BindingFlags.Public)); } }
  99.         public static MethodInfo GetStdOutputMethod { get { return AssignIfNull(ref getStdOutputMethod, () => ProgramType.GetMethod("GetStandardOutput", BindingFlags.Instance | BindingFlags.Public)); } }
  100.  
  101.         private static Assembly editorAsm;
  102.         private static Type[] editorTypes;
  103.         private static Type monoIslandType;
  104.         private static Type csCompilerType;
  105.         private static Type jsCompilerType;
  106.         private static Type booCompilerType;
  107.         private static Type programType;
  108.         private static MethodInfo startCompilerMethod;
  109.         private static MethodInfo getErrorOutputMethod;
  110.         private static MethodInfo getStdOutputMethod;
  111.  
  112.         private static T AssignIfNull<T>(ref T value, Func<T> get)
  113.         {
  114.             if (value == null || value.Equals(null))
  115.                 value = get();
  116.             return value;
  117.         }
  118.     }
  119. }
  120.  
  121. public class CSCompiler : Compiler
  122. {
  123.     protected override Type CompilerType
  124.     {
  125.         get { return Cache.CsCompilerType; }
  126.     }
  127. }
  128.  
  129. public class JSCompiler : Compiler
  130. {
  131.     protected override Type CompilerType
  132.     {
  133.         get { return Cache.JsCompilerType; }
  134.     }
  135. }
  136.  
  137. public static class CompilerTest
  138. {
  139.     public static string UnityEngineDllLocation
  140.     {
  141.         get { return typeof(GameObject).Assembly.Location; }
  142.     }
  143.  
  144.     [MenuItem("CompilerTest/Compile CS")]
  145.     public static void CompileCS()
  146.     {
  147.         var sources = Directory.GetFiles(@"Assets\CSs", "*.cs");
  148.  
  149.         var references = new string[]
  150.         {
  151.             UnityEngineDllLocation
  152.         };
  153.  
  154.         var output = @"C:\Users\vexe\Desktop\Local DuneDashingDubai\Assets\csoutput.dll";
  155.  
  156.         Compiler.Create<CSCompiler>(BuildTarget.StandaloneWindows64, sources, references, output).Compile();
  157.     }
  158.  
  159.     [MenuItem("CompilerTest/Compile JS")]
  160.     public static void CompileJS()
  161.     {
  162.         var sources = Directory.GetFiles(@"Assets/JSs", "*.js", SearchOption.AllDirectories);
  163.  
  164.         var references = new string[]
  165.         {
  166.             UnityEngineDllLocation
  167.         };
  168.  
  169.         var output = @"C:\Users\vexe\Desktop\Local DuneDashingDubai\Assets\jsoutput.dll";
  170.  
  171.         Compiler.Create<JSCompiler>(BuildTarget.StandaloneWindows64, sources, references, output).Compile();
  172.     }
  173.  
  174.     [MenuItem("CompilerTest/Compile CS Seperate")]
  175.     public static void CompileCSSeperate()
  176.     {
  177.         var sources = Directory.GetFiles(@"Assets\CSs", "*.cs");
  178.  
  179.         var references = new string[]
  180.         {
  181.             UnityEngineDllLocation
  182.         };
  183.  
  184.         var output = @"C:\Users\vexe\Desktop\Local DuneDashingDubai\Assets\csoutput.dll";
  185.  
  186.         var compiler = new CSCompiler()
  187.         {
  188.             References = references,
  189.             Output = output,
  190.             BuildTarget = BuildTarget.StandaloneWindows64,
  191.         };
  192.  
  193.         foreach (var file in sources)
  194.         {
  195.             compiler.SourceFiles = new string[] { file };
  196.             compiler.Compile();
  197.         }
  198.     }
  199. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement