code generator that automatically switches endianness
This commit is contained in:
parent
e603c154b9
commit
5532c4f5a8
|
@ -22,6 +22,10 @@
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0"/>
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1"/>
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1"/>
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1"/>
|
||||||
|
|
||||||
|
<ProjectReference Include="../EndiannessSourceGenerator/EndiannessSourceGenerator.csproj"
|
||||||
|
OutputItemType="Analyzer"
|
||||||
|
ReferenceOutputAssembly="false"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -14,7 +14,7 @@ internal sealed class DisplayConnection(IOptions<DisplayConfiguration> options)
|
||||||
|
|
||||||
public ValueTask SendClearAsync()
|
public ValueTask SendClearAsync()
|
||||||
{
|
{
|
||||||
var header = new HeaderWindow { Command = DisplayCommand.Clear };
|
var header = new HeaderWindow { Command = (ushort)DisplayCommand.Clear };
|
||||||
|
|
||||||
return SendAsync(header, Memory<byte>.Empty);
|
return SendAsync(header, Memory<byte>.Empty);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ internal sealed class DisplayConnection(IOptions<DisplayConfiguration> options)
|
||||||
{
|
{
|
||||||
var header = new HeaderWindow
|
var header = new HeaderWindow
|
||||||
{
|
{
|
||||||
Command = DisplayCommand.Cp437Data,
|
Command = (ushort)DisplayCommand.Cp437Data,
|
||||||
Height = grid.Height,
|
Height = grid.Height,
|
||||||
Width = grid.Width,
|
Width = grid.Width,
|
||||||
PosX = x,
|
PosX = x,
|
||||||
|
@ -37,7 +37,7 @@ internal sealed class DisplayConnection(IOptions<DisplayConfiguration> options)
|
||||||
{
|
{
|
||||||
var header = new HeaderWindow
|
var header = new HeaderWindow
|
||||||
{
|
{
|
||||||
Command = DisplayCommand.CharBrightness,
|
Command = (ushort)DisplayCommand.CharBrightness,
|
||||||
PosX = x,
|
PosX = x,
|
||||||
PosY = y,
|
PosY = y,
|
||||||
Height = luma.Height,
|
Height = luma.Height,
|
||||||
|
@ -49,7 +49,7 @@ internal sealed class DisplayConnection(IOptions<DisplayConfiguration> options)
|
||||||
|
|
||||||
public async ValueTask SendBrightnessAsync(byte brightness)
|
public async ValueTask SendBrightnessAsync(byte brightness)
|
||||||
{
|
{
|
||||||
var header = new HeaderWindow { Command = DisplayCommand.Brightness };
|
var header = new HeaderWindow { Command = (ushort)DisplayCommand.Brightness };
|
||||||
|
|
||||||
var payloadBuffer = _arrayPool.Rent(1);
|
var payloadBuffer = _arrayPool.Rent(1);
|
||||||
var payload = payloadBuffer.AsMemory(0, 1);
|
var payload = payloadBuffer.AsMemory(0, 1);
|
||||||
|
@ -61,13 +61,13 @@ internal sealed class DisplayConnection(IOptions<DisplayConfiguration> options)
|
||||||
|
|
||||||
public ValueTask SendHardResetAsync()
|
public ValueTask SendHardResetAsync()
|
||||||
{
|
{
|
||||||
var header = new HeaderWindow { Command = DisplayCommand.HardReset };
|
var header = new HeaderWindow { Command = (ushort)DisplayCommand.HardReset };
|
||||||
return SendAsync(header, Memory<byte>.Empty);
|
return SendAsync(header, Memory<byte>.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask SendFadeOutAsync(byte loops)
|
public async ValueTask SendFadeOutAsync(byte loops)
|
||||||
{
|
{
|
||||||
var header = new HeaderWindow { Command = DisplayCommand.FadeOut };
|
var header = new HeaderWindow { Command = (ushort)DisplayCommand.FadeOut };
|
||||||
|
|
||||||
var payloadBuffer = _arrayPool.Rent(1);
|
var payloadBuffer = _arrayPool.Rent(1);
|
||||||
var payload = payloadBuffer.AsMemory(0, 1);
|
var payload = payloadBuffer.AsMemory(0, 1);
|
||||||
|
@ -81,8 +81,9 @@ internal sealed class DisplayConnection(IOptions<DisplayConfiguration> options)
|
||||||
{
|
{
|
||||||
var header = new HeaderWindow
|
var header = new HeaderWindow
|
||||||
{
|
{
|
||||||
Command = DisplayCommand.BitmapLinearWin,
|
Command = (ushort)DisplayCommand.BitmapLinearWin,
|
||||||
PosX = x, PosY = y,
|
PosX = x,
|
||||||
|
PosY = y,
|
||||||
Width = (ushort)(pixels.Width / 8),
|
Width = (ushort)(pixels.Width / 8),
|
||||||
Height = pixels.Height
|
Height = pixels.Height
|
||||||
};
|
};
|
||||||
|
@ -113,7 +114,6 @@ internal sealed class DisplayConnection(IOptions<DisplayConfiguration> options)
|
||||||
var buffer = _arrayPool.Rent(messageSize);
|
var buffer = _arrayPool.Rent(messageSize);
|
||||||
var message = buffer.AsMemory(0, messageSize);
|
var message = buffer.AsMemory(0, messageSize);
|
||||||
|
|
||||||
header.ChangeToNetworkOrder();
|
|
||||||
MemoryMarshal.Write(message.Span, header);
|
MemoryMarshal.Write(message.Span, header);
|
||||||
payload.CopyTo(message[headerSize..]);
|
payload.CopyTo(message[headerSize..]);
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using EndiannessSourceGenerator;
|
||||||
|
|
||||||
namespace DisplayCommands.Internals;
|
namespace DisplayCommands.Internals;
|
||||||
|
|
||||||
|
[StructEndianness(IsLittleEndian = false)]
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 16, Size = 10)]
|
[StructLayout(LayoutKind.Sequential, Pack = 16, Size = 10)]
|
||||||
internal struct HeaderBitmap
|
internal partial struct HeaderBitmap
|
||||||
{
|
{
|
||||||
public DisplayCommand Command;
|
private ushort _command;
|
||||||
|
|
||||||
public ushort Offset;
|
private ushort _offset;
|
||||||
|
|
||||||
public ushort Length;
|
private ushort _length;
|
||||||
|
|
||||||
public DisplaySubCommand SubCommand;
|
private ushort _subCommand;
|
||||||
|
|
||||||
public ushort Reserved;
|
private ushort _reserved;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,19 @@
|
||||||
using System.Buffers.Binary;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using EndiannessSourceGenerator;
|
||||||
|
|
||||||
namespace DisplayCommands.Internals;
|
namespace DisplayCommands.Internals;
|
||||||
|
|
||||||
|
[StructEndianness(IsLittleEndian = false)]
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 16, Size = 10)]
|
[StructLayout(LayoutKind.Sequential, Pack = 16, Size = 10)]
|
||||||
internal struct HeaderWindow
|
internal partial struct HeaderWindow
|
||||||
{
|
{
|
||||||
public DisplayCommand Command;
|
private ushort _command;
|
||||||
|
|
||||||
public ushort PosX;
|
private ushort _posX;
|
||||||
|
|
||||||
public ushort PosY;
|
private ushort _posY;
|
||||||
|
|
||||||
public ushort Width;
|
private ushort _width;
|
||||||
|
|
||||||
public ushort Height;
|
private ushort _height;
|
||||||
|
|
||||||
public void ChangeToNetworkOrder()
|
|
||||||
{
|
|
||||||
if (!BitConverter.IsLittleEndian)
|
|
||||||
return;
|
|
||||||
Command = (DisplayCommand)BinaryPrimitives.ReverseEndianness((ushort)Command);
|
|
||||||
PosX = BinaryPrimitives.ReverseEndianness(PosX);
|
|
||||||
PosY = BinaryPrimitives.ReverseEndianness(PosY);
|
|
||||||
Width = BinaryPrimitives.ReverseEndianness(Width);
|
|
||||||
Height = BinaryPrimitives.ReverseEndianness(Height);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
227
EndiannessSourceGenerator/EndiannessGenerator.cs
Normal file
227
EndiannessSourceGenerator/EndiannessGenerator.cs
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using Microsoft.CodeAnalysis.Text;
|
||||||
|
|
||||||
|
namespace EndiannessSourceGenerator;
|
||||||
|
|
||||||
|
internal class DebugMeException(string message) : Exception(message);
|
||||||
|
|
||||||
|
internal class InvalidUsageException(string message) : Exception(message);
|
||||||
|
|
||||||
|
[Generator]
|
||||||
|
public class StructEndiannessSourceGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
private const string Namespace = "EndiannessSourceGenerator";
|
||||||
|
private const string AttributeName = "StructEndiannessAttribute";
|
||||||
|
private const string IsLittleEndianProperty = "IsLittleEndian";
|
||||||
|
|
||||||
|
private const string AttributeSourceCode =
|
||||||
|
$$"""
|
||||||
|
// <auto-generated/>
|
||||||
|
namespace {{Namespace}}
|
||||||
|
{
|
||||||
|
[System.AttributeUsage(System.AttributeTargets.Struct)]
|
||||||
|
public class {{AttributeName}}: System.Attribute
|
||||||
|
{
|
||||||
|
public required bool {{IsLittleEndianProperty}} { get; init; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
private const string UsingDeclarations =
|
||||||
|
"""
|
||||||
|
using System;
|
||||||
|
using System.Buffers.Binary;
|
||||||
|
""";
|
||||||
|
|
||||||
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
// Register the attribute source
|
||||||
|
context.RegisterForPostInitialization(i => { i.AddSource($"{AttributeName}.g.cs", AttributeSourceCode); });
|
||||||
|
// context.RegisterForSyntaxNotifications(() => new SyntaxCon);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly SymbolDisplayFormat _namespacedNameFormat =
|
||||||
|
new(typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces);
|
||||||
|
|
||||||
|
// TODO: generate syntax tree with roslyn to get rid of string wrangling and so code is properly formatted
|
||||||
|
public void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
var treesWithStructsWithAttributes = context.Compilation.SyntaxTrees
|
||||||
|
.Where(st => st.GetRoot().DescendantNodes()
|
||||||
|
.OfType<StructDeclarationSyntax>()
|
||||||
|
.Any(p => p.DescendantNodes()
|
||||||
|
.OfType<AttributeSyntax>()
|
||||||
|
.Any()))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var tree in treesWithStructsWithAttributes)
|
||||||
|
{
|
||||||
|
var semanticModel = context.Compilation.GetSemanticModel(tree);
|
||||||
|
|
||||||
|
var structsWithAttributes = tree.GetRoot().DescendantNodes()
|
||||||
|
.OfType<StructDeclarationSyntax>()
|
||||||
|
.Where(cd => cd.DescendantNodes()
|
||||||
|
.OfType<AttributeSyntax>()
|
||||||
|
.Any());
|
||||||
|
|
||||||
|
foreach (var structDeclaration in structsWithAttributes)
|
||||||
|
{
|
||||||
|
var foundAttribute = GetEndiannessAttribute(structDeclaration, semanticModel);
|
||||||
|
// not my type
|
||||||
|
if (foundAttribute == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
HandleStruct(context, structDeclaration, semanticModel, foundAttribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleStruct(GeneratorExecutionContext context, StructDeclarationSyntax structDeclaration,
|
||||||
|
SemanticModel semanticModel, AttributeSyntax foundAttribute)
|
||||||
|
{
|
||||||
|
var isPartial = structDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword));
|
||||||
|
if (!isPartial)
|
||||||
|
throw new InvalidUsageException("struct is not marked partial");
|
||||||
|
|
||||||
|
var accessibilityModifier = structDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.InternalKeyword))
|
||||||
|
? "internal"
|
||||||
|
: "public";
|
||||||
|
|
||||||
|
var structType = semanticModel.GetDeclaredSymbol(structDeclaration);
|
||||||
|
if (structType == null)
|
||||||
|
throw new DebugMeException("struct type info is null");
|
||||||
|
|
||||||
|
var structNamespace = structType.ContainingNamespace?.ToDisplayString();
|
||||||
|
if (structNamespace == null)
|
||||||
|
throw new InvalidUsageException("struct has to be contained in a namespace");
|
||||||
|
|
||||||
|
var structIsLittleEndian = GetStructIsLittleEndian(foundAttribute);
|
||||||
|
|
||||||
|
var generatedCode = new StringBuilder();
|
||||||
|
generatedCode.AppendLine(UsingDeclarations);
|
||||||
|
|
||||||
|
generatedCode.AppendLine($"namespace {structNamespace};");
|
||||||
|
generatedCode.AppendLine($$"""{{accessibilityModifier}} partial struct {{structType.Name}} {""");
|
||||||
|
|
||||||
|
var hasProperties = structDeclaration.Members
|
||||||
|
.Any(m => m.IsKind(SyntaxKind.PropertyDeclaration));
|
||||||
|
if (hasProperties)
|
||||||
|
throw new InvalidUsageException("struct cannot have properties");
|
||||||
|
|
||||||
|
var fieldDeclarations = structDeclaration.Members
|
||||||
|
.Where(m => m.IsKind(SyntaxKind.FieldDeclaration)).OfType<FieldDeclarationSyntax>();
|
||||||
|
GenerateStructProperties(generatedCode, fieldDeclarations, semanticModel, structIsLittleEndian);
|
||||||
|
|
||||||
|
generatedCode.AppendLine("}"); // end of struct
|
||||||
|
|
||||||
|
context.AddSource($"{structNamespace}.{structType.Name}.g.cs",
|
||||||
|
SourceText.From(generatedCode.ToString(), Encoding.UTF8));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateStructProperties(StringBuilder generatedCode,
|
||||||
|
IEnumerable<FieldDeclarationSyntax> fieldDeclarations, SemanticModel semanticModel, bool structIsLittleEndian)
|
||||||
|
{
|
||||||
|
foreach (var field in fieldDeclarations)
|
||||||
|
{
|
||||||
|
if (!field.Modifiers.Any(m => m.IsKind(SyntaxKind.PrivateKeyword)))
|
||||||
|
throw new InvalidUsageException("fields have to be private");
|
||||||
|
|
||||||
|
var variableDeclaration = field.DescendantNodes()
|
||||||
|
.OfType<VariableDeclarationSyntax>()
|
||||||
|
.FirstOrDefault();
|
||||||
|
if (variableDeclaration == null)
|
||||||
|
throw new DebugMeException("variable declaration of field declaration null");
|
||||||
|
|
||||||
|
var variableTypeInfo = semanticModel.GetTypeInfo(variableDeclaration.Type).Type;
|
||||||
|
if (variableTypeInfo == null)
|
||||||
|
throw new DebugMeException("variable type info of field declaration null");
|
||||||
|
|
||||||
|
var typeName = variableTypeInfo.ToDisplayString();
|
||||||
|
var fieldName = variableDeclaration.Variables.First().Identifier.ToString();
|
||||||
|
var propertyName = GeneratePropertyName(fieldName);
|
||||||
|
|
||||||
|
GenerateProperty(generatedCode, typeName, propertyName, structIsLittleEndian, fieldName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateProperty(StringBuilder generatedCode, string typeName, string propertyName,
|
||||||
|
bool structIsLittleEndian, string fieldName)
|
||||||
|
{
|
||||||
|
generatedCode.AppendLine($$"""public {{typeName}} {{propertyName}} {""");
|
||||||
|
|
||||||
|
var maybeNegator = structIsLittleEndian ? string.Empty : "!";
|
||||||
|
var sameEndiannessExpression = $"{maybeNegator}BitConverter.IsLittleEndian";
|
||||||
|
|
||||||
|
generatedCode.AppendLine($"get => {sameEndiannessExpression}");
|
||||||
|
generatedCode.AppendLine($" ? {fieldName}");
|
||||||
|
generatedCode.AppendLine($" : BinaryPrimitives.ReverseEndianness({fieldName});");
|
||||||
|
|
||||||
|
generatedCode.AppendLine($"set => {fieldName} = {sameEndiannessExpression}");
|
||||||
|
generatedCode.AppendLine(" ? value");
|
||||||
|
generatedCode.AppendLine(" : BinaryPrimitives.ReverseEndianness(value);");
|
||||||
|
|
||||||
|
generatedCode.AppendLine("}"); // end of property
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GeneratePropertyName(string fieldName)
|
||||||
|
{
|
||||||
|
var propertyName = fieldName;
|
||||||
|
if (propertyName.StartsWith("_"))
|
||||||
|
propertyName = propertyName.Substring(1);
|
||||||
|
if (!char.IsLetter(propertyName, 0) || char.IsUpper(propertyName, 0))
|
||||||
|
throw new InvalidUsageException("field names have to start with a lower case letter");
|
||||||
|
propertyName = propertyName.Substring(0, 1).ToUpperInvariant()
|
||||||
|
+ propertyName.Substring(1);
|
||||||
|
return propertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AttributeSyntax? GetEndiannessAttribute(StructDeclarationSyntax structDeclaration,
|
||||||
|
SemanticModel semanticModel)
|
||||||
|
{
|
||||||
|
AttributeSyntax? foundAttribute = null;
|
||||||
|
foreach (var attributeSyntax in structDeclaration.DescendantNodes().OfType<AttributeSyntax>())
|
||||||
|
{
|
||||||
|
var attributeTypeInfo = semanticModel.GetTypeInfo(attributeSyntax).Type;
|
||||||
|
if (attributeTypeInfo == null)
|
||||||
|
throw new DebugMeException("attribute type info is null");
|
||||||
|
|
||||||
|
if (attributeTypeInfo.ContainingNamespace?.Name != Namespace)
|
||||||
|
continue;
|
||||||
|
if (attributeTypeInfo.Name != AttributeName)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foundAttribute = attributeSyntax;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool GetStructIsLittleEndian(AttributeSyntax foundAttribute)
|
||||||
|
{
|
||||||
|
var endiannessArguments = foundAttribute.ArgumentList;
|
||||||
|
if (endiannessArguments == null)
|
||||||
|
throw new InvalidUsageException("endianness attribute has no arguments");
|
||||||
|
|
||||||
|
var isLittleEndianArgumentSyntax = endiannessArguments.Arguments
|
||||||
|
.FirstOrDefault(argumentSyntax =>
|
||||||
|
argumentSyntax.NameEquals?.Name.Identifier.ToString() == IsLittleEndianProperty);
|
||||||
|
if (isLittleEndianArgumentSyntax == null)
|
||||||
|
throw new InvalidUsageException("endianness attribute argument not found");
|
||||||
|
|
||||||
|
bool? structIsLittleEndian = isLittleEndianArgumentSyntax.Expression.Kind() switch
|
||||||
|
{
|
||||||
|
SyntaxKind.FalseLiteralExpression => false,
|
||||||
|
SyntaxKind.TrueLiteralExpression => true,
|
||||||
|
SyntaxKind.DefaultLiteralExpression => false,
|
||||||
|
_ => throw new InvalidUsageException($"{IsLittleEndianProperty} has to be set with a literal")
|
||||||
|
};
|
||||||
|
return structIsLittleEndian.Value;
|
||||||
|
}
|
||||||
|
}
|
23
EndiannessSourceGenerator/EndiannessSourceGenerator.csproj
Normal file
23
EndiannessSourceGenerator/EndiannessSourceGenerator.csproj
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
|
||||||
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
|
<IsRoslynComponent>true</IsRoslynComponent>
|
||||||
|
<PackageId>EndiannessSourceGenerator</PackageId>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" PrivateAssets="all" />
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.9.2"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
5
EndiannessSourceGenerator/Readme.md
Normal file
5
EndiannessSourceGenerator/Readme.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Endianness Source Generator
|
||||||
|
|
||||||
|
When annotating a struct with the `StructEndianness` attribute, this code generator will generate properties for the declared fields.
|
||||||
|
|
||||||
|
Each time a property is read or written, the endianness is converted from runtime endianness to struct endianness or vice-versa.
|
|
@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TanksServer", "TanksServer\
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DisplayCommands", "DisplayCommands\DisplayCommands.csproj", "{B4B43561-7A2C-486B-99F7-E58A67BC370A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DisplayCommands", "DisplayCommands\DisplayCommands.csproj", "{B4B43561-7A2C-486B-99F7-E58A67BC370A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EndiannessSourceGenerator", "EndiannessSourceGenerator\EndiannessSourceGenerator.csproj", "{D77FE880-F2B8-43B6-8B33-B6FA089CC337}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -18,5 +20,9 @@ Global
|
||||||
{B4B43561-7A2C-486B-99F7-E58A67BC370A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B4B43561-7A2C-486B-99F7-E58A67BC370A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{B4B43561-7A2C-486B-99F7-E58A67BC370A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B4B43561-7A2C-486B-99F7-E58A67BC370A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B4B43561-7A2C-486B-99F7-E58A67BC370A}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B4B43561-7A2C-486B-99F7-E58A67BC370A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D77FE880-F2B8-43B6-8B33-B6FA089CC337}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D77FE880-F2B8-43B6-8B33-B6FA089CC337}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D77FE880-F2B8-43B6-8B33-B6FA089CC337}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D77FE880-F2B8-43B6-8B33-B6FA089CC337}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
Loading…
Reference in a new issue