Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Imison <nosami@users.noreply.github.com>2017-09-08 15:38:29 +0300
committerAlexander Köplinger <alex.koeplinger@outlook.com>2017-09-08 15:38:29 +0300
commit65106878d5d0c45917cfc7646c2509f6eb71dd7f (patch)
tree95ee0f152f463554c0fbedc33a9608eb171a8a70 /packaging
parenta09b912b86e0d488f13d6c1b0b2276e94e0f9499 (diff)
F# portable debugging (#5531)
* Switch F# builds over to portable pdb * Add portable pdb metadata fix from https://github.com/Microsoft/visualfsharp/pull/3553
Diffstat (limited to 'packaging')
-rw-r--r--packaging/MacSDK/fsharp.py2
-rw-r--r--packaging/MacSDK/patches/fsharp-fix-mdb-support.patch29
-rw-r--r--packaging/MacSDK/patches/fsharp-metadata-table-size-fix.patch451
-rw-r--r--packaging/MacSDK/patches/fsharp-portable-pdb.patch21
4 files changed, 473 insertions, 30 deletions
diff --git a/packaging/MacSDK/fsharp.py b/packaging/MacSDK/fsharp.py
index eeab6c36a92..f2e7a9bcdb6 100644
--- a/packaging/MacSDK/fsharp.py
+++ b/packaging/MacSDK/fsharp.py
@@ -8,7 +8,7 @@ class FsharpPackage(GitHubTarballPackage):
override_properties={ 'make': 'make' })
self.extra_stage_files = ['lib/mono/xbuild/Microsoft/VisualStudio/v/FSharp/Microsoft.FSharp.Targets']
- self.sources.extend(['patches/fsharp-fix-mdb-support.patch'])
+ self.sources.extend(['patches/fsharp-portable-pdb.patch', 'patches/fsharp-metadata-table-size-fix.patch'])
def prep(self):
Package.prep(self)
diff --git a/packaging/MacSDK/patches/fsharp-fix-mdb-support.patch b/packaging/MacSDK/patches/fsharp-fix-mdb-support.patch
deleted file mode 100644
index 164ad3d2bc8..00000000000
--- a/packaging/MacSDK/patches/fsharp-fix-mdb-support.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-commit 26e3e557e25b0ba5103dfb683050d2435f7708bb
-Author: Ankit Jain <ankit.jain@xamarin.com>
-Date: Wed Feb 8 18:44:41 2017 -0500
-
- [msbuild] Add support for .mdb files to be copied, with mono's msbuild
-
- msbuild defaults to .pdb files as the default debug file extension.
- Mono's msbuild has `$(_DebugFileExt)` property to override this. We need
- to set that to `.mdb`, else the generated `.mdb` files won't get
- copied/deployed.
-
- But this feature is not upstream yet, so it is not present in upstream
- F# yet.
-
-diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.targets
-index e185bdf..2788988 100644
---- a/src/fsharp/FSharp.Build/Microsoft.FSharp.targets
-+++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.targets
-@@ -38,6 +38,10 @@ this file.
- <RootNamespace Condition="'$(RootNamespace)'==''">RootNamespace</RootNamespace>
- <Actual32Bit Condition="'$(TargetFrameworkVersion)'=='v2.0' or '$(TargetFrameworkVersion)'=='v3.0' or '$(TargetFrameworkVersion)'=='v3.5' or '$(TargetFrameworkVersion)'=='v4.0'">false</Actual32Bit>
- <Actual32Bit Condition="!('$(TargetFrameworkVersion)'=='v2.0' or '$(TargetFrameworkVersion)'=='v3.0' or '$(TargetFrameworkVersion)'=='v3.5' or '$(TargetFrameworkVersion)'=='v4.0')">$(Prefer32Bit)</Actual32Bit>
-+
-+ <!-- _DebugFileExt is not an upstream msbuild feature yet -->
-+ <_DebugFileExt Condition="'$(FscDebugFileExt)' != ''">$(FscDebugFileExt)</_DebugFileExt>
-+ <_DebugFileExt Condition="'$(_DebugFileExt)' == ''">.mdb</_DebugFileExt>
- </PropertyGroup>
-
- <!--
diff --git a/packaging/MacSDK/patches/fsharp-metadata-table-size-fix.patch b/packaging/MacSDK/patches/fsharp-metadata-table-size-fix.patch
new file mode 100644
index 00000000000..cdc0111b0f7
--- /dev/null
+++ b/packaging/MacSDK/patches/fsharp-metadata-table-size-fix.patch
@@ -0,0 +1,451 @@
+From a7ac2facce91c15940e466f67a4ba9a31f687a1a Mon Sep 17 00:00:00 2001
+From: Kevin Ransom <kevinr@microsoft.com>
+Date: Sun, 3 Sep 2017 17:00:18 -0700
+Subject: [PATCH 1/3] Fix MethodDebugTable for portablePDBs
+
+---
+ src/absil/ilwritepdb.fs | 27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs
+index 009d39f653..3d68edee38 100644
+--- a/src/absil/ilwritepdb.fs
++++ b/src/absil/ilwritepdb.fs
+@@ -330,17 +330,22 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou
+ | None -> Array.empty<PdbSequencePoint>
+ | Some (_,_) -> minfo.SequencePoints
+
+- let getDocumentHandle d =
+- if docs.Length = 0 || d < 0 || d > docs.Length then
+- Unchecked.defaultof<DocumentHandle>
+- else
+- match documentIndex.TryGetValue(docs.[d].File) with
+- | false, _ -> Unchecked.defaultof<DocumentHandle>
+- | true, h -> h
+-
+- if sps.Length = 0 then
++ let builder = new BlobBuilder()
++ builder.WriteCompressedInteger(minfo.LocalSignatureToken)
++
++ if sps = Array.empty then
++ builder.WriteCompressedInteger( 0 )
++ builder.WriteCompressedInteger( 0 )
+ Unchecked.defaultof<DocumentHandle>, Unchecked.defaultof<BlobHandle>
+ else
++ let getDocumentHandle d =
++ if docs.Length = 0 || d < 0 || d > docs.Length then
++ Unchecked.defaultof<DocumentHandle>
++ else
++ match documentIndex.TryGetValue(docs.[d].File) with
++ | false, _ -> Unchecked.defaultof<DocumentHandle>
++ | true, h -> h
++
+ // Return a document that the entire method body is declared within.
+ // If part of the method body is in another document returns nil handle.
+ let tryGetSingleDocumentIndex =
+@@ -350,12 +355,8 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou
+ singleDocumentIndex <- -1
+ singleDocumentIndex
+
+- let builder = new BlobBuilder()
+- builder.WriteCompressedInteger(minfo.LocalSignatureToken)
+-
+ // Initial document: When sp's spread over more than one document we put the initial document here.
+ let singleDocumentIndex = tryGetSingleDocumentIndex
+-
+ if singleDocumentIndex = -1 then
+ builder.WriteCompressedInteger( MetadataTokens.GetRowNumber(DocumentHandle.op_Implicit(getDocumentHandle (sps.[0].Document))) )
+
+
+From 01d3e175e7e5c8c554c92bf121adba44e1287f9a Mon Sep 17 00:00:00 2001
+From: Kevin Ransom <kevinr@microsoft.com>
+Date: Tue, 5 Sep 2017 02:59:55 -0700
+Subject: [PATCH 2/3] ensure that pdb gets a record for abstract methods
+
+---
+ src/absil/ilread.fs | 1 -
+ src/absil/ilsupp.fs | 3 --
+ src/absil/ilsupp.fsi | 1 -
+ src/absil/ilwrite.fs | 17 +++++--
+ src/absil/ilwritepdb.fs | 113 ++++++++++++++++++++++++++---------------------
+ src/absil/ilwritepdb.fsi | 2 +-
+ 6 files changed, 77 insertions(+), 60 deletions(-)
+
+diff --git a/src/absil/ilread.fs b/src/absil/ilread.fs
+index c7a435291c..2d42a6abd8 100644
+--- a/src/absil/ilread.fs
++++ b/src/absil/ilread.fs
+@@ -2903,7 +2903,6 @@ and seekReadMethodRVA ctxt (idx,nm,_internalcall,noinline,aggressiveinline,numty
+ try
+
+ let pdbm = pdbReaderGetMethod pdbr (uncodedToken TableNames.Method idx)
+- //let rootScope = pdbMethodGetRootScope pdbm
+ let sps = pdbMethodGetSequencePoints pdbm
+ (*dprintf "#sps for 0x%x = %d\n" (uncodedToken TableNames.Method idx) (Array.length sps) *)
+ (* let roota,rootb = pdbScopeGetOffsets rootScope in *)
+diff --git a/src/absil/ilsupp.fs b/src/absil/ilsupp.fs
+index c95480bc06..66a1a6aa16 100644
+--- a/src/absil/ilsupp.fs
++++ b/src/absil/ilsupp.fs
+@@ -1230,9 +1230,6 @@ let pdbMethodGetToken (meth:PdbMethod) : int32 =
+ let token = meth.symMethod.Token
+ token.GetToken()
+
+-let pdbMethodGetRootScope (meth:PdbMethod) : PdbMethodScope =
+- { symScope = meth.symMethod.RootScope }
+-
+ let pdbMethodGetSequencePoints (meth:PdbMethod) : PdbSequencePoint array =
+ let pSize = meth.symMethod.SequencePointCount
+ let offsets = Array.zeroCreate pSize
+diff --git a/src/absil/ilsupp.fsi b/src/absil/ilsupp.fsi
+index 15da0aa215..3a3748c6d2 100644
+--- a/src/absil/ilsupp.fsi
++++ b/src/absil/ilsupp.fsi
+@@ -73,7 +73,6 @@ val pdbDocumentGetLanguageVendor: PdbDocument -> byte[] (* guid *)
+ val pdbDocumentFindClosestLine: PdbDocument -> int -> int
+
+ val pdbMethodGetToken: PdbMethod -> int32
+-val pdbMethodGetRootScope: PdbMethod -> PdbMethodScope
+ val pdbMethodGetSequencePoints: PdbMethod -> PdbSequencePoint array
+
+ val pdbScopeGetChildren: PdbMethodScope -> PdbMethodScope array
+diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs
+index 838b78783b..3b10ff4340 100644
+--- a/src/absil/ilwrite.fs
++++ b/src/absil/ilwrite.fs
+@@ -2577,7 +2577,7 @@ let GenMethodDefAsRow cenv env midx (md: ILMethodDef) =
+ MethName=md.Name
+ LocalSignatureToken=localToken
+ Params= [| |] (* REVIEW *)
+- RootScope = rootScope
++ RootScope = Some rootScope
+ Range=
+ match ilmbody.SourceMarker with
+ | Some m when cenv.generatePdb ->
+@@ -2592,9 +2592,20 @@ let GenMethodDefAsRow cenv env midx (md: ILMethodDef) =
+ Column=m.EndColumn })
+ | _ -> None
+ SequencePoints=seqpoints }
+-
+ cenv.AddCode code
+- addr
++ addr
++ | MethodBody.Abstract ->
++ // Now record the PDB record for this method - we write this out later.
++ if cenv.generatePdb then
++ cenv.pdbinfo.Add
++ { MethToken = getUncodedToken TableNames.Method midx
++ MethName = md.Name
++ LocalSignatureToken = 0x0 // No locals it's abstract
++ Params = [| |]
++ RootScope = None
++ Range = None
++ SequencePoints = [| |] }
++ 0x0000
+ | MethodBody.Native ->
+ failwith "cannot write body of native method - Abstract IL cannot roundtrip mixed native/managed binaries"
+ | _ -> 0x0000)
+diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs
+index 3d68edee38..996110e9b7 100644
+--- a/src/absil/ilwritepdb.fs
++++ b/src/absil/ilwritepdb.fs
+@@ -81,7 +81,7 @@ type PdbMethodData =
+ MethName:string
+ LocalSignatureToken: int32
+ Params: PdbLocalVar array
+- RootScope: PdbMethodScope
++ RootScope: PdbMethodScope option
+ Range: (PdbSourceLoc * PdbSourceLoc) option
+ SequencePoints: PdbSequencePoint array }
+
+@@ -224,7 +224,7 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou
+ let externalRowCounts = getRowCounts info.TableRowCounts
+ let docs =
+ match info.Documents with
+- | null -> Array.empty<PdbDocumentData>
++ | null -> Array.empty
+ | _ -> info.Documents
+
+ let metadata = MetadataBuilder()
+@@ -324,16 +324,16 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou
+ let docHandle, sequencePointBlob =
+ let sps =
+ match minfo.SequencePoints with
+- | null -> Array.empty<PdbSequencePoint>
++ | null -> Array.empty
+ | _ ->
+ match minfo.Range with
+- | None -> Array.empty<PdbSequencePoint>
++ | None -> Array.empty
+ | Some (_,_) -> minfo.SequencePoints
+
+ let builder = new BlobBuilder()
+ builder.WriteCompressedInteger(minfo.LocalSignatureToken)
+
+- if sps = Array.empty then
++ if sps.Length = 0 then
+ builder.WriteCompressedInteger( 0 )
+ builder.WriteCompressedInteger( 0 )
+ Unchecked.defaultof<DocumentHandle>, Unchecked.defaultof<BlobHandle>
+@@ -407,38 +407,41 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou
+ // Write the scopes
+ let nextHandle handle = MetadataTokens.LocalVariableHandle(MetadataTokens.GetRowNumber(LocalVariableHandle.op_Implicit(handle)) + 1)
+ let writeMethodScope scope =
+- let scopeSorter (scope1:PdbMethodScope) (scope2:PdbMethodScope) =
+- if scope1.StartOffset > scope2.StartOffset then 1
+- elif scope1.StartOffset < scope2.StartOffset then -1
+- elif (scope1.EndOffset - scope1.StartOffset) > (scope2.EndOffset - scope2.StartOffset) then -1
+- elif (scope1.EndOffset - scope1.StartOffset) < (scope2.EndOffset - scope2.StartOffset) then 1
+- else 0
+-
+- let collectScopes scope =
+- let list = new List<PdbMethodScope>()
+- let rec toList scope =
+- list.Add scope
+- scope.Children |> Seq.iter(fun s -> toList s)
+- toList scope
+- list.ToArray() |> Array.sortWith<PdbMethodScope> scopeSorter
+-
+- collectScopes scope |> Seq.iter(fun s ->
+- if s.Children.Length = 0 then
+- metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken),
+- Unchecked.defaultof<ImportScopeHandle>,
+- nextHandle lastLocalVariableHandle,
+- Unchecked.defaultof<LocalConstantHandle>,
+- 0, s.EndOffset - s.StartOffset ) |>ignore
+- else
+- metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken),
+- Unchecked.defaultof<ImportScopeHandle>,
+- nextHandle lastLocalVariableHandle,
+- Unchecked.defaultof<LocalConstantHandle>,
+- s.StartOffset, s.EndOffset - s.StartOffset) |>ignore
+-
+- for localVariable in s.Locals do
+- lastLocalVariableHandle <- metadata.AddLocalVariable(LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString(localVariable.Name))
+- )
++ match scope with
++ | Some scope ->
++ let scopeSorter (scope1:PdbMethodScope) (scope2:PdbMethodScope) =
++ if scope1.StartOffset > scope2.StartOffset then 1
++ elif scope1.StartOffset < scope2.StartOffset then -1
++ elif (scope1.EndOffset - scope1.StartOffset) > (scope2.EndOffset - scope2.StartOffset) then -1
++ elif (scope1.EndOffset - scope1.StartOffset) < (scope2.EndOffset - scope2.StartOffset) then 1
++ else 0
++
++ let collectScopes scope =
++ let list = new List<PdbMethodScope>()
++ let rec toList scope =
++ list.Add scope
++ scope.Children |> Seq.iter(fun s -> toList s)
++ toList scope
++ list.ToArray() |> Array.sortWith<PdbMethodScope> scopeSorter
++
++ collectScopes scope |> Seq.iter(fun s ->
++ if s.Children.Length = 0 then
++ metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken),
++ Unchecked.defaultof<ImportScopeHandle>,
++ nextHandle lastLocalVariableHandle,
++ Unchecked.defaultof<LocalConstantHandle>,
++ 0, s.EndOffset - s.StartOffset ) |>ignore
++ else
++ metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken),
++ Unchecked.defaultof<ImportScopeHandle>,
++ nextHandle lastLocalVariableHandle,
++ Unchecked.defaultof<LocalConstantHandle>,
++ s.StartOffset, s.EndOffset - s.StartOffset) |>ignore
++
++ for localVariable in s.Locals do
++ lastLocalVariableHandle <- metadata.AddLocalVariable(LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString(localVariable.Name))
++ )
++ | None -> ()
+ writeMethodScope minfo.RootScope )
+
+ let entryPoint =
+@@ -554,18 +557,20 @@ let writePdbInfo showTimes f fpdb info cvChunk =
+
+ // Write the scopes
+ let rec writePdbScope parent sco =
+- if parent = None || sco.Locals.Length <> 0 || sco.Children.Length <> 0 then
+- // Only nest scopes if the child scope is a different size from
+- let nested =
+- match parent with
+- | Some p -> sco.StartOffset <> p.StartOffset || sco.EndOffset <> p.EndOffset
+- | None -> true
+- if nested then pdbOpenScope !pdbw sco.StartOffset
+- sco.Locals |> Array.iter (fun v -> pdbDefineLocalVariable !pdbw v.Name v.Signature v.Index)
+- sco.Children |> Array.iter (writePdbScope (if nested then Some sco else parent))
+- if nested then pdbCloseScope !pdbw sco.EndOffset
+-
+- writePdbScope None minfo.RootScope
++ if parent = None || sco.Locals.Length <> 0 || sco.Children.Length <> 0 then
++ // Only nest scopes if the child scope is a different size from
++ let nested =
++ match parent with
++ | Some p -> sco.StartOffset <> p.StartOffset || sco.EndOffset <> p.EndOffset
++ | None -> true
++ if nested then pdbOpenScope !pdbw sco.StartOffset
++ sco.Locals |> Array.iter (fun v -> pdbDefineLocalVariable !pdbw v.Name v.Signature v.Index)
++ sco.Children |> Array.iter (writePdbScope (if nested then Some sco else parent))
++ if nested then pdbCloseScope !pdbw sco.EndOffset
++
++ match minfo.RootScope with
++ | None -> ()
++ | Some rootscope -> writePdbScope None rootscope
+ pdbCloseMethod !pdbw
+ end)
+ reportTime showTimes "PDB: Wrote methods"
+@@ -675,7 +680,10 @@ let writeMdbInfo fmdb f info =
+ for child in scope.Children do
+ writeScope(child)
+ wr?CloseScope(scope.EndOffset)
+- writeScope(meth.RootScope)
++ match meth.RootScope with
++ | None -> ()
++ | Some rootscope -> writeScope(rootscope)
++
+
+ // Finished generating debug information for the curretn method
+ wr?CloseMethod()
+@@ -722,5 +730,8 @@ let logDebugInfo (outfile:string) (info:PdbData) =
+ if scope.Locals.Length > 0 then
+ fprintfn sw " %s Locals: %A" offs [ for p in scope.Locals -> sprintf "%d: %s" p.Index p.Name ]
+ for child in scope.Children do writeScope (offs + " ") child
+- writeScope "" meth.RootScope
++
++ match meth.RootScope with
++ | None -> ()
++ | Some rootscope -> writeScope "" rootscope
+ fprintfn sw ""
+diff --git a/src/absil/ilwritepdb.fsi b/src/absil/ilwritepdb.fsi
+index e5d1c8d03a..af9f16be9e 100644
+--- a/src/absil/ilwritepdb.fsi
++++ b/src/absil/ilwritepdb.fsi
+@@ -44,7 +44,7 @@ type PdbMethodData =
+ MethName:string
+ LocalSignatureToken: int32
+ Params: PdbLocalVar array
+- RootScope: PdbMethodScope
++ RootScope: PdbMethodScope option
+ Range: (PdbSourceLoc * PdbSourceLoc) option
+ SequencePoints: PdbSequencePoint array }
+
+
+From 64ecadb27b24c1486610deb32c3044ad0b3449ae Mon Sep 17 00:00:00 2001
+From: Kevin Ransom <kevinr@microsoft.com>
+Date: Tue, 5 Sep 2017 03:13:04 -0700
+Subject: [PATCH 3/3] minimise diff
+
+---
+ src/absil/ilwritepdb.fs | 92 ++++++++++++++++++++++++-------------------------
+ 1 file changed, 46 insertions(+), 46 deletions(-)
+
+diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs
+index 996110e9b7..f8baa3aea4 100644
+--- a/src/absil/ilwritepdb.fs
++++ b/src/absil/ilwritepdb.fs
+@@ -407,42 +407,42 @@ let generatePortablePdb (embedAllSource:bool) (embedSourceList:string list) (sou
+ // Write the scopes
+ let nextHandle handle = MetadataTokens.LocalVariableHandle(MetadataTokens.GetRowNumber(LocalVariableHandle.op_Implicit(handle)) + 1)
+ let writeMethodScope scope =
+- match scope with
+- | Some scope ->
+- let scopeSorter (scope1:PdbMethodScope) (scope2:PdbMethodScope) =
+- if scope1.StartOffset > scope2.StartOffset then 1
+- elif scope1.StartOffset < scope2.StartOffset then -1
+- elif (scope1.EndOffset - scope1.StartOffset) > (scope2.EndOffset - scope2.StartOffset) then -1
+- elif (scope1.EndOffset - scope1.StartOffset) < (scope2.EndOffset - scope2.StartOffset) then 1
+- else 0
+-
+- let collectScopes scope =
+- let list = new List<PdbMethodScope>()
+- let rec toList scope =
+- list.Add scope
+- scope.Children |> Seq.iter(fun s -> toList s)
+- toList scope
+- list.ToArray() |> Array.sortWith<PdbMethodScope> scopeSorter
+-
+- collectScopes scope |> Seq.iter(fun s ->
+- if s.Children.Length = 0 then
+- metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken),
+- Unchecked.defaultof<ImportScopeHandle>,
+- nextHandle lastLocalVariableHandle,
+- Unchecked.defaultof<LocalConstantHandle>,
+- 0, s.EndOffset - s.StartOffset ) |>ignore
+- else
+- metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken),
+- Unchecked.defaultof<ImportScopeHandle>,
+- nextHandle lastLocalVariableHandle,
+- Unchecked.defaultof<LocalConstantHandle>,
+- s.StartOffset, s.EndOffset - s.StartOffset) |>ignore
+-
+- for localVariable in s.Locals do
+- lastLocalVariableHandle <- metadata.AddLocalVariable(LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString(localVariable.Name))
+- )
+- | None -> ()
+- writeMethodScope minfo.RootScope )
++ let scopeSorter (scope1:PdbMethodScope) (scope2:PdbMethodScope) =
++ if scope1.StartOffset > scope2.StartOffset then 1
++ elif scope1.StartOffset < scope2.StartOffset then -1
++ elif (scope1.EndOffset - scope1.StartOffset) > (scope2.EndOffset - scope2.StartOffset) then -1
++ elif (scope1.EndOffset - scope1.StartOffset) < (scope2.EndOffset - scope2.StartOffset) then 1
++ else 0
++
++ let collectScopes scope =
++ let list = new List<PdbMethodScope>()
++ let rec toList scope =
++ list.Add scope
++ scope.Children |> Seq.iter(fun s -> toList s)
++ toList scope
++ list.ToArray() |> Array.sortWith<PdbMethodScope> scopeSorter
++
++ collectScopes scope |> Seq.iter(fun s ->
++ if s.Children.Length = 0 then
++ metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken),
++ Unchecked.defaultof<ImportScopeHandle>,
++ nextHandle lastLocalVariableHandle,
++ Unchecked.defaultof<LocalConstantHandle>,
++ 0, s.EndOffset - s.StartOffset ) |>ignore
++ else
++ metadata.AddLocalScope(MetadataTokens.MethodDefinitionHandle(minfo.MethToken),
++ Unchecked.defaultof<ImportScopeHandle>,
++ nextHandle lastLocalVariableHandle,
++ Unchecked.defaultof<LocalConstantHandle>,
++ s.StartOffset, s.EndOffset - s.StartOffset) |>ignore
++
++ for localVariable in s.Locals do
++ lastLocalVariableHandle <- metadata.AddLocalVariable(LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString(localVariable.Name))
++ )
++
++ match minfo.RootScope with
++ | None -> ()
++ | Some scope -> writeMethodScope scope )
+
+ let entryPoint =
+ match info.EntryPoint with
+@@ -557,16 +557,16 @@ let writePdbInfo showTimes f fpdb info cvChunk =
+
+ // Write the scopes
+ let rec writePdbScope parent sco =
+- if parent = None || sco.Locals.Length <> 0 || sco.Children.Length <> 0 then
+- // Only nest scopes if the child scope is a different size from
+- let nested =
+- match parent with
+- | Some p -> sco.StartOffset <> p.StartOffset || sco.EndOffset <> p.EndOffset
+- | None -> true
+- if nested then pdbOpenScope !pdbw sco.StartOffset
+- sco.Locals |> Array.iter (fun v -> pdbDefineLocalVariable !pdbw v.Name v.Signature v.Index)
+- sco.Children |> Array.iter (writePdbScope (if nested then Some sco else parent))
+- if nested then pdbCloseScope !pdbw sco.EndOffset
++ if parent = None || sco.Locals.Length <> 0 || sco.Children.Length <> 0 then
++ // Only nest scopes if the child scope is a different size from
++ let nested =
++ match parent with
++ | Some p -> sco.StartOffset <> p.StartOffset || sco.EndOffset <> p.EndOffset
++ | None -> true
++ if nested then pdbOpenScope !pdbw sco.StartOffset
++ sco.Locals |> Array.iter (fun v -> pdbDefineLocalVariable !pdbw v.Name v.Signature v.Index)
++ sco.Children |> Array.iter (writePdbScope (if nested then Some sco else parent))
++ if nested then pdbCloseScope !pdbw sco.EndOffset
+
+ match minfo.RootScope with
+ | None -> ()
diff --git a/packaging/MacSDK/patches/fsharp-portable-pdb.patch b/packaging/MacSDK/patches/fsharp-portable-pdb.patch
new file mode 100644
index 00000000000..3ced495c38b
--- /dev/null
+++ b/packaging/MacSDK/patches/fsharp-portable-pdb.patch
@@ -0,0 +1,21 @@
+diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets
+index 34d716485..ec99e87ed 100644
+--- a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets
++++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets
+@@ -41,6 +41,16 @@ this file.
+ <RootNamespace Condition="'$(RootNamespace)'==''">RootNamespace</RootNamespace>
+ <Actual32Bit Condition="'$(TargetFrameworkVersion)'=='v2.0' or '$(TargetFrameworkVersion)'=='v3.0' or '$(TargetFrameworkVersion)'=='v3.5' or '$(TargetFrameworkVersion)'=='v4.0'">false</Actual32Bit>
+ <Actual32Bit Condition="!('$(TargetFrameworkVersion)'=='v2.0' or '$(TargetFrameworkVersion)'=='v3.0' or '$(TargetFrameworkVersion)'=='v3.5' or '$(TargetFrameworkVersion)'=='v4.0')">$(Prefer32Bit)</Actual32Bit>
++ <!--
++ `/debug+` is produced based on `$(DebugSymols)`, which gets a default value of 'true' in
++ Microsoft.Common.CurrentVersion.targets, with a condition:
++ Condition=" '$(ConfigurationName)' == 'Debug' and '$(DebugSymbols)' == '' and '$(DebugType)'=='' "
++ But that file is imported later, so we cannot depend on the default value of `$(DebugSymbols)` or `$(ConfigurationName)`.
++ -->
++ <_ConfigurationNameTmp>$(ConfigurationName)</_ConfigurationNameTmp>
++ <_ConfigurationNameTmp Condition="'$(ConfigurationName)' == ''">$(Configuration)</_ConfigurationNameTmp>
++
++ <DebugType Condition="'$(OS)' != 'Windows_NT' And ('$(DebugSymbols)'=='True' or ('$(DebugSymbols)'=='' And '$(_ConfigurationNameTmp)'=='Debug'))">portable</DebugType>
+ </PropertyGroup>
+
+ <!--