views:

2394

answers:

2

I'm trying to compile code from F# to use in Silverlight. I compile with:

--noframework --cliroot "C:\program Files\Microsoft Silverlight\2.0.31005.0" --standalone

This generates a standalone assembly that references the SL framework. But when I try to add a reference to the generated assembly, I get this error:

You can only add project references to other Silverlight projects in the solution.

What is the VS plugin doing to determine that this isn't a Silverlight assembly? Here's the manifest:

// Metadata version: v2.0.50727
.assembly extern mscorlib
{
  .publickeytoken = (7C EC 85 D7 BE A7 79 8E )                         // |.....y.
  .ver 2:0:5:0
}
.assembly FSSLLibrary1
{

  // --- The following custom attribute is added automatically, do not uncomment -------
  //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 01 01 00 00 00 00 ) 

  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module 'F#-Module-FSSLLibrary1'
// MVID: {49038883-5D18-7281-A745-038383880349}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x04120000

I don't understand what it's finding that it doesn't like; it's pure verifiable IL. I compared to a SL "class library" assembly, and it looks the same. The only difference was some attributes, but I deleted those and VS still let me reference the DLL. I even added unverifiable IL to the "SL library" DLL and it still loaded.

Any suggestions?

Update: I've done some poking around, and it doesn't seem to be the manifest that matters. It doesn't like something in the IL from the FSharp libraries. They are peverifiable, but something in there is triggering the rejection.

+7  A: 

Answer!

Apparently the problem is that when you add a reference to the bin\Release or bin\Debug, Visual Studio (or the Silverlight project system) decides to try to reference the project. This fails for whatever reason.

If you copy the F# output DLL to another location, then the reference goes through just fine. (This will be a file reference, not a project reference, of course.)

Then setup dependencies so the F# library builds first, then you can use a file reference to get the F#-generated binary.

Update: One more apparent issue. If I turn optimize code on, then I get this error:

C:\test\SilverlightApplication1\FSC(0,0): error FS0193: internal error: the module/namespace 'System' from compilation unit 'mscorlib' did not contain the namespace, module or type 'MarshalByRefObject'

If I keep optimized code off, this goes away and everything works fine.

MichaelGG
I Can't wait to give it a try!
Brian Leahy
A: 

Visual Studio uses the IsSilverlightAssembly() function in the Microsoft.VisualStudio.Silverlight.SLUtil type to check if a reference can be set.

David Betz has a nice blog post describing the details here.

Maurice
Apparently it does a bit more than that inside VS, since moving the file out of the target location makes VS see it as a SL assembly -- the same bits it saw as not-SL before. Although, maybe this is other logic that says "file reference to output path -> project reference".
MichaelGG