1
+ #nullable enable
2
+
3
+ using System ;
1
4
using System . Collections . Generic ;
2
5
using System . IO ;
3
6
using System . IO . Compression ;
4
7
using System . Linq ;
5
- using ILRepacking ;
6
8
using Mono . Cecil ;
7
9
using Mono . Cecil . Cil ;
8
10
9
11
public class RefAssemblyGenerator
10
12
{
11
13
class Resolver : DefaultAssemblyResolver , IAssemblyResolver
12
14
{
13
- private readonly string _dir ;
14
- Dictionary < string , AssemblyDefinition > _cache = new ( ) ;
15
+ readonly string _dir ;
16
+ readonly Dictionary < string , AssemblyDefinition > _cache = new ( ) ;
15
17
16
18
public Resolver ( string dir )
17
19
{
@@ -31,17 +33,17 @@ public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderPar
31
33
32
34
public static void PatchRefAssembly ( string file )
33
35
{
34
- var reader = typeof ( RefAssemblyGenerator ) . Assembly . GetManifestResourceStream ( "avalonia.snk" ) ;
36
+ var reader = typeof ( RefAssemblyGenerator ) . Assembly . GetManifestResourceStream ( "avalonia.snk" ) ! ;
35
37
var snk = new byte [ reader . Length ] ;
36
- reader . Read ( snk , 0 , snk . Length ) ;
38
+ reader . ReadExactly ( snk , 0 , snk . Length ) ;
37
39
38
40
var def = AssemblyDefinition . ReadAssembly ( file , new ReaderParameters
39
41
{
40
42
ReadWrite = true ,
41
43
InMemory = true ,
42
44
ReadSymbols = true ,
43
- SymbolReaderProvider = new DefaultSymbolReaderProvider ( false ) ,
44
- AssemblyResolver = new Resolver ( Path . GetDirectoryName ( file ) )
45
+ SymbolReaderProvider = new DefaultSymbolReaderProvider ( throwIfNoSymbol : true ) ,
46
+ AssemblyResolver = new Resolver ( Path . GetDirectoryName ( file ) ! )
45
47
} ) ;
46
48
47
49
var obsoleteAttribute = def . MainModule . ImportReference ( new TypeReference ( "System" , "ObsoleteAttribute" , def . MainModule ,
@@ -58,7 +60,7 @@ public static void PatchRefAssembly(string file)
58
60
{
59
61
StrongNameKeyBlob = snk ,
60
62
WriteSymbols = def . MainModule . HasSymbols ,
61
- SymbolWriterProvider = new EmbeddedPortablePdbWriterProvider ( ) ,
63
+ SymbolWriterProvider = new PortablePdbWriterProvider ( ) ,
62
64
DeterministicMvid = def . MainModule . HasSymbols
63
65
} ) ;
64
66
}
@@ -146,7 +148,7 @@ static void HideMethod(MethodDefinition m)
146
148
m . Attributes = ( ( m . Attributes | dflags ) ^ dflags ) | MethodAttributes . Assembly ;
147
149
}
148
150
149
- static void MarkAsUnstable ( IMemberDefinition def , MethodReference obsoleteCtor , ICustomAttribute unstableAttribute )
151
+ static void MarkAsUnstable ( IMemberDefinition def , MethodReference obsoleteCtor , ICustomAttribute ? unstableAttribute )
150
152
{
151
153
if ( def . CustomAttributes . Any ( a => a . AttributeType . FullName == "System.ObsoleteAttribute" ) )
152
154
return ;
@@ -172,43 +174,66 @@ static void MarkAsUnstable(IMemberDefinition def, MethodReference obsoleteCtor,
172
174
} ) ;
173
175
}
174
176
175
- public static void GenerateRefAsmsInPackage ( string packagePath )
177
+ public static void GenerateRefAsmsInPackage ( string mainPackagePath , string symbolsPackagePath )
176
178
{
177
- using ( var archive = new ZipArchive ( File . Open ( packagePath , FileMode . Open , FileAccess . ReadWrite ) ,
178
- ZipArchiveMode . Update ) )
179
+ using var mainArchive = OpenPackage ( mainPackagePath ) ;
180
+ using var symbolsArchive = OpenPackage ( symbolsPackagePath ) ;
181
+
182
+ foreach ( var entry in mainArchive . Entries
183
+ . Where ( e => e . FullName . StartsWith ( "ref/" , StringComparison . Ordinal ) )
184
+ . ToArray ( ) )
179
185
{
180
- foreach ( var entry in archive . Entries . ToList ( ) )
181
- {
182
- if ( entry . FullName . StartsWith ( "ref/" ) )
183
- entry . Delete ( ) ;
184
- }
185
-
186
- foreach ( var entry in archive . Entries . ToList ( ) )
186
+ entry . Delete ( ) ;
187
+ }
188
+
189
+ foreach ( var libEntry in GetLibEntries ( mainArchive , ".xml" ) )
190
+ {
191
+ var refEntry = mainArchive . CreateEntry ( "ref/" + libEntry . FullName . Substring ( 4 ) , CompressionLevel . Optimal ) ;
192
+ using var src = libEntry . Open ( ) ;
193
+ using var dst = refEntry . Open ( ) ;
194
+ src . CopyTo ( dst ) ;
195
+ }
196
+
197
+ var pdbEntries = GetLibEntries ( symbolsArchive , ".pdb" ) . ToDictionary ( e => e . FullName ) ;
198
+
199
+ var libs = GetLibEntries ( mainArchive , ".dll" )
200
+ . Select ( e => ( NameParts : e . FullName . Split ( '/' ) , Entry : e ) )
201
+ . Select ( e => (
202
+ Tfm : e . NameParts [ 1 ] ,
203
+ DllName : e . NameParts [ 2 ] ,
204
+ DllEntry : e . Entry ,
205
+ PdbName : Path . ChangeExtension ( e . NameParts [ 2 ] , ".pdb" ) ,
206
+ PdbEntry : pdbEntries . TryGetValue ( Path . ChangeExtension ( e . Entry . FullName , ".pdb" ) , out var pdbEntry ) ?
207
+ pdbEntry :
208
+ throw new InvalidOperationException ( $ "Missing symbols for { e . Entry . FullName } ") ) )
209
+ . GroupBy ( e => e . Tfm ) ;
210
+
211
+ foreach ( var tfm in libs )
212
+ {
213
+ using var _ = Helpers . UseTempDir ( out var temp ) ;
214
+
215
+ foreach ( var lib in tfm )
187
216
{
188
- if ( entry . FullName . StartsWith ( "lib/" ) && entry . Name . EndsWith ( ".xml" ) )
189
- {
190
- var newEntry = archive . CreateEntry ( "ref/" + entry . FullName . Substring ( 4 ) ,
191
- CompressionLevel . Optimal ) ;
192
- using ( var src = entry . Open ( ) )
193
- using ( var dst = newEntry . Open ( ) )
194
- src . CopyTo ( dst ) ;
195
- }
196
- }
217
+ var extractedDllPath = Path . Combine ( temp , lib . DllName ) ;
218
+ var extractedPdbPath = Path . Combine ( temp , lib . PdbName ) ;
219
+
220
+ lib . DllEntry . ExtractToFile ( extractedDllPath ) ;
221
+ lib . PdbEntry . ExtractToFile ( extractedPdbPath ) ;
197
222
198
- var libs = archive . Entries . Where ( e => e . FullName . StartsWith ( "lib/" ) && e . FullName . EndsWith ( ".dll" ) )
199
- . Select ( ( e => new { s = e . FullName . Split ( '/' ) , e = e } ) )
200
- . Select ( e => new { Tfm = e . s [ 1 ] , Name = e . s [ 2 ] , Entry = e . e } )
201
- . GroupBy ( x => x . Tfm ) ;
202
- foreach ( var tfm in libs )
203
- using ( Helpers . UseTempDir ( out var temp ) )
204
- {
205
- foreach ( var l in tfm )
206
- l . Entry . ExtractToFile ( Path . Combine ( temp , l . Name ) ) ;
207
- foreach ( var l in tfm )
208
- PatchRefAssembly ( Path . Combine ( temp , l . Name ) ) ;
209
- foreach ( var l in tfm )
210
- archive . CreateEntryFromFile ( Path . Combine ( temp , l . Name ) , $ "ref/{ l . Tfm } /{ l . Name } ") ;
211
- }
223
+ PatchRefAssembly ( extractedDllPath ) ;
224
+
225
+ mainArchive . CreateEntryFromFile ( extractedDllPath , $ "ref/{ lib . Tfm } /{ lib . DllName } ") ;
226
+ symbolsArchive . CreateEntryFromFile ( extractedPdbPath , $ "ref/{ lib . Tfm } /{ lib . PdbName } ") ;
227
+ }
212
228
}
229
+
230
+ static ZipArchive OpenPackage ( string packagePath )
231
+ => new ( File . Open ( packagePath , FileMode . Open , FileAccess . ReadWrite ) , ZipArchiveMode . Update ) ;
232
+
233
+ static ZipArchiveEntry [ ] GetLibEntries ( ZipArchive archive , string extension )
234
+ => archive . Entries
235
+ . Where ( e => e . FullName . StartsWith ( "lib/" , StringComparison . Ordinal )
236
+ && e . FullName . EndsWith ( extension , StringComparison . Ordinal ) )
237
+ . ToArray ( ) ;
213
238
}
214
239
}
0 commit comments