MonoDevelop: Software Building Architecture
Miguel de Icaza (

This document is the result of various discussions with Mono and MonoDevelop users on their needs to build, package and distribute their software by using Mono Develop.

I will update this as the discussion evolves on the mailing list.


Not all software projects handled by MonoDevelop are equal, there is a range of options that must be taken into consideration:

In addition to the above, certain applications must probe for specific features on the target system where the software is to be deployed (C libraries most of the time) or conditionally use one or more assemblies at build time. Only a minority of applications will require this.

We want applications to be self contained, so running an application within MonoDevelop will not cause a full make/make install process to be triggered before it can be executed.

Instead, applications should run from any directory being invoked, and should pull any data files that they require using relative paths to the executable path. Most of the time this is not an issue, since data files can be embedded into the executable as resource files (images, icons, glade, xml resources are common ones).

This is necessary so when a user runs an application in MonoDevelop, MonoDevelop only needs to trigger the compilation and running of the program on its current path for it to be functional.


The master file remains the "cbmx" Combine file. All the information is kept there, and auxiliary files are only generated to allow people to deploy applications without requiring MonoDevelop to be installed.

The generated output from the new build system should be a hand generated configure script that will probe system features and generate Makefiles to compile, install and remove a piece of software.

Probing for optional configuration options will be done using pkg-config

Autoconf and automake are to be avoided for the traditional C# targets, as these systems are better suited for C and C++ development and have their own sets of portability and dependency problems.


The build should be driven by make in all cases. The current infrastructure should be modified to generate the makefiles for the current project before each compilation, and two targets can provide all the needed features: all builds the software, and run would run the execution script for this program.

This means that instead of calling the compiler with a response file that we have hand-crafted, we should produce the Makefile for it that contains everything we need it to build.

The response file can still be used internally by the Makefile to work around possible command-size limitations in Unix, so something like:

all: program program: program.exe program.exe: make-response mcs @response make-response: echo '/target:executable -warnaserror' > response echo 'f1.cs f2.cs f3.cs' >> response echo 'f4.cs' >> response run: program ./program

Execution Scripts

Mono programs typically include a wrapper script to invoke them, like this:

	/usr/bin/mono /usr/bin/program.exe $*

In certain Linux systems it is possible to have the kernel invoke program.exe directly, but this is a feature only available on certain kernels, not necessarily available to users without root access, and it is definitely not available on the other platforms that Mono supports.

Compiled executables for Mono will contain the above shell script to invoke the program. In addition, the shell script could be used to set an LD_LIBRARY_PATH for glue/helper libraries.

Probing System Features

Our runtime and class libraries can isolate us from many system specific dependencies but there are still some features that we might want to support conditionally.

For the sake of having a binary that works on every platform out of the box without recompilation, it is sometimes preferable to delay until runtime conditional features like this. Although this might not always be possible.

There are two places where probing takes place:

Today we should use pkg-config to do the heavy lifting in terms of probing for existing libraries: a dialog box can be used to define a library, dependencies and possible the conditional build definitions that are needed.

Probing of low-level Unix features in a way that integrates with the IDE has not been yet studied, but I feel that these must be done in a case-by-case basis: Library probing, method probing, or maybe even adding a hook to insert some shell scripts to do the work.

The probing would be generated into a configure file and would update a configuration file (ProjectConfig.cs for C# code, and ProjectConfig.h for C code). The same files that MonoDevelop would maintain from the IDE, these files basically contain:


Web Building

During development, when the user requests to run a web page, or a web service should probe for an available port, launch XSP on that port and finally start a web browser pointing to that address.

The only trick is catching when the web browser has been closed so we can return MonoDevelop to the "development" mode and shut down the XSP server.

We could just plainly ignore this and just trigger the execution.

Java and Mono

We should add a profile for developing using Java targetting the CLI. This would take care of creating the jar files from the referenced assemblies, use the system javac compiler and invoke Mono with IKVM with the proper arguments.

This should bring into consideration the integration of existing JAR files into the IDE, and call IKVMC to build DLL files out of the system jar files.

Source Code Packaging

The generated makefiles should support a target to ship the source code, a feature that should also be available from MonoDevelop's IDE. This probably can be done as a the `dist' makefile targte.

Binary Packaging

Creation of an RPM spec file is a possibility, but RPMs are not portable to every platform. Maybe a zip file, or a compressed tar file are options.

Since the packages should allow to be hosted on any prefix location like MacOS applications, it might not be much of an issue.