1. var bob = new Person();
2. bob.sayHello();
3. bob.wave();
##################################################################################################################

Setting up an M1 Mac Mini for my development workflow

How I've set up my new Mac to work on C# Azure Functions for Zeti

##################################################################################################################
4. var cup = new Coffee();
5. bob.drink(cup);
6. var cupTwo = new Coffee();

I’ve recently gone through a fairly major career change, I’ve left a large organisation and started heading up the technology effort of a very small startup, Zeti. As part of this I’ve now been able to choose my own devices for development, which is extremely exciting for someone like me.

I eagerly switched on the barely used gaming PC that I built 3 years ago, thinking that finally I could use it’s brute force and lack of latency to its full potential. Unfortunately since I built it the world has moved on in a few ways. For one thing I now wear a hearing aid and the constant fan noise from the massive box under my desk was genuinely draining. Then I plugged in its specs to a comparison site and found that a M1 Macbook Air now cleaned the floor with it, in both CPU and GPU.

So I specced up a M1 Mac Mini (I only need a desktop, I’ve got a recent laptop), called it an early birthday present to myself, and now I’m writing this blog post on it. I’ve also been developing the critical infrastructure for Zeti’s new technology platform on it - something I was a bit nervous about initially. When the M1 first came out, I remember seeing a lot of developers being disappointed that Docker would not work on it. I was also nervous about how good Apple’s translation solution, Rosetta, would be at ‘proper’ development tools rather than normal apps.

So first of all I should share a bit about what my development generally consists of. I’m working with C#, Typescript (React mostly, little bit of Node) on Azure Functions. I like to experiment with other stuff too, so in future I’d expect some Python and F#/Q# as well as Rust, but my priority in this was getting my daily driver up and running so I could continue delivering code for Zeti.

Naturally on first opening up the Mac, my first search query into safari is ‘Chrome’. Chrome main build actually has a native M1 binary and gives you the choice to download Intel or ARM versions - it works beautifully. I only actually use chrome for things where Firefox doesn’t work, so the next thing to get is Firefox Developer Edition. This doesn’t have an M1 version so I approach this with a little nervousness, wondering if it’s going to be a nightmare. When installing, it comes up with a little prompt saying it needs to install Rosetta 2, which you never see again, and then otherwise everything just works. I’ve not had any stability issues with Firefox at all.

On to other dev tools. If you download normal VS Code you will be running through Rosetta, but if you opt for Insiders Edition you not only get the goodies of early features but you also get a lovely M1 native binary to choose. VS Code has definitely proven the most reliable tool working across my windows laptop and my apple desktop, always working because it effectively just relies on the CLI to do the work.

I then went on to download homebrew, as you need that to get the Azure Functions Core Tools. This is where things got tricky. I followed the instructions on the homebrew website and it kept choking on the download process. The internet indicated this was due to the fact I was running an M1 rather than an intel chip, and that a magic command in front of all of my terminal commands could force them to run under rosetta:

arch -x86_64

I used that, everything worked fine and then I installed Azure Functions Core Tools using homebrew. The problem with this then emerged later. VS Code prompted me to update my version Azure Functions Core Tools, and then choked on the process. Sometimes this just happens (for whatever reason the terminal command VS Code is running in the background bombs), so I just went to execute the upgrade command myself. It failed too. It turns out, if you install homebrew with that ‘magic’ command in front of it, you then need to use that every single time you use homebrew. Naturally VS Code doesn’t do that, it just calls the actual command. I am far too lazy to execute that command with the prefix myself everytime, I want to click the nice GUI button! I could create an alias or something, but that just seems like a hack. I then stumble upon this bit of documentation on Homebrew’s website: https://docs.brew.sh/Installation#alternative-installs

Turns out it’s just a simple case of the installation location being different. After uninstalling homebrew, following those instructions, everything seems to be alright. I’ll come back and update this if it isn’t. I can certainly run brew commands directly from the terminal now without a prefix, so I expect when the next update comes through VS Code should handle it.

Visual Studio for Mac doesn’t have an M1 build but runs basically fine under Rosetta. I have had a couple of freeze-ups/crashes but its hard to tell if that is M1 vs Rosetta related or just a bug in VS for Mac itself. I did have some difficulty getting the right Azure Functions Core Tools for Visual Studio - it ships with its own install which was out of date. After a tip from a friendly Microsoft dev (thanks Jon Galloway!), I was able to update it and now I can run my C# Azure Functions in both VS Code and Visual Studio for Mac, with all the unit testing and debugging goodness you’d expect.

In terms of SDK’s, neither DotNet nor Node.js seem to have M1 builds yet - at least not on their LTS versions. Both seem to run fine though, and Node still exhibits its consistent speed advantage on Mac over Windows when building this website (difficult to compare like for like, but on build agents the build take around 40% less time on a MacOS/Linux agent than a Windows one).

As part of my Azure Functions work I’ve been using Puppeteer to produce PDF’s (using this excellent article) - This is one area where I am seeing a decent amount of instability. When I set the Chromium to run in non-headless mode so that I can check out what the page looks like before the PDF is generated, it often crashes - occasionally getting into a state where it never starts which I seem to only be able to fix with a restart of my Mac. I’m not sure exactly what’s happening here, but given this browser gets downloaded as part of the build process, I wouldn’t be surprised if the wrong version is getting installed and then called without Rosetta or something. Overall it works consistently when headless so it’s not a major issue but something to mention.

Overall my Mac is now very effective as a dev environment for me. It is silent, so it doesn’t aggravate my hearing aid, and it is nimble and fast - even running Total War: Warhammer 2 without warming up. That was particularly impressive, as a non-development app point. Steam installed under Rosetta fine, and then every game has run under Rosetta perfectly fine too. Given that includes a lot more involved translation of graphics drivers etc, I am quite impressed by that!

I hope this article has been useful - I’ll add more information onto the bottom as and when I find issues that are worth mentioning.

© 2021 - Built by Daniel Bass