Skip to content

Commit 3c77bae

Browse files
saulKevinRansom
authored andcommitted
Add support for --pathmap (#6609)
* Add support for --pathmap * Fix build * Update FSharp.Compiler.Service.fsproj * Markup * Fix tests * Update help40.437.1033.bsl * Update help40-nologo.437.1033.bsl * Update help40.437.1033.bsl
1 parent ae595d4 commit 3c77bae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+631
-130
lines changed

fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@
9393
<Compile Include="$(FSharpSourcesRoot)/utils/prim-parsing.fs">
9494
<Link>LexYaccRuntime/prim-parsing.fs</Link>
9595
</Compile>
96+
<Compile Include="$(FSharpSourcesRoot)/utils/PathMap.fsi">
97+
<Link>Utilities/PathMap.fsi</Link>
98+
</Compile>
99+
<Compile Include="$(FSharpSourcesRoot)/utils/PathMap.fs">
100+
<Link>Utilities/PathMap.fs</Link>
101+
</Compile>
96102
<Compile Include="$(FSharpSourcesRoot)/utils/ResizeArray.fsi">
97103
<Link>Utilities/ResizeArray.fsi</Link>
98104
</Compile>

src/absil/ilwrite.fs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3515,8 +3515,8 @@ let writeDirectory os dict =
35153515
let writeBytes (os: BinaryWriter) (chunk: byte[]) = os.Write(chunk, 0, chunk.Length)
35163516

35173517
let writeBinaryAndReportMappings (outfile,
3518-
ilg: ILGlobals, pdbfile: string option, signer: ILStrongNameSigner option, portablePDB, embeddedPDB,
3519-
embedAllSource, embedSourceList, sourceLink, emitTailcalls, deterministic, showTimes, dumpDebugInfo )
3518+
ilg: ILGlobals, pdbfile: string option, signer: ILStrongNameSigner option, portablePDB, embeddedPDB,
3519+
embedAllSource, embedSourceList, sourceLink, emitTailcalls, deterministic, showTimes, dumpDebugInfo, pathMap)
35203520
modul normalizeAssemblyRefs =
35213521
// Store the public key from the signer into the manifest. This means it will be written
35223522
// to the binary and also acts as an indicator to leave space for delay sign
@@ -3671,7 +3671,7 @@ let writeBinaryAndReportMappings (outfile,
36713671
match portablePDB with
36723672
| true ->
36733673
let (uncompressedLength, contentId, stream) as pdbStream =
3674-
generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic
3674+
generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic pathMap
36753675

36763676
if embeddedPDB then Some (compressPortablePdbStream uncompressedLength contentId stream)
36773677
else Some pdbStream
@@ -4211,7 +4211,7 @@ let writeBinaryAndReportMappings (outfile,
42114211
if embeddedPDB then
42124212
embedPortablePdbInfo originalLength contentId stream showTimes fpdb debugDataChunk debugEmbeddedPdbChunk
42134213
else
4214-
writePortablePdbInfo contentId stream showTimes fpdb debugDataChunk
4214+
writePortablePdbInfo contentId stream showTimes fpdb pathMap debugDataChunk
42154215
| None ->
42164216
#if FX_NO_PDB_WRITER
42174217
Array.empty<idd>
@@ -4284,10 +4284,11 @@ type options =
42844284
emitTailcalls : bool
42854285
deterministic : bool
42864286
showTimes: bool
4287-
dumpDebugInfo: bool }
4287+
dumpDebugInfo: bool
4288+
pathMap: PathMap }
42884289

42894290
let WriteILBinary (outfile, (args: options), modul, normalizeAssemblyRefs) =
42904291
writeBinaryAndReportMappings (outfile,
42914292
args.ilg, args.pdbfile, args.signer, args.portablePDB, args.embeddedPDB, args.embedAllSource,
4292-
args.embedSourceList, args.sourceLink, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo) modul normalizeAssemblyRefs
4293+
args.embedSourceList, args.sourceLink, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo, args.pathMap) modul normalizeAssemblyRefs
42934294
|> ignore

src/absil/ilwrite.fsi

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/// The IL Binary writer.
44
module internal FSharp.Compiler.AbstractIL.ILBinaryWriter
55

6+
open Internal.Utilities
67
open FSharp.Compiler.AbstractIL
78
open FSharp.Compiler.AbstractIL.Internal
89
open FSharp.Compiler.AbstractIL.IL
@@ -27,7 +28,8 @@ type options =
2728
emitTailcalls: bool
2829
deterministic: bool
2930
showTimes : bool
30-
dumpDebugInfo : bool }
31+
dumpDebugInfo : bool
32+
pathMap : PathMap }
3133

3234
/// Write a binary to the file system. Extra configuration parameters can also be specified.
3335
val WriteILBinary: filename: string * options: options * input: ILModuleDef * (ILAssemblyRef -> ILAssemblyRef) -> unit

src/absil/ilwritepdb.fs

Lines changed: 4 additions & 3 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) isDeterministic =
222+
let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (sourceLink: string) showTimes (info: PdbData) isDeterministic (pathMap: PathMap) =
223223
sortMethods showTimes info
224224
let externalRowCounts = getRowCounts info.TableRowCounts
225225
let docs =
@@ -229,6 +229,7 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s
229229

230230
let metadata = MetadataBuilder()
231231
let serializeDocumentName (name: string) =
232+
let name = PathMap.apply pathMap name
232233
let count s c = s |> Seq.filter(fun ch -> if c = ch then true else false) |> Seq.length
233234

234235
let s1, s2 = '/', '\\'
@@ -501,12 +502,12 @@ let compressPortablePdbStream (uncompressedLength: int64) (contentId: BlobConten
501502
stream.WriteTo compressionStream
502503
(uncompressedLength, contentId, compressedStream)
503504

504-
let writePortablePdbInfo (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb cvChunk =
505+
let writePortablePdbInfo (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb pathMap cvChunk =
505506
try FileSystem.FileDelete fpdb with _ -> ()
506507
use pdbFile = new FileStream(fpdb, FileMode.Create, FileAccess.ReadWrite)
507508
stream.WriteTo pdbFile
508509
reportTime showTimes "PDB: Closed"
509-
pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) fpdb cvChunk None 0L None
510+
pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) (PathMap.apply pathMap fpdb) cvChunk None 0L None
510511

511512
let embedPortablePdbInfo (uncompressedLength: int64) (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb cvChunk pdbChunk =
512513
reportTime showTimes "PDB: Closed"

src/absil/ilwritepdb.fsi

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/// The ILPdbWriter
44
module internal FSharp.Compiler.AbstractIL.ILPdbWriter
55

6+
open Internal.Utilities
67
open FSharp.Compiler.AbstractIL.IL
78
open FSharp.Compiler.ErrorLogger
89
open FSharp.Compiler.Range
@@ -82,10 +83,10 @@ type idd =
8283
iddData: byte[];
8384
iddChunk: BinaryChunk }
8485

85-
val generatePortablePdb : embedAllSource:bool -> embedSourceList:string list -> sourceLink: string -> showTimes:bool -> info:PdbData -> isDeterministic:bool -> (int64 * BlobContentId * MemoryStream)
86+
val generatePortablePdb : embedAllSource:bool -> embedSourceList:string list -> sourceLink: string -> showTimes:bool -> info:PdbData -> isDeterministic:bool -> pathMap:PathMap -> (int64 * BlobContentId * MemoryStream)
8687
val compressPortablePdbStream : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> (int64 * BlobContentId * MemoryStream)
8788
val embedPortablePdbInfo : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> cvChunk:BinaryChunk -> pdbChunk:BinaryChunk -> idd[]
88-
val writePortablePdbInfo : contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> cvChunk:BinaryChunk -> idd[]
89+
val writePortablePdbInfo : contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> pathMap:PathMap -> cvChunk:BinaryChunk -> idd[]
8990

9091
#if !FX_NO_PDB_WRITER
9192
val writePdbInfo : showTimes:bool -> f:string -> fpdb:string -> info:PdbData -> cvChunk:BinaryChunk -> idd[]

src/fsharp/CompileOps.fs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2150,6 +2150,8 @@ type TcConfigBuilder =
21502150
mutable internalTestSpanStackReferring: bool
21512151

21522152
mutable noConditionalErasure: bool
2153+
2154+
mutable pathMap: PathMap
21532155
}
21542156

21552157
static member Initial =
@@ -2285,6 +2287,7 @@ type TcConfigBuilder =
22852287
tryGetMetadataSnapshot = (fun _ -> None)
22862288
internalTestSpanStackReferring = false
22872289
noConditionalErasure = false
2290+
pathMap = PathMap.empty
22882291
}
22892292

22902293
static member CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir, reduceMemoryUsage, implicitIncludeDir,
@@ -2408,6 +2411,9 @@ type TcConfigBuilder =
24082411

24092412
member tcConfigB.RemoveReferencedAssemblyByPath (m, path) =
24102413
tcConfigB.referencedDLLs <- tcConfigB.referencedDLLs |> List.filter (fun ar -> not (Range.equals ar.Range m) || ar.Text <> path)
2414+
2415+
member tcConfigB.AddPathMapping (oldPrefix, newPrefix) =
2416+
tcConfigB.pathMap <- tcConfigB.pathMap |> PathMap.addMapping oldPrefix newPrefix
24112417

24122418
static member SplitCommandLineResourceInfo (ri: string) =
24132419
let p = ri.IndexOf ','
@@ -2730,6 +2736,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) =
27302736
member x.optSettings = data.optSettings
27312737
member x.emitTailcalls = data.emitTailcalls
27322738
member x.deterministic = data.deterministic
2739+
member x.pathMap = data.pathMap
27332740
member x.preferredUiLang = data.preferredUiLang
27342741
member x.lcid = data.lcid
27352742
member x.optsOn = data.optsOn
@@ -3407,7 +3414,7 @@ let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, conditionalComp
34073414
try
34083415
let skip = true in (* don't report whitespace from lexer *)
34093416
let lightSyntaxStatus = LightSyntaxStatus (tcConfig.ComputeLightSyntaxInitialStatus filename, true)
3410-
let lexargs = mkLexargs (filename, conditionalCompilationDefines@tcConfig.conditionalCompilationDefines, lightSyntaxStatus, lexResourceManager, ref [], errorLogger)
3417+
let lexargs = mkLexargs (filename, conditionalCompilationDefines@tcConfig.conditionalCompilationDefines, lightSyntaxStatus, lexResourceManager, ref [], errorLogger, tcConfig.pathMap)
34113418
let shortFilename = SanitizeFileName filename tcConfig.implicitIncludeDir
34123419
let input =
34133420
Lexhelp.usingLexbufForParsing (lexbuf, filename) (fun lexbuf ->
@@ -3607,7 +3614,9 @@ let MakeILResource rname bytes =
36073614
CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs
36083615
MetadataIndex = NoMetadataIdx }
36093616

3610-
let PickleToResource inMem file g scope rname p x =
3617+
let PickleToResource inMem file (g: TcGlobals) scope rname p x =
3618+
let file = PathMap.apply g.pathMap file
3619+
36113620
{ Name = rname
36123621
Location = (let bytes = pickleObjWithDanglingCcus inMem file g scope p x in ILResourceLocation.LocalOut bytes)
36133622
Access = ILResourceAccess.Public
@@ -3617,15 +3626,23 @@ let PickleToResource inMem file g scope rname p x =
36173626
let GetSignatureData (file, ilScopeRef, ilModule, byteReader) : PickledDataWithReferences<PickledCcuInfo> =
36183627
unpickleObjWithDanglingCcus file ilScopeRef ilModule unpickleCcuInfo (byteReader())
36193628

3620-
let WriteSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, ccu: CcuThunk, file, inMem) : ILResource =
3629+
let WriteSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, ccu: CcuThunk, file, inMem) : ILResource =
36213630
let mspec = ccu.Contents
36223631
let mspec = ApplyExportRemappingToEntity tcGlobals exportRemapping mspec
36233632
// For historical reasons, we use a different resource name for FSharp.Core, so older F# compilers
36243633
// don't complain when they see the resource.
3625-
let rname = if ccu.AssemblyName = getFSharpCoreLibraryName then FSharpSignatureDataResourceName2 else FSharpSignatureDataResourceName
3634+
let rname = if ccu.AssemblyName = getFSharpCoreLibraryName then FSharpSignatureDataResourceName2 else FSharpSignatureDataResourceName
3635+
3636+
let includeDir =
3637+
if String.IsNullOrEmpty tcConfig.implicitIncludeDir then ""
3638+
else
3639+
tcConfig.implicitIncludeDir
3640+
|> System.IO.Path.GetFullPath
3641+
|> PathMap.applyDir tcGlobals.pathMap
3642+
36263643
PickleToResource inMem file tcGlobals ccu (rname+ccu.AssemblyName) pickleCcuInfo
36273644
{ mspec=mspec
3628-
compileTimeWorkingDir=tcConfig.implicitIncludeDir
3645+
compileTimeWorkingDir=includeDir
36293646
usesQuotations = ccu.UsesFSharp20PlusQuotations }
36303647

36313648
let GetOptimizationData (file, ilScopeRef, ilModule, byteReader) =
@@ -4626,8 +4643,9 @@ type TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAssemblyResolu
46264643

46274644
// OK, now we have both mscorlib.dll and FSharp.Core.dll we can create TcGlobals
46284645
let tcGlobals = TcGlobals(tcConfig.compilingFslib, ilGlobals, fslibCcu,
4629-
tcConfig.implicitIncludeDir, tcConfig.mlCompatibility,
4630-
tcConfig.isInteractive, tryFindSysTypeCcu, tcConfig.emitDebugInfoInQuotations, tcConfig.noDebugData )
4646+
tcConfig.implicitIncludeDir, tcConfig.mlCompatibility,
4647+
tcConfig.isInteractive, tryFindSysTypeCcu, tcConfig.emitDebugInfoInQuotations,
4648+
tcConfig.noDebugData, tcConfig.pathMap)
46314649

46324650
#if DEBUG
46334651
// the global_g reference cell is used only for debug printing

src/fsharp/CompileOps.fsi

100755100644
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module internal FSharp.Compiler.CompileOps
66
open System
77
open System.Text
88
open System.Collections.Generic
9+
open Internal.Utilities
910
open FSharp.Compiler.AbstractIL
1011
open FSharp.Compiler.AbstractIL.IL
1112
open FSharp.Compiler.AbstractIL.ILBinaryReader
@@ -373,6 +374,7 @@ type TcConfigBuilder =
373374
/// Prevent erasure of conditional attributes and methods so tooling is able analyse them.
374375
mutable noConditionalErasure: bool
375376

377+
mutable pathMap : PathMap
376378
}
377379

378380
static member Initial: TcConfigBuilder
@@ -396,7 +398,8 @@ type TcConfigBuilder =
396398
member RemoveReferencedAssemblyByPath: range * string -> unit
397399
member AddEmbeddedSourceFile: string -> unit
398400
member AddEmbeddedResource: string -> unit
399-
401+
member AddPathMapping: oldPrefix: string * newPrefix: string -> unit
402+
400403
static member SplitCommandLineResourceInfo: string -> string * string * ILResourceAccess
401404

402405
[<Sealed>]
@@ -496,6 +499,7 @@ type TcConfig =
496499
member optSettings : Optimizer.OptimizationSettings
497500
member emitTailcalls: bool
498501
member deterministic: bool
502+
member pathMap: PathMap
499503
member preferredUiLang: string option
500504
member optsOn : bool
501505
member productNameForBannerText: string

src/fsharp/CompileOptions.fs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,13 @@ let SetTailcallSwitch (tcConfigB: TcConfigBuilder) switch =
407407
let SetDeterministicSwitch (tcConfigB: TcConfigBuilder) switch =
408408
tcConfigB.deterministic <- (switch = OptionSwitch.On)
409409

410+
let AddPathMapping (tcConfigB: TcConfigBuilder) (pathPair: string) =
411+
match pathPair.Split([|'='|], 2) with
412+
| [| oldPrefix; newPrefix |] ->
413+
tcConfigB.AddPathMapping (oldPrefix, newPrefix)
414+
| _ ->
415+
error(Error(FSComp.SR.optsInvalidPathMapFormat(), rangeCmdArgs))
416+
410417
let jitoptimizeSwitch (tcConfigB: TcConfigBuilder) switch =
411418
tcConfigB.optSettings <- { tcConfigB.optSettings with jitOptUser = Some (switch = OptionSwitch.On) }
412419

@@ -516,6 +523,7 @@ let tagWarnList = "<warn;...>"
516523
let tagSymbolList = "<symbol;...>"
517524
let tagAddress = "<address>"
518525
let tagInt = "<n>"
526+
let tagPathMap = "<path=sourcePath;...>"
519527
let tagNone = ""
520528

521529
// PrintOptionInfo
@@ -786,7 +794,12 @@ let codeGenerationFlags isFsi (tcConfigB: TcConfigBuilder) =
786794
("deterministic", tagNone,
787795
OptionSwitch (SetDeterministicSwitch tcConfigB), None,
788796
Some (FSComp.SR.optsDeterministic()))
789-
797+
798+
CompilerOption
799+
("pathmap", tagPathMap,
800+
OptionStringList (AddPathMapping tcConfigB), None,
801+
Some (FSComp.SR.optsPathMap()))
802+
790803
CompilerOption
791804
("crossoptimize", tagNone,
792805
OptionSwitch (crossOptimizeSwitch tcConfigB), None,

src/fsharp/FSComp.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ optsDebug,"Specify debugging type: full, portable, embedded, pdbonly. ('%s' is t
860860
optsOptimize,"Enable optimizations (Short form: -O)"
861861
optsTailcalls,"Enable or disable tailcalls"
862862
optsDeterministic,"Produce a deterministic assembly (including module version GUID and timestamp)"
863+
optsPathMap,"Maps physical paths to source path names output by the compiler"
863864
optsCrossoptimize,"Enable or disable cross-module optimizations"
864865
optsWarnaserrorPM,"Report all warnings as errors"
865866
optsWarnaserror,"Report specific warnings as errors"
@@ -1140,7 +1141,9 @@ fscTooManyErrors,"Exiting - too many errors"
11401141
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."
11411142
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)."
11421143
2025,fscAssemblyWildcardAndDeterminism,"An %s specified version '%s', but this value is a wildcard, and you have requested a deterministic build, these are in conflict."
1143-
2026,fscDeterministicDebugRequiresPortablePdb,"Determinstic builds only support portable PDBs (--debug:portable or --debug:embedded)"
1144+
2026,fscDeterministicDebugRequiresPortablePdb,"Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded)"
1145+
2027,fscPathMapDebugRequiresPortablePdb,"--pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded)"
1146+
2028,optsInvalidPathMapFormat,"Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath'"
11441147
3000,etIllegalCharactersInNamespaceName,"Character '%s' is not allowed in provided namespace name '%s'"
11451148
3001,etNullOrEmptyMemberName,"The provided type '%s' returned a member with a null or empty member name"
11461149
3002,etNullMember,"The provided type '%s' returned a null member"

src/fsharp/FSharp.Build/Fsc.fs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ type public Fsc () as this =
4242
let mutable noFramework = false
4343
let mutable optimize : bool = true
4444
let mutable otherFlags : string = null
45-
let mutable outputAssembly : string = null
45+
let mutable outputAssembly : string = null
46+
let mutable pathMap : string = null
4647
let mutable pdbFile : string = null
4748
let mutable platform : string = null
4849
let mutable prefer32bit : bool = false
@@ -234,6 +235,10 @@ type public Fsc () as this =
234235
builder.AppendSwitchIfNotNull("--targetprofile:", targetProfile)
235236

236237
builder.AppendSwitch("--nocopyfsharpcore")
238+
239+
match pathMap with
240+
| null -> ()
241+
| _ -> builder.AppendSwitchIfNotNull("--pathmap:", pathMap.Split([|';'; ','|], StringSplitOptions.RemoveEmptyEntries), ",")
237242

238243
if deterministic then
239244
builder.AppendSwitch("--deterministic+")
@@ -354,6 +359,11 @@ type public Fsc () as this =
354359
with get() = outputAssembly
355360
and set(s) = outputAssembly <- s
356361

362+
// --pathmap <string>: Paths to rewrite when producing deterministic builds
363+
member fsc.PathMap
364+
with get() = pathMap
365+
and set(s) = pathMap <- s
366+
357367
// --pdb <string>:
358368
// Name the debug output file
359369
member fsc.PdbFile

0 commit comments

Comments
 (0)