| http://www.devx.com | Printed from http://www.devx.com/opensource/Article/31741/1954 |
|
An Introduction to Mono Development
Microsoft's .NET Framework CLI implementation isn't the only CLI development game in town. The Mono project is both surprisingly mature, and surprisingly compatibleand you can deliver applications built on it to multiple platforms, including Windows.
by
Andrew Troelsen
|
||||||||||||
Even after developers are made aware of .NET code's cross-platform capabilities, they often assume that the scope of platform-independent .NET development is limited to little more than "Hello World" console applications. Here's the reality. Today, you can build production-ready assemblies that make use of ADO.NET, Windows Forms (in addition to alternative GUI toolkits such as Gtk#), ASP.NET, and XML Web services. This article introduces Mono, an open source and OS-agnostic implementation of .NET. You should understand right up front that you can compile the sample application developed in this article on any Mono-supported platform, including (surprise, surprise) Microsoft Windows. Here's some background information on how Mono can make that happen. The Role of the Common Language Infrastructure (CLI) When C# and the .NET platform were released to the world at large, Microsoft Corporation submitted two formal specifications to ECMA (European Computer Manufacturers Association). Once approved, these same specifications were submitted to the International Standards Organization (ISO) and ratified shortly thereafter. So, why on earth should you care? Simply put, these two specifications provide a roadmap for other companies, developers, and organizations to build their own custom distributions of the C# programming language and the .NET platform. The two specifications in question are:
Table 1The ECMA-335 specification is partitioned into several topics.
The point of this article is not to dive into the details of the ECMA-334 and ECMA-335 specificationsnor are you required to know the ins-and-outs of these documents to understand how to build platform-independent .NET assemblies. If you are interested however, you can download both of these specifications for free.
|
| The Mainstream CLI Distributions To date, there are two mainstream implementations of the CLI, beyond Microsoft's CLR and .NET Compact Framework (see Table 2). Table 2: Here are two important CLR implementations in addition to Microsoft's.
Each of the CLI implementations shown in Table 2 provides a fully functionally C# compiler, numerous command line development tools, a Global Assembly Cache (GAC), sample code, a local documentation system, and dozens of assemblies that constitute the base class libraries. Beyond implementing the core libraries defined by Partition IV of ECMA-335, Mono and Portable .NET provide MS-compatible implementations of mscorlib.dll, System.Data.dll, System.Web.dll, System.Drawing.dll and System.Windows.Forms.dll (among many others). In addition, the Mono distribution defines a handful of assemblies specifically targeted at Unix/Linux and Mac OS X operating systems. With this minimal background in mind, you're ready to install Mono itself. Obtaining and Installing Mono First, download the Mono installer for Microsoft Windows. When the download is complete, double click the executable to begin the installation process, accepting each of the default settings.
Examining Mono's Directory Structure By default, Mono installs under C:\Program Files\Mono-<version> (at the time of this article, the latest and greatest version of Mono is 1.1.15). Beneath that root you will find a number of subdirectories (etc, contrib, man, share) that may appear to be strangely named unless you have a background in Unix\Linux development (see Figure 1). In this article, you need only concern yourselves with the following subdirectories:
If all is well, you should see various details regarding the Mono runtime environment (see Figure 2).The Mono Managed Compilers Similar to the Microsoft's CLR distribution, Mono ships with a number of managed compilers:
Boo is a new object-oriented statically-typed programming language for the CLI that sports a Python-based syntax. Check out http://boo.codehaus.org for more details on the Boo programming language. Finally, as you might have guessed, ilasm.exe and ilasm2.exe are the Mono CIL compilers (the second of which supports .NET 2.0 language constructs). Working with the C# Compilers Mcs.exe was the first C# compiler for the Mono project, and it's fully compatible with C# 1.1 (in fact, mcs.exe is written in C#). Like the Microsoft C# command-line compiler (csc.exe) mcs.exe supports response files, a /target: flag (to define the assembly type), an /out: flag (to define the name of the compiled assembly), and a /reference: flag (to update the manifest of the current assembly with external dependencies). You can view all the options of mcs.exe using the following command.
Gmcs.exe (generic mcs.exe), as the name implies, is a version of mcs.exe that has support for .NET 2.0 specific C# language features (generics, covariance/contravariance, nullable types, partial types, etc) and references the .NET 2.0-based base class libraries. The command line options of gmcs.exe are identical to mcs.exe, which you can verify with the following command:
Given the presence of two C# compilers, you might naturally assume that only gmcs.exe can be used to build .NET applications that make use of the C# 2.0 language enhancements. In reality, mcs.exe is the first of the two compilers to support 2.0 features, which are then perfected and ported to gmcs.exe.The difference is that mcs.exe automatically references the .NET 1.1-based base class libraries, while gmcs.exe always references the .NET 2.0-based base class libraries. Given this, gmcs.exe will become the default compiler in a future Mono release leaving mcs.exe in the dust as a historical footnote.
|
| Building a .NET Code Library with Mono To illustrate Mono in action, you will begin by building a code library named CoreLibDumper.dll. This assembly contains a single class type named CoreLibDumper that supports a static method named DumpTypeToFile(). The method takes a string parameter that represents the fully-qualified name of any type within mscorlib.dll, and obtains the related type information via reflection, dumping the class member signatures to a local file on the hard drive. Listing 1 contains the complete code. The method in Listing 1 outputs a .txt file containing the type's details and named according to its fully qualified name. Thus, if the incoming string parameter is System.Threading.Thread, the method creates the output metadata in a local file named System.Threading.Thread.txt. While you could compile this file by specifying each required argument manually at the command line, it's much simpler to use a response file. To do so, create a new file named CoreLibDumper.rsp (in the same location as CoreLibDumper.cs) that contains the following command set:
You can now compile your library at the command line as follows:
This approach is functionally equivalent to the following (more verbose) command set:
Giving CoreLibDumper.dll a Strong NameMono supports the notion of deploying strongly-named and shared assemblies to the Mono Global Assembly Cache (GAC). To generate the necessary public/private key data, Mono provides the sn.exe command line utility, which functions more or less identically to Microsoft's tool of the same name. For example, the following command generates a new *.snk file (specify the -? option to view all the possible commands):
To tell the C# compiler to use the key data to assign a strong name to CoreLibDumper.dll, simply update your CoreLibDumper.rsp file with the additional command shown in bold text below:
Viewing the Updated Manifest with Monodis.exeBefore deploying the assembly to the Mono GAC, allow me to introduce the monodis.exe command-line tool, which is the functional equivalent of Microsoft's ildasm.exe. Using monodis.exe you can view the CIL code, manifest and type metadata for a specified assembly. In this case, you want to view the core details of the new (now strongly named) assembly via the -assembly flag. Figure 3 shows the result of the following command set:
Installing Assemblies into the Mono GAC Now that you have provided CoreLibDumper.dll with a strong name, you install it into the GAC using gacutil.exe. Just like Microsoft's tool of the same name, Mono's gacutil.exe supports options to install, uninstall, and list the current assemblies installed under the Mono GAC (in C:\Program Files\Mono-
If, after running the command, you open the \gac directory, you should find a new folder named CoreLibDumper (see Figure 4), which defines a subdirectory that follows the same naming conventions as Microsoft's GAC (versionOfAssembly__publicKeyToken).
|
| Building a Console Application in Mono Your first Mono client will be a simple console based application named ConsoleClientApp.exe. Create a new C# file named ConsoleClientApp.cs that contains the following code:
Notice that the Main() method in the preceding code simply prompts the user for a fully-qualified type name. The TypeDumper.DumpTypeToFile() method uses the user-entered name to dump the type's members to a local file. Next, create a *.rsp file that references CoreLibDumper.dll:
Finally, compile the executable using gmcs.exe as shown here:
Before you run this application under the Mono runtime, take a moment to rename the CoreLibDumper.dll assembly to DontUseCoreLibDumper.dll using Windows Explorer. The reason is that you've referenced a strongly-named assembly, and therefore wish to use the copy of CoreLibDumper.dll that resides in the GAC, not the local copy in the client's application directory.
For testing purposes, enter System.Threading.Thread at the prompt, and press the Enter key. The program will process the type, and create new file named System.Threading.Thread.txt containing the type's metadata definition. Figure 5 shows this file opened in NotePad.Before building a Windows Forms client, try the following experiment. Open the Windows Explorer and attempt to run your client application by double clicking on ConsoleClientApp.exe. You might be surprised to find that doing so causes a FileNotFoundException. At first glance you might assume this is due to the fact that you renamed CoreLibDumper.dll to DontUseCoreLibDumper.dll. However the true reason is because you just loaded ConsoleClientApp.exe into the Microsoft CLR! To run an application under Mono, you must pass it into the Mono runtime via mono.exe. If you do not, you will be loading your into the Microsoft CLR, which assumes all shared assemblies are installed into the Microsoft GAC located in the <%windir%>\Assembly directory. In fact, that wouldworkbut then you could only use the assembly from .NET applications.
|
| Building a Windows Forms Client Program Before continuing, be sure to rename DontUseCoreLibDumper.dll back to CoreLibDumper.dll. Next, create a new C# file named WinFormsClientApp.cs. This file defines two types, both of which make use of a few C# 2.0 language features, including static classes and anonymous methods. Listing 2 contains the complete code. To compile this Windows Forms application using a response file, create a file named WinFormsClientApp.rsp (shown below) and supply that as an argument to gmcs.exe as shown previously.
Finally, run your Windows Forms application via mono.exe:
Figure 6 shows the output.
Up until now, this article has shown you nothing regarding the .NET base class libraries or the C# programming language that you have not already seen from Microsoft's CLR. However, the importance of Mono becomes quite clear when you view Figure 7, which shows the same exact Windows Forms application running under SuSe Linux. So, you can compile and execute the same exact C# code shown during this article on Linux (or any OS supported by Mono) using the same Mono development tools. In fact, you can copy the assemblies built on here on Win32 to a new OS and run them directly, with no recompile or code modifications required. Just use the mono.exe utility on the target system to run the applications.
To wrap up and give you a path to proceed, Mono ships with a local help system, named Monodoc, which provides documentation of the Mono base class libraries and the C# programming language. You can launch this utility from a Mono command prompt or via the Start | All Programs | Mono As you look over the entries within MonoDoc, you will most certainly find a number of incomplete listings, because MonoDoc relies on the Mono community to provide the documentation of the base class libraries (in fact, you can contribute to the documentation from within MonoDoc itself!). Future articles in this series will dig deeper into the details of Mono development, but this should get you started, and ready for further exploration.
Andrew Troelsen is a .NET trainer and consultant for Intertech Training, a .NET and J2EE education and development company. He is the best-selling author of numerous books on .NET and COM (including the award winning C# and the .NET Platform) and speaks at numerous corporate and academic conferences around the country.
|
| DevX is a division of Jupitermedia Corporation © Copyright 2007 Jupitermedia Corporation. All Rights Reserved. Legal Notices |