Posted by & filed under Mono, Novell, Open-source, Personal. 4,072 views

So as I am boxing things up, preparing for the upcoming move, I stumble upon a lot of old documents, photos and knick knacks I accumulated over the years.

Once upon a time, you’ll remember, I was heading a team that was intent on writing a book about Mono. Addison Wesley had signed us up for a book called Linux Application Development with Mono and I was under contract for a five book series.

Beyond the first Mono book, we had planned on:

  • a book about Mac OS X development with Cocoa# and Mono
  • one about advanced Gtk# development
  • then one about migrating ASP.NET web and web services applications to Mono
  • and finally one about learning how to develop applications using a complete Open Source solution (OS, Desktop, IDE, tool chain)

The last one was my pet project, it sounded worth writing and interesting for college students or people looking to change careers and start developing using a free environment. We had authors lined up and pretty much signed for all those and books 2, 3 and 4 were to be written concurrently.

Though the project looked fun at the time, the team was loosing interest at the same time our editor at AW got laid off, we never heard back from Addison Wesley and let it become defunct.

Years after I wrote it, I still see a lot of people reading my Building a web browser with Mono (and Gecko) so I thought I’d share the first draft of the only chapter ever written for Linux Application Development with Mono:

Chapter 2 – The Mono Tool Chain

Introduction

Written by developers for developers, Mono was always destined to include a solid tool chain.

Though a lot of tools mimic the behavior of their .NET equivalent, as we???ll see in this chapter, the sheer diversity of contributions to the the Mono project brought a lot of innovation especially where developers need to scratch an itch, in typical open source fashion. In typical open source fashion as well, some projects re-created the wheel, were abandoned, rewritten three times and passed on.

In this chapter, we???ll cover the essential (including Integrated Development Environments, compilers and runtime, the superfluous we all want or need to use (profiler, debugger, documentation and packaging tools).

Application Development Cycle

With Mono, the simplest of applications only need three tools to build, an editor, a compiler and a runtime:

-INSERT GRAPHIC-

While I won???t do you the affront to include a ???hello world example??? (class HelloWorld {static void Main(){System.Console.WriteLine(???Hello World???);}}), I???ll tell you how to compile it:

Snow:~/dev/MAD ed$ mcs helloworld.cs

Pretty impressive, isn???t it ? I thought so. What we did here is take a bunch of C# files (one) and used the mono csharp compiler (mcs) to compile them (it). This test case if pretty simple despite its large number (one) of class files (.cs extensions). What did mcs build for us:

Snow:~/dev/MAD ed$ ls -l
total 16
-rw-r--r-- 1 ed ed 80 Jan 24 21:10 helloworld.cs
-rwxr-xr-x 1 ed ed 3072 Jan 24 21:18 helloworld.exe

One .exe file, something must be wrong. Let???s try to execute that binary file in Linux:

Snow:~/dev/MAD ed$ ./helloworld.exe
-bash: ./helloworld.exe: cannot execute binary file

That didn???t work. And the reason is that the Linux kernel doesn???t really know how to run an .exe file (more on .exe and .dll later). So we???ll have to use the mono runtime:

Snow:~/dev/MAD ed$ mono helloworld.exe
Hello World

Well, that was quite something. Or it would have been, had I shown you how to write an ???hello world??? application. Which I didn???t. So to recap, we???ve not looked at source code for an hello world application, then we compiled that source code using the mono csharp compiler (mcs) and ran the resulting application using the mono runtime.

Now, as you may have learned from the previous chapter, the mono runtime is quite language independent:

Imports System
Public Module modmain
Sub Main()
Console.WriteLine (???Hello World???)
End Sub

That???s Visual Basic, I didn???t write that. I looked it up on the Internet. Note that at this point, I have yet to write any piece of hello world application. It???s
in my contract. Now, to build this application, I am going to use the mono Visual Basic compiler, mbas:

Snow:~/dev/MAD ed$ mbas helloworld_basic.vb
MonoBASIC Compiler 1.1.13.2 - (c)2002, 2003, 2004, 2005 Rafael
Teixeira
--------
THIS IS AN ALPHA SOFTWARE.
--------
Compilation succeeded

Now and while mbas is alpha software (it has been since Chevrolet introduced the Chevette in 1974), it???s perfectly able to compile this simplistic
application. Because at this point, our new .exe fi le is just a Command Language Runtime (CLR) executable (with a little bit of VB.NET runtime magic
to let you in on a little secret), let???s use the mono runtime to run it:

Snow:~/dev/MAD ed$ mono helloworld_basic.exe
Hello World

No surprise here.

Application Autopsy

We made it, now we kill it and we open it up. As you saw in the first chapter, those executables we built, despite their name are neither DOS executables nor win32 executables, they???re made of some metadata and some .NET byte code, an intermediary language called IL, think of it as an object oriented assembly language for a machine that???s only virtual and that all those compilers (mcs, mbas, booc, …) can and do target.
So let???s see what???s inside.

Snow:~/dev/MAD ed$ cat helloworld.exe
MZ????@??? ?!?L?!This program cannot be run in DOS mode.
$PEL??C?
@@ ? O@?`
d H.text? `.rsrc?@@@.reloc
`
@B?% @@ Z N _CorExeMainmscoree.dll@ H!?!(
*.rp(
*BSJB
v1.1.4322p?#~(d#Strings?#US?#Blob?#GUIDG D
;S? ?? ?^ &?0?mscorlibObjectSystem.ctorConsole
WriteLinehelloworldhelloworld.exeHelloWorld-
MainHellow World?z\V4??o?~??`K??a~lkC??0?4VS_VERSION_
INFO????DVarFileInfo$Translation??StringFileInfo?007f04b0(Product-
Version $CompanyName $ProductName (LegalCopyright 8
Intern
alNamehelloworld,FileDescription Comments $FileVersion HOriginal-
Filenamehelloworld.exe,LegalTrademarks
0Snow:~/dev/MAD ed$

Not much luck here, the .exe fi les are quite undecipherable. Obviously this

}
.module helloworld.exe // GUID = {8F7E876F-1F91-4B60-AB17-
A9617E6C6B43}
.class private auto ansi beforefi eldinit HelloWorld
extends [mscorlib]System.Object
{
// method line 1
.method public hidebysig specialname rtspecialname
instance default void .ctor () cil managed
{
// Method begins at RVA 0x20ec
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void object::.ctor()
IL_0006: ret
} // end of method HelloWorld::instance default void .ctor ()
// method line 2
.method private static hidebysig
default void Main () cil managed
{
// Method begins at RVA 0x20f4
.entrypoint
// Code size 11 (0xb)
.maxstack 8
IL_0000: ldstr ???Hello World???
IL_0005: call void class [mscorlib]System.Console::
WriteLine(string)
IL_000a: ret
} // end of method HelloWorld::default void Main ()
} // end of class HelloWorld

Now that???s more interesting. No need to explain the whole piece of code but the main method is quite fascinating:

.method private static hidebysig
default void Main () cil managed
{
// Method begins at RVA 0x20f4
.entrypoint
// Code size 11 (0xb)
.maxstack 8
IL_0000: ldstr ???Hello World???
IL_0005: call void class [mscorlib]System.Console::
WriteLine(string)
IL_000a: ret
} // end of method HelloWorld::default void Main ()

There we can see the ???Hello World??? static string loaded on the stack (ldstr) and then a call made to the WriteLine method (the one with one string
parameter) of the System.Console object (which you???ll fi nd in the mscorlib assembly). ret as you???ll expect ends the method. Armed with that knowledge, you???ll quickly see that the fi rst method is the default constructor for the Helloworld object, that does nothing more than call its parent???s constructor.

So we???ve disassembled the application, let???s re-assemble it:

Snow:~/dev/MAD ed$ ilasm /output:frankenstein.exe helloworld.exe
dis
Assembling ???helloworld.exe.dis??? , no listing fi le, to exe -->
???frankenstein.exe???
Operation completed successfully
Snow:~/dev/MAD ed$ mono frankenstein.exe
Hello World

Indeed, the operation was completed successfully and our executable re-created from its corpse.

Snow:~/dev/MAD ed$ mono --verbose helloworld.exe
Method (wrapper managed-to-native) System.Object:__icall_wrapper_
mono_thread_interruption_checkpoint () emitted at 0x4c8048 to
0x4c8108 [helloworld.exe]
Method (wrapper managed-to-native) System.Object:__icall_wrapper_
mono_thread_force_interruption_checkpoint () emitted at 0x4c8110
to 0x4c81ec [helloworld.exe]
....
Method System.Collections.Hashtable:set_comparer (System.Collections.
IComparer) emitted at 0x760330 to 0x760360 [helloworld.exe]
Method System.Runtime.Remoting.Contexts.Context:Finalize () emitted
at 0x760368 to 0x7603b8 [helloworld.exe]

Tools

Now we???ve played around a bit with compilers, runtime, dissasemblers, assemblers, debuggers and profi lers, it???s time to get serious. Let???s examine all of these and others more extensively

Post Mortem

And this is where it ended, unfortunately. We had big plans (see the outline of my chapter below) but they never came to fruition. Linux Applicaiton Development with Mono could have been a great book but, heh, it happens. Le roi est mort, vive le roi !

Outline of the chapter

=IDE=
== MonoDevelop ==
== X-Develop ==
== SharpDevelop ==
== Visual Studio ==
== vi & emacs ==
=Compilers=
== mcs ==
== mbas ==
== other compilers ==
=Runtime=
== mono ==
== mini ==
=Dis/assembler, profi ler, debugger=
=P/Invoking and embedding Mono=
=Bundles, packaging=
=Building applications =
== Makefi les ==
== autotools ==
== NANT ==
== Ant ==
== Visual Studio .csproj fi les ==
== MSBuild ==
=Documentation tools =
== NDoc ==
== Monodoc ==