[Mono-devel-list] Re: Potential GAC implementation ideas.

Jonathan Pryor jonpryor at vt.edu
Fri Oct 24 08:24:10 EDT 2003

Inline...  And apologies for another long email...

On Fri, 2003-10-24 at 07:39, Michal Moskal wrote:
> Assume I'm application developer. I have an assembly that is quite private
> for me, i.e. I see no particular reason anybody else would use it. So I
> place it in /usr/share/apps/foobar/mydll.dll, or something like this. How
> do I tell where this DLL resides to the runtime? My app wouldn't reside
> in /usr/share/apps/foobar/foobar.exe, since in UNIX world it should
> go to /usr/bin/foobar.exe. Shall I compile the /usr/share/apps/foobar
> into foobar.exe binary using some -rpath like mechanism? This seems
> broken (what if user doesn't like /usr/share/apps, what if she wants
> /usr/local/share/apps etc). It's far easier for me to have reasonable
> versioning and private key, and use GAC.

Alas, this is where Unix and Windows differ.  Unix assumes that most
program binaries in are in $prefix/bin, and libraries are in
$prefix/lib.  Windows is...confusing at best, but when it comes to .NET
and Assemblies, it assumes that private assemblies are in the same
directory as the .exe (or in a /bin sub-directory), and public
assemblies in the GAC.

These are two wildly divergent strategies.  And if we're aiming for .NET
compatibility, we'll have to *support* (though not necessarily follow
with RPMs) the .NET way, which would imply one of two things:

  - Place the private assemblies in $prefix/bin, with the app exe.
    This, of course, can lead to file-name conflicts if you have
    multiple .NET apps installed, and is thus Not Good.

  - Place the private assemblies and the program binary in 
    $prefix/share/<program-name>/, and place a symlink to the program
    in $prefix/bin.  This is likely the cleanest approach for .NET apps.

Note that this issue is different from the RPM/packaging issues.  This
is a "I have a .NET app that I want to run in Linux.  How do I do that?"
issue.  We MUST support the .NET way, if only for compatibility, which
means we MUST support a reasonable approach to private assemblies.

Saying that all assemblies should be public and placed in the GAC is NOT
an option.

> Now, if mono doesn't require assembly to have version and public key
> token, then assemblies that don't have it, cannot go into GAC. But the
> standard way of dealing with installation (recommended to the developers)
> should be GAC IMHO. Because it's simple, unified and fast.

But the .NET-recommended approach is to *avoid* the GAC, unless you
really need it.  The GAC implies shared assemblies, which puts a large
number of requirements on the assembly.

>From a Unix perspective, none of these requirements is particularly
difficult -- libraries must be versioned, libraries with the same major
version number must be upwardly compatible, etc -- and have been
followed on Unix for years (decades, likely).

>From a Windows perspective, this hasn't been the case.  Versioning is a
new concept, maintaining forward compatibility won't happen except for
those who need it.

This is why private assemblies are so easy to make (just mcs
-t:library), while public assemblies are difficult (compile, create a
strong-name, sign the assembly, install with gacutil).  Private
assemblies are the preferred method of deployment.

If we want to drop .NET compatibility, then we can recommend
shared-everything, but I don't think either of those is a good idea. 
Private assemblies should remain the default and recommended method of

> What remains to be discussed is if GAC should store files, or maybe just
> references (symlinks or some database) to files. Personally I don't
> care. Storing files, in a fixed way, would simplify packaging a bit,
> since you don't need to choose unique location yourself. And I see no
> reason why should /gac/<version>_<publictoken>/foo.dll be changed, as it
> seems simple and effective.

I agree, and disagree. :-)

I don't care if the GAC stores copies or references, though I suspect
file copies will be the safer approach (when taking package removal and
multiple different apps using the same assembly).

Finding a fixed format should be easy to do -- as Jonathan Hogg pointed
out, this isn't rocket science.

Though I think the format also needs to take assembly culture into
account (to distinguish between English and e.g. Japanese language

What I do worry about is...compatibility.  (It keeps coming up!)

We want to be able to run .NET apps.  .NET developers are not going to
be creating RPMs, at least not for the foreseeable future; Windows will
be their primary platform.

So they'll either be creating .MSI's, .NSI's, custom install .EXEs, or
(if we're lucky) .ZIP packages containing a README for installation.

Assuming a .ZIP and a README, the README is likely to say:

	Run this command at the command line:

		gacutil /i <some-shared-assembly.dll>

This implies that we're going to have to support a gacutil tool, or
totally confuse any Linux users trying to install this program.

So we have two choices: (1) Standardize the directory structure (again,
it's not rocket science), and let gacutil and RPMs assume this directory
structure and Do The Right Thing.  Pros: simple, consistent.  Cons: IF
we ever have to change things, all the RPMs are instantly broken;
gacutil will continue to work.

(2) is to require the use of gacutil for all shared-assembly
installation, as discussed previously in this thread.  Pros:
future-proof; if anything changes, only gacutil and the runtime need to
change.  RPMs/packages are unaffected.  Cons: leads to file duplication.

Personally, I prefer option (2), using Joshua Tauberer's packaging
suggestion (which I expanded upon in my last email).

I think (2) fits in better with Unix, separating policy from mechanism
(or in this case, hiding policy behind a gacutil firewall, so that it
can change without changing the mechanism -- gacutil).  Policies are
likely to change, and we want to make it easy to do so.

(For example, it might be cool to have an LDAP-backed GAC, so that you
can install an assembly once and have it available across a cluster. 
Very cool.  Can't be done if everything and it's brother assumes a
directory structure, because the directory structure might not be used.)

 - Jon

More information about the Mono-devel-list mailing list