Aspnetcore: Blazor WebAssembly publish operation is NOT deterministic (linker might be culprit)

Created on 27 May 2020  路  8Comments  路  Source: dotnet/aspnetcore

Describe the bug

The binaries keep changing from one compilation run to the next dotnet publish on a Blazor WebAssembly project.

This makes it impossible to create a minimal patch to update a previous deployment.

To Reproduce

Create a sample Blazor WebAssembly project. Compile it using dotnet publish. Compute MD5 for all produced files in publish/wwwroot folder. Delete the bin and obj folders and repeat process. The MD5 checksums are not the same between the two runs.

Step-by-step instructions:

  1. Create a new Blazor WebAssembly project
    bash $ dotnet new blazorwasm -n SampleBlazorApp
  2. Switch to newly created folder
    bash $ cd SampleBlazorApp/
  3. Build project in _Release_ configuration (omit compression)
    bash $ dotnet publish -c Release -p:BlazorEnableCompression=false
  4. Compute MD5 of every file
    bash $ find bin/Release/netstandard2.1/publish/wwwroot/ -type f | sort | xargs md5sum 12b23f499811864b9b6b701226a6ead6 *bin/Release/netstandard2.1/publish/wwwroot/_framework/_bin/Microsoft.AspNetCore.Components.dll b7ea31c72c85d3056fcada78d51d467d *bin/Release/netstandard2.1/publish/wwwroot/_framework/_bin/Microsoft.AspNetCore.Components.Web.dll b598f580fb51e0e250640d4f294c16d7 *bin/Release/netstandard2.1/publish/wwwroot/_framework/_bin/Microsoft.AspNetCore.Components.WebAssembly.dll ae34482c74afe3926080527895f9f939 *bin/Release/netstandard2.1/publish/wwwroot/_framework/_bin/Microsoft.Bcl.AsyncInterfaces.dll ... 4859e39ae6c0f1f428f2126a6bb32bd9 *bin/Release/netstandard2.1/publish/wwwroot/favicon.ico 10774826696cea4890d1d932251fe002 *bin/Release/netstandard2.1/publish/wwwroot/index.html 4786ef563a5e1137a17318eb22a84e32 *bin/Release/netstandard2.1/publish/wwwroot/sample-data/weather.json
  5. Delete bin and obj folders
    bash $ rm -rf bin obj
  6. Build project again with the same settings
    bash $ dotnet publish -c Release -p:BlazorEnableCompression=false
  7. Compute MD5 of every file
    bash $ find bin/Release/netstandard2.1/publish/wwwroot/ -type f | sort | xargs md5sum 3172e0947800fb5889ea6e5a46183ceb *bin/Release/netstandard2.1/publish/wwwroot/_framework/_bin/Microsoft.AspNetCore.Components.dll f850b9a5ea01de2f0668975baa4aadcf *bin/Release/netstandard2.1/publish/wwwroot/_framework/_bin/Microsoft.AspNetCore.Components.Web.dll 77d39ecd9d3ac4c95e2537a82267d1e7 *bin/Release/netstandard2.1/publish/wwwroot/_framework/_bin/Microsoft.AspNetCore.Components.WebAssembly.dll ae34482c74afe3926080527895f9f939 *bin/Release/netstandard2.1/publish/wwwroot/_framework/_bin/Microsoft.Bcl.AsyncInterfaces.dll ... 4859e39ae6c0f1f428f2126a6bb32bd9 *bin/Release/netstandard2.1/publish/wwwroot/favicon.ico 10774826696cea4890d1d932251fe002 *bin/Release/netstandard2.1/publish/wwwroot/index.html 4786ef563a5e1137a17318eb22a84e32 *bin/Release/netstandard2.1/publish/wwwroot/sample-data/weather.json

Notice how the first files have different MD5 checksums. However, the last entries, which are static files, are the same.

Further technical details

$ dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   3.1.300
 Commit:    b2475c1295

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.18363
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.1.300\

Host (useful for support):
  Version: 3.1.4
  Commit:  0c2e69caa6

.NET Core SDKs installed:
  2.1.201 [C:\Program Files\dotnet\sdk]
  2.1.202 [C:\Program Files\dotnet\sdk]
  2.1.512 [C:\Program Files\dotnet\sdk]
  2.2.300 [C:\Program Files\dotnet\sdk]
  3.1.200 [C:\Program Files\dotnet\sdk]
  3.1.202 [C:\Program Files\dotnet\sdk]
  3.1.300 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download
area-blazor blazor-wasm investigate

All 8 comments

Addendum: adding <Deterministic>true</Deterministic> to the _.csproj_ file doesn't change the outcome.

Addendum 2: adding <BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking> fixes the issue.

So it appears the linker modifies the assemblies in a non-deterministic fashion.

@lewing should we use the isDeterministic flag when calling the linker going forward and why?

Any progress on this or work around? Thx.

@marek-safar thoughts?

ILLink is not producing deterministic output by default yet. We have tracking issues at https://github.com/mono/linker/issues/1342

Looks like mono/linker#1342 is fixed now, for 3.2 should we pass the flag or pull an updated linker?

This issue is resolved with the 5.0 SDK. I filed https://github.com/dotnet/sdk/issues/13711 as a follow up to this, but it's mostly frivolous.

Was this page helpful?
0 / 5 - 0 ratings