Add wasm debug info (#6186)
* Add source line debug metadata. Works with javascript output. * Add names of arguments and locals when they're stored on the stack (and thus easily visible in the debugger) * Add debugging information to documentation
This commit is contained in:
Родитель
6fdbbbadad
Коммит
2d4981ac9e
|
@ -37,6 +37,7 @@ This is Windows only for now.
|
|||
|
||||
# Useful tips #
|
||||
* To manually make ILC compile to WebAssembly, add ```--wasm``` to the command line.
|
||||
* To debug C# source, add ```-g4``` to the emcc command line and change ```-s WASM=1``` to ```-s WASM=0```. This will generate a JavaScript source map that browser debuggers and Visual Studio Code can work with. Using Visual Studio Code's Chrome debugger works particularly well.
|
||||
* Add ```-g3``` to the emcc command line to generate more debuggable output and a .wast file with the text form of the WebAssembly.
|
||||
* Omit ```-s WASM=1``` from the emcc command line to generate asm.js. Browser debuggers currently work better with asm.js and it's often a bit more readable than wast.
|
||||
* Change ```-s WASM=1``` to ```-s WASM=0``` in the emcc command line to generate asm.js. Browser debuggers currently work better with asm.js and it's often a bit more readable than wast.
|
||||
* Add ```-O2 --llvm-lto 2``` to the emcc command line to enable optimizations. This makes the generated WebAssembly as much as 75% smaller as well as more efficient.
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using LLVMSharp;
|
||||
|
||||
namespace ILCompiler.WebAssembly
|
||||
{
|
||||
class DebugMetadata
|
||||
{
|
||||
public DebugMetadata(LLVMMetadataRef file, LLVMMetadataRef compileUnit)
|
||||
{
|
||||
File = file;
|
||||
CompileUnit = compileUnit;
|
||||
}
|
||||
|
||||
public LLVMMetadataRef CompileUnit { get; }
|
||||
public LLVMMetadataRef File { get; }
|
||||
}
|
||||
}
|
|
@ -5,6 +5,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using Internal.TypeSystem;
|
||||
using ILCompiler;
|
||||
|
@ -12,8 +14,8 @@ using LLVMSharp;
|
|||
using ILCompiler.CodeGen;
|
||||
using ILCompiler.DependencyAnalysis;
|
||||
using ILCompiler.DependencyAnalysisFramework;
|
||||
using ILCompiler.WebAssembly;
|
||||
using Internal.TypeSystem.Ecma;
|
||||
using System.Linq;
|
||||
|
||||
namespace Internal.IL
|
||||
{
|
||||
|
@ -35,6 +37,7 @@ namespace Internal.IL
|
|||
}
|
||||
|
||||
public LLVMModuleRef Module { get; }
|
||||
public LLVMContextRef Context { get; }
|
||||
private readonly MethodDesc _method;
|
||||
private readonly MethodIL _methodIL;
|
||||
private readonly MethodSignature _signature;
|
||||
|
@ -49,6 +52,8 @@ namespace Internal.IL
|
|||
private List<SpilledExpressionEntry> _spilledExpressions = new List<SpilledExpressionEntry>();
|
||||
private int _pointerSize;
|
||||
private readonly byte[] _ilBytes;
|
||||
private MethodDebugInformation _debugInformation;
|
||||
private LLVMMetadataRef _debugFunction;
|
||||
|
||||
/// <summary>
|
||||
/// Stack of values pushed onto the IL stack: locals, arguments, values, function pointer, ...
|
||||
|
@ -106,6 +111,10 @@ namespace Internal.IL
|
|||
_llvmFunction = GetOrCreateLLVMFunction(mangledName, method.Signature);
|
||||
_builder = LLVM.CreateBuilder();
|
||||
_pointerSize = compilation.NodeFactory.Target.PointerSize;
|
||||
|
||||
_debugInformation = _compilation.GetDebugInfo(_methodIL);
|
||||
|
||||
Context = LLVM.GetModuleContext(Module);
|
||||
}
|
||||
|
||||
public void Import()
|
||||
|
@ -174,22 +183,57 @@ namespace Internal.IL
|
|||
signatureIndex++;
|
||||
}
|
||||
|
||||
string[] argNames = null;
|
||||
if (_debugInformation != null)
|
||||
{
|
||||
argNames = _debugInformation.GetParameterNames()?.ToArray();
|
||||
}
|
||||
|
||||
for (int i = 0; i < _signature.Length; i++)
|
||||
{
|
||||
if (CanStoreTypeOnStack(_signature[i]))
|
||||
{
|
||||
LLVMValueRef argStackSlot = LLVM.BuildAlloca(_builder, GetLLVMTypeForTypeDesc(_signature[i]), $"arg{i + thisOffset}_");
|
||||
string argName = String.Empty;
|
||||
if (argNames != null && argNames[i] != null)
|
||||
{
|
||||
argName = argNames[i] + "_";
|
||||
}
|
||||
argName += $"arg{i + thisOffset}_";
|
||||
|
||||
LLVMValueRef argStackSlot = LLVM.BuildAlloca(_builder, GetLLVMTypeForTypeDesc(_signature[i]), argName);
|
||||
LLVM.BuildStore(_builder, LLVM.GetParam(_llvmFunction, (uint)signatureIndex), argStackSlot);
|
||||
_argSlots[i] = argStackSlot;
|
||||
signatureIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
string[] localNames = new string[_locals.Length];
|
||||
if (_debugInformation != null)
|
||||
{
|
||||
foreach (ILLocalVariable localDebugInfo in _debugInformation.GetLocalVariables() ?? Enumerable.Empty<ILLocalVariable>())
|
||||
{
|
||||
// Check whether the slot still exists as the compiler may remove it for intrinsics
|
||||
int slot = localDebugInfo.Slot;
|
||||
if (slot < localNames.Length)
|
||||
{
|
||||
localNames[localDebugInfo.Slot] = localDebugInfo.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _locals.Length; i++)
|
||||
{
|
||||
if (CanStoreLocalOnStack(_locals[i].Type))
|
||||
{
|
||||
LLVMValueRef localStackSlot = LLVM.BuildAlloca(_builder, GetLLVMTypeForTypeDesc(_locals[i].Type), $"local{i}_");
|
||||
string localName = String.Empty;
|
||||
if (localNames[i] != null)
|
||||
{
|
||||
localName = localNames[i] + "_";
|
||||
}
|
||||
|
||||
localName += $"local{i}_";
|
||||
|
||||
LLVMValueRef localStackSlot = LLVM.BuildAlloca(_builder, GetLLVMTypeForTypeDesc(_locals[i].Type), localName);
|
||||
_localSlots[i] = localStackSlot;
|
||||
}
|
||||
}
|
||||
|
@ -398,10 +442,69 @@ namespace Internal.IL
|
|||
|
||||
private void StartImportingInstruction()
|
||||
{
|
||||
if (_debugInformation != null)
|
||||
{
|
||||
bool foundSequencePoint = false;
|
||||
ILSequencePoint curSequencePoint = default;
|
||||
foreach (var sequencePoint in _debugInformation.GetSequencePoints() ?? Enumerable.Empty<ILSequencePoint>())
|
||||
{
|
||||
if (sequencePoint.Offset == _currentOffset)
|
||||
{
|
||||
curSequencePoint = sequencePoint;
|
||||
foundSequencePoint = true;
|
||||
break;
|
||||
}
|
||||
else if (sequencePoint.Offset < _currentOffset)
|
||||
{
|
||||
curSequencePoint = sequencePoint;
|
||||
foundSequencePoint = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundSequencePoint)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// LLVM can't process empty string file names
|
||||
if (String.IsNullOrWhiteSpace(curSequencePoint.Document))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DebugMetadata debugMetadata;
|
||||
if (!_compilation.DebugMetadataMap.TryGetValue(curSequencePoint.Document, out debugMetadata))
|
||||
{
|
||||
string fullPath = curSequencePoint.Document;
|
||||
string fileName = Path.GetFileName(fullPath);
|
||||
string directory = Path.GetDirectoryName(fullPath) ?? String.Empty;
|
||||
LLVMMetadataRef fileMetadata = LLVMPInvokes.LLVMDIBuilderCreateFile(_compilation.DIBuilder, fullPath, fullPath.Length,
|
||||
directory, directory.Length);
|
||||
|
||||
// todo: get the right value for isOptimized
|
||||
LLVMMetadataRef compileUnitMetadata = LLVMPInvokes.LLVMDIBuilderCreateCompileUnit(_compilation.DIBuilder, LLVMDWARFSourceLanguage.LLVMDWARFSourceLanguageC,
|
||||
fileMetadata, "ILC", 3, isOptimized: false, String.Empty, 0, 1, String.Empty, 0, LLVMDWARFEmissionKind.LLVMDWARFEmissionFull, 0, false, false);
|
||||
LLVM.AddNamedMetadataOperand(Module, "llvm.dbg.cu", LLVM.MetadataAsValue(Context, compileUnitMetadata));
|
||||
|
||||
debugMetadata = new DebugMetadata(fileMetadata, compileUnitMetadata);
|
||||
_compilation.DebugMetadataMap[fullPath] = debugMetadata;
|
||||
}
|
||||
|
||||
if (_debugFunction.Pointer == IntPtr.Zero)
|
||||
{
|
||||
_debugFunction = LLVM.DIBuilderCreateFunction(_compilation.DIBuilder, debugMetadata.CompileUnit, _method.Name, String.Empty, debugMetadata.File,
|
||||
(uint)_debugInformation.GetSequencePoints().FirstOrDefault().LineNumber, default(LLVMMetadataRef), 1, 1, 1, 0, IsOptimized: 0, _llvmFunction);
|
||||
}
|
||||
|
||||
LLVMMetadataRef currentLine = LLVMPInvokes.LLVMDIBuilderCreateDebugLocation(Context, (uint)curSequencePoint.LineNumber, 0, _debugFunction, default(LLVMMetadataRef));
|
||||
LLVM.SetCurrentDebugLocation(_builder, LLVM.MetadataAsValue(Context, currentLine));
|
||||
}
|
||||
}
|
||||
|
||||
private void EndImportingInstruction()
|
||||
{
|
||||
// Reset the debug position so it doesn't end up applying to the wrong instructions
|
||||
LLVM.SetCurrentDebugLocation(_builder, default(LLVMValueRef));
|
||||
}
|
||||
|
||||
private void ImportNop()
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using LLVMSharp;
|
||||
|
||||
namespace ILCompiler.WebAssembly
|
||||
{
|
||||
// LLVM P/Invokes copied from LLVMSharp that match the current LLVM surface area.
|
||||
// If we get a new version of LLVMSharp containing these, this file should be removed.
|
||||
internal class LLVMPInvokes
|
||||
{
|
||||
const string libraryPath = "libLLVM";
|
||||
[DllImport(libraryPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern LLVMDIBuilderRef LLVMCreateDIBuilder(LLVMModuleRef M);
|
||||
|
||||
[DllImport(libraryPath, EntryPoint = "LLVMDIBuilderCreateCompileUnit", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef @Builder, LLVMDWARFSourceLanguage @Lang, LLVMMetadataRef @FileRef, [MarshalAs(UnmanagedType.LPStr)] string @Producer, size_t @ProducerLen, LLVMBool @isOptimized, [MarshalAs(UnmanagedType.LPStr)] string @Flags, size_t @FlagsLen, uint @RuntimeVer, [MarshalAs(UnmanagedType.LPStr)] string @SplitName, size_t @SplitNameLen, LLVMDWARFEmissionKind @Kind, uint @DWOId, LLVMBool @SplitDebugInlining, LLVMBool @DebugInfoForProfiling);
|
||||
|
||||
[DllImport(libraryPath, EntryPoint = "LLVMDIBuilderCreateFile", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern LLVMMetadataRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef @Builder, [MarshalAs(UnmanagedType.LPStr)] string @Filename, size_t @FilenameLen, [MarshalAs(UnmanagedType.LPStr)] string @Directory, size_t @DirectoryLen);
|
||||
|
||||
[DllImport(libraryPath, EntryPoint = "LLVMDIBuilderCreateDebugLocation", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern LLVMMetadataRef LLVMDIBuilderCreateDebugLocation(LLVMContextRef @Ctx, uint @Line, uint @Column, LLVMMetadataRef @Scope, LLVMMetadataRef @InlinedAt);
|
||||
}
|
||||
|
||||
internal enum LLVMDWARFSourceLanguage : int
|
||||
{
|
||||
@LLVMDWARFSourceLanguageC89 = 0,
|
||||
@LLVMDWARFSourceLanguageC = 1,
|
||||
@LLVMDWARFSourceLanguageAda83 = 2,
|
||||
@LLVMDWARFSourceLanguageC_plus_plus = 3,
|
||||
@LLVMDWARFSourceLanguageCobol74 = 4,
|
||||
@LLVMDWARFSourceLanguageCobol85 = 5,
|
||||
@LLVMDWARFSourceLanguageFortran77 = 6,
|
||||
@LLVMDWARFSourceLanguageFortran90 = 7,
|
||||
@LLVMDWARFSourceLanguagePascal83 = 8,
|
||||
@LLVMDWARFSourceLanguageModula2 = 9,
|
||||
@LLVMDWARFSourceLanguageJava = 10,
|
||||
@LLVMDWARFSourceLanguageC99 = 11,
|
||||
@LLVMDWARFSourceLanguageAda95 = 12,
|
||||
@LLVMDWARFSourceLanguageFortran95 = 13,
|
||||
@LLVMDWARFSourceLanguagePLI = 14,
|
||||
@LLVMDWARFSourceLanguageObjC = 15,
|
||||
@LLVMDWARFSourceLanguageObjC_plus_plus = 16,
|
||||
@LLVMDWARFSourceLanguageUPC = 17,
|
||||
@LLVMDWARFSourceLanguageD = 18,
|
||||
@LLVMDWARFSourceLanguagePython = 19,
|
||||
@LLVMDWARFSourceLanguageOpenCL = 20,
|
||||
@LLVMDWARFSourceLanguageGo = 21,
|
||||
@LLVMDWARFSourceLanguageModula3 = 22,
|
||||
@LLVMDWARFSourceLanguageHaskell = 23,
|
||||
@LLVMDWARFSourceLanguageC_plus_plus_03 = 24,
|
||||
@LLVMDWARFSourceLanguageC_plus_plus_11 = 25,
|
||||
@LLVMDWARFSourceLanguageOCaml = 26,
|
||||
@LLVMDWARFSourceLanguageRust = 27,
|
||||
@LLVMDWARFSourceLanguageC11 = 28,
|
||||
@LLVMDWARFSourceLanguageSwift = 29,
|
||||
@LLVMDWARFSourceLanguageJulia = 30,
|
||||
@LLVMDWARFSourceLanguageDylan = 31,
|
||||
@LLVMDWARFSourceLanguageC_plus_plus_14 = 32,
|
||||
@LLVMDWARFSourceLanguageFortran03 = 33,
|
||||
@LLVMDWARFSourceLanguageFortran08 = 34,
|
||||
@LLVMDWARFSourceLanguageRenderScript = 35,
|
||||
@LLVMDWARFSourceLanguageBLISS = 36,
|
||||
@LLVMDWARFSourceLanguageMips_Assembler = 37,
|
||||
@LLVMDWARFSourceLanguageGOOGLE_RenderScript = 38,
|
||||
@LLVMDWARFSourceLanguageBORLAND_Delphi = 39,
|
||||
}
|
||||
|
||||
internal enum LLVMDWARFEmissionKind : int
|
||||
{
|
||||
@LLVMDWARFEmissionNone = 0,
|
||||
@LLVMDWARFEmissionFull = 1,
|
||||
@LLVMDWARFEmissionLineTablesOnly = 2,
|
||||
}
|
||||
}
|
|
@ -144,6 +144,8 @@ namespace ILCompiler.DependencyAnalysis
|
|||
// this is the llvm instance.
|
||||
public LLVMModuleRef Module { get; }
|
||||
|
||||
public LLVMDIBuilderRef DIBuilder { get; }
|
||||
|
||||
// This is used to build mangled names
|
||||
private Utf8StringBuilder _sb = new Utf8StringBuilder();
|
||||
|
||||
|
@ -181,6 +183,9 @@ namespace ILCompiler.DependencyAnalysis
|
|||
}
|
||||
|
||||
EmitNativeMain();
|
||||
|
||||
EmitDebugMetadata();
|
||||
|
||||
LLVM.WriteBitcodeToFile(Module, _objectFilePath);
|
||||
#if DEBUG
|
||||
LLVM.PrintModuleToFile(Module, Path.ChangeExtension(_objectFilePath, ".txt"), out string unused2);
|
||||
|
@ -190,6 +195,25 @@ namespace ILCompiler.DependencyAnalysis
|
|||
//throw new NotImplementedException(); // This function isn't complete
|
||||
}
|
||||
|
||||
private void EmitDebugMetadata()
|
||||
{
|
||||
var dwarfVersion = LLVM.MDNode(new[]
|
||||
{
|
||||
LLVM.ConstInt(LLVM.Int32Type(), 2, false),
|
||||
LLVM.MDString("Dwarf Version", 13),
|
||||
LLVM.ConstInt(LLVM.Int32Type(), 4, false)
|
||||
});
|
||||
var dwarfSchemaVersion = LLVM.MDNode(new[]
|
||||
{
|
||||
LLVM.ConstInt(LLVM.Int32Type(), 2, false),
|
||||
LLVM.MDString("Debug Info Version", 18),
|
||||
LLVM.ConstInt(LLVM.Int32Type(), 3, false)
|
||||
});
|
||||
LLVM.AddNamedMetadataOperand(Module, "llvm.module.flags", dwarfVersion);
|
||||
LLVM.AddNamedMetadataOperand(Module, "llvm.module.flags", dwarfSchemaVersion);
|
||||
LLVM.DIBuilderFinalize(DIBuilder);
|
||||
}
|
||||
|
||||
public static LLVMValueRef GetConstZeroArray(int length)
|
||||
{
|
||||
var int8Type = LLVM.Int8Type();
|
||||
|
@ -645,6 +669,7 @@ namespace ILCompiler.DependencyAnalysis
|
|||
_nodeFactory = factory;
|
||||
_objectFilePath = objectFilePath;
|
||||
Module = compilation.Module;
|
||||
DIBuilder = compilation.DIBuilder;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
@ -9,6 +9,7 @@ using Internal.TypeSystem;
|
|||
using ILCompiler.DependencyAnalysis;
|
||||
using ILCompiler.DependencyAnalysisFramework;
|
||||
using LLVMSharp;
|
||||
using ILCompiler.WebAssembly;
|
||||
|
||||
namespace ILCompiler
|
||||
{
|
||||
|
@ -17,18 +18,23 @@ namespace ILCompiler
|
|||
internal WebAssemblyCodegenConfigProvider Options { get; }
|
||||
internal LLVMModuleRef Module { get; }
|
||||
public new WebAssemblyCodegenNodeFactory NodeFactory { get; }
|
||||
internal LLVMDIBuilderRef DIBuilder { get; }
|
||||
internal Dictionary<string, DebugMetadata> DebugMetadataMap { get; }
|
||||
internal WebAssemblyCodegenCompilation(
|
||||
DependencyAnalyzerBase<NodeFactory> dependencyGraph,
|
||||
WebAssemblyCodegenNodeFactory nodeFactory,
|
||||
IEnumerable<ICompilationRootProvider> roots,
|
||||
DebugInformationProvider debugInformationProvider,
|
||||
Logger logger,
|
||||
WebAssemblyCodegenConfigProvider options)
|
||||
: base(dependencyGraph, nodeFactory, GetCompilationRoots(roots, nodeFactory), null, null, logger)
|
||||
: base(dependencyGraph, nodeFactory, GetCompilationRoots(roots, nodeFactory), debugInformationProvider, null, logger)
|
||||
{
|
||||
NodeFactory = nodeFactory;
|
||||
Module = LLVM.ModuleCreateWithName("netscripten");
|
||||
LLVM.SetTarget(Module, "asmjs-unknown-emscripten");
|
||||
Options = options;
|
||||
DIBuilder = LLVMPInvokes.LLVMCreateDIBuilder(Module);
|
||||
DebugMetadataMap = new Dictionary<string, DebugMetadata>();
|
||||
}
|
||||
|
||||
private static IEnumerable<ICompilationRootProvider> GetCompilationRoots(IEnumerable<ICompilationRootProvider> existingRoots, NodeFactory factory)
|
||||
|
|
|
@ -34,8 +34,7 @@ namespace ILCompiler
|
|||
var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_context.GeneratedAssembly));
|
||||
WebAssemblyCodegenNodeFactory factory = new WebAssemblyCodegenNodeFactory(_context, _compilationGroup, _metadataManager, interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider);
|
||||
DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory, new ObjectNode.ObjectNodeComparer(new CompilerComparer()));
|
||||
|
||||
return new WebAssemblyCodegenCompilation(graph, factory, _compilationRoots, _logger, _config);
|
||||
return new WebAssemblyCodegenCompilation(graph, factory, _compilationRoots, _debugInformationProvider, _logger, _config);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,10 @@
|
|||
<Compile Include="..\..\Common\src\TypeSystem\IL\HelperExtensions.cs">
|
||||
<Link>IL\HelperExtensions.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="CodeGen\DebugMetadata.cs" />
|
||||
<Compile Include="CodeGen\ILToWebAssemblyImporter_Statics.cs" />
|
||||
<Compile Include="CodeGen\LLVMMisc.cs" />
|
||||
<Compile Include="CodeGen\LLVMPInvokes.cs" />
|
||||
<Compile Include="CodeGen\WebAssemblyObjectWriter.cs" />
|
||||
<Compile Include="Compiler\DependencyAnalysis\RawMainMethodRootProvider.cs" />
|
||||
<Compile Include="Compiler\DependencyAnalysis\WebAssemblyCodegenNodeFactory.cs" />
|
||||
|
@ -56,13 +58,13 @@
|
|||
<Content Include="..\..\..\packages\llvmsharp\5.0.0\lib\netstandard1.1\LLVMSharp.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\..\..\packages\libllvm\4.0.0\runtimes\osx\native\libLLVM.dylib" Condition="'$(NuPkgRid)' == 'osx-x64'">
|
||||
<Content Include="..\..\..\packages\libllvm\6.0.0-beta1\runtimes\osx\native\libLLVM.dylib" Condition="'$(NuPkgRid)' == 'osx-x64'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\..\..\packages\libllvm\4.0.0\runtimes\linux-x64\native\libLLVM.so" Condition="'$(NuPkgRid)' == 'linux-x64'">
|
||||
<Content Include="..\..\..\packages\libllvm\6.0.0-beta1\runtimes\linux-x64\native\libLLVM.so" Condition="'$(NuPkgRid)' == 'linux-x64'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\..\..\packages\libllvm\4.0.0\runtimes\win-x64\native\libLLVM.dll" Condition="'$(NuPkgRid)' == 'win-x64' or '$(NuPkgRid)' == ''">
|
||||
<Content Include="..\..\..\packages\libllvm\6.0.0-beta1\runtimes\win-x64\native\libLLVM.dll" Condition="'$(NuPkgRid)' == 'win-x64' or '$(NuPkgRid)' == ''">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="libLLVM">
|
||||
<Version>4.0.0</Version>
|
||||
<Version>6.0.0-beta1</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче