Closed CuteLeon closed 4 months ago
I found below content in https://github.com/dotnet/runtime/blob/main/docs/design/specs/PE-COFF.md#deterministic-pecoff-file, think TimeDateStamp doesn't mean compile date time any more, what will be the substitute?
The value of field TimeDateStamp in COFF File Header of a deterministic PE/COFF file does not indicate the date and time when the file was produced and should not be interpreted that way. Instead the value of the field is derived from a hash of the file content.
I implement another solution is that: Create a new AssemblyCompileDateTimeAttribute class and a SourceGenerator project to inject AssemblyCompileDateTimeAttribute declaretion into each project.
This behavior is "By Design". The default for .NET SDK applications is to have deterministic builds. To achieve that the timestamp field is replaced with part of a deterministic hash of the compilation inputs. If you desire the old behavior you can set <Deterministic>false</Deterministic>
in your project file. Doing so is generally not recommended.
Share my workaround:
public class AssemblyCompileDateTimeAttribute : Attribute
{
public string CompileDateTime { get; set; }
public AssemblyCompileDateTimeAttribute(string compileDateTime)
{
this.CompileDateTime = compileDateTime;
}
}
[Generator(LanguageNames.CSharp)]
public class CompileDateTimeSourceGenerator : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
}
public void Execute(GeneratorExecutionContext context)
{
var assemblyName = context.Compilation.Assembly.Name;
var compileDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
context.AddSource($"{assemblyName}.CompileDateTime.g.cs", $"[assembly: AssemblyTools.AssemblyCompileDateTimeAttribute(\"{compileDateTime}\")]");
}
}
public static DateTime? GetCompileDateTimeFromAttribute(this Assembly assembly)
{
var buildDateTime = default(DateTime?);
try
{
var attribute = assembly.GetCustomAttribute<AssemblyCompileDateTimeAttribute>();
if (attribute is not null &&
DateTime.TryParseExact(attribute.CompileDateTime, "yyyy-MM-dd HH:mm:ss.fffffff", CultureInfo.InvariantCulture, DateTimeStyles.None, out var compileDateTime))
{
buildDateTime = compileDateTime;
}
}
finally
{
}
return buildDateTime;
}
Note that a source generator might be an overkill, you can use MSBuild items to create attributes - you don't even need a custom attribute, there is AssemblyMetadataAttribute
that can be used for this purpose - see example in the docs:
<ItemGroup>
<!-- Include must be the fully qualified .NET type name of the Attribute to create. -->
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
<!-- _Parameter1, _Parameter2, etc. correspond to the
matching parameter of a constructor of that .NET attribute type -->
<_Parameter1>BuildDate</_Parameter1>
<_Parameter2>$(Date)</_Parameter2>
</AssemblyAttribute>
</ItemGroup>
generates:
[assembly: System.Reflection.AssemblyMetadataAttribute("BuildDate", "01/19/2024")]
Version Used: How can I get compiler's version? Steps to Reproduce:
Diagnostic Id:
Expected Behavior: I hope this method will read a correct compile time from PEHeaders.CoffHeader.TimeDateStamp;
Actual Behavior: I got a negative integer from PEHeaders.CoffHeader.TimeDateStamp, and incorrect compile time;
Some details: Bytes wrotten in binary program file: Hex value readed from PEReader: Got build date time: