Skip to content

Commit

Permalink
Merge pull request #232 from dotnetcore/any
Browse files Browse the repository at this point in the history
增加编译选项,修复调试BUG
  • Loading branch information
NMSAzulX authored Nov 29, 2023
2 parents 9a89ba5 + 3619530 commit d08738e
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 73 deletions.
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

0 comments on commit d08738e

Please sign in to comment.