Mono Framework For Mac Os

Mono is a software platform designed to allow developers to easily create cross platform applications. It is an open source implementation of Microsoft's.Net Framework based on the ECMA standards for C# and the Common Language Runtime. Mono 's C# compiler is feature complete for C# 1.0, 2.0, 3.0, and 4.0 (ECMA). The runtime implements the ECMA Common Language Infrastructure (CLI). I'm trying to get a Mono install running on a mac (OS X version 10.10.5), and while the install states that it's completed successfully, I'm not able to call mono from the terminal. Has anyone built Mono 2.10.4 or later for Mac OS X PowerPC? The latest binary release with PPC support I can find from Ximian is 2.10.3, but recent versions of MonoDevelop (2.8 - 3.0, which don't appear to contain anything Intel-specific) only support 2.10.4 and later.

-->

In this article, you'll learn how to install .NET Core on macOS. .NET Core is made up of the runtime and the SDK. The runtime is used to run a .NET Core app and may or may not be included with the app. The SDK is used to create .NET Core apps and libraries. The .NET Core runtime is always installed with the SDK.

The latest version of .NET Core is 3.1.

Supported releases

The following table is a list of currently supported .NET Core releases and the versions of macOS they're supported on. These versions remain supported either the version of .NET Core reaches end-of-support.

  • A ✔️ indicates that the version of .NET Core is still supported.
  • A ❌ indicates that the version of .NET Core isn't supported.
Operating System.NET Core 2.1.NET Core 3.1.NET 5 Preview
macOS 10.15 'Catalina'✔️ 2.1 (Release notes)✔️ 3.1 (Release notes)✔️ 5.0 Preview (Release notes)
macOS 10.14 'Mojave'✔️ 2.1 (Release notes)✔️ 3.1 (Release notes)✔️ 5.0 Preview (Release notes)
macOS 10.13 'High Sierra'✔️ 2.1 (Release notes)✔️ 3.1 (Release notes)✔️ 5.0 Preview (Release notes)
macOS 10.12 'Sierra'✔️ 2.1 (Release notes)❌ 3.1 (Release notes)❌ 5.0 Preview (Release notes)

Unsupported releases

The following versions of .NET Core are ❌ no longer supported. The downloads for these still remain published:

  • 3.0 (Release notes)
  • 2.2 (Release notes)
  • 2.0 (Release notes)

Runtime information

The runtime is used to run apps created with .NET Core. When an app author publishes an app, they can include the runtime with their app. If they don't include the runtime, it's up to the user to install the runtime.

There are three different runtimes you can install on macOS:

ASP.NET Core runtime
Runs ASP.NET Core apps. Includes the .NET Core runtime.

.NET Core runtime
This runtime is the simplest runtime and doesn't include any other runtime. It's highly recommended that you install ASP.NET Core runtime for the best compatibility with .NET Core apps.

SDK information

The SDK is used to build and publish .NET Core apps and libraries. Installing the SDK includes both runtimes: ASP.NET Core and .NET Core.

Dependencies

.NET Core is supported on the following macOS releases:

.NET Core VersionmacOSArchitectures
3.1High Sierra (10.13+)x64More information
3.0High Sierra (10.13+)x64More information
2.2Sierra (10.12+)x64More information
2.1Sierra (10.12+)x64More information

Beginning with macOS Catalina (version 10.15), all software built after June 1, 2019 that is distributed with Developer ID, must be notarized. This requirement applies to the .NET Core runtime, .NET Core SDK, and software created with .NET Core.

The installers for .NET Core (both runtime and SDK) versions 3.1, 3.0, and 2.1, have been notarized since February 18, 2020. Prior released versions aren't notarized. If you run a non-notarized app, you'll see an error similar to the following image:

For more information about how enforced-notarization affects .NET Core (and your .NET Core apps), see Working with macOS Catalina Notarization.

libgdiplus

.NET Core applications that use the System.Drawing.Common assembly require libgdiplus to be installed.

Mono Framework For Mac Os 10.13

An easy way to obtain libgdiplus is by using the Homebrew ('brew') package manager for macOS. After installing brew, install libgdiplus by executing the following commands at a Terminal (command) prompt:

Install with an installer

macOS has standalone installers that can be used to install the .NET Core 3.1 SDK:

Download and manually install

As an alternative to the macOS installers for .NET Core, you can download and manually install the SDK and runtime. Manual install is usually performed as part of continuous integration testing. For a developer or user, it's generally better to use an installer.

If you install .NET Core SDK, you don't need to install the corresponding runtime. First, download a binary release for either the SDK or the runtime from one of the following sites:

  • ✔️ .NET 5.0 preview downloads
  • ✔️ .NET Core 3.1 downloads
  • ✔️ .NET Core 2.1 downloads

Next, extract the downloaded file and use the export command to set variables used by .NET Core and then ensure .NET Core is in PATH.

To extract the runtime and make the .NET Core CLI commands available at the terminal, first download a .NET Core binary release. Then, open a terminal and run the following commands from the directory where the file was saved. The archive file name may be different depending on what you downloaded.

Use the following command to extract the runtime:

Use the following command to extract the SDK:

Tip

The preceding export commands only make the .NET Core CLI commands available for the terminal session in which it was run.

You can edit your shell profile to permanently add the commands. There are a number of different shells available for Linux and each has a different profile. For example:

  • Bash Shell: ~/.bash_profile, ~/.bashrc
  • Korn Shell: ~/.kshrc or .profile
  • Z Shell: ~/.zshrc or .zprofile

Edit the appropriate source file for your shell and add :$HOME/dotnet to the end of the existing PATH statement. If no PATH statement is included, add a new line with export PATH=$PATH:$HOME/dotnet.

Also, add export DOTNET_ROOT=$HOME/dotnet to the end of the file.

This approach lets you install different versions into separate locations and choose explicitly which one to use by which application.

Install with Visual Studio for Mac

Visual Studio for Mac installs the .NET Core SDK when the .NET Core workload is selected. To get started with .NET Core development on macOS, see Install Visual Studio 2019 for Mac. For the latest release, .NET Core 3.1, you must use the Visual Studio for Mac 8.4.

Install alongside Visual Studio Code

Visual Studio Code is a powerful and lightweight source code editor that runs on your desktop. Visual Studio Code is available for Windows, macOS, and Linux.

High

While Visual Studio Code doesn't come with an automated .NET Core installer like Visual Studio does, adding .NET Core support is simple.

  1. Download and install Visual Studio Code.
  2. Download and install the .NET Core SDK.
  3. Install the C# extension from the Visual Studio Code marketplace.

Install with bash automation

The dotnet-install scripts are used for automation and non-admin installs of the runtime. You can download the script from the dotnet-install script reference page.

The script defaults to installing the latest long term support (LTS) version, which is .NET Core 3.1. You can choose a specific release by specifying the current switch. Include the runtime switch to install a runtime. Otherwise, the script installs the SDK.

Note

The command above installs the ASP.NET Core runtime for maximum compatability. The ASP.NET Core runtime also includes the standard .NET Core runtime.

Docker

Containers provide a lightweight way to isolate your application from the rest of the host system. Containers on the same machine share just the kernel and use resources given to your application.

.NET Core can run in a Docker container. Official .NET Core Docker images are published to the Microsoft Container Registry (MCR) and are discoverable at the Microsoft .NET Core Docker Hub repository. Each repository contains images for different combinations of the .NET (SDK or Runtime) and OS that you can use.

Microsoft provides images that are tailored for specific scenarios. For example, the ASP.NET Core repository provides images that are built for running ASP.NET Core apps in production.

For more information about using .NET Core in a Docker container, see Introduction to .NET and Docker and Samples.

Next steps

  • How to check if .NET Core is already installed.
  • Working with macOS Catalina notarization.
  • Tutorial: Get started on macOS.
  • Tutorial: Create a new app with Visual Studio Code.
  • Tutorial: Containerize a .NET Core app.

As you’ll no doubt be aware, the Mono Project is an ambitious, open-source initiative, largely coordinated by Novell. The aim is to build a complete suite of ECMA- compliant .NET tools (C# compiler, runtime, class frameworks, etc) which work across all supported platforms, including Linux, Windows and Mac OS X. For more background on the project, check out “Mono (software)” on Wikipedia.

As a keen Mac user, I’m always looking out for new development tools which not only provide a simple, efficient and intuitive API but also – hopefully – offer cross-platform capabilities too. From this perspective, Mono would seem to be ideal; not least, because I’m a fan of Microsoft’s .NET class frameworks which do such a great job of taming the atrocious Win32 API beneath! So, let’s look further...

Mono on the Mac…

Getting started with Mono is relatively straightforward; go to the Mono Project main page, follow the ‘download now’ link (cunningly hidden in the extreme top-right of the screen) and you’ll be able to obtain the Mono distribution appropriate to your platform. For the Mac, this is currently tagged as “Mono 1.2.3_1 Framework - Universal (Stable)”. Once you’ve downloaded and installed the framework, you’ll initially find … nothing! It’s at this point that Windows users start missing the Start Menu and it’s highlighted list of freshly installed goodies. Nothing in the /Applications folder either…hmm….

Mono Framework Mac Os Catalina

Though not blindingly obvious, Mono gets installed as a new framework. The full path is /Library/Frameworks/Mono.framework. The various command-line Mono utilities are accessed via aliases which are automatically placed into /usr/bin. This means that after installing Mono, you can fire up a Terminal window and type (e.g.) ‘mcs’. This will invoke the Mono C# compiler.

Once you’ve got this far, there’s a lot you can do, provided you’re happy to stick with simple text-mode stuff and command line tools. Naturally, the quintessential C# program has got to be a variant on “Hello World” !

Type this into a file called hello.cs, compile it with the mcs compiler and – voila! – you’ll end up with an executable called hello.exe. First thing to say is that the file is just as tiny as you’d expect from Windows development – around 3Kbytes in this particular case. The reason, of course, is that all the .NET class libraries are located in the aforementioned framework directory. What’s perhaps a little more surprising (at least from the perspective of an OS X purist) is that .exe suffix on the end of the file. If you try disassembling the code with any of the usual OS X tools (e.g. otool) you’ll be told in no uncertain terms that hello.exe isn’t a binary file. So what’s going on?

The key point, if you haven’t twigged, is that the Mono development tools generate executables that are 100% binary compatible with Microsoft’s tools running under Windows. You can take that hello.exe file generated on a Mac, stick it on your PC and run it in the usual way. What you can’t do is run it “in the usual way” on your Mac because OS X doesn’t understand .exe files!

Note: If you’re interested, there’s a new product out called CrossOver for the Mac here, which is based around Wine. This makes it possible to run Win32 applications under OS X fairly seamlessly, although I haven’t investigated whether this extends to the execution of Mono executables.

Assuming you’ve still sitting at the Mac, and you don’t use CrossOver, you can run hello.exe by typing the following in a terminal window:

mono hello.exe

In effect, hello.exe gets passed as an argument to the Mono loader which takes care of the program’s execution. A bit klunky, but it works. The accompanying screenshot (Figure 1) shows a partial dump of the various System-prefix assemblies installed by Mono; obviously, all these goodies are accessible from any command-line tools you build using the C# compiler.

X Marks The Spot…

But what about GUI, I hear you cry? After all, System.Windows.Forms.dll is rather obviously present in that last screenshot. It turns out that the news isn’t quite so good here. The introductory link Mono web info has this to say: “Mono is primarily developed on Linux, and most of its users are Linux users, so it is the platform best supported” .

You’d better believe it; although support for System.Windows.Forms is going great guns on Linux, things are by no means as positive where OS X is concerned. Yes, you can create graphical applications with forms, dialogs, etc. But it’s all based around X11. On my machine, I wasn’t able to successfully run a Mono GUI application unless I first started the X server running. This is because Mono’s System.Windows.Forms implementation is built on top of System.Drawing which, in turn, makes use of X11. The net result is that instead of seeing the drop-dead-gorgeous Aqua interface that Mac users take for granted (Jobs famously said that it was so attractive, you’d want to lick it) what you actually get is a kind of retro-looking interface that looks more like Windows 98 than anything else. If you don’t start the X11 server before running your Mono app, you’ll see a whole slew of exception errors. And if you want to do the whole thing properly, you also need to install GTK which in turn requires ‘fink’ which… Well, you get the idea. On the positive side, the Mono folks have written a small utility called macpack which packages up a WinForms executable into an application bundle, meaning it can be started from Finder in the usual way. But that’s quite a small positive when set against the overarching problem that the current state of Mono uses X11 rather than Core Graphics. Figure 2 shows a screenshot of MonoDevelop, a C#-based development system which will even run on the Mac, but it knows nowt about Cocoa. Spot the tell-tale ‘X’ icon in the Dock!

There are a number of web sites around which give a somewhat rosier impression of the state of play as far as Mono development on the Mac is concerned. For example, a recent NewsForge article by Nathan Willis here suggests that Novell’s iFolder is based entirely around Mono. Is it? Well, uhhh..no.

I eagerly downloaded iFolder from here, installed it and then sat back to enjoy my first experience of a turnkey Mono application running under OS X. Needless to say, the user interface looked suspiciously native, and a quick peek inside the application using my favourite spelunking tools revealed that – sure enough – the iFolder front-end is a perfectly conventional Objective-C Mac application written using Cocoa frameworks. So conventional, in fact, that it hasn’t even been converted into a universal binary: it’s a PPC executable! All the Mono code resides in the non-GUI back-end.

Note: I should stress there’s nothing dishonest going on here; I subsequently discovered that the complete source code to iFolder is readily available from the aforementioned web site, and it bears out my findings. But, I do take issue with Nathan using iFolder as an example of a “100% .Net application”. If it is, then I’m Lady Godiva. (Private viewings by appointment only, please…)

Similar considerations apply to Unity, a design tool for 3D game development that runs on both OS X and Windows, available for download here. Again, we’re told this is 100% .NET and again, it isn’t; it’s very easy to find the Cocoa classes and .NIB files inside the executable. The developers themselves make it clear that Mono is used by Unity – but as a scripting language. If you think about it, this makes perfect sense since, with little effort, game-engine developers get a powerful scripting language which executes at near native speed, thanks to the JIT compiler that forms part of the Mono bag o’tricks. In fact, the trend seems to be that several games companies are adopting C# through Mono as a scripting language for complex game systems on non-Wintel platforms. There’s got to be a joke somewhere in there about “Mono-gamists” but as with iFolder, the essential point is that the front-end GUI has nothing to do with Mono.

As a little aside, I recently discovered that some folks are successfully using cross-platform tools to create Mac applications with a near-native look and feel. As one example, get thee hence to this site, and you’ll find a cute little application whose main aim in life is to automatically stitch together multiple images so as to create a seamless panorama. It works well, is fast, and currently supports Windows and OS X. (A Linux version is planned). Peek under the hood and you’ll discover a couple of embedded frameworks called QtCore.framework and QtGui.framework. Yes, it’s our old friend Qt, the cross-platform C++ library from Trolltech (see here, for more on this).

So what’s the bottom line here? On the Mac, Mono is ideal if you need a powerful, efficient scripting language or want to create command-line tools that are portable to Linux and Windows. But if you’re looking to build great-looking GUI applications which are indistinguishable from native Cocoa apps, then I think we’ve still got some way to go. I’ve heard rumours that a Core Graphics version of System.Drawing.dll may be in the pipeline, but don’t hold your breath…

Enter Cocoa#

If that was all there was to say, things might be a bit depressing. However, let me introduce you to another interesting little open-source project variously called Cocoa#, CocoaSharp or Cocoa-Sharp depending on which Web site you visit. As the name (possibly!) suggests, Cocoa# is an interface between the world of Mono and C# on the one hand, and Apple’s Objective-C Cocoa framework on the other. The idea is that, with Cocoa#, C# developers get access to the rich functionality contained in the Cocoa libraries. More importantly, it means that Mono applications on the Mac automatically get the native look and feel that Mac users expect.

In effect, Cocoa# is a Mono/C# binding for Cocoa. You can find more (but not much more) here. This suggests that Cocoa# is included with recent distributions of Mono, which it is – sort of – but the source code isn’t included and the binary is hidden away here:

In any event, the included binary is old. A better bet is to go in search of the Cocoa Sharp Wiki – go to here and then click the wiki link in the right-hand corner of the Web page. This will provide rather more useful information and give you a download link for the version 0.9.1 source code which – again – is old. I couldn’t even get it to compile on my machine.

Fortunately, I was rescued by Todd Schavey, who told me that a more recent version of the source is available via SVN at svn://svn.myrealbox.com/source/trunk/cocoa-sharp/ [this is a subversion (SVN) URL that you'll probably only find useful if you have an SVN client installed, which can use it to download the Cocoa Sharp source - Ed]. With his help, I was able to successfully build the Cocoa# assembly and even run some of the sample applications that are included. As far as we can tell, the current version is 0.9.4. Figure 3 shows the CocoaDoc sample, written in C#, running on my Intel iMac.

Cocoa# works by exploiting the fact that Cocoa messages are essentially procedural at the level of the runtime library. In other words, regular messages map to a call to a runtime routine called objc_msgSend, “super” messages (to the immediate ancestor class) get mapped to a call to objc_msgSendSuper and so on. In both cases, the first implicit, hidden argument is a reference to ‘self’, just like the C++ or Delphi runtime models. If you want to see some really hairy C# code, download the Cocoa# sources and take a look inside the src/interop directory. Guaranteed to make your brain hurt!

Slightly higher up the food-chain, here’s a little snippet from the SavePanel.cs file, which is part of the glue code providing access to Cocoa’s NSSavePanel class:

On the positive side – joy of joys! – the Cocoa# implementation gives ‘real’ properties rather than having to faff around with two distinct accessor methods. On the negative side, it seems that nobody wants to spend their lives writing reams of glue code like that shown above – activity on this project is currently quite low. That’s a real shame since, in my opinion, of the various Mono initiatives around, Cocoa# offers the best hope for coming up with applications that be aesthetically acceptable to the notoriously finicky Mac community!

Mono Framework For Mac Os Versions

While pondering all this stuff, I realised that it ought to be possible to come up with a tool for automating the generation of much of this glue code. There’s a popular developer’s utility called class-dump, which is able to peel apart a Cocoa framework or application, showing the names of all the classes contained therein, as well as the signature of each Cocoa message. I suspect that using something like class-dump, it ought to be possible to take much of the grunt-work out of creating the glue code. However, when suggesting this recently in the appropriate Apple mailing list, I was told it had been tried before without success. If at first you don’t succeed…

Conclusions

Arguably, I’ve been a bit unfair here. The real stomping ground of Mono is undoubtedly Linux and – to a lesser extent – the Win32 platform. That’s apparently where most of the development effort is being expended these days.

As far as OS X is concerned, I fear that Mono is stuck between a rock and a hard place. On the one hand, Cocoa-heads see no compelling reason to embrace a new and alien language while Mac purists (end users, in particular) will have no interest whatsoever in running strange-looking applications which won’t work until they’ve started the X11 server. On the other hand, Linux devotees aren’t particularly fond of OS X, partly because it’s a proprietary closed-source (in part) platform. Furthermore, any efforts expended in terms of building a more feature-complete implementation of Cocoa# would, in a sense, be wasted effort from a portability point of view since Cocoa is obviously only available on the Mac. What’s the point in writing your application using an ECMA certified, platform-neutral language when all you’re doing is making calls to a proprietary, platform-specific toolkit? Sounds a bit daft, doesn’t it?

Install

As regards the other issues I’ve raised, I expect some pundit will be along soon to assure me that if I just added a couple of lines of gobbledegook to this config file, changed a few environment variables here, and altered file permissions there, then it would be possible to get Mono running without X11. Great, and when my Auntie can do that blindfolded, Mono will be ready for the masses. For what it’s worth, I love both C# and Mono, but in terms of how/where they fit into Mac development, I think it’s time to step back and re-evaluate where we’re going.

Further reading on Mono can be found here.

Get ourTech Resources