Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加编译选项,修复调试BUG #232

Merged
merged 1 commit into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions samples/ReferenceSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,26 @@
using System.Text.RegularExpressions;
using Internal;
using System.Runtime.CompilerServices;
using static System.Diagnostics.DebuggableAttribute;
using System.Diagnostics;
using System.Diagnostics.SymbolStore;

namespace ReferenceSample
{

internal class Program
{

static void Main(string[] args)
{
//Run();
NatashaManagement.Preheating(true, true);
GC.Collect();
Thread.Sleep(15000);
//NatashaManagement.Preheating(true, true);
//GC.Collect();
//Thread.Sleep(15000);
var method = typeof(Program).GetMethod("TestMini");
for (int i = 0; i < 5; i++)
{
TestMini();
method.Invoke(null,null);
Thread.Sleep(3000);
}
Console.ReadKey();
Expand All @@ -26,6 +32,7 @@ static void Main(string[] args)

public static void TestMini()
{

AssemblyCSharpBuilder builder = new AssemblyCSharpBuilder();
builder
.UseRandomDomain()
Expand All @@ -34,24 +41,30 @@ public static void TestMini()
Natasha.CSharp.Compiler.CompilerBinderFlags.SuppressConstraintChecks |
Natasha.CSharp.Compiler.CompilerBinderFlags.SuppressObsoleteChecks |
Natasha.CSharp.Compiler.CompilerBinderFlags.SuppressTypeArgumentBinding |
Natasha.CSharp.Compiler.CompilerBinderFlags.SuppressUnsafeDiagnostics))
Natasha.CSharp.Compiler.CompilerBinderFlags.SuppressUnsafeDiagnostics)
)
.DisableSemanticCheck()
.WithDebugCompile(item=>item.WriteToFile())
.OutputAsFullAssembly()
.WithoutPrivateMembers()
.AddReference(typeof(DebuggableAttribute))
.AddReference(typeof(object).Assembly)
.AddReference(typeof(Math).Assembly)
.AddReference(typeof(MathF).Assembly)
.ConfigReferenceCombineBehavior(CombineReferenceBehavior.UseCurrent);

builder.Add(@"public static class A{
builder.Add(@"
public static class A{
public static int N1 = 10;
public static float N2 = 1.2F;
public static double N3 = 3.44;

private static short N4 = 0;
public static object Invoke(){

return N1 + MathF.Log10((float)Math.Sqrt(MathF.Sqrt(N2) + Math.Tan(N3)));
}
}", UsingLoadBehavior.WithCurrent);

var asm = builder.GetAssembly();
var type = asm.GetType("A");
var method = type.GetMethod("Invoke");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using System.Diagnostics;
using System.Reflection.Emit;
using System.Reflection.Metadata;
using System.Runtime.CompilerServices;




Expand All @@ -19,7 +21,7 @@
/// <summary>
/// 程序集编译构建器 - 编译选项
/// </summary>
public sealed partial class AssemblyCSharpBuilder
public sealed partial class AssemblyCSharpBuilder
{

private PluginLoadBehavior _compileReferenceBehavior;
Expand Down Expand Up @@ -110,7 +112,7 @@ public CSharpCompilation GetAvailableCompilation(Func<CSharpCompilationOptions,
// _compilerOptions.WithLowerVersionsAssembly();
//}

var options = _compilerOptions.GetCompilationOptions();
var options = _compilerOptions.GetCompilationOptions(_codeOptimizationLevel);
if (initOptionsFunc != null)
{
options = initOptionsFunc(options);
Expand All @@ -124,13 +126,13 @@ public CSharpCompilation GetAvailableCompilation(Func<CSharpCompilationOptions,
{
references = Domain.References.GetReferences();
}

if (_referencesFilter != null)
{
references = _referencesFilter(references);
}
_compilation = CSharpCompilation.Create(AssemblyName, SyntaxTrees, references, options);

_compilation = CSharpCompilation.Create(AssemblyName, SyntaxTrees, references, options);
#if DEBUG
stopwatch.RestartAndShowCategoreInfo("[Compiler]", "获取编译单元", 2);
#endif
Expand Down Expand Up @@ -169,7 +171,7 @@ public CSharpCompilation GetAvailableCompilation(Func<CSharpCompilationOptions,
/// </remarks>
public Assembly GetAssembly()
{

#if DEBUG
Stopwatch stopwatch = new();
stopwatch.Start();
Expand All @@ -188,17 +190,8 @@ public Assembly GetAssembly()
dllStream = new MemoryStream();
}

if (_needGeneratPdb)
{
if (PdbFilePath != string.Empty)
{
pdbStream = File.Create(PdbFilePath);
}
else
{
pdbStream = new MemoryStream();
}
}



if (XmlFilePath != string.Empty)
{
Expand All @@ -211,19 +204,61 @@ public Assembly GetAssembly()
_compilation = GetAvailableCompilation();
}

var debugInfoFormat = _debugInfo._informationFormat;
if (_compilation.Options.OptimizationLevel == OptimizationLevel.Debug)
{

if (debugInfoFormat == DebugInformationFormat.PortablePdb)
{
if (string.IsNullOrEmpty(PdbFilePath))
{
var tempPdbOutputFolder = Path.Combine(GlobalOutputFolder, Domain.Name!);
PdbFilePath = Path.Combine(tempPdbOutputFolder, $"{AssemblyName}.pdb");
if (!Directory.Exists(tempPdbOutputFolder))
{
Directory.CreateDirectory(tempPdbOutputFolder);
}
}
pdbStream = File.Create(PdbFilePath);
}
else if (debugInfoFormat == DebugInformationFormat.Embedded)
{
PdbFilePath = null;
}
}
else if (!string.IsNullOrEmpty(PdbFilePath))
{
PdbFilePath = null;
debugInfoFormat = 0;
}


var compileResult = _compilation.Emit(
dllStream,
pdbStream: pdbStream,
xmlDocumentationStream: xmlStream,
options: new EmitOptions(pdbFilePath: PdbFilePath == string.Empty ? null : PdbFilePath, debugInformationFormat: DebugInformationFormat.PortablePdb));
options: new EmitOptions(
includePrivateMembers: _includePrivateMembers,
metadataOnly: _isReferenceAssembly,
pdbFilePath: PdbFilePath,
debugInformationFormat: debugInfoFormat
)
);


LogCompilationEvent?.Invoke(_compilation.GetNatashaLog());
Assembly? assembly = null;
if (compileResult.Success)
{
if (_compilation.Options.OptimizationLevel == OptimizationLevel.Debug)
{
if (debugInfoFormat == DebugInformationFormat.PortablePdb)
{
pdbStream?.Dispose();
pdbStream = File.OpenRead(PdbFilePath);
}
}
dllStream.Seek(0, SeekOrigin.Begin);
pdbStream?.Seek(0, SeekOrigin.Begin);
Domain.SetAssemblyLoadBehavior(_compileAssemblyBehavior);
assembly = Domain.LoadAssemblyFromStream(dllStream, pdbStream);
CompileSucceedEvent?.Invoke(_compilation, assembly!);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public AssemblyCSharpBuilder(string assemblyName)
SyntaxTrees = new();
AssemblyName = assemblyName;
DllFilePath = string.Empty;
PdbFilePath = string.Empty;
XmlFilePath = string.Empty;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public sealed partial class AssemblyCSharpBuilder
#region 输出设置相关
public string AssemblyName;
public string DllFilePath;
public string PdbFilePath;
public string? PdbFilePath;
public string XmlFilePath;
public string OutputFolder;
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,53 @@
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Emit;
using System;

public sealed partial class AssemblyCSharpBuilder
{
private DebugOutput _debugInfo = new DebugOutput();

private bool _isReferenceAssembly;

private bool _includePrivateMembers;

/// <summary>
/// pdb文件包含私有字段信息
/// </summary>
/// <returns></returns>
public AssemblyCSharpBuilder WithPrivateMembers()
{
_includePrivateMembers = true;
return this;
}
/// <summary>
/// pdb文件不包含私有字段信息
/// </summary>
/// <returns></returns>
public AssemblyCSharpBuilder WithoutPrivateMembers()
{
_includePrivateMembers = false;
return this;
}

/// <summary>
/// 是否以引用程序集方式输出
/// </summary>
/// <returns></returns>
public AssemblyCSharpBuilder OutputAsRefAssembly()
{
_isReferenceAssembly = true;
return this;
}
/// <summary>
/// 是否以完全程序集方式输出
/// </summary>
/// <returns></returns>
public AssemblyCSharpBuilder OutputAsFullAssembly()
{
_isReferenceAssembly = false;
return this;
}

/// <summary>
/// 清空编译信息, 下次编译重组 Compilation 和语法树.
/// </summary>
Expand All @@ -24,18 +70,29 @@ public AssemblyCSharpBuilder Clear()
return this;
}

private bool _needGeneratPdb;
public AssemblyCSharpBuilder WithoutPdbOutput()

private OptimizationLevel _codeOptimizationLevel = OptimizationLevel.Release;
/// <summary>
/// 编译时使用 debug 模式
/// </summary>
/// <returns></returns>
public AssemblyCSharpBuilder WithDebugCompile(Action<DebugOutput>? action = null)
{
_needGeneratPdb = false;
action?.Invoke(_debugInfo);
_codeOptimizationLevel = OptimizationLevel.Debug;
return this;
}
public AssemblyCSharpBuilder WithPdbOutput()
/// <summary>
/// 编译时使用 release 模式优化(默认)
/// </summary>
/// <returns></returns>
public AssemblyCSharpBuilder WithReleaseCompile()
{
_needGeneratPdb = true;
_codeOptimizationLevel = OptimizationLevel.Release;
return this;
}


/// <summary>
/// 自动使用 GUID 作为程序集名称.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

using Microsoft.CodeAnalysis.Emit;

public class DebugOutput
{

internal DebugInformationFormat _informationFormat = DebugInformationFormat.PortablePdb;

/// <summary>
/// 采用文件加载方式搜集源代码信息
/// </summary>
/// <returns></returns>
public DebugOutput WriteToFile()
{
_informationFormat = DebugInformationFormat.PortablePdb;
return this;
}
/// <summary>
/// 将Pdb输出到程序集中,并直接从程序集加载Pdb调试信息
/// </summary>
/// <returns></returns>
public DebugOutput WriteToAssembly()
{
_informationFormat = DebugInformationFormat.Embedded;
return this;
}

}

Loading
Loading