CopyRefAssembly Could not extract the MVID from reference assembly
See original GitHub issueFollowing up on https://github.com/dotnet/fsharp/pull/12334, I’ve noticed that a project B (csproj) cannot consume a reference assembly of a project A (fsproj) because the mvid
cannot be read from the assembly.
Project structure:
A.fsproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<DotnetFscCompilerPath>C:\Users\nojaf\Projects\fsharp\artifacts\bin\fsc\Debug\net6.0\fsc.dll</DotnetFscCompilerPath>
<OtherFlags>--refout:obj\Debug\net7.0\refint\A.dll</OtherFlags>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
<ItemGroup>
<Compile Include="Library.fs" />
</ItemGroup>
</Project>
B.csproj
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\A\A.fsproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
</Project>
Expected behavior
dotnet build
of B.csproj
will find the reference assembly of project A that was specified using the refout
flag.
Actual behavior
In the MSBuild log we saw the following:
Could not extract the MVID from “obj\Debug\net7.0\refint\A.dll”. Are you sure it is a reference assembly?
This warning was logged by CopyRefAssembly
,
The main problem is that the mvid guid is empty.
The current Number of Sections
inside the COFF Header
is 3
, whereas compared to a C# reference assembly this is 4
. The .mvid
section is missing from the F# generation.
The MSBuild task uses this section to read that guid.
This entire section could be added around
Similar to .text, .sdata, .reloc
I would assume. Conditional logic could be implemented using options.referenceAssemblyOnly
.
Known workarounds
Besides adding the additional section, it is possible to extract the guid currently from the Module metadata table. We were able to read it using:
#r "nuget: System.Reflection.Metadata"
open System.IO
open System.Reflection.PortableExecutable
let refDll = @"C:\Users\nojaf\Projects\reference-assemblies-sample\A\obj\Debug\net7.0\refint\A.dll"
let embeddedReader = new PEReader(File.OpenRead refDll)
let sourceReader = embeddedReader.GetMetadataReader()
let loc = sourceReader.GetModuleDefinition().Mvid
let mvid = sourceReader.GetGuid(loc)
So, from a certain point of view, the mvid
is there. Just not in the way that CopyRefAssembly
reads it.
Related information
Provide any related information (optional):
- Operating system: Win11
- .NET Runtime kind: .NET 7 preview 4
- local compiler, main at 5b1a3ae5d16fe93af1f8b055ab0be5bb5e47ff20
Issue Analytics
- State:
- Created a year ago
- Comments:7 (7 by maintainers)
Top GitHub Comments
Agree. The code in
CopyRefAssembly
is pretty standard for reading an MVID from a PE file. If this task is erroring then likely many other tools in the .NET ecosystem will similarly fail to read the F# ref assembly.Yeah, we probably should start emitting it as part of our work of FSharp.Build support of refassemblies.