# DotGNU Portable.Net FAQ

Rhys Weatherley, rweather@southern-storm.com.au.
Last Modified: $Date: 2004/08/05 06:18:13 $

Copyright © 2001, 2002, 2003, 2004 Southern Storm Software, Pty Ltd.
Permission to distribute unmodified copies of this work is hereby granted.

## Index

1. What is DotGNU Portable.NET?
1.1. What is pnet?
1.2. What is pnetlib?
1.3. What is treecc?
1.4. What is PNetMark?
1.5. What is pnetcurses?
1.6. What is cscctest?
1.7. What is pnetC?
1.8. What is ml-pnet?
1.9. What do all these acronyms mean? IL, CLI, CLR?
2. Installing DotGNU Portable.NET
2.1. Where can I get the most recent version of DotGNU Portable.NET?
2.2. How do I access the source via CVS?
2.3. How do I install DotGNU Portable.NET?
3. Using the runtime engine
3.1. How do I run IL programs?
3.2. Can I avoid typing "ilrun"?
3.3. I've registered "ilrun", but it is running the wrong version. Why?
3.4. Can I use "ilrun" and Wine together?
4. Compiler questions
4.1. How do I use the C# compiler?
4.2. How do I use the C compiler?
4.3. Why not write the compiler tools in C#?
4.4. If the compiler was written in C#, wouldn't reuse be easier?
4.5. How do I write a compiler plug-in?
4.6. I've heard that you can compile C# to the JVM. Is that correct?
4.7. Why don't you use gcc as the basis for your C# compiler?
4.8. What does "cscc" stand for?
4.9. What other languages are supported by "cscc"?
4.10. Can I compile for .NET Framework 1.1?
5. System.Windows.Forms
5.1. Can I use System.Windows.Forms with DotGNU Portable.NET?
5.2. How is the System.Windows.Forms implementation structured?
5.3. How do I write a new System.Windows.Forms toolkit?
5.4. How do I detect the platform to launch my toolkit?
5.5. What other graphical toolkits are there?
6. Other tools
6.1. How do I assemble .il files?
6.2. How do I disassemble IL binaries?
6.3. Does your disassembler and assembler support round-tripping?
6.4. How do I convert resources?
6.5. How do I extract documentation from C# sources?
6.6. Can I build applications without "make"?
6.7. What other tools do you have?
7. Copyright issues
7.1. What is the license on the C# library?
7.2. Who owns the Copyright on patches?
8. How can I help?
8.1. What areas need the most work?
8.2. What is the latest status of pnetlib?
8.3. What else is there?
8.4. Do you have a mailing list for developers?
9. Versions, patches, etc
9.1. What is with the version numbers?
9.2. I have a patch. What should I do now?
9.3. What coding conventions should I follow?
10. Standards
10.1. Where are the ECMA standards?
10.2. Why do you have more classes than ECMA specifies?
10.3. Can I build the ECMA-specified "Compact" and "Kernel" profiles?
11. Other .NET efforts
11.1. What is Mono?
11.2. What is OCL?
11.3. What is Rotor?
12. Other random questions
12.1. Can I use ADO.NET with DotGNU Portable.NET?
12.2. Can I use ASP.NET with DotGNU Portable.NET?
12.3. Why doesn't my C++ application work that I built with Visual Studio.NET?
12.4. Why don't you just use Java?
12.5. Isn't C# just a cheap knock-off of Java?

## 1. What is DotGNU Portable.NET?

DotGNU Portable.NET is a project under the DotGNU meta-project. Its goal is to build a suite of free software tools to build and execute Common Language Infrastructure (CLI) applications. The initial target platform is GNU/Linux, but it has been known to work under Windows, NetBSD, FreeBSD, Solaris, and MacOS X, amongst others. It also runs on a variety of CPU's including x86, PPC, ARM, Sparc, s390, Alpha, ia-64, and PARISC.

DotGNU Portable.NET is built in accordance with the requirements of the GNU Project.

DotGNU Portable.NET is focused on compatibility with the ECMA specifications for CLI and extensions as defined by the .NET Framework SDK. There are other projects under the DotGNU meta-project to build other necessary pieces of infrastructure, and to explore non-CLI approaches to virtual machine implementation. See `http://www.dotgnu.org/` for more information on DotGNU.

### 1.2. What is pnet?

DotGNU Portable.NET contains a runtime engine, C# compiler, and a host of useful development tools, all written in C. This package is generally referred to as "`pnet`".

### 1.2. What is pnetlib?

The C# system library was split off from the main source distribution during the early phases of development to create the "`pnetlib`" package. It contains implementations of the major C# class libraries, including "`mscorlib.dll`", "`System.dll`", "`System.Xml.dll`", "`System.Drawing.dll`", "`System.Windows.Forms.dll`", etc.

### 1.3. What is treecc?

Treecc is a aspect-oriented programming tool that we wrote to assist in the development of DotGNU Portable.NET's compiler, "`cscc`". It complements flex and bison by providing support for abstract syntax tree creation and manipulation.

Treecc performs most of the housekeeping within the core of the compiler, allowing the programmer to concentrate on the specifics of language implementation. A fuller account of how treecc works can be found at its Web site, `http://www.southern-storm.com.au/treecc.html`.

Other tools, such as Antlr, do have similar functionality, but we found it more convenient to write our own tool. We needed something that worked with C and which could perform a large amount of error-checking on the abstract syntax tree definitions. No other tool provided the right combination.

### 1.4. What is PNetMark?

PNetMark is a benchmarking tool for Common Language Runtime (CLR) environments. It is loosely based on the techniques used by the CaffeineMark to benchmark Java. The purpose of this tool is to identify areas of DotGNU Portable.NET that may need further attention. The `README` file within the PNetMark distribution contains additional information on running the benchmark.

You may be tempted to run PNetMark against the Microsoft CLR. If you do, you cannot tell the author of the benchmark, or anyone else for that matter, what the results are. The following is an excerpt from Microsoft's End User License Agreement (EULA) for their .NET Framework SDK redistributables:

> Performance or Benchmark Testing. You may not disclose the results of any benchmark test of either the Server Software or Client Software to any third party without Microsoft's prior written approval.

Thus, you can run the benchmark if you like, but you must keep the results to yourself. If you don't like this, then you will have to take it up with Microsoft's lawyers.

### 1.5. What is pnetcurses?

Pnetcurses is an example package, demonstrating how to wrap up an existing system library (ncurses in this case) using the PInvoke mechanism.

The package also includes the infamous "Curse of Frogger" video game, written in C# and utilising ncurses to provide display output.

### 1.6. What is cscctest?

The regression test suite for the C# compiler is distributed via CVS as the module "`cscctest`".

### 1.7. What is pnetC?

Since version 0.4.4 of DotGNU Portable.NET, the cscc compiler has had support for compiling C programs. The companion libc implementation for the C compiler is called "`pnetC`". The code is based on glibc.

### 1.8. What is ml-pnet?

Since version 0.5.8 of DotGNU Portable.NET, we have distributed some of the Mono upper-level libraries in a form that can be easily compiled and used with our CLI implementation. The source code is Mono's, but the build scripts have been altered to use our tools.

### 1.9. What do all these acronyms mean? IL, CLI, CLR?

IL
  Intermedate Language. This is the bytecode format that is used to represent compiled programs. It has sufficient instructions to support many programming languages, including C#.
CIL
  Common Intermedate Language. This term is used in the ECMA standards. Prior to ECMA standardisation, it was known as IL. We use the two acronyms interchangeably.
MSIL
  Microsoft Intermediate Language. This is exactly the same as CIL, but some media reports have called it "MSIL" for some reason.
CTS
  Common Type System. The standard type system that is used to represent programming language constructs such as objects and types. A language doesn't have to use the CTS, but doing so improves interoperability.
CLS
  Common Language Specification. A set of conventions for types and libraries that promote interoperability between programming languages.
CLR
  Common Language Runtime. The engine that executes CIL programs. In DotGNU Portable.NET's case, this is the "`ilrun`" program.
CLI
  Common Language Infrastructure. The complete system, comprising CIL, CTS, CLS, and CLR.
C#
  Pronounced "C-Sharp". The primary programming language that is used with the CLI, but by no means the only such language.
PE/COFF
  Portable Executable / Common Object File Format. This is the binary format used by 32-bit Windows to represent compiled applications. The CLI extends PE/COFF with new sections containing CIL definitions.
ECMA
  European Computer Manufacturer's Association. The standards body that Microsoft has chosen to standardise CLI.

## 2. Installing DotGNU Portable.NET

### 2.1. Where can I get the most recent version of DotGNU Portable.NET?

The latest release version is always available from the following Web site:

> `http://www.southern-storm.com.au/portable_net.html`

### 2.2. How do I access the source via CVS?

All of the DotGNU Portable.NET code is available via CVS from Savannah, `http://savannah.gnu.org/`. The main project Web page is at `http://savannah.gnu.org/projects/dotgnu-pnet/`, and the CVS instructions are at `http://savannah.gnu.org/cvs/?group_id=353`.

The repository name for DotGNU Portable.NET is "`dotgnu-pnet`", and it contains six modules: "`pnet`", "`pnetlib`", "`pnetC`", "`treecc`", "`cscctest`", and "`ml-pnet`".

When reporting bugs, it is best to check against the CVS version first, as we may have already fixed the problem since the last release.

### 2.3. How do I install DotGNU Portable.NET?

There are 3 main components that you must install in the following order to use DotGNU Portable.NET:

> `treecc`
> `pnet`
> `pnetlib`

And there are 3 optional components:

> `pnetC`
> `ml-pnet`
> `cscctest`

You will need "`pnetC`" if you wish to use the C compiler, and "`cscctest`" if you want to help develop the DotGNU Portable.NET compiler suite. You may need "`ml-pnet`" if you wish to use Mono libraries such as "`System.Data`".

The "`cscctest`" module is only available via CVS because it changes very often - always use the most recent CVS version of "`pnet`" when performing compiler regression tests.

You typically unpack and install each component as follows:

> `gunzip -d <name-version.tar.gz | tar xvf -
> cd name-version
> ./configure
> make
> make install`

See the "`README`" and "`HACKING`" files (where present) in each distribution for further information on install configuration options.

## 3. Using the runtime engine

### 3.1. How do I run IL programs?

IL programs are executed using the "`ilrun` program, as follows:

> `ilrun hello.exe`

The "`.exe`" extension is not required: you can rename the program to "`hello`" if you wish.

If the IL program has command-line options, they can be supplied after the name of the IL executable:

> `ilrun getenv.exe PATH`

### 3.2. Can I avoid typing "ilrun"?

If your operating system uses the Linux kernel, and you have root access, then you can avoid typing "`ilrun`" to execute programs from the command-line.

You must first register "`ilrun`" with the Linux kernel, by executing the following command as root:

> `ilrun --register`

Then you can run programs as follows:

> `chmod +x hello.exe
> ./hello.exe`

This will also work if you rename "`hello.exe`" to "`hello`", and then place it somewhere on your `PATH`.

To unregister "`ilrun`", execute the following command as root:

> `ilrun --unregister`

Note: registration will only work with the Linux kernel (versions 2.2 and later), and when you are logged in as root.

If you prefer to start and stop services with "`init.d`", you can use the script "`pnet/doc/init.d-pnet`" from the source code. Copy it to "`/etc/init.d/pnet`". The script uses "`/usr/local/bin/ilrun`" to register the engine, and it is designed for the RedHat distribution. Minor modifications may be required for other install locations and distributions.

### 3.3. I've registered "ilrun", but it is running the wrong version. Why?

When you register "`ilrun`", it attempts to construct the full path of the engine to pass to the kernel. Normally it does this by searching the `PATH`. You can specify an explicit pathname as follows:

> `ilrun --register /usr/local/bin/ilrun`

### 3.4. Can I use "ilrun" and Wine together?

Because IL programs have a similar format to regular PE/COFF Windows executables, it is not always clear whether a program should be executed with "`ilrun`" or with "`wine`".

If you pass a regular Windows executable to "`ilrun`", it will hand off control to "`wine`" to run the program. It uses the first executable called "`wine`" on the `PATH`.

If your Wine installation is not on the `PATH`, you can set the `WINE` environment variable to specify its location.

Wine also has facilities for registering itself with the Linux kernel to run PE/COFF executables. Only one PE/COFF handler can be registered at a time. It is important that "`ilrun`" be registered as the primary PE/COFF handler, because Wine does not currently know how to hand off IL programs to "`ilrun`".

## 4. compiler questions

### 4.1. How do I use the C# compiler?

The C# compiler is called "`cscc`". It's command-line syntax is very similar to that of gcc. For example, to compile a simple program, you might use:

> `cscc -o hello.exe hello.cs`

The following are the most common command-line options for the compiler:

> `-o file`
>   Write the compiler's output to "`file`".
> `-Dname`
>   Define the pre-processor symbol "`name`" to "`true`".
> `-Ldir`
>   Add "`dir`" to the path to be searched for libraries.
> `-lname`
>   Add "`name.dll`" to the list of libraries to add to the link line.
> `-vv`
>   Print the names of other commands that the compiler executes (plug-ins, assembler, and linker).

Note: the compiler is still a work in progress, so some language features may not work as expected. Contact the authors if you find any such problems.

### 4.2. How do I use the C compiler?

Compiling C programs is very similar to compiling C#:

> `cscc -o hello hello.c`

The usual "`gcc`" command-line options can be used, including pre-processor and linker options.

The C compiler generates pure IL bytecode, with no dependencies upon external native libraries. The ABI (Application Binary Interface) adapts itself to the particulars of the runtime engine that executes the program. You must have `pnetC` installed to compile and run C programs.

More information on the ABI and the C environment can be found in the "`pnet/doc`" directory of the source.

### 4.3. Why not write the compiler tools in C#?

The main reason is the "chicken and egg" problem. We wouldn't have been able to run the compiler until the runtime engine and the full C# system library were fully written.

While it might have been possible to bootstrap off Microsoft's engine and compiler, there was an open legal question in doing this. We wanted to avoid any "booby traps" that may exist in Microsoft licenses that prevent the free development of DotGNU Portable.NET. It is safer to avoid dependence upon Microsoft tools.

Writing the C# compiler in C means we are bootstrapping from gcc, and not Microsoft's compiler, which should avoid any legal problems.

The second reason for writing the compiler in C is security. Independent third parties can inspect the C# compiler source for security problems, and then compile the code with their (hopefully) trusted version of gcc to get a trusted C# compiler.

Writing the compiler in C# would introduce a tough trust problem: you must trust that the bootstrapped binary version of the compiler does not have any back doors. Inspecting the source code is not sufficient to perform a full security audit.

### 4.4. If the compiler was written in C#, wouldn't reuse be easier?

Reuse is the stated reason for why the Mono project is writing all of their tools in C#. Should the Mono project succeed at this goal, then their components should be directly reusable by anyone running DotGNU Portable.NET.

However, nothing in DotGNU Portable.NET's cscc compiler prevents its reuse in other compilers. As long as those compilers are themselves written in C, and covered under the GNU General Public License.

Cscc is architected so that new languages can be easily added as plug-ins. The plug-in converts source code into IL assembly code, which cscc processes to produce the final executable. Plug-ins can either do this conversion their own way, or reuse the existing code to do most of the hard work for them.

### 4.5. How do I write a compiler plug-in?

The "`pnet/doc/pnettools.texi`" file describes the command-line syntax that you must support if you want to write your own plug-in from scratch, without using any of the existing code.

It is not essential that the plugin be written in C. You could write it in C#, Java, Python, or assembly code if you wish. The only requirement is that the plugin can be launched with the "`exec`" system call. You may need to wrap the plugin in a small shell script to achieve this.

### 4.6. I've heard that you can compile C# to the JVM. Is that correct?

Yes. The cscc compiler is architected so that it can compile to either IL or JVM bytecode. Adding other output formats would be quite easy. There is still some work to be done in assembling JVM bytecode, but most of the support code is in place. Volunteers are welcome to help us complete the JVM back-end.

### 4.7. Why don't you use gcc as the basis for your C# compiler?

A common question that arises is why we aren't using gcc to compile C# code to IL. Strategically, we would like to be able to reuse all of the good work that has gone into gcc. The DotGNU Project currently has an open request for someone to volunteer to modify gcc to generate IL bytecode.

However it isn't quite as easy as it looks. The following script of a hypothetical discussion provides a blow by blow account of why this is so hard. This script is based in part on e-mails we have exchanged with users in the past.

Why don't you add C# to the list of languages gcc supports?

Because it won't solve the problem that we need to solve.

Initially we need a C# compiler that can generate IL bytecode for the .NET platform. Later, we may need a C# compiler that can generate native code as well, but that is optional.

Putting a C# parser on the front of gcc would give us a native compiler, but it won't give us an IL bytecode compiler.

So what? Add an IL bytecode backend to gcc, and you'll solve your problem, and also be able to compile C, C++, Fortran, etc, to .NET.

This is not as easy as it looks. Gcc is divided into a number of phases: parsing, semantic analysis, tree-to-RTL conversion, RTL handling (including optimization), and final native code generation.

The hard part is RTL (Register Transfer Language). This part of gcc is hard-wired to generate code for register-based CPU's such as i386, PPC, Sparc, etc. RTL is not designed for generating code for stack-based abstract machines such as IL.

Also, RTL loses a lot of the type and code structure information that IL needs in the final output file. By the time RTL gets the code, information about whether a value is an integer or an object reference is mostly lost. Information about the class structure of the code is lost. This information is critical for correct compilation of C# to IL.

But hang on a second! Gcj, the Java back-end for gcc, does stack machines! Why not do something like that?

Err ... no it doesn't. The Java bytecode stuff in gcj is not organised as an RTL back-end.

When gcj compiles Java, it performs parsing and semantic analysis in the front-end, like the other supported languages. Then the parse tree is sent in one of two different directions.

If gcj is compiling to native, the parse tree is handed to the RTL core of the compiler, and it takes over.

If gcj is compiling to bytecode, the parse tree is handed to a completely separate code generator that knows about Java bytecode.

Because gcj does NOT implement a bytecode RTL back-end for gcc, it cannot compile C, C++, etc down to bytecode. Java bytecode is a special case that only works for the Java front-end.

But what about egcs-jvm? Doesn't it compile C to Java bytecode?

It's a hack. The code that it generates is horrible, and does not conform to the usual conventions that the JVM requires. If one compiled Java code using this back-end, it wouldn't work with normal Java code due to the differences in calling conventions and what-not.

The biggest problem that the author of egcs-jvm he had was trying to work around the register machine assumptions in the code. The result wasn't pretty. He has said that it would be easier to throw the JVM away and invent a register-based abstract machine than try to make gcc generate efficient stack machine code.

Isn't there a gcc port to the Transputer, which is stack-based?

Yes there is, for an older version of gcc (2.7.2). The source can be found here.

It appears to compile the code to a pseudo-register machine, and then fixes up the code to be stack based afterwards. It takes advantage of some register stack features in gcc that egcs-jvm didn't use.

The Transputer is still a traditional CPU despite being stack-based. The gcc port puts pointer values into integer pseudo-registers, which would violate the security requirements of IL.

The i386 gcc port uses a regular set of registers for integer/pointer values, and a register stack for floating point values. The Transputer port uses two register stacks: one for integer/pointer values, and the other for floating point values. It may be possible to use three register stacks for IL: one for integer values, another for pointer values, and a third for floating point values.

However, this still may not give a useful result. This fixes the security problems for the pseudo-registers, but it doesn't fix the security problems for memory. RTL assumes that main memory is a flat, untyped, address space, where any kind of value can be stored in any word. Partitioning main memory into separate types may not be possible without a rewrite of RTL.

OK, so do something similar to gcj for C#. Use two code generators. That would work right?

Yes it would, except for one small catch.

Because there are so many people who don't understand how gcc works, they will assume that they can compile C and C++ to IL bytecode after we release the C# patches.

Then they will discover that this isn't the case and will get extremely angry that we didn't build what they thought we were building. *sigh*

Now matter how we attack the problem, we will end up having to write an IL bytecode backend for RTL, which is extremely difficult because of the various assumptions in the code.

Realistically, someone with a great deal of gcc knowledge needs to go into the gcc core, rip RTL completely out, throw it away, and replace it with something that knows about both register machines and stack machines.

Alternatively, someone could create a STL (Stack Transfer Language), that passes all languages through a separate code generator that knows about stack machines. Then we can write STL back-ends for IL and JVM bytecode. Both gcj and DotGNU would benefit from this.

We're not buying it. It's not as hard as you think.

Fine. Prove us wrong. Download the gcc sources and have at it. The Transputer port may be a good place to start to get ideas, or it may not.

### 4.8. What does "cscc" stand for?

Originally, "`cscc`" was short for "C Sharp Compiler Collection". However, since the introduction of the C language front-end, that name is no longer 100% accurate.

After much discussion on alternative names, it was eventually decided that the acronym for the compiler would still be "`cscc`", but that the correct pronounciation for this acronym would henceforth be "Gargle Blaster Foo Muncher".

### 4.9. What other languages are supported by "cscc"?

There are currently early versions of compiler plug-ins for Java and Visual Basic .NET, as well as some support for Generic C#. Volunteers are welcome to help us finish these languages.

### 4.10. Can I compile for .NET Framework 1.1?

When `pnetlib` is installed, it will normally be configured to build and run applications for the most recent version of the .NET Framework SDK (beta or final). If you compile applications against this version, they may not run on older versions of the .NET Framework.

This is a problem with the way that Microsoft's CLR loads assemblies. If the assembly version numbers do not match exactly, their CLR will refuse to load an application. DotGNU Portable.NET uses a different approach: if the exact version is not available, it will fall back to the default assembly of the same name. We believe that our approach is better because it backs off gracefully rather than exploding in the face of unknown version numbers.

If you wish to build applications for users who have an older version of Microsoft's .NET Framework installed, you can reconfigure `pnetlib` with a different profile. For example:

> `./configure --with-profile=default1.1`

Any applications that you compile thereafter will be appropriately versioned to run on the .NET Framework 1.1.

You can also install multiple versions of `pnetlib` side by side, so that applications will always run against the correct version of the library:

> `./configure
> make
> make install
> make distclean
> ./configure --with-profile=framework1.1
> make
> make install`

This will install the full version as the default, and the 1.1 compatible version as an auxillary installation. See section 10.3 for a list of available profiles.

## 5. System.Windows.Forms

### 5.1. Can I use System.Windows.Forms with DotGNU Portable.NET?

Yes, since version 0.5.8 of DotGNU Portable.NET in mid-2003.

An advantage of our implementation of System.Windows.Forms is that we don't try to wrap up third party widget sets like Gtk, Qt, Wine, etc. Instead, we provide a basic drawing layer and then render the controls ourselves. The approach is similar to Java Swing, in that all controls are implemented in pure C#.

This approach should allow us to emulate the Windows visual appearance and behaviour more closely and portably than other approaches because we don't need to work around the quirks in foreign toolkits. Our implementation has been known to run on x86, PPC, and ARM based GNU/Linux systems, as well as MacOS X. See the DotGNU web site for current screenshots.

However, there are likely to be some strange Windows quirks that can theoretically only be provided by a Wine-based approach. Until recently (mid-2004), the Mono project was taking this route, and it ended up being very difficult to maintain. They have since switched to a pure managed C# approach like DotGNU Portable.NET.

Needless to say, we encourage programmers to write C# code in a portable fashion, avoiding quirky features of particular platforms.

### 5.2. How is the System.Windows.Forms implementation structured?

The DotGNU Portable.NET Forms implementation is structured into three layers, which are found in the source directories "`System.Drawing`", "`System.Drawing/Toolkit`", and "`System.Windows.Forms`".

`System.Drawing`
  Provides the basic drawing functionality, emulating the Windows GDI layer as faithfully as possible. When drawing to a control, use the definitions in "`System.Drawing.Graphics`".
`System.Drawing/Toolkit`
  Defines an interface to primitive drawing toolkits. Toolkits provide simple line/text/etc drawing (`IToolkitGraphics`), plus a simple window mechanism (`IToolkitWindow`).

  There may be multiple toolkits in the system, each providing drawing functionality in a different manner. The current toolkits include "`System.Drawing.Xsharp`", which wraps around the DotGNU Portable.NET "`Xsharp`" library; and "`System.Drawing.Win32`", which wraps up the native Win32 API under Windows.

`System.Windows.Forms`
  Builds upon the primitive drawing and window facilities from "`System.Drawing`" and "`System.Drawing/Toolkit`" to implement the various controls, forms, dialogs, etc, that are defined by the Forms API.

The file "`pnetlib/System.Windows.Forms/HACKING`" in the source code contains more information on developing for our implementation of System.Windows.Forms.

### 5.3. How do I write a new System.Windows.Forms toolkit?

Most of the time you will not need to care about the toolkit layer. If you do wish to port our System.Windows.Forms implementation to a new platform, you need to provide a new assembly called "`System.Windows.Foo`", where "`Foo`" is the name of the graphical toolkit on the system.

The most important class in this new assembly is "`System.Drawing.Toolkit.DrawingToolkit`". This class is instantiated by "`System.Drawing.Toolkit.ToolkitManager`" when graphical operations are requested.

The toolkit class implements "`IToolkit`" to create windows, graphical drawing contexts, pens, brushes, etc. All other toolkit classes hang off this one. You will normally use PInvoke to access the underlying operating system's graphical capabilities.

See the existing toolkits for hints on how to implement a new one, or ask for assistance on the "`developers@dotgnu.org`" mailing list.

### 5.4. How do I detect the platform to launch my toolkit?

Once you have written a new toolkit, you will need to instruct DotGNU Portable.NET to use it instead of the default ("`System.Drawing.Win32`" under Windows and "`System.Drawing.Xsharp`" everywhere else).

For testing, you can set the "`PNET_WINFORMS_TOOLKIT`" environment variable:

>     export PNET_WINFORMS_TOOLKIT=Foo

To make the detection permanent, you will need to modify the "`System.Drawing.Toolkit.ToolkitManager`" class. The following code will return a string that uniquely identifies the platform:

>     String platform = Environment.OSVersion.ToString();

### 5.5. What other graphical toolkits are there?

Qt#
  http://qtcsharp.sourceforge.net
Gtk#
  http://gtk-sharp.sourceforge.net
wx.NET
  http://wxnet.sourceforge.net/
CsGL
  http://csgl.sourceforge.net/
C#-SDL
  http://cs-sdl.sourceforge.net/

## 6. Other tools

### 6.1. How do I assemble .il files?

If you have an IL assembly source file, you can convert it into an IL binary using the "`ilasm`" program. For example:

> `ilasm -o hello.exe hello.il`

The assembler supports the format described in the ECMA specifications.

### 6.2. How do I disassemble IL binaries?

If you have an IL binary, such as a "`.exe`" or a "`.dll`" assembly, you can convert it back into IL assembly source as follows:

> `ildasm hello.exe > hello.il`

### 6.3. Does your disassembler and assembler support round-tripping?

"Round-tripping" is a feature of Microsoft's disassembler and assembler that allows a program to be disassembled, modified in some fashion, and then re-assembled, without having access to the original source.

Our disassembler and assembler don't support round-tripping, although they use similar formats. If someone wants to submit round-tripping patches, then that would be great. But it isn't a high priority for us.

It is debatable whether round-tripping is useful in a Free Software environment. Presumably you already have the original source for the application, and can make the modifications there and recompile.

### 6.4. How do I convert resources?

The "`resgen`" program can be used to convert string resources between a variety of formats: text resources, IL binary resources, XML resources, and GNU gettext resources ("`.po`"). For example:

> `resgen hello.txt hello.resources`

This converts the text resources in "`hello.txt`" into IL binary resources in the file "`hello.resources`". They can be linked against an application as follows:

> `cscc -o hello.exe -fresources=hello.resources hello.cs`

### 6.5. How do I extract documentation from C# sources?

The "`csdoc`" program is very similar to the C# compiler, "`cscc`", except that it outputs XML documentation files instead of IL binaries. For example:

> `csdoc -o hello.xml hello.cs`

The tools must partially compile the input source to collect up the information that it requires. Therefore, it is usually best to ensure that your program compiles with "`cscc`" before attempting to use "`csdoc`".

The output XML file uses the same format as the ECMA's "`All.xml`" file. You can use the programs "`csdoc2html`" and "`csdoc2texi`" to convert the XML file into HTML and Texinfo, respectively.

### 6.6. Can I build applications without "make"?

Some people don't like "`make`" for some reason. They prefer simpler build tools. The "`csant`" program takes an XML file as input, which describes what to build, and then runs the C# compiler to build the requested targets.

The "`csant`" program is similar to, but not quite as powerful as NAnt (`http://nant.sourceforce.net/`). But because "`csant`" is written in C, it can be very useful for bootstrapping C# applications without the aid of a CLR.

### 6.7. What other tools do you have?

We are always adding new utilities as we need them. The following is a sampling:

`csdoc2html`
  Convert XML documentation into HTML.
`csdoc2texi`
  Convert XML documentation into Texinfo.
`csdoc2stub`
  Generate stub C# code from XML documentation.
`csdocvalil`
  Validate an IL binary against an XML documentation file that describes what it should be implementing.
`csunit`
  A C# application that assists with automated regression testing of "`pnetlib`".
`ilalink`
  Link IL object files and libraries together to form an output assembly. This is normally called automatically by the compiler.
`ildd`
  Displays the dependencies that an IL application has on other assemblies and PInvoke functions.
`ildiff`
  Compare two IL binaries and show their differences.
`ilfind`
  Find named symbols within an IL binary.
`ilheader`
  Generates .h files from C# assemblies, that allows them to be imported and called from C.
`ilnative`
  Print information for all native methods that are declared in an IL binary. Native methods include internalcall's and PInvoke's.
`ilsize`
  Print the size of the code, metadata, resource, and other sections in an IL binary.
`ilverify`
  Run the bytecode verifier over an IL binary.

## 7. Copyright issues

### 7.1. What is the license on the C# library?

The license on the C# library, "`pnetlib`", is distributed under a modified GPL license:

> The source code for the library is distributed under the terms of the GNU General Public License, with the following exception:

> As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this library. If you modify this library, you may extend this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version.

We call this the "GPL plus linking exception", which is also used by the GNU Classpath project (`http://www.gnu.org/software/classpath/classpath.html`.

Earlier versions of the C# library's license had the following exception:

> If you link this library against your own program, then you do not need to release the source code for that program. However, any changes that you make to the library itself, or to any native methods upon which the library relies, must be re-distributed in accordance with the terms of the GPL.

It is our intention to keep the exception synchronized with GNU Classpath, so that all similar libraries in the GNU Project have consistent licensing.

### 7.2. Who owns the Copyright on patches?

The DotGNU Project is working on guidelines for explicit Copyright assignment. When they have been finalised, they will replace the guidelines below.

For small patches, Copyright will automatically revert to the primary maintainer for the files or directories being patched. If you don't want this to happen, then don't submit the patch.

For larger patches, you should explicitly assign the Copyright to the primary maintainer or the Free Software Foundation. We prefer that you assign the Copyright to the maintainer of the files you are patching, to prevent dilution of the Copyright on those files. Should problems arise in the future, it is easier to replace an entire file than edit the contents of a single file.

To assign the Copyright, include a notice in the patch comments as to how you want the Copyright assigned. If you don't include such a comment, we will need to contact you via e-mail to get your permission.

The GNU Project has strict guidelines about Copyright assignment. The goal is to have a predictable Copyright on each GNU package, should legal action ever need to be taken to defend the GPL. If you don't agree to these guidelines, then don't submit the patch.

## 8. How can I help?

### 8.1. What areas need the most work?

The biggest area that needs to be tackled is the C# library, "`pnetlib`". Pick a class, any class, implement it, and send us the changes. Or write a test case for our regression test suite. See the question on "Standards" for information on obtaining the ECMA class library documentation.

We could also use some assistance with documentation of the API's within the current code base. Mostly this involves converting the contents of the ".h" files in the "include" directory into Texinfo-compatible documentation and examples.

The runtime engine and the C# compiler are also works in progress. The code is well-commented with "`TODO`" in all of the places where there is still stuff to be done.

### 8.2. What is the latest status of pnetlib?

The latest status of pnetlib can be viewed at the following Web page:

> `http://www.dotgnu.org/pnetlib-status/`

This page is updated periodically based on the compiled pnetlib binaries.

### 8.3. What else is there?

If you find an interesting problem to work on in the DotGNU Portable.NET codebase, then work on it for a bit, and send us the patches. If it is the kind of code we're looking for, we'll discuss further collaboration.

Even if it isn't on the core CLI parts of DotGNU Portable.NET, it may still be interesting. There are number of people working on Java and JVM related extensions, for example.

Also look at the "`HACKING`" files in the "`pnet` and "`pnetlib`" distributions. These provide the most up to date information on how to help out.

### 8.4. Do you have a mailing list for developers?

All discussion of DotGNU Portable.NET happens on the "`developers@dotgnu.org`" mailing list. See `http://www.dotgnu.org/` for subscription details.

## 9. Versions, patches, etc

### 9.1. What is with the version numbers?

Versions 0.1.2 and prior used a version numbering scheme that Rhys Weatherley concocted out of thin air. After the move to the Savannah CVS repository, the following conventions were adopted:

The working CVS version will always end in an odd number, and the released version will always end in an even number. For example, "0.1.3" is the working version that will lead up to the "0.1.4" release version.

Version numbers typically jump to the next-higher level when the last component reaches 9. e.g. "0.2.9" is the working version for the "0.3.0" release version. Major version jumps may also occur when major components have been completed.

This convention will be adopted across all DotGNU Portable.NET components: "`pnet`", "`pnetlib`", and "`treecc`".

Starting from version "0.1.4" of DotGNU Portable.NET, tags will be added to the CVS tree whenever a release version is cut. The tag for version "0.1.4" will be "r_0_1_4". Working versions will never have a tag.

Starting from version "0.4.8" of DotGNU Portable.NET, the main components will use the same version numbers so that it is easier to match the engine and compiler with the corresponding C# library.

### 9.2. I have a patch. What should I do now?

The best way to submit the patch is through the patch manager on Savannah. That will allow us to track it.

Please include comments with your patch that explain what it is for. Also include your full e-mail address, and any information related to Copyright assignment (see "Who owns the Copyright on patches?").

The maintainers will decide on a case by case basis whether to accept a patch. Submitting it does not guarantee inclusion.

The "`HACKING`" files describe how to make a patch file that is easy for the maintainers to apply.

### 9.3. What coding conventions should I follow?

The DotGNU Portable.NET code currently using the following coding conventions:

- TAB's are set at 4, not 8.
- The opening brace for a block is on the next line:

  > `if(condition)
  > {
  > ...
  > }
  > `

- Comments that describe a function are in the .h file, not the .c file. Do not put an extra copy in the .c file, because then the two copies will get out of sync in the future.

If you are submitting patches to an existing file, then use the same conventions as currently exist in that file. If you are writing a completely new source file, then you may use your own coding conventions, but we would prefer consistency with the above.

The "`HACKING`" files describe other coding conventions that may apply.

## 10. Standards

### 10.1. Where are the ECMA standards?

The latest versions of the ECMA standards for the Common Language Infrastructure (CLI) and the C# languages can be found at ECMA's Web site:

> `http://www.ecma.ch/ecma1/STAND/ECMA-334.htm` (C#)
> `http://www.ecma.ch/ecma1/STAND/ECMA-335.htm` (CLI)

If you wish to contribute to the C# library, you will need the following file:

> `ftp://ftp.ecma.ch/ecma-st/Ecma-335-xml.zip`

Unpack this zip file and then use the "`csdoc2html`" program to convert the XML file into HTML, so that you can view its contents more easily.

### 10.2. Why do you have more classes than ECMA specifies?

ECMA specifies the bare minimum necessary to get a Common Language Runtime (CLR) to work. However, this bare minimum is not very useful for realistic C# applications.

Microsoft's .NET Framework SDK contains a lot more classes in its base class libraries. Because we wish to be (more or less) compatible with Microsoft's .NET offerings, we have to implement more than ECMA specifies.

We generally follow the ECMA specifications to the letter, and only deviate from them where they are missing information, or the information conflicts with Microsoft's actual implementation.

The symbol "`ECMA_COMPAT`" may be defined when compiling "`pnetlib`" to force it to strictly conform to the ECMA requirements.

### 10.3. Can I build the ECMA-specified "Compact" and "Kernel" profiles?

DotGNU Portable.NET's runtime engine and C# class library has extensive support for embedded system profiles. Each profile enables or disables features of the system. The following profiles are currently supported:

`full`
  The full version, with all features enabled.
`framework1.1`, `framework1.2`, etc
  Builds the full version in such a way that it is compatible with a specific version of the .NET Framework SDK. When installed, the library can co-exist with `full`.
`default1.1`, `default1.2`, etc
  Same as `framework1.1`, `framework1.2`, etc but the library is installed as the default.
`ecma`
  A strictly ECMA-compatible profile.
`compact`
  The ECMA "Compact" profile, without floating point.
`compact-fp`
  The ECMA "Compact" profile, with floating point.
`kernel`
  The ECMA "Kernel" profile, without floating point.
`kernel-fp`
  The ECMA "Kernel" profile, with floating point.
`tiny`
  The smallest possible profile, which is "Kernel" minus the "RuntimeInfrastructure" subset of ECMA.
`tiny-fp`
  The smallest possible profile, with the addition of floating point.
`mscompact`
  A configuration that endeavours to be compatible with the Compact .NET Framework SDK.

Other profiles may be defined in the future. Check the source directory "`pnetlib/profiles`" for an up to date list.

To build either "`pnet`" or "`pnetlib`" with a profile, you specify its name at configuration time:

> `./configure --with-profile=compact-fp`

## 11. Other .NET efforts

### 11.1. What is Mono?

The Mono project that is run by Ximian has many of the same goals as DotGNU Portable.NET. See their Web site for further details:

> `http://www.go-mono.com/`

We will probably be using some of Mono's upper-level C# libraries, and may co-operate with Mono to improve those libraries. For various technical reasons, Mono's lower-level C# library "corlib" will not work with DotGNU Portable.NET's runtime engine, and so we still need "pnetlib".

Mono is using an older version of DotGNU Portable.NET's internationalization (I18N) framework, which provides a simple plugin architecture for writing globalization routines in C# for different character sets and locales.

### 11.2. What is OCL?

Intel have written a C# class library, which they call the Open CLI Library (OCL). A unique feature of this library is that its interfaces have been automatically generated from the ECMA specifications, whereas DotGNU Portable.NET and Mono have mostly copied the interfaces by hand. The library can be obtained at the following site:

> `http://ocl.sourceforge.net/`

### 11.3. What is Rotor?

Microsoft have released their own "Shared Source" CLI, called Rotor. More information on this can be found at MSDN:

> `http://msdn.microsoft.com/`

Technically, the license on Rotor is neither Free Software nor Open Source. The license is definitely not compatible with the GNU General Public License, and so none of the Rotor code can be used in the DotGNU Portable.NET project.

If you don't have a good reason, we suggest that contributors to DotGNU Portable.NET don't make a habit of looking at the Rotor code. It should only be used if all other options have been exhausted for determining how some feature should operate.

The following is what Eben Moglen, the legal counsel for the Free Software Foundation, has said about the Rotor license:

> The key provision in the license is:

> > You may use any information in intangible form that you remember after accessing the Software. However, this right does not grant you a license to any of Microsoft's copyrights or patents for anything you might create using such information.

> This is pretty clear (they're becoming rather good at drafting "shared source" licenses; I'm beginning to feel stylistically challenged). It means that they don't claim any right to control knowledge you may gain from reading their code, but you can't copy their code or practice any of their patent claims. The patent issue is unaffected by the reading of their code, from our point of view. On the copyright side, our responsibility is the same as it would be under any other circumstances: we must write all our code from scratch, copying nothing contained in their Rotor code. If there is no copying there is no infringement under their license.

> My advice is to tell people to code where possible from the ECMA standard. Where (which is likely to be everywhere), ECMA is insufficiently descriptive to create interoperable code, it is acceptable to read the source of the Rotor implementation. Notes taken in the course of reading that source should be made in pseudocode, so that programmers do not copy snippets of the Rotor source as aides to their memory. We want every line of code in our projects to have come out of the original invention of one of our coders, having been expressed in his or her own way. Ideas abstracted from the Rotor implementation should always have been put in our programmer's own "words," because copyright protects expressions, not ideas.

> -- Eben Moglen, 28 March 2002

## 12. Other random questions

### 12.1. Can I use ADO.NET with DotGNU Portable.NET?

The ADO.NET is based on the Mono project's implementation and also includes some useful SQL providers like NPgsql. This is included in the `ml-pnet` module of DotGNU Portable.NET.

### 12.2. Can I use ASP.NET with DotGNU Portable.NET?

At the moment, no. There are a huge collection of libraries and Web server hooks that need to be built, and it will take time to do so. The DGEE project, though it is currently focussed at running webservices, has potential to host ASP.NET. If you want to volunteer to help out on this, then that would be great.

The Mono project is already working on some of the necessary libraries, which we hope to support when they mature.

### 12.3. Why doesn't my C/C++ application work that I built with Visual Studio.NET?

Usually, the C/C++ applications that are output by Visual Studio.NET are not pure IL binaries. They contain x86 native code, and depend on all kinds of Microsoft-specific libraries. Such applications will never work with a pure-IL engine such as "`ilrun`".

Apparently there are switches that can be supplied to Visual Studio.NET that force it to output pure-IL binaries. But even then, there will still be dependencies on other Microsoft libraries. Your mileage may vary.

Some people have suggested interfacing "`ilrun`" to Wine so as to pick up many of the Windows dependencies. This may work, but we need someone to volunteer to do it first.

If your application is written in C, and does not depend upon Windows-specific features, then you can recompile it using the C language front-end for "`cscc`". The resulting binary is likely to be more portable than that produced by Visual Studio.NET.

Update: more recent versions of Visual Studio.NET apparently generate IL that is more pure. Your mileage may still vary though.

### 12.4. Why don't you just use Java?

This question is usually asked by Java-philes who are suspicious of Microsoft's goals with C# and the CLI.

We think that the C# language and the CLI could be very useful to the Free Software community, if we were to co-opt them for our own purposes. There's nothing that says we have to use these technologies in precisely the same way that Microsoft does.

By building the basics, DotGNU Portable.NET can serve as a platform for the Free Software community to experiment with these technologies in completely unexpected ways.

### 12.5. Isn't C# just a cheap knock-off of Java?

Not really. It includes language features that Java lacks: properties, delegates, events, operators, indexers, enumerations, and value types.

Every language has its adherents and its detractors - the programming community would be very boring if everyone did everything the same way.

Copyright © 2001, 2002, 2003, 2004 Southern Storm Software, Pty Ltd.
Permission to distribute unmodified copies of this work is hereby granted.