Skip to content

Instantly share code, notes, and snippets.

@MarcoMeter
Last active September 2, 2019 19:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save MarcoMeter/7ca803a5c4dcfabb4037728eddb5c95a to your computer and use it in GitHub Desktop.
Save MarcoMeter/7ca803a5c4dcfabb4037728eddb5c95a to your computer and use it in GitHub Desktop.
This Editor Extenstion allows users to right-click on directories inside the Assets folder to compile their CSharp source files to an assembly. That assembly can be loaded and executed on run-time. Be aware that the .net Version has to be set to 2.0 inside the PlayerSettings of Unity.
using UnityEngine;
public class AssemblyLoader : MonoBehaviour
{
void Start ()
{
var assembly = System.Reflection.Assembly.LoadFrom("BCD.dll");
var typeA = assembly.GetType("TriangleBehavior");
gameObject.AddComponent(typeA);
}
}
using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Text;
using System.IO;
using System.Linq;
using UnityEditor;
namespace TinyCompiler
{
/// <summary>
/// The TinyCompilerWindow adds a MenuItem to compile the source files of a selected folder.
/// </summary>
public class TinyCompilerMenuItem : EditorWindow
{
[MenuItem("Assets/Compile Folder")]
private static void CompileSourceFiles()
{
string filePath = AssetDatabase.GetAssetPath(Selection.activeObject);
string[] sourceFiles = GetSourceFiles(filePath);
string destinationPath = EditorUtility.SaveFilePanel("Compile Assembly to", "", ".dll", "dll");
CompileAssembly(destinationPath, sourceFiles);
}
/// <summary>
/// Validation for the MenuItem "Compile Folder" in order to check if the selected asset is a directory.
/// </summary>
/// <returns></returns>
[MenuItem("Assets/Compile Folder", true)]
private static bool CompileSourceFilesValidation()
{
string filePath = AssetDatabase.GetAssetPath(Selection.activeObject);
// check if filePath is empty or null to avoid ArgumentException
if(filePath == null || filePath == "")
{
return false;
}
FileAttributes attr = File.GetAttributes(filePath);
return ((attr & FileAttributes.Directory) == FileAttributes.Directory);
}
/// <summary>
/// Based on a directory's path, all CSharp source files are getting collected within all subdirectories.
/// </summary>
/// <param name="path">Path to the folder with the source files</param>
/// <returns>Returns the paths of all files</returns>
private static string[] GetSourceFiles(string path)
{
var dirInfo = new DirectoryInfo(path);
FileInfo[] files = dirInfo.GetFiles("*.cs", SearchOption.AllDirectories);
return files.Select(file => file.FullName).ToArray();
}
/// <summary>
/// This function compiles source files to a class library assembly.
/// </summary>
/// <param name="destinationPath">Path to the assembly output</param>
/// <param name="sourceFiles">Paths to the source files</param>
private static void CompileAssembly(string destinationPath, string[] sourceFiles)
{
// Configure parameters for compilation
CompilerParameters parameters = new CompilerParameters();
// Generate a class library instead of an executable
parameters.GenerateExecutable = false;
// Set the assembly file name to generate
parameters.OutputAssembly = destinationPath;
// Generate debug information
parameters.IncludeDebugInformation = true;
// Add ALL of the assembly references
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
parameters.ReferencedAssemblies.Add(assembly.Location);
}
// Add specific assembly references
//parameters.ReferencedAssemblies.Add("System.dll");
//parameters.ReferencedAssemblies.Add("UnityEngine.dll");
// Save the assembly as a physical file
parameters.GenerateInMemory = false;
// set wether to treat all warnings as errors
parameters.TreatWarningsAsErrors = false;
// Compile source
CSharpCodeProvider provider = new CSharpCodeProvider();
var result = provider.CompileAssemblyFromFile(parameters, sourceFiles);
// Log exceptions
if (result.Errors.Count > 0)
{
var msg = new StringBuilder();
foreach (CompilerError error in result.Errors)
{
msg.AppendFormat("Error ({0}): {1}\n",
error.ErrorNumber, error.ErrorText);
}
throw new Exception(msg.ToString());
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment