With the new release of the MonoMac add-in for MonoDevelop, you can easily turn your Mono application into a full Mac bundle, and you can also get a Mac installer for your application with all of the Mono dependencies bundled with it as well as creating Mac applications for distribution on the Apple Mac AppStore.
The process turns your executable and your resources into a fully self-contained package that bundles Mono and all of the dependencies your application requires.
Table of contents |
Getting Started
You will need the following components installed:
- From Apple:
- At least XCode 3.2.5, this contains the developer tools to build Mac apps
- Apple's Application Tools (login to developer.apple.com/mac)
- Yes, you need this. No, you can't ignore this. You wont be able to publish to the AppStore without it. Yes, we mean it.
- From Mono:
- Mono 2.8.x
- MonoDevelop 2.4.2 (released on January 19th)
- The latest MonoMac add-in. See how to get this in our MonoMac page.
Creating your Mac application
Mac bundles are directories with the .app extension that contain all of the components necessary for your application to run. They contain your executable, any images, UI definitions, pdfs, graphics, data files, internationalization resources and any other resource that your application needs at runtime. If you want to learn more about what goes in a bundle, you can read Apple's Bundle Programming Guide.
To create native Mac bundles, you should create a new project based on any of the MonoMac profiles: the document-based application, the empty-application, or the window-based application. This will configure your project to be compiled as a Mac bundle.
When you compile your application, MonoDevelop will create a Mac bundle that integrated with the operating system. You will want to provide a custom icon, and tune the launch parameters in the Info.plist file that MonoDevelop generates for you.
Bundles and Mono
By default, MonoDevelop creates application bundles that require the Mono framework to be installed (it is typically installed in /Library/Frameworks/Mono.framework). This creates small bundles, as only your code and your resources are packaged, the entire Mono stack is shared across all of the Mono applications on the System.
But sometimes you want to distribute your application without requiring end users to install Mono on their own, distribute your app on the Mac App Store, or you might want to take a dependency on a particular version of Mono that you have tested and QAed on site. To do this, the new MonoMac packager allows you to distribute the pieces of Mono that you require with your application bundle., making your application entirely self-contained.
We will explain how this work in the following sections.
Linking
MonoMac comes with an assembly linker. The linker can be used to remove unused code from your libraries. For example, if your application uses the Xml streaming parser in System.Xml.XmlReader to process XML documents, but never uses the DOM parser in XmlDocument, the linker can remove the XmlDocument from the resulting executable to shrink your application size. The way the linker works is by tracing all uses of all the methods, properties, classes and fields that you use.
If you use the method System.Console.WriteLine, the linker will trace all of the dependencies for System.Console to work, which include things like String, the String.Format method, the System.IO.Stream class (as the console writes to the console using streams), the Unicode classes (as your program needs to transform the unicode characters into the proper encoding for the terminal) and so on. It will keep all of these dependencies, but will strip out any code that you do not use.
We offer a couple of options on how you can use the linker.
If you select Don't link assemblies, the packager will merely create a bundle with all of the Mono assemblies and your own assemblies that you reference in them. It would not modify the assemblies in any form, it would ship them as-is. This is useful for example, if you plan on using scripting languages like IronPython, IronRuby, Boo, or our own C# scripting engine or if you plan on having plug-ins that might require the full API of the assemblies to be available.
If you choose Link Framework Assemblies, the linker will keep your entire code intact, this includes any assemblies that are not part of Mono that you reference in your project, and the main executable. But it will perform the linking process on any system libraries that your project references, like mscorlib.dll, System.dll, System.Xml.dll, System.Core.dll and so on.
If you choose Link All Assemblies the linker will run in its most aggressive mode and will link not only the system libraries, but also your assemblies and your main program. You could for instance, reuse a popular library, but if you only use one tiny method, only that tiny method will be included, everything else will be removed. This also applies to your own libraries and your main executable.
The linker does not have a way of knowing if at runtime you will Reflect on your types, or if you will dynamically try to use some code. or instance, serialization requires that a type contains a default (parameter less) constructor. In this mode, if the constructor is not statically called by your code, the linker will remove the constructor. You can control this feature by putting a [Preserve] attribute on the member that you don't want to see removed, or you can put a [Preserve (AllMembers = true)] attribute on the type defining the member, to make sure everything is preserved.
The Preserve attribute comes from the MonoMac.Foundation.PreserveAttribute, see the documentation for details on how to use it, and the use of the Conditional and AllMembers options.
Bundle Configuration
By default, when you create your MonoMac-based project, MonoDevelop will create a bundle that requires the Mono framework to be installed on your system.If you want to create a different kind of Bundle, you can do this by selecting your project in the Solution explorer, and then using the Project->Create Mac Installer menu option.
You use this to produce a new bundle with any of the configuration parameters that you need. You should check the option "Include Mono in application Bundle" if you want to bundle the Mono runtime with your application:
When you choose to include Mono in your application, you have a few options with how Mono is included: Don't link assemblies, Link framework assemblies and Link all assemblies.
Creating an Installer package
Even if your bundle is completely self-contained into the .app directory, if you are planning on distributing your app in the Mac AppStore, you must create an installer package. Or you might want to create an installer to give your users an installer, instead of having them drag-and-drop the application into their /Applications folder.
You can distribute this .pkg file to your users, and it will guide them through the process of installing your application, this is what the generated installer looks like if you check this option:
Mac AppStore Distribution
To distribute on the Mac AppStore, you should be enrolled in Apple's Mac developer program, and you should familiarize yourself with the Submitting to the Mac App Store document. There are a couple of requirements on the settings that you need to provide in the Info.plist like a version number, the copyright string and a category identifier (so users can locate your application by category in the Mac appstore). There are other requirements that you should follow, like where you store files in the computer, so you should read that document from top to bottom.
You will need to create and download your certificates for the "Mac App Software" and "Mac Installer Package". Once you have created and downloaded both the application certificate and the installed these certificates on your system, you can select those from the Mac Installer dialog box.
Now when you click "Create Package" you will end up with a signed application, and a signed installer.
The next step is for you to test your installer, follow the instructions in Test the Installation Process.
At this point, you can register your application with iTunes connect: you fill in all the metadata about your application on the web: version, pricing, availability and so on.
Once that is done, you can use the Application Loader to upload your application.


