tag:blogger.com,1999:blog-58031951980805874452024-02-20T06:54:32.500-08:00Serious CodeUnknownnoreply@blogger.comBlogger6125tag:blogger.com,1999:blog-5803195198080587445.post-17728974954435658742017-04-09T13:12:00.001-07:002017-04-09T20:10:53.969-07:00No, Virginia, You Can't Actually Write Unity Apps for HoloLens in F#After starting on a <a href="https://github.com/psfblair/ConwayLifeHoloLens">Conway 3D Game of Life for HoloLens</a> in F#, and experiencing a crash related to IL2CPP, <a href="https://fogbugz.unity3d.com/default.asp?894364_ejukbrck4aott5h9">I filed a bug</a> with Unity. In response, I got bad news:<br />
<br />
<blockquote class="tr_bq">
The error occurs because IL2CPP limits the recursion depth of generics to seven levels currently. Unfortunately, this is is not an error which is reported well the version of Unity you are using. The most recent Unity patch releases handle this error case better by throwing a managed exception. </blockquote>
<blockquote class="tr_bq">
However, that does not correct the root issue. Often with F# code we see deeply nested generic type and method hierarchies which hit this limit. Can you use a different library, not written in F#? Since F# is not a supported scripting language in Unity, we don't plan to actually correct this bug.</blockquote>
<div>
This effectively means F# is out for writing HoloLens apps, or even Unity apps at all, since Unity plans to move its scripting back-ends to IL2CPP entirely in the near future.</div>
<div>
<br /></div>
<div>
<strike>You can up vote the bug <a href="https://issuetracker.unity3d.com/issues/il2cpp-windows-store-build-results-in-access-violation-crash-const-methodinfo-resolves-to-null">here</a> if you think we can get Unity to change their mind.</strike> Turns out you can't even up vote the bug since it's been marked resolved. However, you can vote for Unity F# support <a href="https://feedback.unity3d.com/suggestions/f-support">here</a>.<br />
<br />
<i>Addendum: It's worth noting that F# support is currently Unity's <a href="https://feedback.unity3d.com/forums/unity/suggestions?utf8=%E2%9C%93&status=0&category=&view=most_voted">seventh-most requested</a> feature.</i></div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-5803195198080587445.post-52128633267122244862017-03-12T20:46:00.000-07:002017-03-12T20:53:36.569-07:00Some Gotchas Writing Unity Apps in F#If you're writing your Unity code in F#, here are some useful tips that may not be immediately obvious:<br />
<br />
<h3>
Nullable Fields in Monobehaviours</h3>
<div>
<br />
A lot of Unity scripts involve classes that inherit from MonoBehaviour, some of which will have fields that become settable properties in the Unity editor. Because of to the way Unity does serialization, the values are not passed to your class' constructor. (Unity wants you to use a no-argument constructor, if any; you shouldn't be calling any Unity API methods from it.)</div>
<div>
<br />
As a result, you need fields that initialize to <code>null</code>, which Unity will then in turn set. Since F# is designed to interoperate with .NET, it foresees this eventuality (while screaming at you that it's generally a bad design decision):
</div>
<pre class="brush: fsharp">namespace My.Unity.FSharp
open UnityEngine
type MyBehaviour() =
inherit MonoBehaviour()
[<SerializeField>] [<DefaultValue>] val mutable MyGameObject: GameObject
</pre>
<div>
<br />
Using <code>val mutable</code> with the <code>[<DefaultValue>]</code> attribute allows for the field to take on a "zero" value when it is initialized; for reference objects this is <code>null</code>.<br />
<br />
<h3>
Mutable Struct Fields</h3>
</div>
<div>
<br />
Many Unity data structures—<code>Quaternion</code>, for example—are implemented as .NET structs. You may find yourself bewildered at why this code doesn't work:
<br />
<br /></div>
<pre class="brush: fsharp"> let toQuat: Quaternion = Camera.main.transform.localRotation
toQuat.x <- 0.0f
</pre>
<div>
<br />
If you hover your mouse over the <code>x</code> in <code>toQuat.x</code>, the helpful hover tip will tell you <code>val mutable x: float32</code>. Yet you still get the error <code>"Error: A value must be mutable in order to mutate the contents or take the address of a value type, e.g., let mutable x = ..."</code> If you read this too quickly, it looks it's telling you <code>x</code> has to be mutable, but we've already seen that it is a mutable field.
<br />
<br />
The answer is that for a value type's fields to be mutable, it itself has to be mutable. So the correct code is:<br />
<br /></div>
<pre class="brush: fsharp"> let mutable toQuat: Quaternion = Camera.main.transform.localRotation
toQuat.x <- 0.0f
</pre>
<h3>
</h3>
<h3>
Dependencies on Scripts in Prefabs</h3>
<div>
<br />
If you happen to be working your way through the HoloLens tutorials, as I have been, you'll reach Chapter 6 of Holograms 101, where you're given code referencing <code>SpatialMapping.Instance</code>. If you write this in F#, you'll likely see <code>Error: The namespace or module 'SpatialMapping' is not defined.</code></div>
<div>
<br />
The problem is that the <code>SpatialMapping</code> class is part of the SpatialMapping prefab asset that you're given in the exercise; the script is built into the prefab. But writing F# code for Unity requires compiling to a plugin, so we need the <code>SpatialMapping</code> class to be compiled in order to be able to refer to it.</div>
<div>
<br />
The solution is actually not difficult. If you build your Unity project, Unity will create an <code>Assembly-CSharp.csproj</code> file at the root of your Unity project. This project file corresponds to a .NET project that you can reference as a project reference in your F# project. Once that dependent project's DLL is built, your F# code will be able to pick up the necessary references.</div>
<br/>
<h3>
Out Parameters for Complex Method Signatures</h3>
<div>
<br />
Another issue I encountered was that in some cases, Unity's APIs take an <code>out</code> parameter but don't make it the last parameter in the method signature. While in general F# is smart with .NET <code>out</code> parameters—you call the method without the <code>out</code> parameter, and you get back a tuple pairing a boolean with the returned value—I wasn't able to make this work with a long method signature having the <code>out</code> parameter in the middle, e.g.<br />
<br /></div>
<pre class="brush: csharp"> public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);
</pre>
<div>
<br />
It's possible that the reason F# can't return a tuple is that the method signature without the <code>out</code> parameter collides with a different method signature of <code>Physics.Raycast</code>. In any event, here you have to handle the <code>out</code> parameter explicitly, so the F# code would look like this:<br />
<br /></div>
<pre class="brush: fsharp"> let mutable hitInfo = Unchecked.defaultof<RaycastHit>
if Physics.Raycast(headPosition, gazeDirection, &hitInfo, maxDistance, SpatialMapping.PhysicsRaycastMask) then
this.transform.parent.position <- hitinfo.point
</pre>
<div>
<br />
Note how <code>Unchecked.defaultof<'T></code> is used in F# to assign a null value to a binding for a reference object. The binding has to be mutable, and gets passed as an <code>out</code> parameter using the <code>&</code> prefix.
<br />
<br />
As I come up with more gotchas, I'll keep posting...</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5803195198080587445.post-60384286740974845642017-03-12T19:27:00.003-07:002017-03-12T19:52:40.034-07:00… and You Can Write HoloLens Apps in macOS / Linux Too (Part 3: Deploy to HoloLens)<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
In <a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">Part 1</a> we saw how to set up a cloud server to build Unity apps for HoloLens, and <a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-2.html" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">Part 2</a> covered how to set up a Unity HoloLens project to build in the cloud. Now we’ll look at how to get the compiled code up to the HoloLens.</div>
<h2 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 28px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
One-Time Setup</h2>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
To get set up to push app bundles to the HoloLens, you first need to set up the HoloLens to use the Windows Device Portal. This is a web server on the HoloLens that lets you connect and manage the HoloLens from a browser outside the device.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
You set up the device portal from within the HoloLens, using the Settings app. Select the “Update” menu item and then the “For developers” menu item. Enable “Developer Mode” and then scroll down and enable “Device Portal”.</div>
<h2 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 28px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Accessing the HoloLens Via Browser</h2>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Make sure the HoloLens is connected to WiFi (make sure it’s a secure WiFi that you trust), and then look up its IP address by going to “Settings > Network & Internet > Wi-Fi > Advanced Options”.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
From a web browser on a development machine in the same WiFi network, go to <code>https://[HOLOLENS_IP_ADDRESS]</code> .</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
The first time you connect, the browser should tell you that there’s a problem with the website’s security certificate. Assuming you’re on a WiFi that you trust, ignore this for the time being (we’ll fix it later).</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
The first time you connect, you’ll also need to create a username and password. When you connect, the first page you see should be the “Set up access” page. Click or tap “Request pin” — then if you look at the HoloLens display, you’ll see a PIN number that it generated that you should enter into the “PIN displayed on your device” textbox. After that, you can enter a username and password of your choice (the password has to have at least seven characters). Then click “Pair” to connect to the Windows Device Portal on the HoloLens.<span id="fn1" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-3.html#password-reset" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">1</a></span></div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now you can fix the certificate issue. Go to the “Security” page on the Device Portal, either by clicking the “Security” link from the top right icon list or by navigating to: <code>https://[HOLOLENS_IP_ADDRESS]/devicesecurity.htm</code>. From that page you can download the device’s certificate.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
If you’re on macOS, you’ll need to add a .p12 extension to the certificate name. Then you can double-click it and it will install into your keychain. Next, double-click it in the keychain and next to “Secure Sockets Layer (SSL)” select “Always Trust”.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
If you’re on Windows, from the “Run” app, type “Manage Computer Certificates” and start the applet. Expand the “Trusted Root Certification Authority” folder, and click on the “Certificates” folder. Then, from the Action menu, select: “All Tasks > Import…” Once you complete the Certificate Import Wizard using the downloaded certificate file, you will have installed the certificate in the Trusted Root Certification Authorities store on your local machine.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
(I’m not sure what needs to be done on Linux; if someone fills me in I’ll add it here.)</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
You’ll need to restart your browser for it to recognize the imported certificate.</div>
<h2 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 28px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Deploying Your App To the HoloLens</h2>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now in the Windows Device Portal, click “Apps”. Under “Install App” you can select your app bundle: Click the “Choose File” button under “App package” and navigate to the network share from the remote build server, and drill down under the AppPackages directory under the solution directory of your IL2CPP build. You want the file named after your project with the extension <code>.appxbundle</code>.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Then under “Deploy”, click “Go” to deploy the app package to the HoloLens.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
It’s as easy as that!<br />
<br />
[This piece was originally posted <a href="https://seriouscodeblog.wordpress.com/2017/02/24/and-you-can-write-hololens-apps-in-macos-linux-too-part-3/">here</a>.]</div>
<hr style="border-color: rgb(204, 204, 204); border-left-width: 0px; border-right-width: 0px; border-style: solid; border-top-width: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; height: 0px; margin-bottom: 24px; margin-top: -1px; padding-top: 24px;" />
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<span id="password-reset" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-3.html#fn1" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">1</a></span> If you want to change the username or password later, you can visit the device security page by either clicking the Security link along the top right, or by navigating to: <code>https://[HOLOLENS_IP_ADDRESS]/devicesecurity.htm</code> .</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5803195198080587445.post-39247928024134204452017-03-12T19:24:00.000-07:002017-03-12T19:49:12.457-07:00… and You Can Write HoloLens Apps in macOS / Linux Too (Part 2: Project Setup)<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
In <a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">Part 1 </a>we saw how to set up a cloud server to build Unity apps for HoloLens. That was setup you only need to do once. For remote builds, however, you’ll also need to do a bit of setup for each project you create.</div>
<h2 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 28px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Set Up Your Remote Git Repository</h2>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
You’ll need a place to push and build your project on the remote server, so you’ll need to initialize a repository. However, we can’t just initialize a bare git repository, because we’ll need the files to be checked out.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Here are the commands to run in git bash which should already be installed in your VM to get things set up (the items in brackets are things you’ll need to fill in):</div>
<pre class="brush: bash"># One-time git setup; git will be annoyed at you if you don't do this.
git config --global user.email [YOUR_EMAIL]
git config --global user.name [YOUR_NAME]
cd /c/Users/[USER]/[PATH_TO_DIRECTORY_CONTAINING_REPOSITORIES]
git init [PROJECT_NAME]
cd [PROJECT_NAME]
# Allow pushing to checked-out (non-bare) repository
git config receive.denyCurrentBranch updateInstead
</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now you’ll need to set your local git repository up to push to the remote repository. If you use the script from Part 1 to modify your <code>/etc/hosts</code> file when you connect to the remote server, you won’t need to modify the git remote URL each time the remote VM starts up and gets a new IP address.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
To get set up, you’ll need the Unity project on your local development machine to be checked in to git. Now you can run</div>
<pre class="brush: bash">git remote add holodevelop ssh://[WINUSER]@holodevelop/Users/[PATH_TO_REPO_WITH_FORWARD_SLASHES]</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Note the forward slashes in the URL, and also the fact that for some reason there’s no “C:” in the path. I’m not sure why this is the case.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Note also that instead of “origin,” I call the remote repository “holodevelop,” but you can call it what you want. Note in addition that the remote server alias is also “holodevelop,” which should correspond to the alias the script creates in your <code>/etc/hosts</code> file.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now you’ll be able to push your git repository to the remote server. For example, to push the master branch (if the remote repository is called “holodevelop”) the command would be:</div>
<pre class="brush: bash">git push holodevelop master</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Since you’re pushing to a repository that has files checked out in the workspace, there are a few things you need to take note of. If you have unstaged changes in the remote repository which Unity sometimes initiates or if the remote gets ahead of the local repository, git won’t let you do a push; it will tell you you have unstaged changes in the remote directory, or that the remote contains work you don’t have locally. You’ll need to commit any unstaged changes into the remote repository first, then pull them back to your local repository (<code>git pull holodevelop master</code>) and merge them in if necessary.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
With the setup so far, every time you push with git you’ll be asked for your password. To use public key authentication, put the following in your <code>~/.ssh/config</code> file (assuming the remote host alias in <code>/etc/hosts</code>is holodevelop and your private key is named holodevelop):</div>
<pre class="brush: bash">Host holodevelop
Hostname holodevelop
IdentityFile ~/.ssh/holodevelop
IdentitiesOnly yes</pre>
<h2 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 28px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Pushing Up Your DLLs</h2>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
For those building in F# or some other language not directly supported by Unity scripting, you’ll be compiling your script code into DLLs which will need to be copied into the Assets/Plugins directory of your Unity project. Since it’s not a good idea to put compiled artifacts into git, we’ll use a different approach.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
First, make an Assets/Plugins directory in your Unity project and put an empty file named <code>.gitkeep</code> in there, to make sure the folder exists when you push your git repository to the remote server. You’ll also want to add <code>Assets/Plugins/*.dll*</code> (and if you’re on macOS, <code>.DS_Store</code>) to your <code>.gitignore</code> file.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
To get the DLLs onto the remote server, you’ll need a post-build step that copies them to the right place. Since we’ve already mounted a file share on the remote server, this should be as easy as doing a copy command.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
One way to accomplish this is to add a post-build step to your MSBuild project file, but this will make your project file not work across platforms. (I also tried it, and it isn’t evident how to do it if you want to go this route I suggest using Xamarin Studio to edit the build configuration and add the post-build step.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
I use the FAKE build tool for building F# projects; the Ionide IDE is also integrated with Forge, which creates the whole F# project for you. For the post-build step, I change the Deploy target in the build.fsx file to the following</div>
<pre class="brush: bash">let remoteProjectPath = "[PATH_TO_PROJECT_ON_FILESHARE]"
Target "Deploy" (fun _ ->
let myCodeDll = buildDir + "[PROJECT_NAME].dll"
let fsharpDll = buildDir + "FSharp.Core.dll"
Copy "../Assets/Plugins" [ myCodeDll; fsharpDll ]
Copy (remoteProjectPath + "/Assets/Plugins") [ myCodeDll; fsharpDll ]
)</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
I also change the <code>RunTargetOrDefault</code> entry at the bottom of the file to “Deploy”. Now in the Ionide command menu I can enter “FAKE: Build Default” and the DLLs will be copied to the Assets/Plugins directory in both the local and remote projects. NOTE: To prevent getting a “Lock violation on path” error when trying to copy up the dlls, don’t have the remote folder open or even visible in your Finder window (smb will lock it).</div>
<h2 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 28px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Doing a Unity Build</h2>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Before you can run a Unity headless build for HoloLens, you’ll need to do a few things.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
First, annoyingly, Unity apparently needs to reactivate itself every time you start the VM, so each time you start the VM, or even restart Windows on the VM, you’ll need to open Unity. (I’m hoping Unity support can give me some workaround for this.)</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
The first time you create a HoloLens project on the remote box, you have to open it in Unity to add a few settings that can only be added when you’re running Unity in Windows:</div>
<ul style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 27px 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">In the build settings, make sure you Switch Platforms to Windows Store. Set the SDK to Universal 10 and the target device to HoloLens.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">In the player settings, click the Windows Store tab and go to Other Settings > Rendering. Check the “Virtual Reality Supported” box, and make sure Windows Holographic is under the Virtual Reality SDKs.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">In the player settings, under Configuration > Scripting backend pull down IL2CPP.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Save the project, commit, and pull any changes back to local machine.</li>
</ul>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
If you’re compiling F# or other code to plugin .DLLs, before you close the project you’ll also need to make sure the MonoBehaviours in your code are attached to the relevant objects. Don’t delete the DLLs while Unity is open, or they’ll get detached and you’ll have to reattach them.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now you’ll need a headless build script for Unity. This comes in two parts. The first is a Unity-flavored Javascript file that has to go in Assets/Editor, and the second a batch file that can go at the top-level of your Unity project.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Here’s the Javascript file; I call it <code>build.js</code>:</div>
<pre class="brush: js">import System.Diagnostics;
class Autobuild {
static function Build() {
// The path to the directory where the IL2CPP files will be built.
var path = "C:/[PATH_TO_OUTPUT_DIR]";
// An array of paths to the files for the scenes you want to build.
var scenes : String[] = [ "Assets/[SCENE_NAME].unity" ];
// Build the player.
BuildPipeline.BuildPlayer(scenes, path, BuildTarget.WSAPlayer, BuildOptions.None);
}
}
</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
You’ll need to fill in the path where you want the C++ files build, as well as the scenes you want to include. Note that the path starts with the drive letter, and the path dividers are forward slashes.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now you’ll need a batch file to trigger the build; we’ll put this in <code>unity_headless_build.bat</code> at the root of the Unity project:</div>
<pre class="brush: bash">SET UNITY_FOLDER=[UNITY_VERSION_NAME]
SET OUTPUT_DIR=[PATH_TO_OUTPUT_DIR]
cd %~dp0
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"
"C:\Program Files\%UNITY_FOLDER%\Editor\Unity.exe" -batchmode -quit -projectPath %~dp0 -executeMethod Autobuild.Build
</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Here you need to fill in the name of the folder where Unity is installed (the full path is created further down) and the path to the directory where the IL2CPP files will be build. This needs to be Windows-style, with backslashes.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
You should be able to run this batch file from the Windows command prompt and see a new Visual Studio project built in your target directory.</div>
<h2 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 28px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Running MSBuild</h2>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
To get the final executable you can run on the HoloLens, you now have to build the project that Unity generated. You can do this by running msbuild using the following script, which I call <code>msbuild_headless.bat</code>and put in the root of my Unity project:</div>
<pre class="brush: bash">SET OUTPUT_DIR=[PATH_TO_OUTPUT_DIR]
set SOLUTION_FILE_NAME=[PROJECT_NAME].sln
cd "%OUTPUT_DIR%"
msbuild.exe %SOLUTION_FILE_NAME% /t:Build /p:Configuration=Release;Platform=x86;AppxBundle=Always</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Here again the path to the project should use the Windows-style path, and you’ll also need to fill in the name of the solution file generated by Unity.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Running this script at the command prompt should give you a new AppPackages directory inside the solution directory, and several levels under that you’ll see a file named after your project with the extension <code>.appxbundle</code>. This is the executable you’ll upload to your HoloLens (or deploy to the emulator).</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
If you want to run everything from your local command line in one step, you can make a <code>remote_build.sh</code> script as follows:</div>
<pre class="brush: bash">ssh [USER]@holodevelop "cd [UNITY_PROJECT_DIR] && unity_headless_build.bat && msbuild_headless.bat"</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Here, you should fill in your user ID on the remote machine and a Windows-style path to the Unity project directory.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
This should give you all you need to run a remote build of your application. In the <a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-3.html" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">last part</a> of this series, we’ll look at how to deploy the application to the HoloLens.<br />
<br />
[This piece was originally posted <a href="https://seriouscodeblog.wordpress.com/2017/02/23/and-you-can-write-hololens-apps-in-macos-linux-too-part-2/">here</a>.]</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5803195198080587445.post-62727545891391519992017-03-12T19:17:00.000-07:002017-03-12T19:45:57.748-07:00… and You Can Write HoloLens Apps in macOS / Linux Too (Part 1: The Cloud Server)<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Interested in doing all your HoloLens development while running macOS or Linux? Well, you can’t — not all of it, anyway. HoloLens applications have to be compiled to UWP applications by the .NET Native compiler, which only runs on Windows. And Unity only builds Windows Store apps on Windows. Both Microsoft’s and Unity’s emulators only run on Windows.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
But..</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
What you can do is write your Unity code locally on macOS or Linux, push it up to a remote build server, and build it there. This might also be a desirable option if you have an underpowered Windows machine and want to speed up your builds.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
And, depending on your usage, you can have the cloud server free of cost for a year.</div>
<h2 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 28px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Caveats</h2>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
If you don’t have a HoloLens, this setup might not be for you. Currently there is no way to run either Microsoft’s or Unity’s emulator in the cloud.<span id="fn1" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#emulator-problems" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">1</a></span> So if you want to develop on Mac or Linux your best bet is to get yourself a HoloLens to test on. (Or, you could get a Windows machine just for build and emulation, in which case some of the information below will still be of use to you.)</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
There’s also the issue of debugging. You can use the Visual Studio debugger on apps running in the emulator or on even on the device; there may be ways to do this from Xamarin Studio or the command line, but I haven’t tried to make that work.</div>
<h2 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 28px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Setting Up the Cloud Server</h2>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
For this article, we’re going to use Microsoft’s <a href="https://azure.microsoft.com/e" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">Azure</a> cloud service, though you could also use Amazon’s AWS or other cloud services. One advantage of Azure is that as a developer, you can sign up for <a href="https://www.visualstudio.com/dev-essentials/" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">Visual Studio Dev Essentials</a> and get $25 per month of complimentary Azure credit for your first year.<span id="fn2" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#visual-studio-team-services" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">2</a></span> Depending on the size of the VM you choose, you should be able to stay under that budget.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Once you’ve signed up, go to the <a href="https://my.visualstudio.com/" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">Subscriber Portal</a>, find the Azure feature, and click the “Activate” link. This will set you up with your Azure account and give you a <a href="https://portal.azure.com/" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">dashboard</a>, as well as a screen where you can <a href="https://account.windowsazure.com/Subscriptions" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">view your developer subscription</a> and see how much credit you’ve used for the month.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
The dashboard is where you create the virtual machine on which your build server will run. Here’s how:</div>
<ol style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 27px 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">In the portal menu on the right, select <code>+ New > Compute</code></li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Hit the “See All” link</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Search for “Visual Studio Community 2017 RC on Windows Server 2016 (x64)”</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Click on it, then select the “Resource Manager” Deployment Model</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">For the Basics step:<ul style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; list-style: disc; margin: 0px 0px 0px 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Give your VM a name.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Choose an SSD disk.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Create a username and password.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Use your “Developer Program Benefit” subscription</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Create a new “resource group”<span id="fn3" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#resource-group" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">3</a></span> (unless you have one you already want to use) and give it a name.</li>
</ul>
</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">For the Size step, choose your VM size. To fit within the developer benefit budget, you’ll probably need to use a DS2_V2, depending on how much you use the VM. Ideally you’ll want more than 8GB of RAM, and 4 cores is as many as you can get with the developer license, so you might prefer an F4S or DS3_V2 instead. Note that you won’t be using the VM 24×7, so the monthly prices are higher than what you’re going to pay, but you may have to limit your usage to fit inside the $25/month credit.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">For the Settings step, choose Managed disks (there’s no price difference, and it’s easier), and otherwise leave the defaults.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Once you create the VM, you should see it in your dashboard, at least under “All Resources.” If not, click on “All Resources.” You can click on your VM to see it, and it will then appear under “All Resources.”</li>
</ol>
<h3 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 24px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Connecting to the Server</h3>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Before you connect to the VM, you’ll need a remote desktop client. For macOS I suggest the <a href="https://blogs.technet.microsoft.com/enterprisemobility/2015/08/11/introducing-the-new-microsoft-remote-desktop-preview-app-for-mac/" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">Microsoft Remote Desktop Beta</a>, but you can also get the non-beta version on the app store.<span id="fn4" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#remote-desktop" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">4</a></span> For Linux, there are several RDP clients out there you can choose from. (I’m not using Linux, so I can’t make recommendations.)</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
To connect to the server, double-click on your VM in the Azure dashboard. You’ll see a row of buttons at the top the leftmost of which is “Connect.” Clicking it will cause you to download a file with the .rdp extension. On macOS, double-clicking the RDP file should open a connection to the remote server in the Microsoft remote desktop client.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Note that if you don’t want to spend the extra money for a static IP address, the IP address will change every time you restart the virtual machine. Since you’ll be using various automated scripts, you’d need to change the IP address in each one every time. Instead, you can write a script to read the IP address from the RDP file and modify /etc/hosts with the new IP address. Then you can use the alias in /etc/hosts in your scripts without having to modify them.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Here’s an example of such a script, which you can modify and run whenever you download a new RDP file; it uses the alias <code>holodevelop</code>for the remote server. (This script is for macOS but a Linux version would be similar.) The script will automatically open the desktop client for you once it finishes modifying the hosts file, and then mount the \Users folder on the remote system, which the Azure VM should automatically share with you:</div>
<pre class="brush: bash">#/bin/sh
# May need to modify this for whatever directory the rdp files get downloaded to
RDP_FILE=`ls -tr ~/Downloads/*.rdp | tail -1`
# sed -E is for OS X, use sed -r on linux
IP_ADDRESS=`cat "$RDP_FILE" | grep 'address' | sed -E 's/.*s:(.*):[[:digit:]]+/\1/' | tr -d '\015' | tr -d '\012'`
# Before running this script for the first time, initialize /etc/hosts with:
# 0.0.0.0 holodevelop
# Dig the remote IP address out of the RDP file
sudo sed -e 's/.* holodevelop'"/$IP_ADDRESS holodevelop/" -i old /etc/hosts
# This will open a session to the server in Microsoft Remote Desktop
open "$RDP_FILE"
# You'll need to add your remote user ID for USER and a path to a local directory LOCAL_PATH where you'll mount the drive
mount -t smbfs "//[USER]@$IP_ADDRESS/Users" "[LOCAL_PATH]"
</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Before this script can mount the remote file share, you have to tell Azure to let requests on port 445 access the server:</div>
<ul style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 27px 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">In the Azure web portal, find the Network Security Group you created. (You may have to go to Resource Groups and click link on your resource group to find it.)</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Click on Inbound Security Rules > Add</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Use the following settings — Source: Any, Service: Custom, Port Range: 445, Action: Allow</li>
</ul>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Note that when the script mounts the remote file share, it will ask you for your password on the remote machine.</div>
<h3 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 24px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Basic Server Setup</h3>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Once you remote in to your VM, here are some things to check and changes I recommend:</div>
<ul style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 27px 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">You should see Visual Studio 2017 Community and Unity already installed.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">You should also see the directory <code>C:\Program Files (x86)\Microsoft Visual Studio Tools for Unity.</code></li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">You should see Git installed in <code>C:\Program Files\Git</code>.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">You may want to set your time zone on the server in Settings > Time and Language > Date and Time</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Turn off IE Enhanced Security Configuration, or your experience downloading additional software will be miserable. (You can turn it back on later, but this may not be the kind of server where you worry too much about locking down the browser.) To do this, go to Server Manager > Local Server, locate “IE Enhanced Security Configuration” in the right-hand column and click the link next to it. You should see a screen that lets you turn it off.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Add <code>C:\Program Files\Git\mingw64\bin</code> and <code>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin</code> to the System PATH environment variable. (Use Control Panel > System and Security > System, click the Advanced System Settings on the right, and hit the Environment Variables button at the bottom.) The first is needed for remote git to work, and the second for msbuild.exe to be accessible by your build scripts.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Create a directory where you will put your git repositories for your projects. Mine is <code>Documents/holodevelop</code>.</li>
</ul>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now it’s time to install a few things you need.</div>
<h3 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 24px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Install the Unity Beta</h3>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
If you’re going to be doing IL2CPP builds from Unity — and this is the future of Unity scripting, not to mention a necessity for writing Unity scripts in F# — you’ll want to <a href="https://unity3d.com/unity/beta" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">download</a> and install the latest Unity beta, since they’re working hard on improving the performance of this feature. At the installer options, uncheck the standard assets, documentation, and download of Visual Studio 2015, and check the Windows Store il2cpp scripting backend.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
After installing Unity, make sure it’s pointing to the path to Visual Studio 2017 as the script editor. (This isn’t strictly speaking necessary, since you’re going to do headless builds, but it will help if you decide to do any work directly on the remote server.)</div>
<ul style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 27px 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Open Unity; Go to Edit -> Preferences, and make sure that Visual Studio 2017 Community is selected as the External Script Editor</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">If not, choose Browse in the External Script Editor pulldown, and point to the Visual Studio executable (which should be <code>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\devenv.exe</code>)</li>
</ul>
<h3 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 24px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Install and Set Up SSH</h3>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
We will use git over SSH to transfer code from your local machine to the server.<span id="fn5" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#ssh" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">5</a> </span></div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Download and install the <a href="https://www.bitvise.com/ssh-server-download" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">Bitvise Secure Windows Remote Access</a> server, which is free for non-commercial use. Run the installer and accept the default install, check “Run Bitvise SSH Server Control Panel when done,” and select the Personal Edition.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
After you’ve finished, you’ll see a Settings page. Click the “Open easy settings” link.</div>
<ul style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 27px 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">For Open Windows Firewall: Pull down “Open port(s) to any computer”</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Click the “Next” button</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">On “Windows Accounts” unclick “Allow Login to Any Windows Account”</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">On “Windows Accounts” click “Add” and add your own Windows account.</li>
</ul>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now back on the main control panel screen, click the “Start Server” link (just above the Host Keys).</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Before you can use SSH, you have to tell Azure to let requests on port 22 access the server:</div>
<ul style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 27px 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">In the Azure web portal, find the Network Security Group you created. (You may have to go to Resource Groups and click link on your resource group to find it.)</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Click on Inbound Security Rules > Add</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Use the following settings — Source: Any, Service: SSH, Action: Allow</li>
</ul>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now set up public-key authentication, which will allow scripts to transfer files without you having to enter a password each time.</div>
<ul style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 27px 27px; outline: 0px; padding: 0px; vertical-align: baseline;"><ul style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; list-style: square; margin: 0px 0px 27px 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">On your local machine, run the command <code>ssh-keygen -t rsa</code></li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Note that you don’t want a passphrase for this key, because it will be used by automated programs. Keep it safe!</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Name the private and public key files something that will distinguish them from other keys you might have, e.g., holodevelop.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Generally it’s customary to keep the key pair in your <code>~/.ssh</code>folder.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Copy the public key up to the Windows remote server using the shared folder you created.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Import the public key on the remote server. From the Start menu, open the Bitvise SSH Server Control Panel, click the “Open easy settings” link, click the “Next” button, and select your own account in the “Windows Accounts” screen. Click on the “Public Keys” link and add the public key that you copied up in the last step.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Now you can delete the public key file you copied up from the remote Windows machine.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Restart Windows.</li>
</ul>
</ul>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now test to see if you can connect using your public key, for example:</div>
<pre class="brush: bash">ssh -i ~/.ssh/holodevelop [USER]@holodevelop</pre>
<h3 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 24px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Modify Windows Defender</h3>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Windows Defender is an antivirus program that does security scans of the local system. Subjecting your git repository and your build directories to Windows Defender scans may slow your build. We’ll exclude these directories from being scanned by Windows Defender:</div>
<ul style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 27px 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Settings > Update & Security > Windows Defender</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Scroll down to Exclusions and click Add an Exclusion</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Exclude the folder that will hold your git repository as well as the folder you created on the E: drive for builds).</li>
</ul>
<h2 style="border: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Source Sans Pro', sans-serif; font-size: 28px; font-weight: 400; margin: 27px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
Some Last Thoughts for Part 1</h2>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
When you’re done with the VM, stop it so that you’re not incurring charges for the VM time. You’ll need to remember to restart it when you want to do development. To stop a VM go into the Azure portal, click on the VM, and hit Stop from the buttons at the top row.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Now we’re ready for <a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-2.html" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">Part 2</a>, where we’ll do one-time project-specific setup.<br />
<br />
[This piece was originally posted <a href="https://seriouscodeblog.wordpress.com/2017/02/21/and-you-can-write-hololens-apps-in-macos-linux-too-part-1/">here</a>.]</div>
<hr style="border-color: rgb(204, 204, 204); border-left-width: 0px; border-right-width: 0px; border-style: solid; border-top-width: 0px; box-sizing: border-box; clear: both; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; height: 0px; margin-bottom: 24px; margin-top: -1px; padding-top: 24px;" />
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<span id="emulator-problems" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#fn1" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">1</a></span> Microsoft’s HoloLens emulator requires Hyper-V, and since Azure VMs are already virtualized, and <a href="https://social.msdn.microsoft.com/Forums/en-US/ee654842-5007-4456-96ab-a682ec18591d/nested-virtualization-inside-azure" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">you can’t have nested Hyper-V</a>, it won’t work. (I’ve tested this.) If you want to run Microsoft’s emulator, you’ll need a machine running Windows Pro or some other edition of Windows that supports Hyper-V.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Unity’s Holographic Emulation also has <a href="https://forum.unity3d.com/threads/holographic-emulation-not-working-on-5-6-0b9.457589/#post-2968377" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">problems in a VM environment</a>.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<span id="visual-studio-team-services" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#fn2" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">2</a></span> Microsoft also has a build service included in <a href="https://www.visualstudio.com/team-services/" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">Visual Studio Team Services</a>, which is free of charge for teams of fewer than five members. Unfortunately, it currently <a href="https://developercommunity.visualstudio.com/content/problem/18981/build-cant-read-vs-or-sdk-installation-directories.html" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">doesn’t support Unity builds</a>.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<span id="resource-group" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#fn3" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">3</a></span> A resource group holds everything you’re going to create — not just the virtual machine, but the network interface, IP address, network security group, storage, etc. This is so that if you want to get rid of a VM you can get rid of the entire group and not continue to be charged for resources outside the VM, such as storage.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<span id="remote-desktop" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#fn4" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">4</a></span> One productivity tip: Once logged in to a remote server using the macOS remote desktop client, if I Cmd-Tab switched from that app, I found myself unable to Cmd-Tab back to the remote screen; I’d always come back to the “View Connection Center” window of the desktop client, and then have to double-click on my active connection to switch to the main screen. To be able to Cmd-Tab back directly to the remote screen, minimize the View Connection Center window after connecting.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<span id="ssh" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#fn5" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">5</a></span> I tried doing this by having git use the drive shared from the server, but git doesn’t play nice with smb protocol, at least not when going from macOS to Windows.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<span id="imdisk" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#fn6" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">6</a></span> The -a switch creates a new disk, -t puts it in virtual memory, -s is the size, -m creates it as drive E:, and the options to -p say to create an ntfs file system, do a quick format on it, and automatically answer “Yes” to the user prompts. The second line creates a holodevelop folder in the E: drive. (You can name it whatever you want instead.)</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<span id="ramdisk" style="border: 0px; bottom: 1ex; box-sizing: border-box; font-family: inherit; font-size: 0.8125em; font-style: inherit; height: 0px; line-height: 0; margin: 0px; outline: 0px; padding: 0px; position: relative; vertical-align: baseline;"><a href="http://seriouscodeblog.blogspot.ca/2017/03/write-hololens-apps-on-macos-linux-1.html#fn7" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; transition: all 0.2s ease-in-out; vertical-align: baseline;">7</a></span> Each time you log in to the VM the script will run, but it’s idempotent so nothing is harmed by running it more than once. You could have the E: drive created whenever Windows starts by creating a Windows service, but that’s is more complicated. Also, imdisk has a -P parameter which will create the drive on Windows startup, but it won’t format it, so there would be a manual step involved.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5803195198080587445.post-30313607844849510972017-02-19T13:16:00.000-08:002017-04-09T13:18:13.581-07:00Yes, Virginia, You Can Write HoloLens Apps in F#<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
[Unfortunately, after this post was written I discovered incompatibilities which pretty much kill the idea of writing HoloLens applications in F#. See "<a href="http://seriouscodeblog.blogspot.ca/2017/04/no-virginia-you-cant-actually-write.html">No Virginia, You Can't Actually Write Unity Apps for HoloLens in F#</a>" for details.]<br />
<br />
F# fans who want to write applications for the Windows Store have been disconcerted by <a href="https://github.com/Microsoft/visualfsharp/issues/1096" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">this thread</a> on GitHub, which indicates that .NET native doesn’t support all the IL that F#’s compiler can generate. That seems to throw cold water those of us wanting to write HoloLens applications in F#, since applications for HoloLens have to be UWP apps for the Windows Store.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
This is a big deal. The HoloLens platform is going to be a huge draw of new developers to the Microsoft community; people who want to be on the cutting edge want to use cutting-edge tools. In the most recent Stack Overflow poll of developers, F# came out the <a href="https://fossbytes.com/loved-programming-languages-rust-swift-go/" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">third most loved programming language</a>, behind Rust and Swift. I can believe it. Programming in F# makes me happy.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
I was overjoyed to discover that there is a fairly straightforward way to write 3D HoloLens applications in F#, as long as you’re using <a href="https://unity3d.com/" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">the Unity 3D game engine</a>. Unity comes with two “scripting backends” that incorporate developers’ .NET code into a Unity3D app. One of these scripting backends is called “IL2CPP.” When it is used, the IL in .NET assemblies used by the Unity project — including F# assemblies — is translated into C++, which is then compiled to .NET native code. Unity has said that <a href="https://blogs.unity3d.com/2014/05/20/the-future-of-scripting-in-unity/" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">IL2CPP is the future of scripting</a> in Unity.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
To use IL2CPP for Windows Store apps, you have to be using Unity on Windows, and you have to have the IL2CPP scripting back end installed. (It’s one of the options when you install Unity). Then, in Build Settings > Player Settings choose the Settings for Windows Store tab and look under Other Settings > Configuration > Scripting Backend and select IL2CPP.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
To code in F# for Unity, the basic idea is that you compile your F# code into a DLL (targeting .NET 3.5), and then have a post-build step copy the DLL and the FSharp.Core DLL into the Assets\Plugins folder in the Unity project. The classes inside the DLL show up in the project window and can be dragged onto Unity components just like scripts. (For more details, see Jackson Dunstan’s <a href="http://jacksondunstan.com/articles/3229" style="-webkit-transition: all 0.2s ease-in-out; border: 0px; box-sizing: border-box; color: #1c7c7c; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; transition: all 0.2s ease-in-out; vertical-align: baseline;">tutorial</a>.)</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
The GitHub thread mentioned above says that one of the blocks to getting F# support for UWP is that tail call optimization isn’t supported by .NET Native. What happens when we instead translate the IL to C++ using IL2CPP? I tested this tail call to see what would happen:</div>
<pre class="brush: fsharp"> let rec callTailRecursiveFunction index =
if index callTailRecursiveFunction</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
<br />
IL2CPP turns it into this:</div>
<pre class="brush: cpp">extern "C" void MyClass_callTailRecursiveFunction_m1362434375 (MyClass_t1938649317 * __this, int32_t ___index0, const MethodInfo* method)
{
IL_0000:
{
int32_t L_0 = ___index0;
if ((((int32_t)L_0) > ((int32_t)0)))
{
goto IL_0006;
}
}
{
return;
}
IL_0006:
{
int32_t L_1 = ___index0;
___index0 = ((int32_t)((int32_t)L_1-(int32_t)1));
__this = __this;
goto IL_0000;
}
}</pre>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Which seems to indicate that, in this case at least, tail calls are optimized.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
I haven’t done exhaustive testing so there may be other aspects of F# IL that IL2CPP has trouble with. But I have been able to get a small demo app running with the scripts all in F#.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
Hopefully full UWP support for F# is not far off. But it’s great that the Unity folks have made it possible for us to be writing HoloLens apps in F# right now.</div>
<div style="border: 0px; box-sizing: border-box; color: #666666; font-family: 'Libre Baskerville', serif; font-size: 18px; margin-bottom: 27px; outline: 0px; padding: 0px; vertical-align: baseline;">
[This post was originally posted <a href="https://seriouscodeblog.wordpress.com/2017/02/19/fsharp-hololens-apps/">here</a>.]</div>
Unknownnoreply@blogger.com0