{"id":176,"date":"2015-09-01T02:47:16","date_gmt":"2015-09-01T02:47:16","guid":{"rendered":"http:\/\/www.voidbred.com\/blog\/?p=176"},"modified":"2015-09-01T02:47:16","modified_gmt":"2015-09-01T02:47:16","slug":"automatic-f-compilation-in-unity","status":"publish","type":"post","link":"http:\/\/www.voidbred.com\/blog\/2015\/09\/automatic-f-compilation-in-unity\/","title":{"rendered":"Automatic F# Compilation in Unity"},"content":{"rendered":"<p>I was playing around with F# and Unity integration and there are some nice examples out there \u00a0but they all relied on compilation systems outside of Unity, <em>build some .dll in Xamarin then drop it into a Unity project<\/em>. \u00a0Cool, but it&#8217;s not usable if we don&#8217;t hook into Unity&#8217;s build system and get a fresh build every time we edit a .fs file. \u00a0So, I decided to explore doing just that with UnityEditor.AssetPostprocessor. \u00a0When you implement a AssetPostprocessor you get called with a message every time you reimport an Asset. \u00a0This happens when the file gets touched on disk. \u00a0So what we can do with AssetPostprocessor is recompile a .dll full of F# code whenever a dependent F# file is edited.<\/p>\n<p>Here is example code of that method:<\/p>\n<pre class=\"toolbar:1 lang:default decode:true \">using System;\r\nusing UnityEditor;\r\nusing UnityEngine;\r\n\r\nnamespace PostProcessor\r\n{\r\n    public class FSCompiler : AssetPostprocessor\r\n    {\r\n        static void OnPostprocessAllAssets(string[] importedAssets,\r\n                                           string[] deletedAssets,\r\n                                           string[] movedAssets,\r\n                                           string[] movedFromAssetPaths) \r\n        {\r\n            foreach (var str in importedAssets)\r\n            {\r\n                Debug.Log(\"Reimported Asset: \" + str);\r\n                if (System.IO.Path.GetExtension(str) == \".fs\") {\r\n                    var cmd = \"\/Library\/Frameworks\/Mono.framework\/Commands\/fsharpc\";\r\n                    var outDir = System.IO.Path.GetDirectoryName(str);\r\n                    var filenameBase = System.IO.Path.GetFileNameWithoutExtension(str);\r\n                    var outPath = System.IO.Path.Combine(outDir, filenameBase + \".dll\");\r\n                    var args = \" --target:library --reference:\/Applications\/Unity\/Unity.app\/Contents\/Frameworks\/Managed\/UnityEngine.dll \" + str + \" --out:\" + outPath;\r\n                    var process = System.Diagnostics.Process.Start(cmd, args);\r\n                    process.WaitForExit();\r\n                    if (process.ExitCode != 0) {\r\n                        throw new ArgumentException(str);\r\n                    }\r\n                    Debug.Log (\"exec:\"+ process.ExitCode + \" \" + cmd + \" \" + args);                \r\n                    AssetDatabase.ImportAsset(outPath);\r\n                }\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<p>In order to actually use this you&#8217;ll need to build a target in MonoDevelop for a .dll that will contain this AssetPostprocessor. \u00a0Put that .dll in your project&#8217;s Assets. \u00a0You&#8217;ll also have to make sure that your Unity project has FSharp.Core.dll as an Asset if you want to use your F# code. \u00a0I had luck using version 2.3.0. \u00a0You can check the version with &#8220;monodis &#8211;assembly &lt;path to dll&gt;&#8221;. \u00a0The build rule will have to be made a bit more robust if you wanted to compile something with a more complex dependency tree of course. \u00a0If you need help making MonoBehaviours in F#,\u00a0<a href=\"https:\/\/github.com\/eriksvedang\/FSharp-Unity\" target=\"_blank\">this will help.<\/a><\/p>\n<p>Sorry I didn&#8217;t didn&#8217;t post this on Github. \u00a0There is a considerable amount of work to make this idea handle most cases. \u00a0It served my purpose as is, maybe I&#8217;ll package it up later.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was playing around with F# and Unity integration and there are some nice examples out there \u00a0but they all relied on compilation systems outside of Unity, build some .dll in Xamarin then drop it into a Unity project. \u00a0Cool, but it&#8217;s not usable if we don&#8217;t hook into Unity&#8217;s build system and get a&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[27,11],"_links":{"self":[{"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/posts\/176"}],"collection":[{"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/comments?post=176"}],"version-history":[{"count":2,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/posts\/176\/revisions"}],"predecessor-version":[{"id":178,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/posts\/176\/revisions\/178"}],"wp:attachment":[{"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/media?parent=176"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/categories?post=176"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.voidbred.com\/blog\/wp-json\/wp\/v2\/tags?post=176"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}