_Microsoft.Android.Resource.Designer.dll carries the build's wall-clock time as its PE TimeDateStamp, so Release builds are not reproducible (GenerateResourceDesignerAssembly passes no WriterParameters.Timestamp)
Los mantenedores suelen responder en 1 día
@jonathanpeppers ya está trabajando en esto.
Desde el 14/10/2026.
- #13144 de @copilot-swe-agent — abierto
Evaluación
Este issue todavía no se ha evaluado.
Descripción
Android framework version
net10.0-android
Affected platform version
.NET SDK 10.0.303, workload set 10.0.302.1, Microsoft.Android.Sdk.Windows 36.1.69, Microsoft.NETCore.App.Runtime.Mono.android-arm64 10.0.10, MAUI 10.0.110, Windows 11 x64 host. The generator source on main as of 2026-10-14 (src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs) shows the same code path.
Description
I am working towards reproducible Release builds of a MAUI Android app (OWASP MASWE-0075). With the toolchain pinned (global.json, lock files), deterministic passed to the Mono AOT compiler, --deterministic to the trimmer and ContinuousIntegrationBuild=true, two builds of one commit from a clean obj still differ, and the first stage at which a difference appears is the generated obj/Release/net10.0-android/_Microsoft.Android.Resource.Designer.dll.
Between two builds of the same commit that file differs in exactly 18 bytes:
- the COFF header
TimeDateStamp(file offsets 137-140), which is the wall-clock time of the build:0x6acf16c1(2026-10-14 05:44:33Z) in one build,0x6acf1946in the next; - the 16-byte MVID in the
#GUIDheap, which Cecil derives by hashing the written image, stamp included, whenDeterministicMvidis set.
As far as I can read it, GenerateResourceDesignerAssembly writes with new WriterParameters { DeterministicMvid = Deterministic } and no Timestamp, and Cecil's ModuleDefinition initialises a new module's timestamp from DateTime.UtcNow (Mono.Cecil/ModuleDefinition.cs), so every build gets a new stamp and, from it, a new "deterministic" MVID. Cecil reads no environment variable such as SOURCE_DATE_EPOCH.
The difference cascades. Roslyn's portable PDB records each metadata reference's MVID, so the application assembly's own deterministic outputs change too: 72 bytes (PE stamp, MVID, PDB id, PDB checksum), IL and metadata otherwise byte-identical. Downstream, libassembly-store.so, libxamarin-app.so (the type map) and the two libaot-*.dll.so images for these assemblies differ by those ids. In my measurement that accounts for 8 of the 16 entries that still differ between two clean builds of one commit (the other 8 are a separate Mono AOT compiler matter, reported on dotnet/runtime).
Expected: with Deterministic true, the generated designer assembly is byte-identical for identical inputs, for example WriterParameters.Timestamp set to a fixed value, to a value derived from the content (as Roslyn does), or to SOURCE_DATE_EPOCH when it is set.
Steps to Reproduce
dotnet new maui -n Reprotargeting net10.0-android; leaveDeterministicat its default (true).dotnet publish -f net10.0-android -c Release; copyobj/Release/net10.0-android/_Microsoft.Android.Resource.Designer.dllaside.- Delete
binandobj; publish again. - Compare the two copies:
cmp -llists 18 differing bytes (offsets 137-140 and the 16 bytes of the MVID in the GUID heap);[System.Reflection.Assembly]::ReflectionOnlyLoadFrom(path).ManifestModule.ModuleVersionIddiffers between the two; theTimeDateStampread ate_lfanew + 8is each build's wall-clock time.
Did you find any workaround?
No. AndroidUseDesignerAssembly=false (the designer as C# source) stops with XA1034 as soon as a referenced library uses the designer assembly; Microsoft.Maui.Controls, Microsoft.Maui and Microsoft.Identity.Client all do. Rewriting the generated file with a fixed timestamp in a custom target would work, but a custom step over a generated file is not something I want to maintain.
Relevant log output
cmp -l build1/_Microsoft.Android.Resource.Designer.dll build2/_Microsoft.Android.Resource.Designer.dll
18 bytes differ: offsets 137-138 (within the TimeDateStamp at 137-140) and 702925-702940 (the MVID), file size 731648 in both
PE TimeDateStamp: build1 0x6acf16c1 (2026-10-14 05:44:33Z), build2 0x6acf1946 (2026-10-14 05:55:18Z)
MVID: build1 7b52a131-b4f4-49f8-af05-f1f48b2279f9, build2 fd067989-df7b-4d27-bc12-a1e00dffd964
Application assembly from the same two builds (Roslyn, Deterministic + ContinuousIntegrationBuild):
72 bytes differ: 137-140 (TimeDateStamp), 708901-708916 (MVID), 779129-779132, 779213-779228 (PDB id), 779307-779338 (PDB checksum)
- Lenguaje dominante
- C#
- Estrellas
- 2.1k
- Forks
- 581
- Merge medio
- 1 d 21 h
- PR fusionados (30 d)
- 241
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Sin guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de dotnet/android
-
Area: App+Library Build
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
EditText.getText() isn't boundAbiertoArea: Mono.Android
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
dotnet/android#9192 · 4 comentarios · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
Area: Mono.Android needs-triage
Dificultad 4/5 3-5 días Aptitud para principiantes 30/100
Los mantenedores suelen responder en 1 día
-
Area: App Runtime needs-triage
Dificultad 4/5 3-5 días Aptitud para principiantes 22/100
Los mantenedores suelen responder en 1 día
-
flaky-ci flaky-tests needs-triage
Dificultad 5/5 Más de una semana Aptitud para principiantes 8/100
Los mantenedores suelen responder en 1 día
Todos los issues de dotnet/android
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 60/100
Los mantenedores suelen responder en 1 día
-
area: design documentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
eyalgolan/statecraft-israel#883 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 3 días
-
area/indexing bug package/core triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
Los mantenedores suelen responder en 1 día
-
Debug-only options are confusingAbiertoBug
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
nunit/nunit-console#1913 ·
Los mantenedores suelen responder en 1 día