Skip to content

Commit 2dcdb46

Browse files
davidglassborowKevinRansom
authored andcommitted
Determinism of the F# Compiler #1042 (#2954)
* Add IL output option for deterministic output Thread a new option through the options to the code writing the IL. For the moment just use a constant for deterministic timestamp, and use 0 as the timestamp in the MVID * Basic check to prevent wildcard version + deterministic at the same time * Hash the code, data and metadata, and use for mvid + timestamp * Fix fsc & fsci help tests by adding in new command line option for deterministic * tests for command line, wildcard versions, normal non-deterministic behaviour * Attempt to get CI to support timeout * Allow PRECMD to call FSI more than once, and use this for copying files and pausing to prevent race-condition * PortablePdbBuilder use consistent id If compiling deterministically, use deterministic id provider support in making a pdb builder. see https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/PEWriter/PeWriter.cs#L132 * Portable and Embedded pdb now deterministic * wip: fix up timestamp in pdb, but mvids still out of sequence * Fix breaking change from rebasing on master * Add notes about determinism with non portable pdbs Make the checks for finding embedded guids more strict and unique * Throw error if determinsitc build and non-portable pdb specified
1 parent c4a8ff2 commit 2dcdb46

23 files changed

+175
-22
lines changed

src/absil/ilwrite.fs

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ type MetadataTable =
551551
type cenv =
552552
{ ilg: ILGlobals
553553
emitTailcalls: bool
554+
deterministic: bool
554555
showTimes: bool
555556
desiredMetadataVersion: ILVersionInfo
556557
requiredDataFixups: (int32 * (int * bool)) list ref
@@ -2903,9 +2904,15 @@ and newGuid (modul: ILModuleDef) =
29032904
let m2 = hash modul.Name
29042905
[| b0 m; b1 m; b2 m; b3 m; b0 m2; b1 m2; b2 m2; b3 m2; 0xa7uy; 0x45uy; 0x03uy; 0x83uy; b0 n; b1 n; b2 n; b3 n |]
29052906

2906-
and GetModuleAsRow cenv (modul: ILModuleDef) =
2907+
and deterministicGuid (modul: ILModuleDef) =
2908+
let n = 16909060
2909+
let m = hash n
2910+
let m2 = hash modul.Name
2911+
[| b0 m; b1 m; b2 m; b3 m; b0 m2; b1 m2; b2 m2; b3 m2; 0xa7uy; 0x45uy; 0x03uy; 0x83uy; b0 n; b1 n; b2 n; b3 n |]
2912+
2913+
and GetModuleAsRow (cenv:cenv) (modul: ILModuleDef) =
29072914
// Store the generated MVID in the environment (needed for generating debug information)
2908-
let modulGuid = newGuid modul
2915+
let modulGuid = if cenv.deterministic then deterministicGuid modul else newGuid modul
29092916
cenv.moduleGuid <- modulGuid
29102917
UnsharedRow
29112918
[| UShort (uint16 0x0)
@@ -2954,11 +2961,12 @@ let GenModule (cenv : cenv) (modul: ILModuleDef) =
29542961
GenTypeDefsPass4 [] cenv tds
29552962
reportTime cenv.showTimes "Module Generation Pass 4"
29562963

2957-
let generateIL requiredDataFixups (desiredMetadataVersion,generatePdb, ilg : ILGlobals, emitTailcalls,showTimes) (m : ILModuleDef) cilStartAddress =
2964+
let generateIL requiredDataFixups (desiredMetadataVersion,generatePdb, ilg : ILGlobals, emitTailcalls, deterministic, showTimes) (m : ILModuleDef) cilStartAddress =
29582965
let isDll = m.IsDLL
29592966

29602967
let cenv =
29612968
{ emitTailcalls=emitTailcalls
2969+
deterministic = deterministic
29622970
showTimes=showTimes
29632971
ilg = ilg
29642972
desiredMetadataVersion=desiredMetadataVersion
@@ -3098,7 +3106,7 @@ module FileSystemUtilites =
30983106
#endif
30993107
()
31003108

3101-
let writeILMetadataAndCode (generatePdb,desiredMetadataVersion,ilg,emitTailcalls,showTimes) modul cilStartAddress =
3109+
let writeILMetadataAndCode (generatePdb,desiredMetadataVersion,ilg,emitTailcalls,deterministic,showTimes) modul cilStartAddress =
31023110

31033111
// When we know the real RVAs of the data section we fixup the references for the FieldRVA table.
31043112
// These references are stored as offsets into the metadata we return from this function
@@ -3107,7 +3115,7 @@ let writeILMetadataAndCode (generatePdb,desiredMetadataVersion,ilg,emitTailcalls
31073115
let next = cilStartAddress
31083116

31093117
let strings,userStrings,blobs,guids,tables,entryPointToken,code,requiredStringFixups,data,resources,pdbData,mappings =
3110-
generateIL requiredDataFixups (desiredMetadataVersion,generatePdb,ilg,emitTailcalls,showTimes) modul cilStartAddress
3118+
generateIL requiredDataFixups (desiredMetadataVersion,generatePdb,ilg,emitTailcalls,deterministic,showTimes) modul cilStartAddress
31113119

31123120
reportTime showTimes "Generated Tables and Code"
31133121
let tableSize (tab: TableName) = tables.[tab.Index].Count
@@ -3404,7 +3412,7 @@ let writeILMetadataAndCode (generatePdb,desiredMetadataVersion,ilg,emitTailcalls
34043412

34053413
reportTime showTimes "Layout Metadata"
34063414

3407-
let metadata =
3415+
let metadata, guidStart =
34083416
let mdbuf = ByteBuffer.Create 500000
34093417
mdbuf.EmitIntsAsBytes
34103418
[| 0x42; 0x53; 0x4a; 0x42; // Magic signature
@@ -3462,6 +3470,7 @@ let writeILMetadataAndCode (generatePdb,desiredMetadataVersion,ilg,emitTailcalls
34623470

34633471
reportTime showTimes "Write Metadata User Strings";
34643472
// The GUID stream
3473+
let guidStart = mdbuf.Position
34653474
Array.iter mdbuf.EmitBytes guids;
34663475

34673476
// The blob stream
@@ -3473,7 +3482,7 @@ let writeILMetadataAndCode (generatePdb,desiredMetadataVersion,ilg,emitTailcalls
34733482
mdbuf.EmitIntAsByte 0x00;
34743483
reportTime showTimes "Write Blob Stream";
34753484
// Done - close the buffer and return the result.
3476-
mdbuf.Close()
3485+
mdbuf.Close(), guidStart
34773486

34783487

34793488
// Now we know the user string tables etc. we can fixup the
@@ -3488,7 +3497,7 @@ let writeILMetadataAndCode (generatePdb,desiredMetadataVersion,ilg,emitTailcalls
34883497
applyFixup32 code locInCode token
34893498
reportTime showTimes "Fixup Metadata";
34903499

3491-
entryPointToken,code, codePadding,metadata,data,resources,!requiredDataFixups,pdbData,mappings
3500+
entryPointToken,code, codePadding,metadata,data,resources,!requiredDataFixups,pdbData,mappings,guidStart
34923501

34933502
//---------------------------------------------------------------------
34943503
// PHYSICAL METADATA+BLOBS --> PHYSICAL PE FORMAT
@@ -3550,7 +3559,7 @@ let writeBytes (os: BinaryWriter) (chunk:byte[]) = os.Write(chunk,0,chunk.Length
35503559

35513560
let writeBinaryAndReportMappings (outfile,
35523561
ilg: ILGlobals, pdbfile: string option, signer: ILStrongNameSigner option, portablePDB, embeddedPDB,
3553-
embedAllSource, embedSourceList, sourceLink, emitTailcalls, showTimes, dumpDebugInfo) modul =
3562+
embedAllSource, embedSourceList, sourceLink, emitTailcalls, deterministic, showTimes, dumpDebugInfo ) modul =
35543563
// Store the public key from the signer into the manifest. This means it will be written
35553564
// to the binary and also acts as an indicator to leave space for delay sign
35563565

@@ -3666,8 +3675,8 @@ let writeBinaryAndReportMappings (outfile,
36663675
| Some v -> v
36673676
| None -> failwith "Expected msorlib to have a version number"
36683677

3669-
let entryPointToken,code,codePadding,metadata,data,resources,requiredDataFixups,pdbData,mappings =
3670-
writeILMetadataAndCode ((pdbfile <> None), desiredMetadataVersion, ilg,emitTailcalls,showTimes) modul next
3678+
let entryPointToken,code,codePadding,metadata,data,resources,requiredDataFixups,pdbData,mappings,guidStart =
3679+
writeILMetadataAndCode ((pdbfile <> None), desiredMetadataVersion, ilg,emitTailcalls, deterministic, showTimes) modul next
36713680

36723681
reportTime showTimes "Generated IL and metadata";
36733682
let _codeChunk,next = chunk code.Length next
@@ -3703,7 +3712,7 @@ let writeBinaryAndReportMappings (outfile,
37033712
let pdbOpt =
37043713
match portablePDB with
37053714
| true ->
3706-
let (uncompressedLength, contentId, stream) as pdbStream = generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData
3715+
let (uncompressedLength, contentId, stream) as pdbStream = generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic
37073716
if embeddedPDB then Some (compressPortablePdbStream uncompressedLength contentId stream)
37083717
else Some (pdbStream)
37093718
| _ -> None
@@ -3849,7 +3858,33 @@ let writeBinaryAndReportMappings (outfile,
38493858
writeInt32AsUInt16 os 0x014c; // Machine - IMAGE_FILE_MACHINE_I386
38503859

38513860
writeInt32AsUInt16 os numSections;
3852-
writeInt32 os timestamp // date since 1970
3861+
3862+
let pdbData =
3863+
if deterministic then
3864+
// Hash code, data and metadata
3865+
use sha = System.Security.Cryptography.SHA1.Create() // IncrementalHash is core only
3866+
let hCode = sha.ComputeHash code
3867+
let hData = sha.ComputeHash data
3868+
let hMeta = sha.ComputeHash metadata
3869+
let final = [| hCode; hData; hMeta |] |> Array.collect id |> sha.ComputeHash
3870+
3871+
// Confirm we have found the correct data and aren't corrupting the metadata
3872+
if metadata.[ guidStart..guidStart+3] <> [| 4uy; 3uy; 2uy; 1uy |] then failwith "Failed to find MVID"
3873+
if metadata.[ guidStart+12..guidStart+15] <> [| 4uy; 3uy; 2uy; 1uy |] then failwith "Failed to find MVID"
3874+
3875+
// Update MVID guid in metadata
3876+
Array.blit final 0 metadata guidStart 16
3877+
3878+
// Use last 4 bytes for timestamp - High bit set, to stop tool chains becoming confused
3879+
let timestamp = int final.[16] ||| (int final.[17] <<< 8) ||| (int final.[18] <<< 16) ||| (int (final.[19] ||| 128uy) <<< 24)
3880+
writeInt32 os timestamp
3881+
// Update pdbData with new guid and timestamp. Portable and embedded PDBs don't need the ModuleID
3882+
// Full and PdbOnly aren't supported under deterministic builds currently, they rely on non-determinsitic Windows native code
3883+
{ pdbData with ModuleID = final.[0..15] ; Timestamp = timestamp }
3884+
else
3885+
writeInt32 os timestamp // date since 1970
3886+
pdbData
3887+
38533888
writeInt32 os 0x00; // Pointer to Symbol Table Always 0
38543889
// 00000090
38553890
writeInt32 os 0x00; // Number of Symbols Always 0
@@ -4277,12 +4312,13 @@ type options =
42774312
sourceLink: string
42784313
signer: ILStrongNameSigner option
42794314
emitTailcalls : bool
4315+
deterministic : bool
42804316
showTimes: bool
42814317
dumpDebugInfo:bool }
42824318

42834319
let WriteILBinary (outfile, (args: options), modul) =
42844320
writeBinaryAndReportMappings (outfile,
42854321
args.ilg, args.pdbfile, args.signer, args.portablePDB, args.embeddedPDB, args.embedAllSource,
4286-
args.embedSourceList, args.sourceLink, args.emitTailcalls, args.showTimes, args.dumpDebugInfo) modul
4322+
args.embedSourceList, args.sourceLink, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo) modul
42874323
|> ignore
42884324

src/absil/ilwrite.fsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type options =
2525
sourceLink: string
2626
signer : ILStrongNameSigner option
2727
emitTailcalls: bool
28+
deterministic: bool
2829
showTimes : bool
2930
dumpDebugInfo : bool }
3031

src/absil/ilwritepdb.fs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ let getRowCounts tableRowCounts =
219219
tableRowCounts |> Seq.iter(fun x -> builder.Add(x))
220220
builder.MoveToImmutable()
221221

222-
let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sourceLink:string) showTimes (info:PdbData) =
222+
let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sourceLink:string) showTimes (info:PdbData) isDeterministic =
223223
sortMethods showTimes info
224224
let externalRowCounts = getRowCounts info.TableRowCounts
225225
let docs =
@@ -445,7 +445,19 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou
445445
| None -> MetadataTokens.MethodDefinitionHandle(0)
446446
| Some x -> MetadataTokens.MethodDefinitionHandle(x)
447447

448-
let serializer = PortablePdbBuilder(metadata, externalRowCounts, entryPoint, null)
448+
let deterministicIdProvider isDeterministic : System.Func<IEnumerable<Blob>, BlobContentId> =
449+
match isDeterministic with
450+
| false -> null
451+
| true ->
452+
let convert (content:IEnumerable<Blob>) =
453+
use sha = System.Security.Cryptography.SHA1.Create() // IncrementalHash is core only
454+
let hash = content
455+
|> Seq.map ( fun c -> c.GetBytes().Array |> sha.ComputeHash )
456+
|> Seq.collect id |> Array.ofSeq |> sha.ComputeHash
457+
BlobContentId.FromHash(hash)
458+
System.Func<IEnumerable<Blob>, BlobContentId>( convert )
459+
460+
let serializer = PortablePdbBuilder(metadata, externalRowCounts, entryPoint, deterministicIdProvider isDeterministic)
449461
let blobBuilder = new BlobBuilder()
450462
let contentId= serializer.Serialize(blobBuilder)
451463
let portablePdbStream = new MemoryStream()

src/absil/ilwritepdb.fsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ type idd =
8282
iddData: byte[];
8383
iddChunk: BinaryChunk }
8484

85-
val generatePortablePdb : embedAllSource:bool -> embedSourceList:string list -> sourceLink: string -> showTimes:bool -> info:PdbData -> (int64 * BlobContentId * MemoryStream)
85+
val generatePortablePdb : embedAllSource:bool -> embedSourceList:string list -> sourceLink: string -> showTimes:bool -> info:PdbData -> isDeterministic:bool -> (int64 * BlobContentId * MemoryStream)
8686
val compressPortablePdbStream : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> (int64 * BlobContentId * MemoryStream)
8787
val embedPortablePdbInfo : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> cvChunk:BinaryChunk -> pdbChunk:BinaryChunk -> idd[]
8888
val writePortablePdbInfo : contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> cvChunk:BinaryChunk -> idd[]

src/fsharp/CompileOps.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,6 +2133,7 @@ type TcConfigBuilder =
21332133
mutable optsOn : bool (* optimizations are turned on *)
21342134
mutable optSettings : Optimizer.OptimizationSettings
21352135
mutable emitTailcalls : bool
2136+
mutable deterministic : bool
21362137
#if PREFERRED_UI_LANG
21372138
mutable preferredUiLang: string option
21382139
#endif
@@ -2301,6 +2302,7 @@ type TcConfigBuilder =
23012302
optsOn = false
23022303
optSettings = Optimizer.OptimizationSettings.Defaults
23032304
emitTailcalls = true
2305+
deterministic = false
23042306
#if PREFERRED_UI_LANG
23052307
preferredUiLang = None
23062308
#endif
@@ -2791,6 +2793,7 @@ type TcConfig private (data : TcConfigBuilder,validate:bool) =
27912793
member x.doFinalSimplify = data.doFinalSimplify
27922794
member x.optSettings = data.optSettings
27932795
member x.emitTailcalls = data.emitTailcalls
2796+
member x.deterministic = data.deterministic
27942797
#if PREFERRED_UI_LANG
27952798
member x.preferredUiLang = data.preferredUiLang
27962799
#endif

src/fsharp/CompileOps.fsi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ type TcConfigBuilder =
342342
mutable optsOn : bool
343343
mutable optSettings : Optimizer.OptimizationSettings
344344
mutable emitTailcalls : bool
345+
mutable deterministic : bool
345346
#if PREFERRED_UI_LANG
346347
mutable preferredUiLang: string option
347348
#endif
@@ -494,6 +495,7 @@ type TcConfig =
494495
member doFinalSimplify : bool
495496
member optSettings : Optimizer.OptimizationSettings
496497
member emitTailcalls : bool
498+
member deterministic : bool
497499
#if PREFERRED_UI_LANG
498500
member preferredUiLang: string option
499501
#else

src/fsharp/CompileOptions.fs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,10 @@ let SetOptimizeSwitch (tcConfigB : TcConfigBuilder) switch =
420420

421421
let SetTailcallSwitch (tcConfigB : TcConfigBuilder) switch =
422422
tcConfigB.emitTailcalls <- (switch = OptionSwitch.On)
423-
423+
424+
let SetDeterministicSwitch (tcConfigB : TcConfigBuilder) switch =
425+
tcConfigB.deterministic <- (switch = OptionSwitch.On)
426+
424427
let jitoptimizeSwitch (tcConfigB : TcConfigBuilder) switch =
425428
tcConfigB.optSettings <- { tcConfigB.optSettings with jitOptUser = Some (switch = OptionSwitch.On) }
426429

@@ -676,6 +679,8 @@ let codeGenerationFlags isFsi (tcConfigB : TcConfigBuilder) =
676679
Some (FSComp.SR.optsOptimize()))
677680
CompilerOption("tailcalls", tagNone, OptionSwitch (SetTailcallSwitch tcConfigB), None,
678681
Some (FSComp.SR.optsTailcalls()))
682+
CompilerOption("deterministic", tagNone, OptionSwitch (SetDeterministicSwitch tcConfigB), None,
683+
Some (FSComp.SR.optsDeterministic()))
679684
CompilerOption("crossoptimize", tagNone, OptionSwitch (crossOptimizeSwitch tcConfigB), None,
680685
Some (FSComp.SR.optsCrossoptimize()))
681686
]

src/fsharp/FSComp.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,7 @@ optsDebugPM,"Emit debug information (Short form: -g)"
859859
optsDebug,"Specify debugging type: full, portable, embedded, pdbonly. ('%s' is the default if no debuggging type specified and enables attaching a debugger to a running program, 'portable' is a cross-platform format, 'embedded' is a cross-platform format embedded into the output file)."
860860
optsOptimize,"Enable optimizations (Short form: -O)"
861861
optsTailcalls,"Enable or disable tailcalls"
862+
optsDeterministic,"Produce a deterministic assembly (including module version GUID and timestamp)"
862863
optsCrossoptimize,"Enable or disable cross-module optimizations"
863864
optsWarnaserrorPM,"Report all warnings as errors"
864865
optsWarnaserror,"Report specific warnings as errors"
@@ -1137,6 +1138,8 @@ fscTooManyErrors,"Exiting - too many errors"
11371138
2022,pathIsInvalid,"Problem with filename '%s': Illegal characters in path."
11381139
2023,fscResxSourceFileDeprecated,"Passing a .resx file (%s) as a source file to the compiler is deprecated. Use resgen.exe to transform the .resx file into a .resources file to pass as a --resource option. If you are using MSBuild, this can be done via an <EmbeddedResource> item in the .fsproj project file."
11391140
2024,fscStaticLinkingNoProfileMismatches,"Static linking may not be used on an assembly referencing mscorlib (e.g. a .NET Framework assembly) when generating an assembly that references System.Runtime (e.g. a .NET Core or Portable assembly)."
1141+
2025,fscAssemblyWildcardAndDeterminism,"An %s specified version '%s', but this value is a wildcard, and you have requested a deterministic build, these are in conflict."
1142+
2026,fscDeterministicDebugRequiresPortablePdb,"Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded)"
11401143
3000,etIllegalCharactersInNamespaceName,"Character '%s' is not allowed in provided namespace name '%s'"
11411144
3001,etNullOrEmptyMemberName,"The provided type '%s' returned a member with a null or empty member name"
11421145
3002,etNullMember,"The provided type '%s' returned a null member"

src/fsharp/fsc.fs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ let ProcessCommandLineFlags (tcConfigB: TcConfigBuilder, setProcessThreadLocals,
249249
if not (String.IsNullOrEmpty(tcConfigB.sourceLink)) then
250250
error(Error(FSComp.SR.optsSourceLinkRequirePortablePDBs(), rangeCmdArgs))
251251

252+
if tcConfigB.deterministic && tcConfigB.debuginfo && (tcConfigB.portablePDB = false) then
253+
error(Error(FSComp.SR.fscDeterministicDebugRequiresPortablePdb(), rangeCmdArgs))
254+
252255
let inputFiles = List.rev !inputFilesRef
253256

254257
// Check if we have a codepage from the console
@@ -704,9 +707,11 @@ module AttributeHelpers =
704707
None
705708

706709
// Try to find an AssemblyVersion attribute
707-
let TryFindVersionAttribute g attrib attribName attribs =
710+
let TryFindVersionAttribute g attrib attribName attribs deterministic =
708711
match TryFindStringAttribute g attrib attribs with
709712
| Some versionString ->
713+
if deterministic && versionString.Contains("*") then
714+
errorR(Error(FSComp.SR.fscAssemblyWildcardAndDeterminism(attribName, versionString), Range.rangeStartup))
710715
try Some (IL.parseILVersion versionString)
711716
with e ->
712717
warning(Error(FSComp.SR.fscBadAssemblyVersion(attribName, versionString), Range.rangeStartup))
@@ -1810,7 +1815,7 @@ let main1(Args (ctok, tcGlobals, tcImports: TcImports, frameworkTcImports, gener
18101815

18111816
// Try to find an AssemblyVersion attribute
18121817
let assemVerFromAttrib =
1813-
match AttributeHelpers.TryFindVersionAttribute tcGlobals "System.Reflection.AssemblyVersionAttribute" "AssemblyVersionAttribute" topAttrs.assemblyAttrs with
1818+
match AttributeHelpers.TryFindVersionAttribute tcGlobals "System.Reflection.AssemblyVersionAttribute" "AssemblyVersionAttribute" topAttrs.assemblyAttrs tcConfig.deterministic with
18141819
| Some v ->
18151820
match tcConfig.version with
18161821
| VersionNone -> Some v
@@ -1896,7 +1901,7 @@ let main1OfAst (ctok, legacyReferenceResolver, openBinariesInMemory, assemblyNam
18961901

18971902
// Try to find an AssemblyVersion attribute
18981903
let assemVerFromAttrib =
1899-
match AttributeHelpers.TryFindVersionAttribute tcGlobals "System.Reflection.AssemblyVersionAttribute" "AssemblyVersionAttribute" topAttrs.assemblyAttrs with
1904+
match AttributeHelpers.TryFindVersionAttribute tcGlobals "System.Reflection.AssemblyVersionAttribute" "AssemblyVersionAttribute" topAttrs.assemblyAttrs tcConfig.deterministic with
19001905
| Some v ->
19011906
match tcConfig.version with
19021907
| VersionNone -> Some v
@@ -2016,6 +2021,7 @@ let main4 dynamicAssemblyCreator (Args (ctok, tcConfig, errorLogger: ErrorLogger
20162021
{ ilg = tcGlobals.ilg
20172022
pdbfile=pdbfile
20182023
emitTailcalls = tcConfig.emitTailcalls
2024+
deterministic = tcConfig.deterministic
20192025
showTimes = tcConfig.showTimes
20202026
portablePDB = tcConfig.portablePDB
20212027
embeddedPDB = tcConfig.embeddedPDB

0 commit comments

Comments
 (0)