From edc7e76658c5d4fb2c80c56a0f3ac7dc616e0448 Mon Sep 17 00:00:00 2001 From: saulr Date: Fri, 19 Oct 2018 14:20:03 +0100 Subject: [PATCH 1/8] Add support for --pathmap --- src/absil/ilwrite.fs | 13 ++-- src/absil/ilwrite.fsi | 4 +- src/absil/ilwritepdb.fs | 10 ++-- src/absil/ilwritepdb.fsi | 5 +- src/fsharp/CompileOps.fs | 34 ++++++++--- src/fsharp/CompileOps.fsi | 5 ++ src/fsharp/CompileOptions.fs | 10 ++++ src/fsharp/FSComp.txt | 5 +- .../FSharp.Compiler.Private.fsproj | 6 ++ src/fsharp/TastPickle.fs | 4 +- src/fsharp/TcGlobals.fs | 4 +- src/fsharp/TypeChecker.fs | 6 +- src/fsharp/fsc.fs | 11 +++- src/fsharp/fsi/fsi.fs | 2 +- src/fsharp/lexhelp.fs | 19 +++--- src/fsharp/lexhelp.fsi | 5 +- src/fsharp/service/ServiceLexing.fs | 5 +- src/fsharp/service/service.fs | 3 +- src/fsharp/xlf/FSComp.txt.cs.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.de.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.en.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.es.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.fr.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.it.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.ja.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.ko.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.pl.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.pt-BR.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.ru.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.tr.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.zh-Hans.xlf | 19 +++++- src/fsharp/xlf/FSComp.txt.zh-Hant.xlf | 19 +++++- src/utils/PathMap.fs | 60 +++++++++++++++++++ src/utils/PathMap.fsi | 22 +++++++ .../HashIfExpression.fs | 3 +- .../fsc/determinism/PathMap1/pathmap.fs | 43 +++++++++++++ .../fsc/determinism/PathMap2/pathmap.fs | 43 +++++++++++++ .../fsc/determinism/binaryCompare.fsx | 34 +++++++---- .../CompilerOptions/fsc/determinism/dummy.fs | 2 +- .../CompilerOptions/fsc/determinism/env.lst | 27 +++++++-- .../CompilerOptions/fsc/determinism/keep.lst | 1 + .../determinism/pathmapRequiresPortablePdb.fs | 3 + .../fsc/determinism/pathmapValid.fs | 3 + .../fsc/determinism/portablePdbOnly.fs | 2 +- .../Source/CompilerOptions/fsc/pdb/env.lst | 2 +- tests/fsharpqa/Source/run.pl | 19 +++--- tests/fsharpqa/fsharpqafiles.csproj | 1 + tests/fsharpqa/run.fsharpqa.test.fsx | 59 ++++++++++-------- 48 files changed, 615 insertions(+), 126 deletions(-) create mode 100644 src/utils/PathMap.fs create mode 100644 src/utils/PathMap.fsi create mode 100644 tests/fsharpqa/Source/CompilerOptions/fsc/determinism/PathMap1/pathmap.fs create mode 100644 tests/fsharpqa/Source/CompilerOptions/fsc/determinism/PathMap2/pathmap.fs create mode 100644 tests/fsharpqa/Source/CompilerOptions/fsc/determinism/keep.lst create mode 100644 tests/fsharpqa/Source/CompilerOptions/fsc/determinism/pathmapRequiresPortablePdb.fs create mode 100644 tests/fsharpqa/Source/CompilerOptions/fsc/determinism/pathmapValid.fs diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs index d28348bf860..1ab417b24a0 100644 --- a/src/absil/ilwrite.fs +++ b/src/absil/ilwrite.fs @@ -3509,8 +3509,8 @@ let writeDirectory os dict = let writeBytes (os: BinaryWriter) (chunk:byte[]) = os.Write(chunk, 0, chunk.Length) let writeBinaryAndReportMappings (outfile, - ilg: ILGlobals, pdbfile: string option, signer: ILStrongNameSigner option, portablePDB, embeddedPDB, - embedAllSource, embedSourceList, sourceLink, emitTailcalls, deterministic, showTimes, dumpDebugInfo ) + ilg: ILGlobals, pdbfile: string option, signer: ILStrongNameSigner option, portablePDB, embeddedPDB, + embedAllSource, embedSourceList, sourceLink, emitTailcalls, deterministic, showTimes, dumpDebugInfo, pathMap) modul normalizeAssemblyRefs = // Store the public key from the signer into the manifest. This means it will be written // to the binary and also acts as an indicator to leave space for delay sign @@ -3664,7 +3664,7 @@ let writeBinaryAndReportMappings (outfile, let pdbOpt = match portablePDB with | true -> - let (uncompressedLength, contentId, stream) as pdbStream = generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic + let (uncompressedLength, contentId, stream) as pdbStream = generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic pathMap if embeddedPDB then Some (compressPortablePdbStream uncompressedLength contentId stream) else Some (pdbStream) | _ -> None @@ -4199,7 +4199,7 @@ let writeBinaryAndReportMappings (outfile, if embeddedPDB then embedPortablePdbInfo originalLength contentId stream showTimes fpdb debugDataChunk debugEmbeddedPdbChunk else - writePortablePdbInfo contentId stream showTimes fpdb debugDataChunk + writePortablePdbInfo contentId stream showTimes fpdb pathMap debugDataChunk | None -> #if FX_NO_PDB_WRITER Array.empty @@ -4272,10 +4272,11 @@ type options = emitTailcalls : bool deterministic : bool showTimes: bool - dumpDebugInfo:bool } + dumpDebugInfo:bool + pathMap: PathMap } let WriteILBinary (outfile, (args: options), modul, normalizeAssemblyRefs) = writeBinaryAndReportMappings (outfile, args.ilg, args.pdbfile, args.signer, args.portablePDB, args.embeddedPDB, args.embedAllSource, - args.embedSourceList, args.sourceLink, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo) modul normalizeAssemblyRefs + args.embedSourceList, args.sourceLink, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo, args.pathMap) modul normalizeAssemblyRefs |> ignore diff --git a/src/absil/ilwrite.fsi b/src/absil/ilwrite.fsi index fc23d028bd5..666fd60f206 100644 --- a/src/absil/ilwrite.fsi +++ b/src/absil/ilwrite.fsi @@ -3,6 +3,7 @@ /// The IL Binary writer. module internal Microsoft.FSharp.Compiler.AbstractIL.ILBinaryWriter +open Internal.Utilities open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.IL @@ -27,7 +28,8 @@ type options = emitTailcalls: bool deterministic: bool showTimes : bool - dumpDebugInfo : bool } + dumpDebugInfo : bool + pathMap : PathMap } /// Write a binary to the file system. Extra configuration parameters can also be specified. val WriteILBinary: filename: string * options: options * input: ILModuleDef * (ILAssemblyRef -> ILAssemblyRef) -> unit diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 61771a9b2de..d8c41302c35 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -129,7 +129,7 @@ type idd = // Portable PDB Writer //--------------------------------------------------------------------- let cvMagicNumber = 0x53445352L -let pdbGetCvDebugInfo (mvid:byte[]) (timestamp:int32) (filepath:string) (cvChunk:BinaryChunk) = +let pdbGetCvDebugInfo (mvid:byte[]) (timestamp:int32) (filepath:string) (cvChunk:BinaryChunk) = let iddCvBuffer = // Debug directory entry let path = (System.Text.Encoding.UTF8.GetBytes filepath) @@ -219,7 +219,7 @@ let getRowCounts tableRowCounts = tableRowCounts |> Seq.iter(fun x -> builder.Add(x)) builder.MoveToImmutable() -let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sourceLink:string) showTimes (info:PdbData) isDeterministic = +let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sourceLink:string) showTimes (info:PdbData) isDeterministic (pathMap:PathMap) = sortMethods showTimes info let externalRowCounts = getRowCounts info.TableRowCounts let docs = @@ -229,6 +229,8 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou let metadata = MetadataBuilder() let serializeDocumentName (name:string) = + let name = PathMap.apply pathMap name + let count s c = s |> Seq.filter(fun ch -> if c = ch then true else false) |> Seq.length let s1, s2 = '/', '\\' @@ -474,12 +476,12 @@ let compressPortablePdbStream (uncompressedLength:int64) (contentId:BlobContentI stream.WriteTo(compressionStream) (uncompressedLength, contentId, compressedStream) -let writePortablePdbInfo (contentId:BlobContentId) (stream:MemoryStream) showTimes fpdb cvChunk = +let writePortablePdbInfo (contentId:BlobContentId) (stream:MemoryStream) showTimes fpdb pathMap cvChunk = try FileSystem.FileDelete fpdb with _ -> () use pdbFile = new FileStream(fpdb, FileMode.Create, FileAccess.ReadWrite) stream.WriteTo(pdbFile) reportTime showTimes "PDB: Closed" - pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) fpdb cvChunk None 0L None + pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) (PathMap.apply pathMap fpdb) cvChunk None 0L None let embedPortablePdbInfo (uncompressedLength:int64) (contentId:BlobContentId) (stream:MemoryStream) showTimes fpdb cvChunk pdbChunk = reportTime showTimes "PDB: Closed" diff --git a/src/absil/ilwritepdb.fsi b/src/absil/ilwritepdb.fsi index af9f16be9e8..146c2256be7 100644 --- a/src/absil/ilwritepdb.fsi +++ b/src/absil/ilwritepdb.fsi @@ -3,6 +3,7 @@ /// The ILPdbWriter module internal Microsoft.FSharp.Compiler.AbstractIL.ILPdbWriter +open Internal.Utilities open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.Range @@ -82,10 +83,10 @@ type idd = iddData: byte[]; iddChunk: BinaryChunk } -val generatePortablePdb : embedAllSource:bool -> embedSourceList:string list -> sourceLink: string -> showTimes:bool -> info:PdbData -> isDeterministic:bool -> (int64 * BlobContentId * MemoryStream) +val generatePortablePdb : embedAllSource:bool -> embedSourceList:string list -> sourceLink: string -> showTimes:bool -> info:PdbData -> isDeterministic:bool -> pathMap:PathMap -> (int64 * BlobContentId * MemoryStream) val compressPortablePdbStream : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> (int64 * BlobContentId * MemoryStream) val embedPortablePdbInfo : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> cvChunk:BinaryChunk -> pdbChunk:BinaryChunk -> idd[] -val writePortablePdbInfo : contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> cvChunk:BinaryChunk -> idd[] +val writePortablePdbInfo : contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> pathMap:PathMap -> cvChunk:BinaryChunk -> idd[] #if !FX_NO_PDB_WRITER val writePdbInfo : showTimes:bool -> f:string -> fpdb:string -> info:PdbData -> cvChunk:BinaryChunk -> idd[] diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 3517d044284..ab0dc7d762d 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -2348,6 +2348,8 @@ type TcConfigBuilder = mutable tryGetMetadataSnapshot : ILReaderTryGetMetadataSnapshot mutable internalTestSpanStackReferring : bool + + mutable pathMap : PathMap } static member Initial = @@ -2485,6 +2487,7 @@ type TcConfigBuilder = shadowCopyReferences = false tryGetMetadataSnapshot = (fun _ -> None) internalTestSpanStackReferring = false + pathMap = PathMap.empty } static member CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir, reduceMemoryUsage, implicitIncludeDir, @@ -2608,6 +2611,9 @@ type TcConfigBuilder = member tcConfigB.RemoveReferencedAssemblyByPath (m, path) = tcConfigB.referencedDLLs <- tcConfigB.referencedDLLs |> List.filter (fun ar-> ar.Range <> m || ar.Text <> path) + + member tcConfigB.AddPathMapping (oldPrefix, newPrefix) = + tcConfigB.pathMap <- tcConfigB.pathMap |> PathMap.addMapping oldPrefix newPrefix static member SplitCommandLineResourceInfo (ri:string) = let p = ri.IndexOf ',' @@ -2925,6 +2931,7 @@ type TcConfig private (data : TcConfigBuilder, validate:bool) = member x.optSettings = data.optSettings member x.emitTailcalls = data.emitTailcalls member x.deterministic = data.deterministic + member x.pathMap = data.pathMap member x.preferredUiLang = data.preferredUiLang member x.lcid = data.lcid member x.optsOn = data.optsOn @@ -3580,7 +3587,7 @@ let ParseOneInputLexbuf (tcConfig:TcConfig, lexResourceManager, conditionalCompi try let skip = true in (* don't report whitespace from lexer *) let lightSyntaxStatus = LightSyntaxStatus (tcConfig.ComputeLightSyntaxInitialStatus(filename), true) - let lexargs = mkLexargs (filename, conditionalCompilationDefines@tcConfig.conditionalCompilationDefines, lightSyntaxStatus, lexResourceManager, ref [], errorLogger) + let lexargs = mkLexargs (filename, conditionalCompilationDefines@tcConfig.conditionalCompilationDefines, lightSyntaxStatus, lexResourceManager, ref [], errorLogger, tcConfig.pathMap) let shortFilename = SanitizeFileName filename tcConfig.implicitIncludeDir let input = Lexhelp.usingLexbufForParsing (lexbuf, filename) (fun lexbuf -> @@ -3782,7 +3789,9 @@ let MakeILResource rname bytes = CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs MetadataIndex = NoMetadataIdx } -let PickleToResource inMem file g scope rname p x = +let PickleToResource inMem file (g: TcGlobals) scope rname p x = + let file = PathMap.apply g.pathMap file + { Name = rname Location = (let bytes = pickleObjWithDanglingCcus inMem file g scope p x in ILResourceLocation.LocalOut bytes) Access = ILResourceAccess.Public @@ -3792,15 +3801,23 @@ let PickleToResource inMem file g scope rname p x = let GetSignatureData (file, ilScopeRef, ilModule, byteReader) : PickledDataWithReferences = unpickleObjWithDanglingCcus file ilScopeRef ilModule unpickleCcuInfo (byteReader()) -let WriteSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, ccu: CcuThunk, file, inMem) : ILResource = +let WriteSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, ccu: CcuThunk, file, inMem) : ILResource = let mspec = ccu.Contents let mspec = ApplyExportRemappingToEntity tcGlobals exportRemapping mspec // For historical reasons, we use a different resource name for FSharp.Core, so older F# compilers // don't complain when they see the resource. - let rname = if ccu.AssemblyName = GetFSharpCoreLibraryName() then FSharpSignatureDataResourceName2 else FSharpSignatureDataResourceName + let rname = if ccu.AssemblyName = GetFSharpCoreLibraryName() then FSharpSignatureDataResourceName2 else FSharpSignatureDataResourceName + + let includeDir = + if String.IsNullOrEmpty tcConfig.implicitIncludeDir then "" + else + tcConfig.implicitIncludeDir + |> System.IO.Path.GetFullPath + |> PathMap.applyDir tcGlobals.pathMap + PickleToResource inMem file tcGlobals ccu (rname+ccu.AssemblyName) pickleCcuInfo { mspec=mspec - compileTimeWorkingDir=tcConfig.implicitIncludeDir + compileTimeWorkingDir=includeDir usesQuotations = ccu.UsesFSharp20PlusQuotations } let GetOptimizationData (file, ilScopeRef, ilModule, byteReader) = @@ -3809,7 +3826,7 @@ let GetOptimizationData (file, ilScopeRef, ilModule, byteReader) = let WriteOptimizationData (tcGlobals, file, inMem, ccu: CcuThunk, modulInfo) = // For historical reasons, we use a different resource name for FSharp.Core, so older F# compilers // don't complain when they see the resource. - let rname = if ccu.AssemblyName = GetFSharpCoreLibraryName() then FSharpOptimizationDataResourceName2 else FSharpOptimizationDataResourceName + let rname = if ccu.AssemblyName = GetFSharpCoreLibraryName() then FSharpOptimizationDataResourceName2 else FSharpOptimizationDataResourceName PickleToResource inMem file tcGlobals ccu (rname+ccu.AssemblyName) Optimizer.p_CcuOptimizationInfo modulInfo //---------------------------------------------------------------------------- @@ -4770,8 +4787,9 @@ type TcImports(tcConfigP:TcConfigProvider, initialResolutions:TcAssemblyResoluti // OK, now we have both mscorlib.dll and FSharp.Core.dll we can create TcGlobals let tcGlobals = TcGlobals(tcConfig.compilingFslib, ilGlobals, fslibCcu, - tcConfig.implicitIncludeDir, tcConfig.mlCompatibility, - tcConfig.isInteractive, tryFindSysTypeCcu, tcConfig.emitDebugInfoInQuotations, tcConfig.noDebugData ) + tcConfig.implicitIncludeDir, tcConfig.mlCompatibility, + tcConfig.isInteractive, tryFindSysTypeCcu, tcConfig.emitDebugInfoInQuotations, + tcConfig.noDebugData, tcConfig.pathMap) #if DEBUG // the global_g reference cell is used only for debug printing diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index eb371fa5927..2918b497051 100755 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -6,6 +6,7 @@ module internal Microsoft.FSharp.Compiler.CompileOps open System open System.Text open System.Collections.Generic +open Internal.Utilities open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.ILBinaryReader @@ -366,6 +367,8 @@ type TcConfigBuilder = /// if true - 'let mutable x = Span.Empty', the value 'x' is a stack referring span. Used for internal testing purposes only until we get true stack spans. mutable internalTestSpanStackReferring : bool + + mutable pathMap : PathMap } static member Initial: TcConfigBuilder @@ -389,6 +392,7 @@ type TcConfigBuilder = member RemoveReferencedAssemblyByPath: range * string -> unit member AddEmbeddedSourceFile: string -> unit member AddEmbeddedResource: string -> unit + member AddPathMapping: oldPrefix: string * newPrefix: string -> unit static member SplitCommandLineResourceInfo: string -> string * string * ILResourceAccess @@ -491,6 +495,7 @@ type TcConfig = member optSettings : Optimizer.OptimizationSettings member emitTailcalls: bool member deterministic: bool + member pathMap: PathMap member preferredUiLang: string option member optsOn : bool member productNameForBannerText: string diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index 6ae18644dea..856f132c4b2 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -422,6 +422,13 @@ let SetTailcallSwitch (tcConfigB : TcConfigBuilder) switch = let SetDeterministicSwitch (tcConfigB : TcConfigBuilder) switch = tcConfigB.deterministic <- (switch = OptionSwitch.On) +let AddPathMapping (tcConfigB : TcConfigBuilder) (pathPair : string) = + match pathPair.Split([|'='|], 2) with + | [| oldPrefix; newPrefix |] -> + tcConfigB.AddPathMapping (oldPrefix, newPrefix) + | _ -> + error(Error(FSComp.SR.optsInvalidPathMapFormat(), rangeCmdArgs)) + let jitoptimizeSwitch (tcConfigB : TcConfigBuilder) switch = tcConfigB.optSettings <- { tcConfigB.optSettings with jitOptUser = Some (switch = OptionSwitch.On) } @@ -507,6 +514,7 @@ let tagWarnList = "" let tagSymbolList = "" let tagAddress = "
" let tagInt = "" +let tagPathMap = "" let tagNone = "" // PrintOptionInfo @@ -700,6 +708,8 @@ let codeGenerationFlags isFsi (tcConfigB : TcConfigBuilder) = Some (FSComp.SR.optsTailcalls())) CompilerOption("deterministic", tagNone, OptionSwitch (SetDeterministicSwitch tcConfigB), None, Some (FSComp.SR.optsDeterministic())) + CompilerOption("pathmap", tagPathMap, OptionStringList (AddPathMapping tcConfigB), None, + Some (FSComp.SR.optsPathMap())) CompilerOption("crossoptimize", tagNone, OptionSwitch (crossOptimizeSwitch tcConfigB), None, Some (FSComp.SR.optsCrossoptimize())) ] diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index a3f5f82d0ea..90bf59ba6b2 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -856,6 +856,7 @@ optsDebug,"Specify debugging type: full, portable, embedded, pdbonly. ('%s' is t optsOptimize,"Enable optimizations (Short form: -O)" optsTailcalls,"Enable or disable tailcalls" optsDeterministic,"Produce a deterministic assembly (including module version GUID and timestamp)" +optsPathMap,"Maps physical paths to source path names output by the compiler" optsCrossoptimize,"Enable or disable cross-module optimizations" optsWarnaserrorPM,"Report all warnings as errors" optsWarnaserror,"Report specific warnings as errors" @@ -1135,7 +1136,9 @@ fscTooManyErrors,"Exiting - too many errors" 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 item in the .fsproj project file." 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)." 2025,fscAssemblyWildcardAndDeterminism,"An %s specified version '%s', but this value is a wildcard, and you have requested a deterministic build, these are in conflict." -2026,fscDeterministicDebugRequiresPortablePdb,"Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded)" +2026,fscDeterministicDebugRequiresPortablePdb,"Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded)" +2027,fscPathMapDebugRequiresPortablePdb,"--pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded)" +2028,optsInvalidPathMapFormat,"Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath'" 3000,etIllegalCharactersInNamespaceName,"Character '%s' is not allowed in provided namespace name '%s'" 3001,etNullOrEmptyMemberName,"The provided type '%s' returned a member with a null or empty member name" 3002,etNullMember,"The provided type '%s' returned a null member" diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index 0c72713522c..3722e3c4e35 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -170,6 +170,12 @@ Utilities\rational.fs + + Utilities\PathMap.fsi + + + Utilities\PathMap.fs + ErrorLogging\range.fsi diff --git a/src/fsharp/TastPickle.fs b/src/fsharp/TastPickle.fs index 3f184165ad2..7d59cb1b07c 100755 --- a/src/fsharp/TastPickle.fs +++ b/src/fsharp/TastPickle.fs @@ -1226,7 +1226,9 @@ let u_qlist uv = u_wrap QueueList.ofList (u_list uv) let u_namemap u = u_Map u_string u let p_pos (x: pos) st = p_tup2 p_int p_int (x.Line,x.Column) st -let p_range (x: range) st = p_tup3 p_string p_pos p_pos (x.FileName, x.Start, x.End) st +let p_range (x: range) st = + let fileName = PathMap.apply st.oglobals.pathMap x.FileName + p_tup3 p_string p_pos p_pos (fileName, x.Start, x.End) st let p_dummy_range : range pickler = fun _x _st -> () let p_ident (x: Ident) st = p_tup2 p_string p_range (x.idText,x.idRange) st let p_xmldoc (XmlDoc x) st = p_array p_string x st diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index d6fb7cd3c73..cf48e31ef7a 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -179,7 +179,8 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d mlCompatibility: bool, isInteractive:bool, // The helper to find system types amongst referenced DLLs tryFindSysTypeCcu, - emitDebugInfoInQuotations: bool, noDebugData: bool) = + emitDebugInfoInQuotations: bool, noDebugData: bool, + pathMap: PathMap) = let vara = NewRigidTypar "a" envRange let varb = NewRigidTypar "b" envRange @@ -901,6 +902,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member __.mlCompatibility = mlCompatibility member __.emitDebugInfoInQuotations = emitDebugInfoInQuotations member __.directoryToResolveRelativePaths= directoryToResolveRelativePaths + member __.pathMap = pathMap member __.unionCaseRefEq x y = primUnionCaseRefEq compilingFslib fslibCcu x y member __.valRefEq x y = primValRefEq compilingFslib fslibCcu x y member __.fslibCcu = fslibCcu diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index c558602ffa9..597ff1c6c8a 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9925,7 +9925,8 @@ and TcMethodApplication | CallerLineNumber, _ when typeEquiv cenv.g currCalledArgTy cenv.g.int_ty -> emptyPreBinder, Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) | CallerFilePath, _ when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> - emptyPreBinder, Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, currCalledArgTy) + let fileName = mMethExpr.FileName |> System.IO.Path.GetFullPath |> PathMap.apply cenv.g.pathMap + emptyPreBinder, Expr.Const(Const.String(fileName), mMethExpr, currCalledArgTy) | CallerMemberName, Some(callerName) when (typeEquiv cenv.g currCalledArgTy cenv.g.string_ty) -> emptyPreBinder, Expr.Const(Const.String(callerName), mMethExpr, currCalledArgTy) | _ -> @@ -9964,7 +9965,8 @@ and TcMethodApplication let lineExpr = Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, calledNonOptTy) emptyPreBinder, mkUnionCaseExpr(mkSomeCase cenv.g, [calledNonOptTy], [lineExpr], mMethExpr) | CallerFilePath, _ when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> - let filePathExpr = Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, calledNonOptTy) + let fileName = mMethExpr.FileName |> System.IO.Path.GetFullPath |> PathMap.apply cenv.g.pathMap + let filePathExpr = Expr.Const(Const.String(fileName), mMethExpr, calledNonOptTy) emptyPreBinder, mkUnionCaseExpr(mkSomeCase cenv.g, [calledNonOptTy], [filePathExpr], mMethExpr) | CallerMemberName, Some(callerName) when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> let memberNameExpr = Expr.Const(Const.String(callerName), mMethExpr, calledNonOptTy) diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index e418b1bb9b1..dd9a410e057 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -242,8 +242,12 @@ let ProcessCommandLineFlags (tcConfigB: TcConfigBuilder, setProcessThreadLocals, if not (String.IsNullOrEmpty(tcConfigB.sourceLink)) then error(Error(FSComp.SR.optsSourceLinkRequirePortablePDBs(), rangeCmdArgs)) - if tcConfigB.deterministic && tcConfigB.debuginfo && (tcConfigB.portablePDB = false) then - error(Error(FSComp.SR.fscDeterministicDebugRequiresPortablePdb(), rangeCmdArgs)) + if tcConfigB.debuginfo && not tcConfigB.portablePDB then + if tcConfigB.deterministic then + error(Error(FSComp.SR.fscDeterministicDebugRequiresPortablePdb(), rangeCmdArgs)) + + if tcConfigB.pathMap <> PathMap.empty then + error(Error(FSComp.SR.fscPathMapDebugRequiresPortablePdb(), rangeCmdArgs)) let inputFiles = List.rev !inputFilesRef @@ -2066,7 +2070,8 @@ let main4 dynamicAssemblyCreator (Args (ctok, tcConfig, tcImports: TcImports, t embedSourceList = tcConfig.embedSourceList sourceLink = tcConfig.sourceLink signer = GetStrongNameSigner signingInfo - dumpDebugInfo = tcConfig.dumpDebugInfo }, + dumpDebugInfo = tcConfig.dumpDebugInfo + pathMap = tcConfig.pathMap }, ilxMainModule, normalizeAssemblyRefs ) diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index eb926991dc1..1fec1695a68 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1768,7 +1768,7 @@ type internal FsiStdinLexerProvider Lexhelp.resetLexbufPos sourceFileName lexbuf let skip = true // don't report whitespace from lexer let defines = "INTERACTIVE"::tcConfigB.conditionalCompilationDefines - let lexargs = mkLexargs (sourceFileName,defines, interactiveInputLightSyntaxStatus, lexResourceManager, ref [], errorLogger) + let lexargs = mkLexargs (sourceFileName,defines, interactiveInputLightSyntaxStatus, lexResourceManager, ref [], errorLogger, PathMap.empty) let tokenizer = LexFilter.LexFilter(interactiveInputLightSyntaxStatus, tcConfigB.compilingFslib, Lexer.token lexargs skip, lexbuf) tokenizer diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index b7603baf15f..d868cc17274 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -58,7 +58,8 @@ type lexargs = resourceManager: LexResourceManager lightSyntaxStatus : LightSyntaxStatus errorLogger: ErrorLogger - applyLineDirectives: bool } + applyLineDirectives: bool + pathMap: PathMap } /// possible results of lexing a long unicode escape sequence in a string literal, e.g. "\UDEADBEEF" type LongUnicodeLexResult = @@ -66,13 +67,14 @@ type LongUnicodeLexResult = | SingleChar of uint16 | Invalid -let mkLexargs (_filename, defines, lightSyntaxStatus, resourceManager, ifdefStack, errorLogger) = +let mkLexargs (_filename, defines, lightSyntaxStatus, resourceManager, ifdefStack, errorLogger, pathMap:PathMap) = { defines = defines ifdefStack= ifdefStack lightSyntaxStatus=lightSyntaxStatus resourceManager=resourceManager errorLogger=errorLogger - applyLineDirectives=true } + applyLineDirectives=true + pathMap=pathMap } /// Register the lexbuf and call the given function let reusingLexbufForParsing lexbuf f = @@ -327,16 +329,19 @@ module Keywords = match s with | "__SOURCE_DIRECTORY__" -> let filename = fileOfFileIndex lexbuf.StartPos.FileIndex - let dirname = + let dirname = if String.IsNullOrWhiteSpace(filename) then String.Empty else if filename = stdinMockFilename then System.IO.Directory.GetCurrentDirectory() else - filename + filename |> FileSystem.GetFullPathShim (* asserts that path is already absolute *) |> System.IO.Path.GetDirectoryName - KEYWORD_STRING dirname + + if String.IsNullOrEmpty dirname then dirname + else PathMap.applyDir args.pathMap dirname + |> KEYWORD_STRING | "__SOURCE_FILE__" -> KEYWORD_STRING (System.IO.Path.GetFileName((fileOfFileIndex lexbuf.StartPos.FileIndex))) | "__LINE__" -> @@ -439,4 +444,4 @@ module Keywords = "<@", FSComp.SR.keywordDescriptionTypedQuotation() "@>", FSComp.SR.keywordDescriptionTypedQuotation() "<@@", FSComp.SR.keywordDescriptionUntypedQuotation() - "@@>", FSComp.SR.keywordDescriptionUntypedQuotation() ] \ No newline at end of file + "@@>", FSComp.SR.keywordDescriptionUntypedQuotation() ] diff --git a/src/fsharp/lexhelp.fsi b/src/fsharp/lexhelp.fsi index 5c534fd7b38..69c87d3da9e 100644 --- a/src/fsharp/lexhelp.fsi +++ b/src/fsharp/lexhelp.fsi @@ -33,7 +33,8 @@ type lexargs = resourceManager: LexResourceManager lightSyntaxStatus : LightSyntaxStatus errorLogger: ErrorLogger - applyLineDirectives: bool } + applyLineDirectives: bool + pathMap: PathMap } type LongUnicodeLexResult = | SurrogatePair of uint16 * uint16 @@ -41,7 +42,7 @@ type LongUnicodeLexResult = | Invalid val resetLexbufPos : string -> UnicodeLexing.Lexbuf -> unit -val mkLexargs : 'a * string list * LightSyntaxStatus * LexResourceManager * LexerIfdefStack * ErrorLogger -> lexargs +val mkLexargs : 'a * string list * LightSyntaxStatus * LexResourceManager * LexerIfdefStack * ErrorLogger * PathMap -> lexargs val reusingLexbufForParsing : UnicodeLexing.Lexbuf -> (unit -> 'a) -> 'a val usingLexbufForParsing : UnicodeLexing.Lexbuf * string -> (UnicodeLexing.Lexbuf -> 'a) -> 'a diff --git a/src/fsharp/service/ServiceLexing.fs b/src/fsharp/service/ServiceLexing.fs index abf3cde1c70..0b7216c2e42 100755 --- a/src/fsharp/service/ServiceLexing.fs +++ b/src/fsharp/service/ServiceLexing.fs @@ -17,6 +17,7 @@ open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.Lexhelp open Microsoft.FSharp.Compiler.Lib +open Internal.Utilities type Position = int * int type Range = Position * Position @@ -755,8 +756,8 @@ type FSharpLineTokenizer(lexbuf: UnicodeLexing.Lexbuf, type FSharpSourceTokenizer(defineConstants : string list, filename : Option) = let lexResourceManager = new Lexhelp.LexResourceManager() - let lexArgsLightOn = mkLexargs(filename,defineConstants,LightSyntaxStatus(true,false),lexResourceManager, ref [],DiscardErrorsLogger) - let lexArgsLightOff = mkLexargs(filename,defineConstants,LightSyntaxStatus(false,false),lexResourceManager, ref [],DiscardErrorsLogger) + let lexArgsLightOn = mkLexargs(filename,defineConstants,LightSyntaxStatus(true,false),lexResourceManager, ref [],DiscardErrorsLogger, PathMap.empty) + let lexArgsLightOff = mkLexargs(filename,defineConstants,LightSyntaxStatus(false,false),lexResourceManager, ref [],DiscardErrorsLogger, PathMap.empty) member this.CreateLineTokenizer(lineText: string) = let lexbuf = UnicodeLexing.StringAsLexbuf lineText diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index be7157ddde7..f390d4d3de4 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -1539,7 +1539,8 @@ module internal Parser = let lexResourceManager = new Lexhelp.LexResourceManager() // When analyzing files using ParseOneFile, i.e. for the use of editing clients, we do not apply line directives. - let lexargs = mkLexargs(fileName, defines, lightSyntaxStatus, lexResourceManager, ref [], errHandler.ErrorLogger) + // TODO(pathmap): expose PathMap on the service API, and thread it through here + let lexargs = mkLexargs(fileName, defines, lightSyntaxStatus, lexResourceManager, ref [], errHandler.ErrorLogger, PathMap.empty) let lexargs = { lexargs with applyLineDirectives = false } let tokenizer = LexFilter.LexFilter(lightSyntaxStatus, options.CompilingFsLib, Lexer.token lexargs true, lexbuf) diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index 1c840d2c66e..3fa60241ed6 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - Deterministická sestavení podporují jenom soubory PDB typu Portable (--debug:portable nebo --debug:embedded). + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + Deterministická sestavení podporují jenom soubory PDB typu Portable (--debug:portable nebo --debug:embedded). @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index cd09b539e4b..4a2e146164e 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - Deterministische Builds unterstützen nur portierbare PDbs ("--debug:portable" oder "--debug:embedded"). + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + Deterministische Builds unterstützen nur portierbare PDbs ("--debug:portable" oder "--debug:embedded"). @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.en.xlf b/src/fsharp/xlf/FSComp.txt.en.xlf index 69e90b775be..38acd6dbe56 100644 --- a/src/fsharp/xlf/FSComp.txt.en.xlf +++ b/src/fsharp/xlf/FSComp.txt.en.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index cab140a050a..4aec947a10b 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - Las compilaciones deterministas solo admiten PDB portátiles (--debug:portable o --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + Las compilaciones deterministas solo admiten PDB portátiles (--debug:portable o --debug:embedded) @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index 0ef363d31e4..be887a3a73e 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - Les builds déterministes ne prennent en charge que les fichiers PDB portables (--debug:portable ou --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + Les builds déterministes ne prennent en charge que les fichiers PDB portables (--debug:portable ou --debug:embedded) @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index 5c224442175..333ee0d1a06 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - Le compilazioni deterministiche supportano solo file PDB portatili (--debug:portable o --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + Le compilazioni deterministiche supportano solo file PDB portatili (--debug:portable o --debug:embedded) @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index 168cd7d6efb..27174329d93 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - 決定論的ビルドはポータブル PDB のみをサポートします (--debug:portable または --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + 決定論的ビルドはポータブル PDB のみをサポートします (--debug:portable または --debug:embedded) @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index 3dd8fa16415..39dcaa393d9 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - 결정적 빌드는 이식 가능한 PDB만 지원합니다(--debug:portable 또는 --debug:embedded). + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + 결정적 빌드는 이식 가능한 PDB만 지원합니다(--debug:portable 또는 --debug:embedded). @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index a2e4ad8a2b5..d3a33c9d9f9 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - Kompilacje deterministyczne obsługują tylko przenośne pliki PDB (--debug:portable lub --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + Kompilacje deterministyczne obsługują tylko przenośne pliki PDB (--debug:portable lub --debug:embedded) @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index b81572e3a73..8dadb50d7e5 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - Compilações determinísticas dão suporte somente a PDBs portáteis (--debug:portable ou --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + Compilações determinísticas dão suporte somente a PDBs portáteis (--debug:portable ou --debug:embedded) @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index e3b2d9f4b51..10062d8da63 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - Детерминированные сборки поддерживают только переносимые PDB-файлы (--debug:portable или --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + Детерминированные сборки поддерживают только переносимые PDB-файлы (--debug:portable или --debug:embedded) @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index 9c9f740dcb7..dee9d614a6b 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - Belirleyici derlemeler yalnızca taşınabilir PDB'leri (--debug:portable veya --debug:embedded) destekler + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + Belirleyici derlemeler yalnızca taşınabilir PDB'leri (--debug:portable veya --debug:embedded) destekler @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index 180d2f95b6a..b097b04211d 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - 确定性的生成仅支持可移植 PDB (--debug:portable 或 --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + 确定性的生成仅支持可移植 PDB (--debug:portable 或 --debug:embedded) @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 6e0f7e50c20..a3a8762de7f 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -5543,8 +5543,8 @@ - Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded) - 確定性組建僅支援可攜式 PDB (--debug:portable 或 --debug:embedded) + Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded) + 確定性組建僅支援可攜式 PDB (--debug:portable 或 --debug:embedded) @@ -7082,6 +7082,21 @@ Active patterns do not have fields. This syntax is invalid. + + Maps physical paths to source path names output by the compiler + Maps physical paths to source path names output by the compiler + + + + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + --pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded) + + + + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath' + + \ No newline at end of file diff --git a/src/utils/PathMap.fs b/src/utils/PathMap.fs new file mode 100644 index 00000000000..3e4f6fad96c --- /dev/null +++ b/src/utils/PathMap.fs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +/// Functions to map real paths to paths to be written to PDB/IL +namespace Internal.Utilities + +open System +open System.IO + +type PathMap = PathMap of Map + +[] +module internal PathMap = + + let dirSepStr = Path.DirectorySeparatorChar.ToString() + + let empty = PathMap Map.empty + + let addMapping (src : string) (dst : string) (PathMap map) : PathMap = + // Normalise the path + let normalSrc = Path.GetFullPath src + + let oldPrefix = + if normalSrc.EndsWith dirSepStr then normalSrc + else normalSrc + dirSepStr + + // Always add a path separator + map |> Map.add oldPrefix dst |> PathMap + + // Map a file path with its replacement. + // This logic replicates C#'s PathUtilities.NormalizePathPrefix + let apply (PathMap map) (filePath : string) : string = + // Find the first key in the path map that matches a prefix of the + // normalized path. We expect the client to use consistent capitalization; + // we use ordinal (case-sensitive) comparisons. + map + |> Map.tryPick (fun oldPrefix replacementPrefix -> + // oldPrefix always ends with a path separator, so there's no need + // to check if it was a partial match + // e.g. for the map /goo=/bar and filename /goooo + if filePath.StartsWith(oldPrefix, StringComparison.Ordinal) then + let replacement = replacementPrefix + filePath.Substring (oldPrefix.Length - 1) + + // Normalize the path separators if used uniformly in the replacement + let hasSlash = replacementPrefix.IndexOf '/' >= 0 + let hasBackslash = replacementPrefix.IndexOf '\\' >= 0 + + if hasSlash && not hasBackslash then replacement.Replace('\\', '/') + elif hasBackslash && not hasSlash then replacement.Replace('/', '\\') + else replacement + |> Some + else + None + ) + |> Option.defaultValue filePath + + let applyDir pathMap (dirName : string) : string = + if dirName.EndsWith dirSepStr then apply pathMap dirName + else + let mapped = apply pathMap (dirName + dirSepStr) + mapped.TrimEnd (Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) diff --git a/src/utils/PathMap.fsi b/src/utils/PathMap.fsi new file mode 100644 index 00000000000..8cf4e2f2485 --- /dev/null +++ b/src/utils/PathMap.fsi @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +/// Functions to map real paths to paths to be written to PDB/IL +namespace Internal.Utilities + +type PathMap + +[] +module internal PathMap = + + val empty : PathMap + + /// Add a path mapping to the map. + val addMapping : string -> string -> PathMap -> PathMap + + /// Map a file path with its replacement. + /// Prefixes are compared case sensitively. + val apply : PathMap -> string -> string + + /// Map a directory name with its replacement. + /// Prefixes are compared case sensitively. + val applyDir : PathMap -> string -> string diff --git a/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs b/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs index 7e9139bc30f..1e6b752986d 100644 --- a/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs +++ b/tests/FSharp.Compiler.UnitTests/HashIfExpression.fs @@ -14,6 +14,7 @@ open Microsoft.FSharp.Compiler.Lexhelp open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.Ast +open Internal.Utilities [] type HashIfExpression() = @@ -63,7 +64,7 @@ type HashIfExpression() = let resourceManager = LexResourceManager () let defines = [] let startPos = Position.Empty - let args = mkLexargs ("dummy", defines, lightSyntax, resourceManager, stack, errorLogger) + let args = mkLexargs ("dummy", defines, lightSyntax, resourceManager, stack, errorLogger, PathMap.empty) CompileThreadStatic.ErrorLogger <- errorLogger diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/PathMap1/pathmap.fs b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/PathMap1/pathmap.fs new file mode 100644 index 00000000000..a5cdf2d0239 --- /dev/null +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/PathMap1/pathmap.fs @@ -0,0 +1,43 @@ +// #NoMT #CompilerOptions #Deterministic +// +// +// IMPORTANT: PathMap1/pathmap.fs and PathMap2/pathmap.fs must be identical! +module TestPathMap + +open System.Runtime.CompilerServices + +type SomeType () = + static member GetCallerFilePath ([] ?filePath : string) = + match filePath with + | None -> "(Unknown)" + | Some filePath -> filePath + +[] +let main argv = + let srcDir = __SOURCE_DIRECTORY__ + printfn "Current __SOURCE_DIRECTORY__ = %s" srcDir + if srcDir <> "/src" then exit 1 + + let srcFile = __SOURCE_FILE__ + printfn "Current __SOURCE_FILE__ = %s" srcDir + if srcFile <> "pathmap.fs" then exit 1 + + let callerFilePath = SomeType.GetCallerFilePath () + printfn "Current CallerFilePath = %s" srcDir + if callerFilePath <> "/src/pathmap.fs" then exit 1 + +#line 2 @"F:/foo/SomethingElse.fs" + + let srcDir = __SOURCE_DIRECTORY__ + printfn "Changed __SOURCE_DIRECTORY__ = %s" srcDir + if srcDir <> "/etc/foo" then exit 1 + + let srcFile = __SOURCE_FILE__ + printfn "Changed __SOURCE_FILE__ = %s" srcDir + if srcFile <> "SomethingElse.fs" then exit 1 + + let callerFilePath = SomeType.GetCallerFilePath () + printfn "Changed CallerFilePath = %s" srcDir + if callerFilePath <> "/etc/foo/SomethingElse.fs" then exit 1 + + 0 diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/PathMap2/pathmap.fs b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/PathMap2/pathmap.fs new file mode 100644 index 00000000000..a5cdf2d0239 --- /dev/null +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/PathMap2/pathmap.fs @@ -0,0 +1,43 @@ +// #NoMT #CompilerOptions #Deterministic +// +// +// IMPORTANT: PathMap1/pathmap.fs and PathMap2/pathmap.fs must be identical! +module TestPathMap + +open System.Runtime.CompilerServices + +type SomeType () = + static member GetCallerFilePath ([] ?filePath : string) = + match filePath with + | None -> "(Unknown)" + | Some filePath -> filePath + +[] +let main argv = + let srcDir = __SOURCE_DIRECTORY__ + printfn "Current __SOURCE_DIRECTORY__ = %s" srcDir + if srcDir <> "/src" then exit 1 + + let srcFile = __SOURCE_FILE__ + printfn "Current __SOURCE_FILE__ = %s" srcDir + if srcFile <> "pathmap.fs" then exit 1 + + let callerFilePath = SomeType.GetCallerFilePath () + printfn "Current CallerFilePath = %s" srcDir + if callerFilePath <> "/src/pathmap.fs" then exit 1 + +#line 2 @"F:/foo/SomethingElse.fs" + + let srcDir = __SOURCE_DIRECTORY__ + printfn "Changed __SOURCE_DIRECTORY__ = %s" srcDir + if srcDir <> "/etc/foo" then exit 1 + + let srcFile = __SOURCE_FILE__ + printfn "Changed __SOURCE_FILE__ = %s" srcDir + if srcFile <> "SomethingElse.fs" then exit 1 + + let callerFilePath = SomeType.GetCallerFilePath () + printfn "Changed CallerFilePath = %s" srcDir + if callerFilePath <> "/etc/foo/SomethingElse.fs" then exit 1 + + 0 diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/binaryCompare.fsx b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/binaryCompare.fsx index 2147b88cb83..7d68f167a3f 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/binaryCompare.fsx +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/binaryCompare.fsx @@ -1,22 +1,30 @@ -// sgiven 'dummy' and 'dummy2', and 'dummy.exe' and 'dummy.pdb' exist in the current directory -// this will check 'dummy.exe' and 'dummy2.exe are exactly the same, and the same for the 'pdb' files -// expects 1 arg: whether files should be exactly the same -let shouldBeSame = bool.Parse fsi.CommandLineArgs.[1] - -let areSame (first,second) = +let areSame (first,second) = let load = System.IO.File.ReadAllBytes (load first) = (load second) -let filePairsToCheck = - System.IO.Directory.EnumerateFiles(__SOURCE_DIRECTORY__, "dummy.*") - |> Seq.filter (fun s -> s.EndsWith(".fs") |> not ) // Don't check the source code - |> Seq.map (fun f -> f, f.Replace("dummy","dummy2")) - -let compareFiles pair = +let compareFiles shouldBeSame pair = let correct = areSame pair = shouldBeSame if not correct then printfn "Expected %s and %s to be %s" (fst pair) (snd pair) (if shouldBeSame then "same" else "different") correct // Check all pairs of files are exactly the same -exit (if filePairsToCheck |> Seq.forall compareFiles then 0 else 1) +let shouldBeSame, filePairsToCheck = + match fsi.CommandLineArgs with + | [| _; shouldBeSame |] -> + // given 'dummy' and 'dummy2', and 'dummy.exe' and 'dummy.pdb' exist in the current directory + // this will check 'dummy.exe' and 'dummy2.exe are exactly the same, and the same for the 'pdb' files + // expects 1 arg: whether files should be exactly the same + + bool.Parse shouldBeSame, System.IO.Directory.EnumerateFiles(__SOURCE_DIRECTORY__, "dummy.*") + |> Seq.filter (fun s -> s.EndsWith(".fs") |> not ) // Don't check the source code + |> Seq.map (fun f -> f, f.Replace("dummy","dummy2")) + | args when args.Length >= 3 -> + true, args + |> Seq.pairwise + |> Seq.indexed + |> Seq.choose (fun (i, pair) -> if i % 2 = 1 then Some pair else None) + | args -> + failwithf "Expected '' or ' '" + +exit (if filePairsToCheck |> Seq.forall (compareFiles shouldBeSame) then 0 else 1) diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/dummy.fs b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/dummy.fs index 431026692aa..a6ada9f55fa 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/dummy.fs +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/dummy.fs @@ -1,3 +1,3 @@ // #NoMT #CompilerOptions #Deterministic -module TestDeterminsticCompilation +module TestDeterministicCompilation exit 0 diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/env.lst b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/env.lst index 5767e939fda..d522ba1292e 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/env.lst +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/env.lst @@ -1,7 +1,22 @@ +# Path mapping with embedded PDBs + SOURCE=PathMap1\\pathmap.fs SCFLAGS="--pathmap:\$CWD\\PathMap1=/src,F:\\=/etc --deterministic --embed --debug:embedded --out:PathMap1\\pathmap.exe" + SOURCE=PathMap2\\pathmap.fs SCFLAGS="--pathmap:\$CWD\\PathMap2=/src,F:\\=/etc --deterministic --embed --debug:embedded --out:PathMap2\\pathmap.exe" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx PathMap1\\pathmap.exe PathMap2\\pathmap.exe" + +# Path mapping with portable PDBs + SOURCE=PathMap1\\pathmap.fs SCFLAGS="--pathmap:\$CWD\\PathMap1=/src,F:\\=/etc --deterministic --embed --debug:portable --pdb:PathMap1\\pathmap.pdb --out:PathMap1\\pathmap.exe" + SOURCE=PathMap2\\pathmap.fs SCFLAGS="--pathmap:\$CWD\\PathMap2=/src,F:\\=/etc --deterministic --embed --debug:portable --pdb:PathMap2\\pathmap.pdb --out:PathMap2\\pathmap.exe" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx PathMap1\\pathmap.exe PathMap2\\pathmap.exe PathMap1\\pathmap.pdb PathMap2\\pathmap.pdb" + +# Confirm only portable and embedded debug PDBs are supported with pathmap, not full or pdbonly + SOURCE=pathmapRequiresPortablePdb.fs SCFLAGS="--pathmap:C:\\=/ --debug:full" + SOURCE=pathmapRequiresPortablePdb.fs SCFLAGS="--pathmap:C:\\=/ --debug:pdbonly" + +# Pathmap argument requires maps to be of the format 'path=sourcePath' + SOURCE=pathmapValid.fs SCFLAGS="--pathmap:C:\\NoOtherPath --debug:embedded" + # Sanity check - simply check that the option is valid - SOURCE=dummy.fs SCFLAGS="--deterministic" - SOURCE=dummy.fs SCFLAGS="--deterministic+" - SOURCE=dummy.fs SCFLAGS="--deterministic-" + SOURCE=dummy.fs SCFLAGS="--deterministic" + SOURCE=dummy.fs SCFLAGS="--deterministic+" + SOURCE=dummy.fs SCFLAGS="--deterministic-" SOURCE=dummy.fs SCFLAGS="--deterministic" FSIMODE=EXEC COMPILE_ONLY=1 SOURCE=dummy.fs SCFLAGS="--deterministic+" FSIMODE=EXEC COMPILE_ONLY=1 SOURCE=dummy.fs SCFLAGS="--deterministic-" FSIMODE=EXEC COMPILE_ONLY=1 @@ -12,7 +27,7 @@ # Confirm specific versions are allowed SOURCE=specificVersionSpecifed.fs SCFLAGS="--deterministic" -# Confirm in normal not-determinstic mode, the same file compiled twice leads to different exes & pdbs +# Confirm in normal not-deterministic mode, the same file compiled twice leads to different exes & pdbs # NOTE: we need to use the timeout because non-determinism in fsc is due to datetime, so we need to guarentee at least 1 sec difference SOURCE=dummy.fs PRECMD="\$FSC_PIPE dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" SOURCE=dummy.fs SCFLAGS="--debug:full" PRECMD="\$FSC_PIPE --debug:full dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" @@ -20,11 +35,11 @@ SOURCE=dummy.fs SCFLAGS="--debug:portable" PRECMD="\$FSC_PIPE --debug:portable dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" SOURCE=dummy.fs SCFLAGS="--debug:embedded" PRECMD="\$FSC_PIPE --debug:embedded dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" -# Confirm in determinstic mode, the same file compiled twice leads to exactly the same exe & pdbs +# Confirm in deterministic mode, the same file compiled twice leads to exactly the same exe & pdbs SOURCE=dummy.fs SCFLAGS="--deterministic" PRECMD="\$FSC_PIPE --deterministic dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx true" SOURCE=dummy.fs SCFLAGS="--deterministic --debug:portable" PRECMD="\$FSC_PIPE --deterministic --debug:portable dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx true" SOURCE=dummy.fs SCFLAGS="--deterministic --debug:embedded" PRECMD="\$FSC_PIPE --deterministic --debug:embedded dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx true" -# Confirm only portable and embeded debug PDBs are supported under determinstic build, not full or pdbonly +# Confirm only portable and embedded debug PDBs are supported under deterministic build, not full or pdbonly SOURCE=portablePdbOnly.fs SCFLAGS="--deterministic --debug:full" SOURCE=portablePdbOnly.fs SCFLAGS="--deterministic --debug:pdbonly" diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/keep.lst b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/keep.lst new file mode 100644 index 00000000000..f59ec20aabf --- /dev/null +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/keep.lst @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/pathmapRequiresPortablePdb.fs b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/pathmapRequiresPortablePdb.fs new file mode 100644 index 00000000000..80243879471 --- /dev/null +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/pathmapRequiresPortablePdb.fs @@ -0,0 +1,3 @@ +// #NoMT #CompilerOptions #Determinism +//--pathmap can only be used with portable PDBs \(--debug:portable or --debug:embedded\) +exit 0 diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/pathmapValid.fs b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/pathmapValid.fs new file mode 100644 index 00000000000..1ec61fc9a8f --- /dev/null +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/pathmapValid.fs @@ -0,0 +1,3 @@ +// #NoMT #CompilerOptions #Determinism +//Invalid path map\. Mappings must be comma separated and of the format 'path=sourcePath' +exit 0 diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/portablePdbOnly.fs b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/portablePdbOnly.fs index c1b99e6a41e..d5c358b34f6 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/portablePdbOnly.fs +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/portablePdbOnly.fs @@ -1,3 +1,3 @@ // #NoMT #CompilerOptions #Determinism -//Determinstic builds only support portable PDBs +//Deterministic builds only support portable PDBs exit 0 diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/pdb/env.lst b/tests/fsharpqa/Source/CompilerOptions/fsc/pdb/env.lst index 938bd76d2e7..1fd2562d4f0 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/pdb/env.lst +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/pdb/env.lst @@ -14,7 +14,7 @@ NOMONO SOURCE=pdb01.fs SCFLAGS="--debug --pdb:.\\pdb01.pdb" PRECMD="IF EXIST pd NOMONO SOURCE=pdb01.fs SCFLAGS="-g --debug:embedded --pdb:.\\pdbembedded.pdb" PRECMD="IF EXIST pdbembedded.pdb DEL pdbembedded.pdb" POSTCMD="IF EXIST pdbembedded.pdb dir pdbembedded.pdb&EXIT 1" # If pdb file exists then it didn't embed so fail. -NOMONO SOURCE=pdb01.fs SCFLAGS="-g --debug:portable --embed:pdb01.fs --pdb:.\\pdbportable.pdb" PRECMD="IF EXIST pdbportable.pdb DEL pdbportable.pdb" POSTCMD="IF not EXIST pdbportable.pdb dir pdbportable.pdb&EXIT 1" # If pdb file doesn't exist then it failed to generate portable pdb with embeded source. +NOMONO SOURCE=pdb01.fs SCFLAGS="-g --debug:portable --embed:pdb01.fs --pdb:.\\pdbportable.pdb" PRECMD="IF EXIST pdbportable.pdb DEL pdbportable.pdb" POSTCMD="IF not EXIST pdbportable.pdb dir pdbportable.pdb&EXIT 1" # If pdb file doesn't exist then it failed to generate portable pdb with embedded source. NOMONO SOURCE=pdb01.fs SCFLAGS="-g --out:pdbembedded.exe --debug:embedded --embed:pdb01.fs PRECMD="IF EXIST pdbembedded.exe DEL pdbembedded.exe" POSTCMD="IF NOT EXIST pdbembedded.exe dir pdbembedded.exe &EXIT 1" # If pdb file doesn't exist then it failed to embedded a pdb with embedded source. NOMONO SOURCE=pdb05.fs SCFLAGS="-g --debug:full --embed" # --embed with --debug:full is build error diff --git a/tests/fsharpqa/Source/run.pl b/tests/fsharpqa/Source/run.pl index c999def6387..53a506f8e75 100644 --- a/tests/fsharpqa/Source/run.pl +++ b/tests/fsharpqa/Source/run.pl @@ -75,7 +75,10 @@ $VerifyStrongName = 1 if ($ENV{VERIFYSTRONGNAME} =~ /TRUE/i); # Check for any compiler flags -my $SCFLAGS = $ENV{SCFLAGS}; +my $CWD = cwd(); +$_ = $ENV{SCFLAGS}; +s/\$CWD/$CWD/g; +my $SCFLAGS = $_; # Check for any compiler 'tail' flags my $TAILFLAGS = $ENV{TAILFLAGS}; @@ -159,12 +162,12 @@ # SOURCE=foo.fs PRECMD="\$FSC_PIPE bar.fs" # and it will expanded into $FSC_PIPE before invoking it $_ = $ENV{PRECMD}; - s/^\$FSC_PIPE/$FSC_PIPE/; + s/^\$FSC_PIPE/$FSC_PIPE/g; s/\$FSI_PIPE/$FSI_PIPE/g; - s/^\$FSI32_PIPE/$FSI32_PIPE/; - s/\$ISCFLAGS/$ISCFLAGS/; - s/^\$CSC_PIPE/$CSC_PIPE/; - s/^\$VBC_PIPE/$VBC_PIPE/; + s/^\$FSI32_PIPE/$FSI32_PIPE/g; + s/\$ISCFLAGS/$ISCFLAGS/g; + s/^\$CSC_PIPE/$CSC_PIPE/g; + s/^\$VBC_PIPE/$VBC_PIPE/g; RunExit(TEST_FAIL, "Fail to execute the PRECMD" . @CommandOutput . "\n") if RunCommand("PRECMD",$_ ,1); } @@ -487,11 +490,9 @@ sub RunCommand { # GetSrc -- Find the source file to build # sub GetSrc() { - my $cwd = cwd(); - # The environment SOURCE var usually defines what to compile $_ = $ENV{SOURCE}; - s/\$CWD/$cwd/; + s/\$CWD/$CWD/; my $source = $_; return($source) if defined($source); diff --git a/tests/fsharpqa/fsharpqafiles.csproj b/tests/fsharpqa/fsharpqafiles.csproj index d014c7a3096..6e6ef645b38 100644 --- a/tests/fsharpqa/fsharpqafiles.csproj +++ b/tests/fsharpqa/fsharpqafiles.csproj @@ -10,6 +10,7 @@ + diff --git a/tests/fsharpqa/run.fsharpqa.test.fsx b/tests/fsharpqa/run.fsharpqa.test.fsx index 101e41f7a2d..fe410ebb0b3 100644 --- a/tests/fsharpqa/run.fsharpqa.test.fsx +++ b/tests/fsharpqa/run.fsharpqa.test.fsx @@ -6,14 +6,14 @@ open System.Diagnostics let releaseOrDebug = "Debug" let setEnvVar name value = - System.Environment.SetEnvironmentVariable(name, value) + System.Environment.SetEnvironmentVariable(name, value) let addToPath path = - let currentPath = System.Environment.GetEnvironmentVariable "PATH" - - let splits = currentPath.Split(Path.PathSeparator) - if not(Array.contains path splits) then - setEnvVar "PATH" (path + (string Path.PathSeparator) + currentPath) + let currentPath = System.Environment.GetEnvironmentVariable "PATH" + + let splits = currentPath.Split(Path.PathSeparator) + if not(Array.contains path splits) then + setEnvVar "PATH" (path + (string Path.PathSeparator) + currentPath) let rootFolder = Path.Combine(__SOURCE_DIRECTORY__, "..", "..") let compilerBinFolder = Path.Combine(rootFolder, releaseOrDebug, "net40", "bin") @@ -23,24 +23,35 @@ setEnvVar "FSCOREDLLPATH" (Path.Combine(compilerBinFolder, "FSharp.Core.dll")) addToPath compilerBinFolder let runPerl arguments = - // a bit expeditive, but does the deed - Process.GetProcessesByName("perl") |> Array.iter (fun p -> p.Kill()) - use perlProcess = new Process() - perlProcess.StartInfo.set_FileName (Path.Combine(rootFolder, "packages", "StrawberryPerl64.5.22.2.1", "Tools", "perl", "bin", "perl.exe")) - perlProcess.StartInfo.set_Arguments (arguments |> Array.map(fun a -> @"""" + a + @"""") |> String.concat " ") - perlProcess.StartInfo.set_WorkingDirectory (Path.Combine(rootFolder, "tests", "fsharpqa", "source")) - perlProcess.StartInfo.set_RedirectStandardOutput true - perlProcess.StartInfo.set_RedirectStandardError true - perlProcess.StartInfo.set_UseShellExecute false - perlProcess.Start() |> ignore - while (not perlProcess.StandardOutput.EndOfStream) do - perlProcess.StandardOutput.ReadLine() |> printfn "%s" - while (not perlProcess.StandardError.EndOfStream) do - perlProcess.StandardError.ReadLine() |> printfn "%s" - perlProcess.WaitForExit() - if perlProcess.ExitCode <> 0 then - failwithf "exit code: %i" perlProcess.ExitCode + // Kill all Perl processes, and their children + ProcessStartInfo( + FileName = "taskkill", + Arguments = "/im perl.exe /f /t", + CreateNoWindow = true, + UseShellExecute = false + ) + |> Process.Start + |> fun p -> p.WaitForExit() + + use perlProcess = + ProcessStartInfo( + FileName = Path.Combine(rootFolder, "packages", "StrawberryPerl64.5.22.2.1", "Tools", "perl", "bin", "perl.exe"), + Arguments = (arguments |> Array.map(fun a -> @"""" + a + @"""") |> String.concat " "), + WorkingDirectory = Path.Combine(rootFolder, "tests", "fsharpqa", "source"), + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false + ) + |> Process.Start + + while (not perlProcess.StandardOutput.EndOfStream) do + perlProcess.StandardOutput.ReadLine() |> printfn "%s" + while (not perlProcess.StandardError.EndOfStream) do + perlProcess.StandardError.ReadLine() |> printfn "%s" + perlProcess.WaitForExit() + if perlProcess.ExitCode <> 0 then + failwithf "exit code: %i" perlProcess.ExitCode let testResultDir = Path.Combine(rootFolder, "tests", "TestResults") let perlScript = Path.Combine(rootFolder, "tests", "fsharpqa", "testenv", "bin", "runall.pl") -runPerl [|perlScript; "-resultsroot";testResultDir ;"-ttags:Conformance06"|] \ No newline at end of file +runPerl [|perlScript; "-resultsroot";testResultDir ;"-ttags:Determinism"|] \ No newline at end of file From fe2046c299207daa2afa1ec1769fb4439c777b29 Mon Sep 17 00:00:00 2001 From: Saul Rennison Date: Mon, 22 Apr 2019 20:04:45 +0100 Subject: [PATCH 2/8] Fix build --- src/fsharp/CompileOps.fsi | 4 ++-- src/fsharp/FSharp.Build/Fsc.fs | 12 +++++++++++- src/fsharp/FSharp.Build/Microsoft.FSharp.Targets | 1 + src/fsharp/TastPickle.fs | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index 653320f0eca..3c463a98cd1 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -370,10 +370,10 @@ type TcConfigBuilder = /// if true - 'let mutable x = Span.Empty', the value 'x' is a stack referring span. Used for internal testing purposes only until we get true stack spans. mutable internalTestSpanStackReferring : bool - mutable pathMap : PathMap - /// Prevent erasure of conditional attributes and methods so tooling is able analyse them. mutable noConditionalErasure: bool + + mutable pathMap : PathMap } static member Initial: TcConfigBuilder diff --git a/src/fsharp/FSharp.Build/Fsc.fs b/src/fsharp/FSharp.Build/Fsc.fs index d1f0ea78d94..a3803f4b449 100644 --- a/src/fsharp/FSharp.Build/Fsc.fs +++ b/src/fsharp/FSharp.Build/Fsc.fs @@ -41,7 +41,8 @@ type public Fsc () as this = let mutable noFramework = false let mutable optimize : bool = true let mutable otherFlags : string = null - let mutable outputAssembly : string = null + let mutable outputAssembly : string = null + let mutable pathMap : string = null let mutable pdbFile : string = null let mutable platform : string = null let mutable prefer32bit : bool = false @@ -233,6 +234,10 @@ type public Fsc () as this = builder.AppendSwitchIfNotNull("--targetprofile:", targetProfile) builder.AppendSwitch("--nocopyfsharpcore") + + match pathMap with + | null -> () + | _ -> builder.AppendSwitchIfNotNull("--pathmap:", pathMap.Split([|';'; ','|], StringSplitOptions.RemoveEmptyEntries), ",") // OtherFlags - must be second-to-last builder.AppendSwitchUnquotedIfNotNull("", otherFlags) @@ -346,6 +351,11 @@ type public Fsc () as this = with get() = outputAssembly and set(s) = outputAssembly <- s + // --pathmap : Paths to rewrite when producing deterministic builds + member fsc.PathMap + with get() = pathMap + and set(s) = pathMap <- s + // --pdb : // Name the debug output file member fsc.PdbFile diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets index 19f9843e4ae..ff1cfbb9b50 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets @@ -294,6 +294,7 @@ this file. Optimize="$(Optimize)" OtherFlags="$(FscOtherFlags)" OutputAssembly="@(IntermediateAssembly)" + PathMap="$(PathMap)" PdbFile="$(PdbFile)" Platform="$(PlatformTarget)" Prefer32Bit="$(Actual32Bit)" diff --git a/src/fsharp/TastPickle.fs b/src/fsharp/TastPickle.fs index 68cf00aa8bd..00fd581d1d0 100644 --- a/src/fsharp/TastPickle.fs +++ b/src/fsharp/TastPickle.fs @@ -1318,7 +1318,7 @@ let p_pos (x: pos) st = p_tup2 p_int p_int (x.Line, x.Column) st let p_range (x: range) st = let fileName = PathMap.apply st.oglobals.pathMap x.FileName - p_tup3 p_string p_pos p_pos (x.FileName, x.Start, x.End) st + p_tup3 p_string p_pos p_pos (fileName, x.Start, x.End) st let p_dummy_range : range pickler = fun _x _st -> () let p_ident (x: Ident) st = p_tup2 p_string p_range (x.idText, x.idRange) st From c8a4c403cae1b24e1636472c2c017fa14ab51691 Mon Sep 17 00:00:00 2001 From: Saul Rennison Date: Mon, 22 Apr 2019 20:40:06 +0100 Subject: [PATCH 3/8] Update FSharp.Compiler.Service.fsproj --- fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index 68983105861..d3e78c9f637 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -93,6 +93,12 @@ LexYaccRuntime/prim-parsing.fs + + Utilities/PathMap.fsi + + + Utilities/PathMap.fs + Utilities/ResizeArray.fsi From d566379a84970ca319cd3c39e85508ab99141950 Mon Sep 17 00:00:00 2001 From: Saul Rennison Date: Tue, 23 Apr 2019 09:31:15 +0100 Subject: [PATCH 4/8] Markup --- src/fsharp/CompileOps.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 9a72d2b3a69..74da1750b42 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -2286,8 +2286,8 @@ type TcConfigBuilder = useSdkRefs = true tryGetMetadataSnapshot = (fun _ -> None) internalTestSpanStackReferring = false - pathMap = PathMap.empty noConditionalErasure = false + pathMap = PathMap.empty } static member CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir, reduceMemoryUsage, implicitIncludeDir, From 9f7bcd60fa4ecc4195c8cd1a4a5e9d0710d63755 Mon Sep 17 00:00:00 2001 From: Saul Rennison Date: Tue, 23 Apr 2019 10:10:17 +0100 Subject: [PATCH 5/8] Fix tests --- .../Source/CompilerOptions/fsc/determinism/env.lst | 6 +++--- .../Source/CompilerOptions/fsc/help/help40.437.1033.bsl | 2 ++ tests/fsharpqa/run.fsharpqa.test.fsx | 7 ++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/env.lst b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/env.lst index d56dc0e1714..082e76dec6a 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/env.lst +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/determinism/env.lst @@ -29,9 +29,9 @@ # Confirm in normal not-deterministic mode, the same file compiled twice leads to different exes & pdbs # NOTE: we need to use the timeout because non-determinism in fsc is due to datetime, so we need to guarentee at least 1 sec difference - SOURCE=dummy.fs PRECMD="\$FSC_PIPE dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" - SOURCE=dummy.fs SCFLAGS="--debug:full" PRECMD="\$FSC_PIPE --debug:full dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" - SOURCE=dummy.fs SCFLAGS="--debug:pdbonly" PRECMD="\$FSC_PIPE --debug:pdbonly dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" + SOURCE=dummy.fs PRECMD="\$FSC_PIPE dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" + SOURCE=dummy.fs SCFLAGS="--debug:full" PRECMD="\$FSC_PIPE --debug:full dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" + SOURCE=dummy.fs SCFLAGS="--debug:pdbonly" PRECMD="\$FSC_PIPE --debug:pdbonly dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" SOURCE=dummy.fs SCFLAGS="--debug:portable" PRECMD="\$FSC_PIPE --debug:portable dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" SOURCE=dummy.fs SCFLAGS="--debug:embedded" PRECMD="\$FSC_PIPE --debug:embedded dummy.fs && \$FSI_PIPE copyArtifacts.fsx" POSTCMD="\$FSI_PIPE --nologo --quiet --exec binaryCompare.fsx false" diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl index 1014e10ca6a..b0fd6746810 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl @@ -80,6 +80,8 @@ Copyright (c) Microsoft Corporation. All Rights Reserved. --deterministic[+|-] Produce a deterministic assembly (including module version GUID and timestamp) +--pathmap: Maps physical paths to source path + names output by the compiler --crossoptimize[+|-] Enable or disable cross-module optimizations diff --git a/tests/fsharpqa/run.fsharpqa.test.fsx b/tests/fsharpqa/run.fsharpqa.test.fsx index fe410ebb0b3..a29a242625b 100644 --- a/tests/fsharpqa/run.fsharpqa.test.fsx +++ b/tests/fsharpqa/run.fsharpqa.test.fsx @@ -15,9 +15,10 @@ let addToPath path = if not(Array.contains path splits) then setEnvVar "PATH" (path + (string Path.PathSeparator) + currentPath) +let nugetCache = Path.Combine(System.Environment.GetEnvironmentVariable "USERPROFILE", ".nuget", "packages") let rootFolder = Path.Combine(__SOURCE_DIRECTORY__, "..", "..") -let compilerBinFolder = Path.Combine(rootFolder, releaseOrDebug, "net40", "bin") -setEnvVar "CSC_PIPE" (Path.Combine(rootFolder, "packages", "Microsoft.Net.Compilers.2.7.0", "tools", "csc.exe")) +let compilerBinFolder = Path.Combine(rootFolder, "artifacts", "bin", "fsc", releaseOrDebug, "net472") +setEnvVar "CSC_PIPE" (Path.Combine(nugetCache, "Microsoft.Net.Compilers", "2.7.0", "tools", "csc.exe")) setEnvVar "FSC" (Path.Combine(compilerBinFolder, "fsc.exe")) setEnvVar "FSCOREDLLPATH" (Path.Combine(compilerBinFolder, "FSharp.Core.dll")) addToPath compilerBinFolder @@ -35,7 +36,7 @@ let runPerl arguments = use perlProcess = ProcessStartInfo( - FileName = Path.Combine(rootFolder, "packages", "StrawberryPerl64.5.22.2.1", "Tools", "perl", "bin", "perl.exe"), + FileName = Path.Combine(nugetCache, "StrawberryPerl64", "5.22.2.1", "Tools", "perl", "bin", "perl.exe"), Arguments = (arguments |> Array.map(fun a -> @"""" + a + @"""") |> String.concat " "), WorkingDirectory = Path.Combine(rootFolder, "tests", "fsharpqa", "source"), RedirectStandardOutput = true, From ff0a9600a3d5d74af961c79aacb8b62197259663 Mon Sep 17 00:00:00 2001 From: Saul Rennison Date: Tue, 23 Apr 2019 10:11:34 +0100 Subject: [PATCH 6/8] Update help40.437.1033.bsl --- .../Source/CompilerOptions/fsi/help/help40.437.1033.bsl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl index a57b389a873..34d28e5f70b 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40.437.1033.bsl @@ -33,6 +33,8 @@ Usage: fsi.exe [script.fsx []] --deterministic[+|-] Produce a deterministic assembly (including module version GUID and timestamp) +--pathmap: Maps physical paths to source path + names output by the compiler --crossoptimize[+|-] Enable or disable cross-module optimizations From f3553a4e427716e94264209470836faaa2ac381d Mon Sep 17 00:00:00 2001 From: Saul Rennison Date: Tue, 23 Apr 2019 10:12:15 +0100 Subject: [PATCH 7/8] Update help40-nologo.437.1033.bsl --- .../Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl index 4346db21448..242cb274d2d 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsi/help/help40-nologo.437.1033.bsl @@ -31,6 +31,8 @@ Usage: fsi.exe [script.fsx []] --deterministic[+|-] Produce a deterministic assembly (including module version GUID and timestamp) +--pathmap: Maps physical paths to source path + names output by the compiler --crossoptimize[+|-] Enable or disable cross-module optimizations From 718a6b03a7c243db7ece711523d4d3baca716d1d Mon Sep 17 00:00:00 2001 From: Saul Rennison Date: Tue, 23 Apr 2019 17:09:04 +0100 Subject: [PATCH 8/8] Update help40.437.1033.bsl --- .../Source/CompilerOptions/fsi/exename/help40.437.1033.bsl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/fsharpqa/Source/CompilerOptions/fsi/exename/help40.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsi/exename/help40.437.1033.bsl index aab81bde226..d19a024e300 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsi/exename/help40.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsi/exename/help40.437.1033.bsl @@ -31,6 +31,8 @@ Usage: fsharpi [script.fsx []] --deterministic[+|-] Produce a deterministic assembly (including module version GUID and timestamp) +--pathmap: Maps physical paths to source path + names output by the compiler --crossoptimize[+|-] Enable or disable cross-module optimizations