Skip to content

Commit d08738e

Browse files
authored
Merge pull request #232 from dotnetcore/any
增加编译选项,修复调试BUG
2 parents 9a89ba5 + 3619530 commit d08738e

File tree

10 files changed

+209
-73
lines changed

10 files changed

+209
-73
lines changed

samples/ReferenceSample/Program.cs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,26 @@
44
using System.Text.RegularExpressions;
55
using Internal;
66
using System.Runtime.CompilerServices;
7+
using static System.Diagnostics.DebuggableAttribute;
8+
using System.Diagnostics;
9+
using System.Diagnostics.SymbolStore;
710

811
namespace ReferenceSample
912
{
13+
1014
internal class Program
1115
{
16+
1217
static void Main(string[] args)
1318
{
1419
//Run();
15-
NatashaManagement.Preheating(true, true);
16-
GC.Collect();
17-
Thread.Sleep(15000);
20+
//NatashaManagement.Preheating(true, true);
21+
//GC.Collect();
22+
//Thread.Sleep(15000);
23+
var method = typeof(Program).GetMethod("TestMini");
1824
for (int i = 0; i < 5; i++)
1925
{
20-
TestMini();
26+
method.Invoke(null,null);
2127
Thread.Sleep(3000);
2228
}
2329
Console.ReadKey();
@@ -26,6 +32,7 @@ static void Main(string[] args)
2632

2733
public static void TestMini()
2834
{
35+
2936
AssemblyCSharpBuilder builder = new AssemblyCSharpBuilder();
3037
builder
3138
.UseRandomDomain()
@@ -34,24 +41,30 @@ public static void TestMini()
3441
Natasha.CSharp.Compiler.CompilerBinderFlags.SuppressConstraintChecks |
3542
Natasha.CSharp.Compiler.CompilerBinderFlags.SuppressObsoleteChecks |
3643
Natasha.CSharp.Compiler.CompilerBinderFlags.SuppressTypeArgumentBinding |
37-
Natasha.CSharp.Compiler.CompilerBinderFlags.SuppressUnsafeDiagnostics))
44+
Natasha.CSharp.Compiler.CompilerBinderFlags.SuppressUnsafeDiagnostics)
45+
)
3846
.DisableSemanticCheck()
47+
.WithDebugCompile(item=>item.WriteToFile())
48+
.OutputAsFullAssembly()
49+
.WithoutPrivateMembers()
50+
.AddReference(typeof(DebuggableAttribute))
3951
.AddReference(typeof(object).Assembly)
4052
.AddReference(typeof(Math).Assembly)
4153
.AddReference(typeof(MathF).Assembly)
4254
.ConfigReferenceCombineBehavior(CombineReferenceBehavior.UseCurrent);
4355

44-
builder.Add(@"public static class A{
56+
builder.Add(@"
57+
public static class A{
4558
public static int N1 = 10;
4659
public static float N2 = 1.2F;
4760
public static double N3 = 3.44;
48-
61+
private static short N4 = 0;
4962
public static object Invoke(){
5063
5164
return N1 + MathF.Log10((float)Math.Sqrt(MathF.Sqrt(N2) + Math.Tan(N3)));
5265
}
5366
}", UsingLoadBehavior.WithCurrent);
54-
67+
5568
var asm = builder.GetAssembly();
5669
var type = asm.GetType("A");
5770
var method = type.GetMethod("Invoke");

src/Natasha.CSharp/Natasha.CSharp.Compiler/MultiDomain/CompileUnit/AssemblyCSharpBuilder.Compile.cs

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
using System.Diagnostics;
1010
using System.Reflection.Emit;
1111
using System.Reflection.Metadata;
12+
using System.Runtime.CompilerServices;
13+
1214

1315

1416

@@ -19,7 +21,7 @@
1921
/// <summary>
2022
/// 程序集编译构建器 - 编译选项
2123
/// </summary>
22-
public sealed partial class AssemblyCSharpBuilder
24+
public sealed partial class AssemblyCSharpBuilder
2325
{
2426

2527
private PluginLoadBehavior _compileReferenceBehavior;
@@ -110,7 +112,7 @@ public CSharpCompilation GetAvailableCompilation(Func<CSharpCompilationOptions,
110112
// _compilerOptions.WithLowerVersionsAssembly();
111113
//}
112114

113-
var options = _compilerOptions.GetCompilationOptions();
115+
var options = _compilerOptions.GetCompilationOptions(_codeOptimizationLevel);
114116
if (initOptionsFunc != null)
115117
{
116118
options = initOptionsFunc(options);
@@ -124,13 +126,13 @@ public CSharpCompilation GetAvailableCompilation(Func<CSharpCompilationOptions,
124126
{
125127
references = Domain.References.GetReferences();
126128
}
127-
129+
128130
if (_referencesFilter != null)
129131
{
130132
references = _referencesFilter(references);
131133
}
132-
_compilation = CSharpCompilation.Create(AssemblyName, SyntaxTrees, references, options);
133134

135+
_compilation = CSharpCompilation.Create(AssemblyName, SyntaxTrees, references, options);
134136
#if DEBUG
135137
stopwatch.RestartAndShowCategoreInfo("[Compiler]", "获取编译单元", 2);
136138
#endif
@@ -169,7 +171,7 @@ public CSharpCompilation GetAvailableCompilation(Func<CSharpCompilationOptions,
169171
/// </remarks>
170172
public Assembly GetAssembly()
171173
{
172-
174+
173175
#if DEBUG
174176
Stopwatch stopwatch = new();
175177
stopwatch.Start();
@@ -188,17 +190,8 @@ public Assembly GetAssembly()
188190
dllStream = new MemoryStream();
189191
}
190192

191-
if (_needGeneratPdb)
192-
{
193-
if (PdbFilePath != string.Empty)
194-
{
195-
pdbStream = File.Create(PdbFilePath);
196-
}
197-
else
198-
{
199-
pdbStream = new MemoryStream();
200-
}
201-
}
193+
194+
202195

203196
if (XmlFilePath != string.Empty)
204197
{
@@ -211,19 +204,61 @@ public Assembly GetAssembly()
211204
_compilation = GetAvailableCompilation();
212205
}
213206

207+
var debugInfoFormat = _debugInfo._informationFormat;
208+
if (_compilation.Options.OptimizationLevel == OptimizationLevel.Debug)
209+
{
210+
211+
if (debugInfoFormat == DebugInformationFormat.PortablePdb)
212+
{
213+
if (string.IsNullOrEmpty(PdbFilePath))
214+
{
215+
var tempPdbOutputFolder = Path.Combine(GlobalOutputFolder, Domain.Name!);
216+
PdbFilePath = Path.Combine(tempPdbOutputFolder, $"{AssemblyName}.pdb");
217+
if (!Directory.Exists(tempPdbOutputFolder))
218+
{
219+
Directory.CreateDirectory(tempPdbOutputFolder);
220+
}
221+
}
222+
pdbStream = File.Create(PdbFilePath);
223+
}
224+
else if (debugInfoFormat == DebugInformationFormat.Embedded)
225+
{
226+
PdbFilePath = null;
227+
}
228+
}
229+
else if (!string.IsNullOrEmpty(PdbFilePath))
230+
{
231+
PdbFilePath = null;
232+
debugInfoFormat = 0;
233+
}
234+
235+
214236
var compileResult = _compilation.Emit(
215237
dllStream,
216238
pdbStream: pdbStream,
217239
xmlDocumentationStream: xmlStream,
218-
options: new EmitOptions(pdbFilePath: PdbFilePath == string.Empty ? null : PdbFilePath, debugInformationFormat: DebugInformationFormat.PortablePdb));
240+
options: new EmitOptions(
241+
includePrivateMembers: _includePrivateMembers,
242+
metadataOnly: _isReferenceAssembly,
243+
pdbFilePath: PdbFilePath,
244+
debugInformationFormat: debugInfoFormat
245+
)
246+
);
219247

220248

221249
LogCompilationEvent?.Invoke(_compilation.GetNatashaLog());
222250
Assembly? assembly = null;
223251
if (compileResult.Success)
224252
{
253+
if (_compilation.Options.OptimizationLevel == OptimizationLevel.Debug)
254+
{
255+
if (debugInfoFormat == DebugInformationFormat.PortablePdb)
256+
{
257+
pdbStream?.Dispose();
258+
pdbStream = File.OpenRead(PdbFilePath);
259+
}
260+
}
225261
dllStream.Seek(0, SeekOrigin.Begin);
226-
pdbStream?.Seek(0, SeekOrigin.Begin);
227262
Domain.SetAssemblyLoadBehavior(_compileAssemblyBehavior);
228263
assembly = Domain.LoadAssemblyFromStream(dllStream, pdbStream);
229264
CompileSucceedEvent?.Invoke(_compilation, assembly!);

src/Natasha.CSharp/Natasha.CSharp.Compiler/MultiDomain/CompileUnit/AssemblyCSharpBuilder.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ public AssemblyCSharpBuilder(string assemblyName)
3333
SyntaxTrees = new();
3434
AssemblyName = assemblyName;
3535
DllFilePath = string.Empty;
36-
PdbFilePath = string.Empty;
3736
XmlFilePath = string.Empty;
3837
}
3938

src/Natasha.CSharp/Natasha.CSharp.Compiler/Public/CompileUnit/AssemblyCSharpBuilder.Ouput.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public sealed partial class AssemblyCSharpBuilder
1010
#region 输出设置相关
1111
public string AssemblyName;
1212
public string DllFilePath;
13-
public string PdbFilePath;
13+
public string? PdbFilePath;
1414
public string XmlFilePath;
1515
public string OutputFolder;
1616
/// <summary>

src/Natasha.CSharp/Natasha.CSharp.Compiler/Public/CompileUnit/AssemblyCSharpBuilder.Share.cs

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,53 @@
1-
using System;
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.Emit;
3+
using System;
24

35
public sealed partial class AssemblyCSharpBuilder
46
{
7+
private DebugOutput _debugInfo = new DebugOutput();
8+
9+
private bool _isReferenceAssembly;
10+
11+
private bool _includePrivateMembers;
12+
13+
/// <summary>
14+
/// pdb文件包含私有字段信息
15+
/// </summary>
16+
/// <returns></returns>
17+
public AssemblyCSharpBuilder WithPrivateMembers()
18+
{
19+
_includePrivateMembers = true;
20+
return this;
21+
}
22+
/// <summary>
23+
/// pdb文件不包含私有字段信息
24+
/// </summary>
25+
/// <returns></returns>
26+
public AssemblyCSharpBuilder WithoutPrivateMembers()
27+
{
28+
_includePrivateMembers = false;
29+
return this;
30+
}
31+
32+
/// <summary>
33+
/// 是否以引用程序集方式输出
34+
/// </summary>
35+
/// <returns></returns>
36+
public AssemblyCSharpBuilder OutputAsRefAssembly()
37+
{
38+
_isReferenceAssembly = true;
39+
return this;
40+
}
41+
/// <summary>
42+
/// 是否以完全程序集方式输出
43+
/// </summary>
44+
/// <returns></returns>
45+
public AssemblyCSharpBuilder OutputAsFullAssembly()
46+
{
47+
_isReferenceAssembly = false;
48+
return this;
49+
}
50+
551
/// <summary>
652
/// 清空编译信息, 下次编译重组 Compilation 和语法树.
753
/// </summary>
@@ -24,18 +70,29 @@ public AssemblyCSharpBuilder Clear()
2470
return this;
2571
}
2672

27-
private bool _needGeneratPdb;
28-
public AssemblyCSharpBuilder WithoutPdbOutput()
73+
74+
private OptimizationLevel _codeOptimizationLevel = OptimizationLevel.Release;
75+
/// <summary>
76+
/// 编译时使用 debug 模式
77+
/// </summary>
78+
/// <returns></returns>
79+
public AssemblyCSharpBuilder WithDebugCompile(Action<DebugOutput>? action = null)
2980
{
30-
_needGeneratPdb = false;
81+
action?.Invoke(_debugInfo);
82+
_codeOptimizationLevel = OptimizationLevel.Debug;
3183
return this;
3284
}
33-
public AssemblyCSharpBuilder WithPdbOutput()
85+
/// <summary>
86+
/// 编译时使用 release 模式优化(默认)
87+
/// </summary>
88+
/// <returns></returns>
89+
public AssemblyCSharpBuilder WithReleaseCompile()
3490
{
35-
_needGeneratPdb = true;
91+
_codeOptimizationLevel = OptimizationLevel.Release;
3692
return this;
3793
}
3894

95+
3996
/// <summary>
4097
/// 自动使用 GUID 作为程序集名称.
4198
/// </summary>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+

2+
using Microsoft.CodeAnalysis.Emit;
3+
4+
public class DebugOutput
5+
{
6+
7+
internal DebugInformationFormat _informationFormat = DebugInformationFormat.PortablePdb;
8+
9+
/// <summary>
10+
/// 采用文件加载方式搜集源代码信息
11+
/// </summary>
12+
/// <returns></returns>
13+
public DebugOutput WriteToFile()
14+
{
15+
_informationFormat = DebugInformationFormat.PortablePdb;
16+
return this;
17+
}
18+
/// <summary>
19+
/// 将Pdb输出到程序集中,并直接从程序集加载Pdb调试信息
20+
/// </summary>
21+
/// <returns></returns>
22+
public DebugOutput WriteToAssembly()
23+
{
24+
_informationFormat = DebugInformationFormat.Embedded;
25+
return this;
26+
}
27+
28+
}
29+

0 commit comments

Comments
 (0)