From 6ed3e72b017ba82b044ce46bdfd189a78d38c226 Mon Sep 17 00:00:00 2001 From: Andrey <54708336+BadRyuner@users.noreply.github.com> Date: Wed, 20 Mar 2024 13:56:28 +0300 Subject: [PATCH 001/103] (#294) Fastest Unescape --- Cesium.CodeGen/Cesium.CodeGen.csproj | 2 +- Cesium.Parser/Cesium.Parser.csproj | 3 +- Cesium.Parser/TokenExtensions.cs | 202 +++++++++++++++------------ 3 files changed, 112 insertions(+), 95 deletions(-) diff --git a/Cesium.CodeGen/Cesium.CodeGen.csproj b/Cesium.CodeGen/Cesium.CodeGen.csproj index f1c067c7..cd553c35 100644 --- a/Cesium.CodeGen/Cesium.CodeGen.csproj +++ b/Cesium.CodeGen/Cesium.CodeGen.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable true diff --git a/Cesium.Parser/Cesium.Parser.csproj b/Cesium.Parser/Cesium.Parser.csproj index cade06f2..2894495a 100644 --- a/Cesium.Parser/Cesium.Parser.csproj +++ b/Cesium.Parser/Cesium.Parser.csproj @@ -1,8 +1,9 @@ - net7.0 + net8.0 enable + True diff --git a/Cesium.Parser/TokenExtensions.cs b/Cesium.Parser/TokenExtensions.cs index 7f0b5053..878438b2 100644 --- a/Cesium.Parser/TokenExtensions.cs +++ b/Cesium.Parser/TokenExtensions.cs @@ -1,3 +1,4 @@ +using System.Runtime.CompilerServices; using System.Text; using Cesium.Core; using Yoakke.SynKit.C.Syntax; @@ -7,143 +8,158 @@ namespace Cesium.Parser; public static class TokenExtensions { - public static string UnwrapStringLiteral(this IToken token) + public unsafe static string UnwrapStringLiteral(this IToken token) { if (token.Kind != CTokenType.StringLiteral) throw new ParseException($"Non-string literal token: {token.Kind} {token.Text}"); - var result = token.Text[1..^1]; + var result = token.Text[1..^1]; // allocates new sliced string - // simple escape sequences - var builder = new StringBuilder(result.Length); - for (int i = 0; i < result.Length; ++i) + if (result.IndexOf('\\') == -1) // no \ no fun no unescape + return result; + + fixed (char* p = result) { - if (result.ElementAt(i) == '\\' && i < result.Length - 1) + var span = new Span(p, result.Length + 1); // create a span for string. Also +1 for \0 + int eaten = 0; + while (true) // loop { - char currentChar = result.ElementAt(i + 1); - switch (currentChar) + var i = span.IndexOf('\\'); // SIMD search \. Blazing fast. + if (i == -1) break; // break if there is no more \ + + int shift = 1; // how many characters we're gonna skip + + switch (span[i + 1]) { - case '\'': - case '\"': - case '?': - case '\\': - builder.Append(currentChar); - break; - case 'a': - builder.Append('\a'); - break; - case 'b': - builder.Append('\b'); - break; - case 'f': - builder.Append('\f'); - break; - case 'n': - builder.Append('\n'); - break; - case 'r': - builder.Append('\r'); - break; - case 't': - builder.Append('\t'); - break; - case 'v': - builder.Append('\v'); - break; - case '0': + // Simple escape sequences + case '"': span[i] = '"'; break; + case '?': span[i] = '?'; break; + case '\'': span[i] = '\''; break; + case '\\': span[i] = '\\'; break; + case 'a': span[i] = '\a'; break; + case 'b': span[i] = '\b'; break; + case 'f': span[i] = '\f'; break; + case 'n': span[i] = '\n'; break; + case 'r': span[i] = '\r'; break; + case 't': span[i] = '\t'; break; + case 'v': span[i] = '\v'; break; + // Numeric escape sequences + case '0': // arbitrary octal value '\nnn' { - int counter = 2; - int octalNumber = 0; - if (result.Length <= i + counter) + if (span.Length <= i + 2 || span[i + 2] == '\0') // \0 check for 2nd..n iters. { - builder.Append('\0'); + span[i] = '\0'; break; } - char current = result.ElementAt(i + counter); + int number = 0; + var c = span[i + shift + 1]; // get next char after 0 do { - octalNumber = octalNumber * 8 + (current - '0'); - counter++; - if (result.Length <= i + counter) - break; - current = result.ElementAt(i + counter); + number = number * 8 + (c - '0'); + shift++; + c = span[i + shift + 1]; } - while (current >= '0' && current <= '7'); - i += counter - 1; - builder.Append(char.ConvertFromUtf32(octalNumber)); + while (char.IsBetween(c, '0', '7')); + span[i] = (char)number; break; } case 'x': - case 'X': + case 'X': // \Xn... arbitrary hexadecimal value { - int counter = 2; - int octalNumber = 0; - if (result.Length <= i + counter) + if (span.Length <= i + 2 || span[i + 2] == '\0') // \0 check for 2nd..n iters. { - builder.Append('\\'); - builder.Append(currentChar); + shift = 0; break; } - char current = result.ElementAt(i + counter); + int number = 0; + var c = span[i + 1 + shift]; // shift == 1, so i + 2 points at next char after '\' 'X' do { - int digit = Char.IsAsciiDigit(current) ? current - '0' : (char.ToUpperInvariant(current) - 'A') + 10; - octalNumber = octalNumber * 16 + digit; - counter++; - if (result.Length <= i + counter) - break; - current = result.ElementAt(i + counter); + int digit = char.IsAsciiDigit(c) ? c - '0' : (char.ToUpperInvariant(c) - 'A') + 10; + number = number * 16 + digit; + shift++; + c = span[i + 1 + shift]; } - while (Char.IsAsciiDigit(current) || (current >= 'A' && current <= 'F') || (current >= 'a' && current <= 'f')); - i += counter - 1; - builder.Append((char)octalNumber); + while (char.IsAsciiDigit(c) || char.IsBetween(c, 'a', 'f') || char.IsBetween(c, 'A', 'F')); + span[i] = (char)number; break; } - case 'u': - case 'U': + // Universal character names + case 'u': // \unnnn + case 'U': // \Unnnnnnnn { - int counter = 2; - int octalNumber = 0; - if (result.Length <= i + counter) + int counter = span[i + 1] == 'U' ? 8 : 4; + if (span.Length <= i + counter) // no free chars no fun { - builder.Append('\\'); - builder.Append(currentChar); + shift = 0; break; } - char current = result.ElementAt(i + counter); - do + int number = 0; + for (int n = 0; n < counter; n++) { - int digit = Char.IsAsciiDigit(current) ? current - '0' : (char.ToUpperInvariant(current) - 'A') + 10; - octalNumber = octalNumber * 16 + digit; - counter++; - if (result.Length <= i + counter) - break; - current = result.ElementAt(i + counter); + var c = span[i + 2 + n]; // i + 2 points at next char after '\', 'U', + // in theory, we should throw an error. + if (!(char.IsAsciiDigit(c) || char.IsBetween(c, 'a', 'f') || char.IsBetween(c, 'A', 'F'))) break; + int digit = char.IsAsciiDigit(c) ? c - '0' : (char.ToUpperInvariant(c) - 'A') + 10; + number = number * 16 + digit; + shift++; } - while (Char.IsAsciiDigit(current) || (current >= 'A' && current <= 'F') || (current >= 'a' && current <= 'f')); - i += counter - 1; - builder.Append(char.ConvertFromUtf32(octalNumber)); + // char.ConvertFromUtf32(number) allocates string :( + // create span from pointer to our number represented as ref byte + var spanCodeSeq = new Span(Unsafe.AsPointer(ref Unsafe.As(ref number)), 4); + // get utf16 chars from utf32 bytes seq without allocations yeeeah + if (!Encoding.UTF32.TryGetChars(spanCodeSeq, span.Slice(i), out int written)) throw new Exception("Bad UTF32 sequence!"); + // if we writted one char, so just do nothing + // if we writted two chars, so just skip one char + i += written - 1; + shift -= written - 1; break; } default: + // from orig method: // TODO[#295]: maybe smarter handling of this edge case with errors/warnings - builder.Append('\\'); - --i; // don't skip next + // builder.Append('\\'); + // --i; // don't skip next + // mmm, idk when that might happen break; } - ++i; // skip next - } - else - { - builder.Append(result.ElementAt(i)); + if (shift == 0) + { + span = span.Slice(1); // skip 1 char + continue; + } + + // ex: + // before + // span[i] = '\' span[i+1] = 'n' span[i+2] = 'h' + // after + // shift = 1 + // span[i] = '\n' span[i+1] = 'n' span[i+2] = 'h' + // it is required to shift all subsequent chars by (1..shift) to the left + // result slice slice copy + // span[i] = '\n' span[i+1] = 'h' span[i+2] = (previous span)[i+3] + var start = i + shift; + var source = span.Slice(start + 1); // next from consumed chars + var destination = span.Slice(i + 1); // next from span[i] = '\n' + // If copy properly in chunks, rather than continuously copying the WHOLE unchecked string, unescape will be even faster + source.CopyTo(destination); // <--- copies the WHOLE unchecked string. bad. bad. but also SIMDed, so it's still very fast + span = destination; // next iter + eaten += shift; } - } - result = builder.ToString(); - return result; + // oh wait + // before: "kek \\n\\n\\n kek" len 17 + // after "kek \n\n\n kek\0\0\0" len 17 + // create copy & alocate it again + // we can change the length of an existing string, but GC always *bonk* for it + result = new ReadOnlySpan(p, result.Length - eaten).ToString(); // alocate x2 >< + // after: "kek \n\n\n kek" len 14 + + return result; + } } } From be220248868a8bfbd3538630ed02a1ecf509d1de Mon Sep 17 00:00:00 2001 From: Andrey <54708336+BadRyuner@users.noreply.github.com> Date: Fri, 22 Mar 2024 16:47:55 +0300 Subject: [PATCH 002/103] (#66) Main func sig equivalency --- Cesium.CodeGen.Tests/CodeGenMethodTests.cs | 3 ++ ...eGenMethodTests.ConstArgcMain.verified.txt | 43 +++++++++++++++++++ ...GenMethodTests.ConstConstMain.verified.txt | 43 +++++++++++++++++++ ...ethodTests.PointerPointerMain.verified.txt | 43 +++++++++++++++++++ .../Ir/BlockItems/FunctionDefinition.cs | 8 +++- 5 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 Cesium.CodeGen.Tests/verified/CodeGenMethodTests.ConstArgcMain.verified.txt create mode 100644 Cesium.CodeGen.Tests/verified/CodeGenMethodTests.ConstConstMain.verified.txt create mode 100644 Cesium.CodeGen.Tests/verified/CodeGenMethodTests.PointerPointerMain.verified.txt diff --git a/Cesium.CodeGen.Tests/CodeGenMethodTests.cs b/Cesium.CodeGen.Tests/CodeGenMethodTests.cs index 9c4002fa..7c3549c2 100644 --- a/Cesium.CodeGen.Tests/CodeGenMethodTests.cs +++ b/Cesium.CodeGen.Tests/CodeGenMethodTests.cs @@ -77,6 +77,9 @@ int main() [Fact] public Task VoidParameterMain() => DoTest("int main(void){}"); [Fact] public Task PointerReceivingFunction() => DoTest("void foo(int *ptr){}"); [Fact] public Task StandardMain() => DoTest("int main(int argc, char *argv[]){}"); + [Fact] public Task PointerPointerMain() => DoTest("int main(int argc, char **argv){}"); + [Fact] public Task ConstConstMain() => DoTest("int main(int argc, const char * const *argv){}"); + [Fact] public Task ConstArgcMain() => DoTest("int main(const int argc, char* argv[]){}"); [Fact, NoVerify] public void NonstandardMainDoesNotCompile1() => DoesNotCompile("void main(){}", "Invalid return type"); [Fact, NoVerify] public void NonstandardMainDoesNotCompile2() => DoesNotCompile("int main(int c){}", "Invalid parameter"); [Fact, NoVerify] diff --git a/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.ConstArgcMain.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.ConstArgcMain.verified.txt new file mode 100644 index 00000000..5fbf42bb --- /dev/null +++ b/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.ConstArgcMain.verified.txt @@ -0,0 +1,43 @@ +System.Int32 ::main(System.Int32 argc, System.Byte** argv) + IL_0000: ldc.i4.0 + IL_0001: ret + +System.Int32 ::(System.String[] args) + Locals: + System.Int32 V_0 + System.Byte*[] V_1 + System.Byte*[] V_2 + System.Byte*[] (pinned) V_3 + System.Int32 V_4 + IL_0000: ldarg.0 + IL_0001: ldlen + IL_0002: ldc.i4.1 + IL_0003: add + IL_0004: stloc.0 + IL_0005: ldarg.0 + IL_0006: call System.Byte*[] Cesium.Runtime.RuntimeHelpers::ArgsToArgv(System.String[]) + IL_000b: stloc.1 + IL_000c: ldloc.1 + IL_000d: ldlen + IL_000e: newarr System.Byte* + IL_0013: stloc.2 + IL_0014: ldloc.1 + IL_0015: ldloc.2 + IL_0016: ldc.i4.0 + IL_0017: call System.Void System.Array::CopyTo(System.Array,System.Int32) + IL_001c: ldloc.0 + IL_001d: ldloc.2 + IL_001e: stloc.3 + IL_001f: ldloc.3 + IL_0020: ldc.i4.0 + IL_0021: ldelema System.Byte* + IL_0026: call System.Int32 ::main(System.Int32,System.Byte**) + IL_002b: stloc.s V_4 + IL_002d: ldnull + IL_002e: stloc.3 + IL_002f: ldloc.1 + IL_0030: call System.Void Cesium.Runtime.RuntimeHelpers::FreeArgv(System.Byte*[]) + IL_0035: ldloc.s V_4 + IL_0037: call System.Void Cesium.Runtime.RuntimeHelpers::Exit(System.Int32) + IL_003c: ldloc.s V_4 + IL_003e: ret diff --git a/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.ConstConstMain.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.ConstConstMain.verified.txt new file mode 100644 index 00000000..5fbf42bb --- /dev/null +++ b/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.ConstConstMain.verified.txt @@ -0,0 +1,43 @@ +System.Int32 ::main(System.Int32 argc, System.Byte** argv) + IL_0000: ldc.i4.0 + IL_0001: ret + +System.Int32 ::(System.String[] args) + Locals: + System.Int32 V_0 + System.Byte*[] V_1 + System.Byte*[] V_2 + System.Byte*[] (pinned) V_3 + System.Int32 V_4 + IL_0000: ldarg.0 + IL_0001: ldlen + IL_0002: ldc.i4.1 + IL_0003: add + IL_0004: stloc.0 + IL_0005: ldarg.0 + IL_0006: call System.Byte*[] Cesium.Runtime.RuntimeHelpers::ArgsToArgv(System.String[]) + IL_000b: stloc.1 + IL_000c: ldloc.1 + IL_000d: ldlen + IL_000e: newarr System.Byte* + IL_0013: stloc.2 + IL_0014: ldloc.1 + IL_0015: ldloc.2 + IL_0016: ldc.i4.0 + IL_0017: call System.Void System.Array::CopyTo(System.Array,System.Int32) + IL_001c: ldloc.0 + IL_001d: ldloc.2 + IL_001e: stloc.3 + IL_001f: ldloc.3 + IL_0020: ldc.i4.0 + IL_0021: ldelema System.Byte* + IL_0026: call System.Int32 ::main(System.Int32,System.Byte**) + IL_002b: stloc.s V_4 + IL_002d: ldnull + IL_002e: stloc.3 + IL_002f: ldloc.1 + IL_0030: call System.Void Cesium.Runtime.RuntimeHelpers::FreeArgv(System.Byte*[]) + IL_0035: ldloc.s V_4 + IL_0037: call System.Void Cesium.Runtime.RuntimeHelpers::Exit(System.Int32) + IL_003c: ldloc.s V_4 + IL_003e: ret diff --git a/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.PointerPointerMain.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.PointerPointerMain.verified.txt new file mode 100644 index 00000000..5fbf42bb --- /dev/null +++ b/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.PointerPointerMain.verified.txt @@ -0,0 +1,43 @@ +System.Int32 ::main(System.Int32 argc, System.Byte** argv) + IL_0000: ldc.i4.0 + IL_0001: ret + +System.Int32 ::(System.String[] args) + Locals: + System.Int32 V_0 + System.Byte*[] V_1 + System.Byte*[] V_2 + System.Byte*[] (pinned) V_3 + System.Int32 V_4 + IL_0000: ldarg.0 + IL_0001: ldlen + IL_0002: ldc.i4.1 + IL_0003: add + IL_0004: stloc.0 + IL_0005: ldarg.0 + IL_0006: call System.Byte*[] Cesium.Runtime.RuntimeHelpers::ArgsToArgv(System.String[]) + IL_000b: stloc.1 + IL_000c: ldloc.1 + IL_000d: ldlen + IL_000e: newarr System.Byte* + IL_0013: stloc.2 + IL_0014: ldloc.1 + IL_0015: ldloc.2 + IL_0016: ldc.i4.0 + IL_0017: call System.Void System.Array::CopyTo(System.Array,System.Int32) + IL_001c: ldloc.0 + IL_001d: ldloc.2 + IL_001e: stloc.3 + IL_001f: ldloc.3 + IL_0020: ldc.i4.0 + IL_0021: ldelema System.Byte* + IL_0026: call System.Int32 ::main(System.Int32,System.Byte**) + IL_002b: stloc.s V_4 + IL_002d: ldnull + IL_002e: stloc.3 + IL_002f: ldloc.1 + IL_0030: call System.Void Cesium.Runtime.RuntimeHelpers::FreeArgv(System.Byte*[]) + IL_0035: ldloc.s V_4 + IL_0037: call System.Void Cesium.Runtime.RuntimeHelpers::Exit(System.Int32) + IL_003c: ldloc.s V_4 + IL_003e: ret diff --git a/Cesium.CodeGen/Ir/BlockItems/FunctionDefinition.cs b/Cesium.CodeGen/Ir/BlockItems/FunctionDefinition.cs index e8cd3bec..1199925e 100644 --- a/Cesium.CodeGen/Ir/BlockItems/FunctionDefinition.cs +++ b/Cesium.CodeGen/Ir/BlockItems/FunctionDefinition.cs @@ -125,12 +125,16 @@ private MethodDefinition GenerateSyntheticEntryPoint( bool isValid = true; var argc = parameterList[0]; - if (argc.Type is not PrimitiveType { Kind: PrimitiveTypeKind.Int }) isValid = false; + if (argc.Type is not PrimitiveType { Kind: PrimitiveTypeKind.Int } // int argc + and not ConstType { Base: PrimitiveType { Kind: PrimitiveTypeKind.Int } /* const int argc */ }) isValid = false; var argv = parameterList[1]; - if (argv.Type is not PointerType + if (argv.Type is not PointerType // char** or char*[] { Base: PointerType { Base: PrimitiveType { Kind: PrimitiveTypeKind.Char } } + } and not PointerType // [opt const] char * const * + { + Base: PointerType { Base: ConstType { Base: PrimitiveType { Kind: PrimitiveTypeKind.Char } } } }) isValid = false; if (!isValid) From 98d1a87a3b994fc025662254c875377eaebd45fe Mon Sep 17 00:00:00 2001 From: Andrey <54708336+BadRyuner@users.noreply.github.com> Date: Sat, 23 Mar 2024 12:55:34 +0300 Subject: [PATCH 003/103] (#197) Add unary plus --- Cesium.CodeGen.Tests/CodeGenMethodTests.cs | 10 ++++++ ...MethodTests.UnaryPlusAndStart.verified.txt | 33 +++++++++++++++++++ .../Ir/Expressions/UnaryOperator.cs | 1 + .../Ir/Expressions/UnaryOperatorExpression.cs | 10 ++++++ Cesium.IntegrationTests/some_unaryops.c | 10 ++++++ Cesium.Parser/CParser.cs | 2 +- 6 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 Cesium.CodeGen.Tests/verified/CodeGenMethodTests.UnaryPlusAndStart.verified.txt create mode 100644 Cesium.IntegrationTests/some_unaryops.c diff --git a/Cesium.CodeGen.Tests/CodeGenMethodTests.cs b/Cesium.CodeGen.Tests/CodeGenMethodTests.cs index 7c3549c2..cc786ee3 100644 --- a/Cesium.CodeGen.Tests/CodeGenMethodTests.cs +++ b/Cesium.CodeGen.Tests/CodeGenMethodTests.cs @@ -113,6 +113,16 @@ public Task Arithmetic() => DoTest(@"int main(void) } "); + [Fact] + public Task UnaryPlusAndStart() => DoTest(@" +int main() { + short a = -2; + short* b = &a; + short c = *b; + int x = (+c) - (+1) - (-1); + return sizeof(+c); +} "); + [Fact] public Task ReturnWithoutArgument() => DoTest(@"void console_read() { diff --git a/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.UnaryPlusAndStart.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.UnaryPlusAndStart.verified.txt new file mode 100644 index 00000000..7e322293 --- /dev/null +++ b/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.UnaryPlusAndStart.verified.txt @@ -0,0 +1,33 @@ +System.Int32 ::main() + Locals: + System.Int16 V_0 + System.Int16* V_1 + System.Int16 V_2 + System.Int32 V_3 + IL_0000: ldc.i4.s -2 + IL_0002: conv.i2 + IL_0003: stloc.0 + IL_0004: ldloca.s V_0 + IL_0006: stloc.1 + IL_0007: ldloc.1 + IL_0008: ldind.i2 + IL_0009: stloc.2 + IL_000a: ldloc.2 + IL_000b: conv.i4 + IL_000c: ldc.i4.1 + IL_000d: sub + IL_000e: ldc.i4.m1 + IL_000f: sub + IL_0010: stloc.3 + IL_0011: sizeof System.Int32 + IL_0017: ret + +System.Int32 ::() + Locals: + System.Int32 V_0 + IL_0000: call System.Int32 ::main() + IL_0005: stloc.s V_0 + IL_0007: ldloc.s V_0 + IL_0009: call System.Void Cesium.Runtime.RuntimeHelpers::Exit(System.Int32) + IL_000e: ldloc.s V_0 + IL_0010: ret diff --git a/Cesium.CodeGen/Ir/Expressions/UnaryOperator.cs b/Cesium.CodeGen/Ir/Expressions/UnaryOperator.cs index 7a2baa85..cce75e94 100644 --- a/Cesium.CodeGen/Ir/Expressions/UnaryOperator.cs +++ b/Cesium.CodeGen/Ir/Expressions/UnaryOperator.cs @@ -3,6 +3,7 @@ namespace Cesium.CodeGen.Ir.Expressions; public enum UnaryOperator { Negation, // - + Promotion, // + BitwiseNot, // ~ LogicalNot, // ! AddressOf, // & diff --git a/Cesium.CodeGen/Ir/Expressions/UnaryOperatorExpression.cs b/Cesium.CodeGen/Ir/Expressions/UnaryOperatorExpression.cs index cabbd90f..01c961cc 100644 --- a/Cesium.CodeGen/Ir/Expressions/UnaryOperatorExpression.cs +++ b/Cesium.CodeGen/Ir/Expressions/UnaryOperatorExpression.cs @@ -55,6 +55,11 @@ public void EmitTo(IEmitScope scope) scope.Method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4_0)); scope.Method.Body.Instructions.Add(Instruction.Create(OpCodes.Ceq)); break; + case UnaryOperator.Promotion: + Target.EmitTo(scope); + if (ShouldBePromoted(Target.GetExpressionType((IDeclarationScope)scope))) + scope.Method.Body.Instructions.Add(Instruction.Create(OpCodes.Conv_I4)); + break; default: Target.EmitTo(scope); scope.Method.Body.Instructions.Add(GetInstruction()); @@ -72,12 +77,17 @@ public void EmitTo(IEmitScope scope) public IType GetExpressionType(IDeclarationScope scope) => Operator switch { UnaryOperator.AddressOf => Target.GetExpressionType(scope).MakePointerType(), // address-of returns T* + UnaryOperator.Promotion => ShouldBePromoted(Target.GetExpressionType(scope)) ? new PrimitiveType(PrimitiveTypeKind.Int) : Target.GetExpressionType(scope), _ => Target.GetExpressionType(scope), // other operators return T }; + // TargetArchitectureSet is not important. Short way to check for int, short, byte. + private static bool ShouldBePromoted(IType input) => input is PrimitiveType pt && (pt.GetSizeInBytes(TargetArchitectureSet.Bit32)! < 4); + private static UnaryOperator GetOperatorKind(string @operator) => @operator switch { "-" => UnaryOperator.Negation, + "+" => UnaryOperator.Promotion, "!" => UnaryOperator.LogicalNot, "~" => UnaryOperator.BitwiseNot, "&" => UnaryOperator.AddressOf, diff --git a/Cesium.IntegrationTests/some_unaryops.c b/Cesium.IntegrationTests/some_unaryops.c new file mode 100644 index 00000000..2f133ea3 --- /dev/null +++ b/Cesium.IntegrationTests/some_unaryops.c @@ -0,0 +1,10 @@ +#include + +int main() { + short c = -2; + int x = 0; + long long d = 0; + printf("%d %d %d %d %d %d", c, +c, sizeof(c), sizeof(+c), sizeof(+x), sizeof(+d)); + // -2 -2 2 4 4 8 + return 42; +} diff --git a/Cesium.Parser/CParser.cs b/Cesium.Parser/CParser.cs index 2d3e8b60..da6889e5 100644 --- a/Cesium.Parser/CParser.cs +++ b/Cesium.Parser/CParser.cs @@ -182,7 +182,7 @@ private static Expression MakeUnaryOperatorExpression(ICToken @operator, Express : new UnaryOperatorExpression(@operator.Text, target); [Rule("unary_operator: '&'")] - // TODO[#207]: [Rule("unary_operator: '+'")] + [Rule("unary_operator: '+'")] [Rule("unary_operator: '-'")] [Rule("unary_operator: '~'")] [Rule("unary_operator: '!'")] From eb9c18addc48147066e8056a79fc4a0045f311b1 Mon Sep 17 00:00:00 2001 From: Mark Cilia Vincenti Date: Sun, 21 Apr 2024 11:36:05 +0200 Subject: [PATCH 004/103] Made use of AsyncNonKeyedLocker; bumped AsyncKeyedLock library --- Cesium.IntegrationTests/Cesium.IntegrationTests.csproj | 1 - Cesium.TestFramework/CSharpCompilationUtil.cs | 10 +++------- Cesium.TestFramework/Cesium.TestFramework.csproj | 3 ++- Directory.Packages.props | 4 ++-- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Cesium.IntegrationTests/Cesium.IntegrationTests.csproj b/Cesium.IntegrationTests/Cesium.IntegrationTests.csproj index 9c69036e..c4bb6c58 100644 --- a/Cesium.IntegrationTests/Cesium.IntegrationTests.csproj +++ b/Cesium.IntegrationTests/Cesium.IntegrationTests.csproj @@ -12,7 +12,6 @@ - diff --git a/Cesium.TestFramework/CSharpCompilationUtil.cs b/Cesium.TestFramework/CSharpCompilationUtil.cs index 7a08a7f8..b6f87809 100644 --- a/Cesium.TestFramework/CSharpCompilationUtil.cs +++ b/Cesium.TestFramework/CSharpCompilationUtil.cs @@ -1,5 +1,6 @@ using System.Xml.Linq; using System.Xml.XPath; +using AsyncKeyedLock; using Cesium.CodeGen; using Xunit.Abstractions; @@ -15,7 +16,7 @@ public static class CSharpCompilationUtil private const string _projectName = "TestProject"; /// Semaphore that controls the amount of simultaneously running tests. - private static readonly SemaphoreSlim _testSemaphore = new(Environment.ProcessorCount); + private static readonly AsyncNonKeyedLocker _testSemaphore = new(Environment.ProcessorCount); public static async Task CompileCSharpAssembly( ITestOutputHelper output, @@ -23,8 +24,7 @@ public static async Task CompileCSharpAssembly( string cSharpSource) { if (runtime != DefaultRuntime) throw new Exception($"Runtime {runtime} not supported for test compilation."); - await _testSemaphore.WaitAsync(); - try + using (await _testSemaphore.LockAsync()) { var directory = Path.GetTempFileName(); File.Delete(directory); @@ -35,10 +35,6 @@ public static async Task CompileCSharpAssembly( await CompileCSharpProject(output, directory, _projectName); return Path.Combine(projectDirectory, "bin", _configuration, _targetRuntime, _projectName + ".dll"); } - finally - { - _testSemaphore.Release(); - } } private static async Task CreateCSharpProject(ITestOutputHelper output, string directory) diff --git a/Cesium.TestFramework/Cesium.TestFramework.csproj b/Cesium.TestFramework/Cesium.TestFramework.csproj index d4c1bed7..a73f3be2 100644 --- a/Cesium.TestFramework/Cesium.TestFramework.csproj +++ b/Cesium.TestFramework/Cesium.TestFramework.csproj @@ -6,7 +6,8 @@ - + + diff --git a/Directory.Packages.props b/Directory.Packages.props index 2779af0a..432a4607 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,7 +3,7 @@ true - + @@ -22,4 +22,4 @@ - + \ No newline at end of file From adc9bcff5c8367b916d9a1f05e4dceb59e60707e Mon Sep 17 00:00:00 2001 From: Mark Cilia Vincenti Date: Sun, 21 Apr 2024 16:07:20 +0200 Subject: [PATCH 005/103] Bump AsyncKeyedLock to 6.4.2 --- Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 432a4607..977c9a0c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,7 +3,7 @@ true - + @@ -22,4 +22,4 @@ - \ No newline at end of file + From c668097f485cc686911e5ef78a39e8d8216ebae2 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sun, 21 Apr 2024 18:03:24 +0200 Subject: [PATCH 006/103] CI: enable Dependabot to upgrade GitHub Actions and NuGet packages --- .github/dependabot.yml | 15 +++++++++++++++ Cesium.sln | 3 +++ 2 files changed, 18 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..505f01ea --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2024 Friedrich von Never +# +# SPDX-License-Identifier: MIT + +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "nuget" + directory: "/" + schedule: + interval: "daily" diff --git a/Cesium.sln b/Cesium.sln index 47985c04..c79a3a7f 100644 --- a/Cesium.sln +++ b/Cesium.sln @@ -17,6 +17,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{720F6830-E724-4B3A-BFDC-3FA1301A59D0}" + ProjectSection(SolutionItems) = preProject + .github\dependabot.yml = .github\dependabot.yml + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{C08E4851-DE2E-490E-970D-4F6A0A902A98}" ProjectSection(SolutionItems) = preProject From 2e5e0d3036c7bddb95cbbfd7462865c1d9af7113 Mon Sep 17 00:00:00 2001 From: Andrey <54708336+BadRyuner@users.noreply.github.com> Date: Sat, 20 Apr 2024 16:42:45 +0300 Subject: [PATCH 007/103] (#494) Reverse FuncPtr interop --- Cesium.Runtime.Tests/PtrTests.cs | 15 ++++++++++++--- Cesium.Runtime/FuncPtr.cs | 20 +++++++++++++++++--- Cesium.Runtime/VoidPtr.cs | 12 ++++++------ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/Cesium.Runtime.Tests/PtrTests.cs b/Cesium.Runtime.Tests/PtrTests.cs index afae7533..392a2f4e 100644 --- a/Cesium.Runtime.Tests/PtrTests.cs +++ b/Cesium.Runtime.Tests/PtrTests.cs @@ -9,7 +9,7 @@ public void VoidPtrTests() Assert.Equal(0x1234L, (long)v.AsPtr()); Assert.Equal(0x1234L, (long)v.AsPtr()); - Assert.Equal(sizeof(long), sizeof(VoidPtr)); + Assert.Equal(sizeof(IntPtr), sizeof(VoidPtr)); } [Fact] @@ -20,7 +20,7 @@ public void CPtrTests() Assert.Equal((IntPtr)0x2345, t.AsIntPtr()); Assert.Equal(0x2345L, (long)t.AsPtr()); - Assert.Equal(sizeof(long), sizeof(CPtr)); + Assert.Equal(sizeof(IntPtr), sizeof(CPtr)); } [Fact] @@ -28,6 +28,15 @@ public void FuncPtrTests() { var a = new FuncPtr((void*)0x1234); Assert.Equal(0x1234L, (long)a.AsPtr()); - Assert.Equal(sizeof(long), sizeof(FuncPtr)); + Assert.Equal(sizeof(IntPtr), sizeof(FuncPtr)); + + FuncPtr> funcPtr = (Func)SomeAnonFunc; + var func = SomeAnonFunc; + Assert.Equal(funcPtr.AsDelegate()(), func()); + + funcPtr = (delegate*)&SomeAnonFunc; + Assert.Equal(funcPtr.AsDelegate()(), func()); + + static int SomeAnonFunc() => 5; } } diff --git a/Cesium.Runtime/FuncPtr.cs b/Cesium.Runtime/FuncPtr.cs index 98460430..7f2c0e81 100644 --- a/Cesium.Runtime/FuncPtr.cs +++ b/Cesium.Runtime/FuncPtr.cs @@ -1,14 +1,28 @@ +using System.Runtime.InteropServices; + namespace Cesium.Runtime; /// A class encapsulating a C function pointer. -public readonly unsafe struct FuncPtr where TDelegate : Delegate // TODO[#487]: Think about vararg and empty parameter list encoding. +public readonly unsafe struct FuncPtr where TDelegate : MulticastDelegate // TODO[#487]: Think about vararg and empty parameter list encoding. { - private readonly long _value; + private readonly IntPtr _value; public FuncPtr(void* ptr) { - _value = (long)ptr; + _value = (IntPtr)ptr; + } + + public FuncPtr(IntPtr ptr) + { + _value = ptr; } + public static implicit operator TDelegate(FuncPtr funcPtr) => (TDelegate)Activator.CreateInstance(typeof(TDelegate), [null, funcPtr._value])!; + public static implicit operator FuncPtr(TDelegate @delegate) => @delegate.Method.MethodHandle.GetFunctionPointer(); + public static implicit operator FuncPtr(IntPtr funcPtr) => new(funcPtr); + public static implicit operator FuncPtr(void* funcPtr) => new(funcPtr); + + public TDelegate AsDelegate() => this; + public void* AsPtr() => (void*)_value; } diff --git a/Cesium.Runtime/VoidPtr.cs b/Cesium.Runtime/VoidPtr.cs index ec581f48..32d403ff 100644 --- a/Cesium.Runtime/VoidPtr.cs +++ b/Cesium.Runtime/VoidPtr.cs @@ -3,14 +3,14 @@ namespace Cesium.Runtime; /// A class encapsulating an opaque pointer (aka void* in C). public readonly unsafe struct VoidPtr { - private readonly long _value; + private readonly IntPtr _value; - private VoidPtr(long value) + private VoidPtr(IntPtr value) { _value = value; } - public static implicit operator VoidPtr(void* ptr) => new((long)ptr); + public static implicit operator VoidPtr(void* ptr) => new((IntPtr)ptr); public void* AsPtr() => (void*)_value; public TResult* AsPtr() where TResult : unmanaged => (TResult*)_value; public IntPtr AsIntPtr() => (IntPtr)AsPtr(); @@ -21,14 +21,14 @@ private VoidPtr(long value) /// Type this pointer may be resolved to. public readonly unsafe struct CPtr where T : unmanaged { - private readonly long _value; + private readonly IntPtr _value; - private CPtr(long value) + private CPtr(IntPtr value) { _value = value; } - public static implicit operator CPtr(T* ptr) => new((long)ptr); + public static implicit operator CPtr(T* ptr) => new((IntPtr)ptr); public T* AsPtr() => (T*)_value; public TResult* AsPtr() where TResult : unmanaged => (TResult*)_value; public IntPtr AsIntPtr() => (IntPtr)AsPtr(); From 2509caf20fbf5ffa13d6fb2a2183ab205dffdba3 Mon Sep 17 00:00:00 2001 From: Andrey <54708336+BadRyuner@users.noreply.github.com> Date: Sat, 20 Apr 2024 19:04:22 +0300 Subject: [PATCH 008/103] Better string interop --- .../CodeGenNetInteropTests.cs | 18 +++ ...ttribute_architecture=Dynamic.verified.txt | 29 ++++ ...peAttribute_architecture=Wide.verified.txt | 29 ++++ Cesium.CodeGen/Extensions/TypeSystemEx.cs | 16 ++ .../Ir/Expressions/FunctionCallExpression.cs | 5 +- .../Expressions/FunctionCallExpressionBase.cs | 23 ++- Cesium.Runtime.Tests/StringTests.cs | 26 ++++ .../Attributes/EquivalentTypeAttribute.cs | 7 + Cesium.Runtime/FuncPtr.cs | 7 +- Cesium.Runtime/StringFunctions.cs | 91 ++---------- Cesium.Runtime/UTF8String.cs | 139 ++++++++++++++++++ 11 files changed, 305 insertions(+), 85 deletions(-) create mode 100644 Cesium.CodeGen.Tests/verified/CodeGenNetInteropTests.TestEquivalentTypeAttribute_architecture=Dynamic.verified.txt create mode 100644 Cesium.CodeGen.Tests/verified/CodeGenNetInteropTests.TestEquivalentTypeAttribute_architecture=Wide.verified.txt create mode 100644 Cesium.Runtime.Tests/StringTests.cs create mode 100644 Cesium.Runtime/Attributes/EquivalentTypeAttribute.cs create mode 100644 Cesium.Runtime/UTF8String.cs diff --git a/Cesium.CodeGen.Tests/CodeGenNetInteropTests.cs b/Cesium.CodeGen.Tests/CodeGenNetInteropTests.cs index 8480f7aa..d3c8a203 100644 --- a/Cesium.CodeGen.Tests/CodeGenNetInteropTests.cs +++ b/Cesium.CodeGen.Tests/CodeGenNetInteropTests.cs @@ -170,4 +170,22 @@ int main(void) return Func(&myFunc) - 1; } """); + + [Theory] + [InlineData(TargetArchitectureSet.Dynamic)] + [InlineData(TargetArchitectureSet.Wide)] + public Task TestEquivalentTypeAttribute(TargetArchitectureSet architecture) => DoTest(architecture, +@"using Cesium.Runtime; +public static unsafe class Test +{ + public static int Func(UTF8String str) => (int)str.Length; +}", +@" +__cli_import(""Test::Func"") +int Func(char*); + +int main(void) +{ + return Func(""Hi"") - 2; +}"); } diff --git a/Cesium.CodeGen.Tests/verified/CodeGenNetInteropTests.TestEquivalentTypeAttribute_architecture=Dynamic.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenNetInteropTests.TestEquivalentTypeAttribute_architecture=Dynamic.verified.txt new file mode 100644 index 00000000..1db6d463 --- /dev/null +++ b/Cesium.CodeGen.Tests/verified/CodeGenNetInteropTests.TestEquivalentTypeAttribute_architecture=Dynamic.verified.txt @@ -0,0 +1,29 @@ +Module: Primary + Type: + Methods: + System.Int32 ::main() + IL_0000: ldsflda / ::ConstDataBuffer0 + IL_0005: call Cesium.Runtime.UTF8String Cesium.Runtime.UTF8String::op_Implicit(System.Byte*) + IL_000a: call System.Int32 Test::Func(Cesium.Runtime.UTF8String) + IL_000f: ldc.i4.2 + IL_0010: sub + IL_0011: ret + + System.Int32 ::() + Locals: + System.Int32 V_0 + IL_0000: call System.Int32 ::main() + IL_0005: stloc.s V_0 + IL_0007: ldloc.s V_0 + IL_0009: call System.Void Cesium.Runtime.RuntimeHelpers::Exit(System.Int32) + IL_000e: ldloc.s V_0 + IL_0010: ret + + Type: + Nested types: + Type: / + Pack: 1 + Size: 3 + Fields: + / ::ConstDataBuffer0 + Init with (UTF-8 x 3 bytes): "Hi" diff --git a/Cesium.CodeGen.Tests/verified/CodeGenNetInteropTests.TestEquivalentTypeAttribute_architecture=Wide.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenNetInteropTests.TestEquivalentTypeAttribute_architecture=Wide.verified.txt new file mode 100644 index 00000000..1db6d463 --- /dev/null +++ b/Cesium.CodeGen.Tests/verified/CodeGenNetInteropTests.TestEquivalentTypeAttribute_architecture=Wide.verified.txt @@ -0,0 +1,29 @@ +Module: Primary + Type: + Methods: + System.Int32 ::main() + IL_0000: ldsflda / ::ConstDataBuffer0 + IL_0005: call Cesium.Runtime.UTF8String Cesium.Runtime.UTF8String::op_Implicit(System.Byte*) + IL_000a: call System.Int32 Test::Func(Cesium.Runtime.UTF8String) + IL_000f: ldc.i4.2 + IL_0010: sub + IL_0011: ret + + System.Int32 ::() + Locals: + System.Int32 V_0 + IL_0000: call System.Int32 ::main() + IL_0005: stloc.s V_0 + IL_0007: ldloc.s V_0 + IL_0009: call System.Void Cesium.Runtime.RuntimeHelpers::Exit(System.Int32) + IL_000e: ldloc.s V_0 + IL_0010: ret + + Type: + Nested types: + Type: / + Pack: 1 + Size: 3 + Fields: + / ::ConstDataBuffer0 + Init with (UTF-8 x 3 bytes): "Hi" diff --git a/Cesium.CodeGen/Extensions/TypeSystemEx.cs b/Cesium.CodeGen/Extensions/TypeSystemEx.cs index 720ac72e..ef9110a7 100644 --- a/Cesium.CodeGen/Extensions/TypeSystemEx.cs +++ b/Cesium.CodeGen/Extensions/TypeSystemEx.cs @@ -13,6 +13,7 @@ internal static class TypeSystemEx public const string CPtrFullTypeName = "Cesium.Runtime.CPtr`1"; public const string VoidPtrFullTypeName = "Cesium.Runtime.VoidPtr"; public const string FuncPtrFullTypeName = "Cesium.Runtime.FuncPtr`1"; + public const string EquivalentTypeAttributeName = "Cesium.Runtime.Attributes.EquivalentTypeAttribute"; public static MethodReference MethodLookup( this TranslationUnitContext context, @@ -160,6 +161,21 @@ private static bool TypesCorrespond(TypeSystem typeSystem, TypeReference type1, return type1 is PointerType pt && pt.ElementType.IsEqualTo(typeSystem.Void); } + var resolvedType2 = type2.Resolve(); + if (resolvedType2.HasCustomAttributes) + { + // check for EquivalentTypeAttribute + foreach(var attr in resolvedType2.CustomAttributes) + { + if (!attr.AttributeType.FullName.Equals(EquivalentTypeAttributeName)) + continue; + + var eqType = (TypeReference)attr.ConstructorArguments[0].Value; + if (type1.FullName == eqType.FullName) + return true; + } + } + if (type2 is not GenericInstanceType type2Instance) return false; var type2Definition = type2.GetElementType(); if (type1.IsPointer) diff --git a/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs b/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs index 8bdda7ae..3a75c28c 100644 --- a/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs +++ b/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs @@ -124,11 +124,12 @@ public override void EmitTo(IEmitScope scope) if (_callee == null) throw new AssertException("Should be lowered"); - EmitArgumentList(scope, _callee.Parameters, _arguments); - var functionName = _function.Identifier; var callee = _callee ?? throw new CompilationException($"Function \"{functionName}\" was not lowered."); var methodReference = callee.MethodReference ?? throw new CompilationException($"Function \"{functionName}\" was not found."); + + EmitArgumentList(scope, _callee.Parameters, _arguments, methodReference); + scope.Method.Body.Instructions.Add(Instruction.Create(OpCodes.Call, methodReference)); } diff --git a/Cesium.CodeGen/Ir/Expressions/FunctionCallExpressionBase.cs b/Cesium.CodeGen/Ir/Expressions/FunctionCallExpressionBase.cs index 79b51909..8f7abe36 100644 --- a/Cesium.CodeGen/Ir/Expressions/FunctionCallExpressionBase.cs +++ b/Cesium.CodeGen/Ir/Expressions/FunctionCallExpressionBase.cs @@ -1,6 +1,7 @@ using Cesium.CodeGen.Contexts; using Cesium.CodeGen.Extensions; using Cesium.CodeGen.Ir.Types; +using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Rocks; @@ -12,7 +13,7 @@ internal abstract class FunctionCallExpressionBase : IExpression public abstract void EmitTo(IEmitScope scope); public abstract IType GetExpressionType(IDeclarationScope scope); - protected void EmitArgumentList(IEmitScope scope, ParametersInfo? paramInfo, IReadOnlyList arguments) + protected void EmitArgumentList(IEmitScope scope, ParametersInfo? paramInfo, IReadOnlyList arguments, MethodReference? method = null) { var explicitParametersCount = paramInfo?.Parameters.Count ?? 0; var varArgParametersCount = arguments.Count - explicitParametersCount; @@ -39,8 +40,28 @@ protected void EmitArgumentList(IEmitScope scope, ParametersInfo? paramInfo, IRe scope.AddInstruction(OpCodes.Stloc, varArgBuffer); } + var counter = 0; foreach (var argument in arguments.Take(explicitParametersCount)) + { argument.EmitTo(scope); + if (paramInfo?.IsVarArg != true && method != null) + { + var passedArg = argument.GetExpressionType((IDeclarationScope)scope).Resolve(scope.Context); + var actualArg = method.Parameters[counter].ParameterType; + counter++; + if (passedArg.FullName != actualArg.FullName) + { + //var conversion = actualArg.Resolve().Methods.FirstOrDefault(method => method.Name == "op_Implicit" && + // method.ReturnType == actualArg && method.Parameters[0].ParameterType == passedArg); <--- exception :( + //if (conversion == null) + // continue; + var conversion = new MethodReference("op_Implicit", actualArg, actualArg); // Gentlemen are taken at their word. + conversion.Parameters.Add(new(passedArg)); + + scope.AddInstruction(OpCodes.Call, conversion); + } + } + } if (paramInfo?.IsVarArg == true) { diff --git a/Cesium.Runtime.Tests/StringTests.cs b/Cesium.Runtime.Tests/StringTests.cs new file mode 100644 index 00000000..804100fb --- /dev/null +++ b/Cesium.Runtime.Tests/StringTests.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; + +namespace Cesium.Runtime.Tests; +public unsafe class StringTests +{ + [Fact] + public void ComplexTest() + { + UTF8String someString = (byte*)Marshal.StringToHGlobalAnsi("Hello world!\0"); + + Assert.Equal("Hello world!".Length, (int)someString.Length); + Assert.Equal("Hello world!".Length + 1, (int)someString.NullTerminatedLength); + Assert.Equal("Hello world!", someString.ToString()); + + UTF8String someMemory = stackalloc byte[(int)someString.NullTerminatedLength]; + someString.CopyTo(someMemory); + Assert.Equal(someString.ToString(), someMemory.ToString()); + + UTF8String someOtherMemory = stackalloc byte[(int)someString.NullTerminatedLength]; + someString.CopyTo(someOtherMemory, 5); + someOtherMemory[6] = (byte)'\0'; + Assert.Equal("Hello", someOtherMemory.ToString()); + + Assert.Equal((byte)'o', someString.At(4)[0]); + } +} diff --git a/Cesium.Runtime/Attributes/EquivalentTypeAttribute.cs b/Cesium.Runtime/Attributes/EquivalentTypeAttribute.cs new file mode 100644 index 00000000..0d613d2c --- /dev/null +++ b/Cesium.Runtime/Attributes/EquivalentTypeAttribute.cs @@ -0,0 +1,7 @@ +namespace Cesium.Runtime.Attributes; + +[AttributeUsage(AttributeTargets.Struct)] +public class EquivalentTypeAttribute(Type equivalentType) : Attribute +{ + public Type EquivalentType { get; } = equivalentType; +} diff --git a/Cesium.Runtime/FuncPtr.cs b/Cesium.Runtime/FuncPtr.cs index 7f2c0e81..f69220b9 100644 --- a/Cesium.Runtime/FuncPtr.cs +++ b/Cesium.Runtime/FuncPtr.cs @@ -12,14 +12,9 @@ public FuncPtr(void* ptr) _value = (IntPtr)ptr; } - public FuncPtr(IntPtr ptr) - { - _value = ptr; - } - public static implicit operator TDelegate(FuncPtr funcPtr) => (TDelegate)Activator.CreateInstance(typeof(TDelegate), [null, funcPtr._value])!; public static implicit operator FuncPtr(TDelegate @delegate) => @delegate.Method.MethodHandle.GetFunctionPointer(); - public static implicit operator FuncPtr(IntPtr funcPtr) => new(funcPtr); + public static implicit operator FuncPtr(IntPtr funcPtr) => new((void*)funcPtr); public static implicit operator FuncPtr(void* funcPtr) => new(funcPtr); public TDelegate AsDelegate() => this; diff --git a/Cesium.Runtime/StringFunctions.cs b/Cesium.Runtime/StringFunctions.cs index df755188..182912b2 100644 --- a/Cesium.Runtime/StringFunctions.cs +++ b/Cesium.Runtime/StringFunctions.cs @@ -12,81 +12,32 @@ namespace Cesium.Runtime; /// public static unsafe class StringFunctions { - public static nuint StrLen(byte* str) - { -#if NETSTANDARD - if (str == null) - { - return 0; - } + public static nuint StrLen(UTF8String str) => str.Length; - Encoding encoding = Encoding.UTF8; - int byteLength = 0; - byte* search = str; - while (*search != '\0') - { - byteLength++; - search++; - } - - int stringLength = encoding.GetCharCount(str, byteLength); - return (uint)stringLength; -#else - return (uint)(Marshal.PtrToStringUTF8((nint)str)?.Length ?? 0); -#endif - } - public static byte* StrCpy(byte* dest, byte* src) + public static byte* StrCpy(UTF8String dest, UTF8String src) { - if (dest == null) - { + if (!dest) return null; - } - var result = dest; - if (src == null) - { + if (!src) return dest; - } - byte* search = src; - while (*search != '\0') - { - *dest = *search; - search++; - dest++; - } + src.CopyTo(dest); - *dest = 0; - return result; + return dest; } - public static byte* StrNCpy(byte* dest, byte* src, nuint count) + + public static byte* StrNCpy(UTF8String dest, UTF8String src, nuint count) { - if (dest == null) - { + if (!dest) return null; - } - var result = dest; - if (src == null) - { + if (!src) return dest; - } - uint counter = 0; - byte* search = src; - while (*search != '\0') - { - *dest = *search; - search++; - dest++; - counter++; - if (counter == count) - { - break; - } - } + src.CopyTo(dest, count); - return result; + return dest; } public static byte* StrCat(byte* dest, byte* src) { @@ -184,24 +135,12 @@ public static int StrNCmp(byte* lhs, byte* rhs, nuint count) return dest; } - public static byte* StrChr(byte* str, int ch) + public static byte* StrChr(UTF8String str, int ch) { - if (str == null) - { + if (!str) return null; - } - - while (*str != 0) - { - if (*str == ch) - { - return str; - } - - str++; - } - return null; + return str.FindEntry((byte)ch); } public static int StrCmp(byte* lhs, byte* rhs) diff --git a/Cesium.Runtime/UTF8String.cs b/Cesium.Runtime/UTF8String.cs new file mode 100644 index 00000000..ce04253d --- /dev/null +++ b/Cesium.Runtime/UTF8String.cs @@ -0,0 +1,139 @@ +using Cesium.Runtime.Attributes; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Cesium.Runtime; + +/// +/// A useful wrapper over UTF8 strings. +/// +[EquivalentType(typeof(byte*))] +[StructLayout(LayoutKind.Sequential)] +public unsafe readonly struct UTF8String +{ + public readonly static UTF8String NullString = new UTF8String((byte*)0); + + private readonly byte* _value; + + public UTF8String(byte* text) => _value = text; + + public byte this[int index] + { + get => _value[index]; + set => _value[index] = value; + } + + public byte this[nuint index] + { + get => _value[index]; + set => _value[index] = value; + } + + /// + /// String length + /// + public nuint Length + { + get + { + nuint length = 0; + while (_value[length] != 0) length++; + return length; + } + } + + /// + /// String length including '\0' + /// + public nuint NullTerminatedLength + { + get + { + nuint length = 0; + while (_value[length] != 0) length++; + return length + 1; + } + } + +#if !NETSTANDARD + /// + /// Creates a Span for the full length of the string + /// + public Span Span => new(_value, (int)Length); + + /// + /// Creates Span(ptr, int.MaxValue) + /// + public Span UncheckedSpan => new(_value, int.MaxValue); +#endif + + /// + /// Copies the contents of a string for its entire length to another string + /// + /// Destination + public void CopyTo(UTF8String dest) + { + var len = NullTerminatedLength; + +#if NETSTANDARD + for(nuint i = 0; i < len; i++) + dest[i] = _value[i]; +#else + UncheckedSpan.Slice(0, (int)len).CopyTo(dest.UncheckedSpan); +#endif + } + + /// + /// Copies "count" bytes of a string to another string + /// + /// Destination + /// How many bytes to copy + public void CopyTo(UTF8String dest, nuint count) + { + var len = Math.Min(NullTerminatedLength, count); + +#if NETSTANDARD + for (nuint i = 0; i < len; i++) + dest[i] = _value[i]; +#else + UncheckedSpan.Slice(0, (int)len).CopyTo(dest.UncheckedSpan); +#endif + } + + /// + /// Looks for a literal in a string + /// + /// ASCII literal + /// Pointer to the literal + public UTF8String FindEntry(byte ch) + { +#if NETSTANDARD + var len = Length; + for (nuint i = 0; i < len; i++) + if (this[i] == ch) + return At(i); + return NullString; +#else + var index = Span.IndexOf(ch); + if (index == -1) return NullString; + return (byte*)Unsafe.AsPointer(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(_value), (nuint)index)); +#endif + } + + public UTF8String At(int index) => new UTF8String(_value + index); + public UTF8String At(nuint index) => new UTF8String(_value + index); + + public override string ToString() => new string((sbyte*)_value); + + public static bool operator !(UTF8String str) => (nuint)str._value == 0; + + public static implicit operator byte*(UTF8String str) => str._value; + public static implicit operator IntPtr(UTF8String str) => (IntPtr)str._value; + + public static implicit operator UTF8String(byte* p) => new UTF8String(p); + public static implicit operator UTF8String(sbyte* p) => new UTF8String((byte*)p); + public static implicit operator UTF8String(IntPtr p) => new UTF8String((byte*)p); + public static implicit operator UTF8String(CPtr p) => new UTF8String(p.AsPtr()); + public static implicit operator UTF8String(CPtr p) => new UTF8String((byte*)p.AsPtr()); +} From 7b298abb55425c56e299ce0412fcd9e9dfe2be32 Mon Sep 17 00:00:00 2001 From: Andrey <54708336+BadRyuner@users.noreply.github.com> Date: Sun, 21 Apr 2024 07:31:33 +0300 Subject: [PATCH 009/103] Fixed minor issue --- Cesium.Runtime.Tests/PtrTests.cs | 4 ++-- Cesium.Runtime.Tests/StringTests.cs | 2 ++ Cesium.Runtime/FuncPtr.cs | 6 ++--- Cesium.Runtime/UTF8String.cs | 34 +++++++++++++++-------------- Cesium.Runtime/VoidPtr.cs | 12 +++++----- 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/Cesium.Runtime.Tests/PtrTests.cs b/Cesium.Runtime.Tests/PtrTests.cs index 392a2f4e..83f43dc9 100644 --- a/Cesium.Runtime.Tests/PtrTests.cs +++ b/Cesium.Runtime.Tests/PtrTests.cs @@ -9,7 +9,7 @@ public void VoidPtrTests() Assert.Equal(0x1234L, (long)v.AsPtr()); Assert.Equal(0x1234L, (long)v.AsPtr()); - Assert.Equal(sizeof(IntPtr), sizeof(VoidPtr)); + Assert.Equal(sizeof(long), sizeof(VoidPtr)); } [Fact] @@ -20,7 +20,7 @@ public void CPtrTests() Assert.Equal((IntPtr)0x2345, t.AsIntPtr()); Assert.Equal(0x2345L, (long)t.AsPtr()); - Assert.Equal(sizeof(IntPtr), sizeof(CPtr)); + Assert.Equal(sizeof(long), sizeof(CPtr)); } [Fact] diff --git a/Cesium.Runtime.Tests/StringTests.cs b/Cesium.Runtime.Tests/StringTests.cs index 804100fb..fbd77522 100644 --- a/Cesium.Runtime.Tests/StringTests.cs +++ b/Cesium.Runtime.Tests/StringTests.cs @@ -6,6 +6,8 @@ public unsafe class StringTests [Fact] public void ComplexTest() { + Assert.Equal(sizeof(long), sizeof(UTF8String)); + UTF8String someString = (byte*)Marshal.StringToHGlobalAnsi("Hello world!\0"); Assert.Equal("Hello world!".Length, (int)someString.Length); diff --git a/Cesium.Runtime/FuncPtr.cs b/Cesium.Runtime/FuncPtr.cs index f69220b9..4310681b 100644 --- a/Cesium.Runtime/FuncPtr.cs +++ b/Cesium.Runtime/FuncPtr.cs @@ -5,14 +5,14 @@ namespace Cesium.Runtime; /// A class encapsulating a C function pointer. public readonly unsafe struct FuncPtr where TDelegate : MulticastDelegate // TODO[#487]: Think about vararg and empty parameter list encoding. { - private readonly IntPtr _value; + private readonly long _value; public FuncPtr(void* ptr) { - _value = (IntPtr)ptr; + _value = (long)ptr; } - public static implicit operator TDelegate(FuncPtr funcPtr) => (TDelegate)Activator.CreateInstance(typeof(TDelegate), [null, funcPtr._value])!; + public static implicit operator TDelegate(FuncPtr funcPtr) => (TDelegate)Activator.CreateInstance(typeof(TDelegate), [null, (IntPtr)funcPtr._value])!; public static implicit operator FuncPtr(TDelegate @delegate) => @delegate.Method.MethodHandle.GetFunctionPointer(); public static implicit operator FuncPtr(IntPtr funcPtr) => new((void*)funcPtr); public static implicit operator FuncPtr(void* funcPtr) => new(funcPtr); diff --git a/Cesium.Runtime/UTF8String.cs b/Cesium.Runtime/UTF8String.cs index ce04253d..2285fe04 100644 --- a/Cesium.Runtime/UTF8String.cs +++ b/Cesium.Runtime/UTF8String.cs @@ -14,20 +14,22 @@ public unsafe readonly struct UTF8String { public readonly static UTF8String NullString = new UTF8String((byte*)0); - private readonly byte* _value; + private readonly long _value; - public UTF8String(byte* text) => _value = text; + public UTF8String(byte* text) => _value = (long)text; + + public byte* Pointer => (byte*)_value; public byte this[int index] { - get => _value[index]; - set => _value[index] = value; + get => Pointer[index]; + set => Pointer[index] = value; } public byte this[nuint index] { - get => _value[index]; - set => _value[index] = value; + get => Pointer[index]; + set => Pointer[index] = value; } /// @@ -38,7 +40,7 @@ public nuint Length get { nuint length = 0; - while (_value[length] != 0) length++; + while (Pointer[length] != 0) length++; return length; } } @@ -51,7 +53,7 @@ public nuint NullTerminatedLength get { nuint length = 0; - while (_value[length] != 0) length++; + while (Pointer[length] != 0) length++; return length + 1; } } @@ -60,12 +62,12 @@ public nuint NullTerminatedLength /// /// Creates a Span for the full length of the string /// - public Span Span => new(_value, (int)Length); + public Span Span => new(Pointer, (int)Length); /// /// Creates Span(ptr, int.MaxValue) /// - public Span UncheckedSpan => new(_value, int.MaxValue); + public Span UncheckedSpan => new(Pointer, int.MaxValue); #endif /// @@ -78,7 +80,7 @@ public void CopyTo(UTF8String dest) #if NETSTANDARD for(nuint i = 0; i < len; i++) - dest[i] = _value[i]; + dest[i] = this[i]; #else UncheckedSpan.Slice(0, (int)len).CopyTo(dest.UncheckedSpan); #endif @@ -95,7 +97,7 @@ public void CopyTo(UTF8String dest, nuint count) #if NETSTANDARD for (nuint i = 0; i < len; i++) - dest[i] = _value[i]; + dest[i] = this[i]; #else UncheckedSpan.Slice(0, (int)len).CopyTo(dest.UncheckedSpan); #endif @@ -117,18 +119,18 @@ public UTF8String FindEntry(byte ch) #else var index = Span.IndexOf(ch); if (index == -1) return NullString; - return (byte*)Unsafe.AsPointer(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(_value), (nuint)index)); + return (byte*)Unsafe.AsPointer(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(Pointer), (nuint)index)); #endif } - public UTF8String At(int index) => new UTF8String(_value + index); - public UTF8String At(nuint index) => new UTF8String(_value + index); + public UTF8String At(int index) => new UTF8String(Pointer + index); + public UTF8String At(nuint index) => new UTF8String(Pointer + index); public override string ToString() => new string((sbyte*)_value); public static bool operator !(UTF8String str) => (nuint)str._value == 0; - public static implicit operator byte*(UTF8String str) => str._value; + public static implicit operator byte*(UTF8String str) => str.Pointer; public static implicit operator IntPtr(UTF8String str) => (IntPtr)str._value; public static implicit operator UTF8String(byte* p) => new UTF8String(p); diff --git a/Cesium.Runtime/VoidPtr.cs b/Cesium.Runtime/VoidPtr.cs index 32d403ff..ec581f48 100644 --- a/Cesium.Runtime/VoidPtr.cs +++ b/Cesium.Runtime/VoidPtr.cs @@ -3,14 +3,14 @@ namespace Cesium.Runtime; /// A class encapsulating an opaque pointer (aka void* in C). public readonly unsafe struct VoidPtr { - private readonly IntPtr _value; + private readonly long _value; - private VoidPtr(IntPtr value) + private VoidPtr(long value) { _value = value; } - public static implicit operator VoidPtr(void* ptr) => new((IntPtr)ptr); + public static implicit operator VoidPtr(void* ptr) => new((long)ptr); public void* AsPtr() => (void*)_value; public TResult* AsPtr() where TResult : unmanaged => (TResult*)_value; public IntPtr AsIntPtr() => (IntPtr)AsPtr(); @@ -21,14 +21,14 @@ private VoidPtr(IntPtr value) /// Type this pointer may be resolved to. public readonly unsafe struct CPtr where T : unmanaged { - private readonly IntPtr _value; + private readonly long _value; - private CPtr(IntPtr value) + private CPtr(long value) { _value = value; } - public static implicit operator CPtr(T* ptr) => new((IntPtr)ptr); + public static implicit operator CPtr(T* ptr) => new((long)ptr); public T* AsPtr() => (T*)_value; public TResult* AsPtr() where TResult : unmanaged => (TResult*)_value; public IntPtr AsIntPtr() => (IntPtr)AsPtr(); From addb10c0e01ede9c55bd6763b9995c395769babf Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 9 Jul 2023 04:07:08 +0200 Subject: [PATCH 010/103] SDK: Initial progress --- .gitignore | 1 + Cesium.Ast/Cesium.Ast.csproj | 1 + Cesium.Compiler/Cesium.Compiler.csproj | 9 + .../Cesium.Preprocessor.csproj | 10 +- Cesium.Runtime/Cesium.Runtime.csproj | 14 +- Cesium.Sdk/Cesium.Sdk.csproj | 19 ++ Cesium.Sdk/CesiumCompile.cs | 287 ++++++++++++++++++ Cesium.Sdk/Sdk/Sdk.props | 29 ++ Cesium.Sdk/Sdk/Sdk.targets | 17 ++ Cesium.sln | 6 + Directory.Build.props | 3 + nuget.config | 10 + 12 files changed, 394 insertions(+), 12 deletions(-) create mode 100644 Cesium.Sdk/Cesium.Sdk.csproj create mode 100644 Cesium.Sdk/CesiumCompile.cs create mode 100644 Cesium.Sdk/Sdk/Sdk.props create mode 100644 Cesium.Sdk/Sdk/Sdk.targets create mode 100644 nuget.config diff --git a/.gitignore b/.gitignore index a58baf71..d7e0a87f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ bin/ obj/ +artifacts/ *.dll *.exe diff --git a/Cesium.Ast/Cesium.Ast.csproj b/Cesium.Ast/Cesium.Ast.csproj index 444a7901..fdc5611d 100644 --- a/Cesium.Ast/Cesium.Ast.csproj +++ b/Cesium.Ast/Cesium.Ast.csproj @@ -3,6 +3,7 @@ net7.0 enable + true diff --git a/Cesium.Compiler/Cesium.Compiler.csproj b/Cesium.Compiler/Cesium.Compiler.csproj index 9b78d196..979c81d9 100644 --- a/Cesium.Compiler/Cesium.Compiler.csproj +++ b/Cesium.Compiler/Cesium.Compiler.csproj @@ -7,6 +7,7 @@ true true true + Major @@ -36,4 +37,12 @@ + + + true + tools + false + + + diff --git a/Cesium.Preprocessor/Cesium.Preprocessor.csproj b/Cesium.Preprocessor/Cesium.Preprocessor.csproj index 8fb1047f..fe7710f3 100644 --- a/Cesium.Preprocessor/Cesium.Preprocessor.csproj +++ b/Cesium.Preprocessor/Cesium.Preprocessor.csproj @@ -6,14 +6,14 @@ - - - - + + + + - + diff --git a/Cesium.Runtime/Cesium.Runtime.csproj b/Cesium.Runtime/Cesium.Runtime.csproj index d8fe30c4..a8da8707 100644 --- a/Cesium.Runtime/Cesium.Runtime.csproj +++ b/Cesium.Runtime/Cesium.Runtime.csproj @@ -1,12 +1,12 @@ - - netstandard2.0;net6.0 - enable - enable - true - latest - + + netstandard2.0;net6.0 + enable + enable + true + latest + diff --git a/Cesium.Sdk/Cesium.Sdk.csproj b/Cesium.Sdk/Cesium.Sdk.csproj new file mode 100644 index 00000000..e4aea2c6 --- /dev/null +++ b/Cesium.Sdk/Cesium.Sdk.csproj @@ -0,0 +1,19 @@ + + + + net8.0 + + enable + true + + + + + + + + + + + + diff --git a/Cesium.Sdk/CesiumCompile.cs b/Cesium.Sdk/CesiumCompile.cs new file mode 100644 index 00000000..0f272959 --- /dev/null +++ b/Cesium.Sdk/CesiumCompile.cs @@ -0,0 +1,287 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Cesium.Sdk; + +/* + -o, --out Sets path for the output assembly file + --framework (Default: Net) Valid values: Net, NetFramework, NetStandard + --arch (Default: Dynamic) Valid values: Dynamic, Bit32, Bit64 + --modulekind Valid values: Dll, Console, Windows, NetModule + --nologo Suppress compiler banner message + --namespace Sets default namespace instead of "global" + --globalclass Sets default global class instead of "" + --import Provides path to assemblies which would be added as references automatically into resulting executable. + --corelib Sets path to CoreLib assembly + --runtime Sets path to Cesium C Runtime assembly + -O Set the optimization level + -W Enable warnings set + -D Define constants for preprocessor + --help Display this help screen. + --version Display version information. + value pos. 0 + */ + +public class CesiumCompile : Task +{ + [Required] public ITaskItem CompilerExe { get; set; } = null!; + [Required] public ITaskItem[] InputFiles { get; set; } = null!; + [Required] public ITaskItem OutputFile { get; set; } = null!; + + public string? Namespace { get; set; } + public string? Framework { get; set; } + public string? Architecture { get; set; } + public string? ModuleType { get; set; } + public ITaskItem? CoreLibPath { get; set; } + public ITaskItem? RuntimePath { get; set; } + public ITaskItem[] ImportItems { get; set; } = Array.Empty(); + public ITaskItem[] PreprocessorItems { get; set; } = Array.Empty(); + + [Output] public string? ResultingCommandLine { get; private set; } + + public override bool Execute() + { + if (!TryValidate(out var options) || options is null) + { + return false; + } + + var args = CollectCommandLineArguments(options); + var compilerProcess = new Process + { + StartInfo = + { + FileName = options.CompilerExe, + UseShellExecute = false, + } + }; + + foreach (var arg in args) + { + compilerProcess.StartInfo.ArgumentList.Add(arg); + } + + compilerProcess.Start(); + compilerProcess.WaitForExit(); + + return true; + } + + private static (bool, FrameworkKind?) TryParseFramework(string? framework) => framework switch + { + null => (true, null), + nameof(FrameworkKind.Net) => (true, FrameworkKind.Net), + nameof(FrameworkKind.NetFramework) => (true, FrameworkKind.NetFramework), + nameof(FrameworkKind.NetStandard) => (true, FrameworkKind.NetStandard), + _ => (false, null) + }; + + private static (bool, ArchitectureKind?) TryParseArchitectureKind(string? archKind) => archKind switch + { + null => (true, null), + nameof(ArchitectureKind.Dynamic) => (true, ArchitectureKind.Dynamic), + nameof(ArchitectureKind.Bit32) => (true, ArchitectureKind.Bit32), + nameof(ArchitectureKind.Bit64) => (true, ArchitectureKind.Bit64), + _ => (false, null) + }; + + private static (bool, ModuleKind?) TryParseModuleKind(string? moduleKind) => moduleKind switch + { + null => (true, null), + nameof(ModuleKind.Dll) => (true, ModuleKind.Dll), + nameof(ModuleKind.Console) => (true, ModuleKind.Console), + nameof(ModuleKind.Windows) => (true, ModuleKind.Windows), + nameof(ModuleKind.NetModule) => (true, ModuleKind.NetModule), + _ => (false, null) + }; + + private bool TryValidate(out ValidatedOptions? options) + { + options = null; + var success = true; + + + if (!string.IsNullOrWhiteSpace(CompilerExe.ItemSpec) && !File.Exists(CompilerExe.ItemSpec)) + { + ReportValidationError("CES1000", $"Compiler executable doesn't exist under path '{CompilerExe?.ItemSpec}'"); + success = false; + } + + var (isFrameworkValid, framework) = TryParseFramework(Framework); + if (!isFrameworkValid) + { + var validValues = Enum.GetValues().Select(kind => kind.ToString()); + ReportValidationError("CES1004", $"Framework should be in range: '{string.Join(", ", validValues)}'"); + success = false; + } + + var (isArchValid, arch) = TryParseArchitectureKind(Architecture); + if (!isArchValid) + { + var validValues = Enum.GetValues().Select(kind => kind.ToString()); + ReportValidationError("CES1005", $"Architecture should be in range: '{string.Join(", ", validValues)}'"); + success = false; + } + + var (isModuleKindValid, moduleKind) = TryParseModuleKind(ModuleType); + if (!isModuleKindValid) + { + var validValues = Enum.GetValues().Select(kind => kind.ToString()); + ReportValidationError("CES1006", $"ModuleKind should be in range: '{string.Join(", ", validValues)}'"); + success = false; + } + + var missingCompileItems = InputFiles.Where(item => !File.Exists(item.ItemSpec)).ToList(); + foreach (var item in missingCompileItems) + { + ReportValidationError("CES1001", $"Source file doesn't exist: '{item.ItemSpec}'"); + success = false; + } + + if (!string.IsNullOrWhiteSpace(CoreLibPath?.ItemSpec) && !File.Exists(CoreLibPath.ItemSpec)) + { + ReportValidationError("CES1002", $"CorLib doesn't exist under path '{CoreLibPath?.ItemSpec}'"); + success = false; + } + + if (!string.IsNullOrWhiteSpace(RuntimePath?.ItemSpec) && !File.Exists(RuntimePath.ItemSpec)) + { + ReportValidationError("CES1003", $"Cesium.Runtime doesn't exist under path '{RuntimePath.ItemSpec}'"); + success = false; + } + + var missingAssemblyImportItems = ImportItems.Where(item => !File.Exists(item.ItemSpec)).ToList(); + foreach (var item in missingAssemblyImportItems) + { + ReportValidationError("CES1001", $"Imported assembly doesn't exist: '{item.ItemSpec}'"); + success = false; + } + + if (!success) return false; + + options = new ValidatedOptions( + CompilerExe: CompilerExe?.ItemSpec ?? throw new UnreachableException(), + InputItems: InputFiles.Select(item => item.ItemSpec).ToArray(), + OutputFile: OutputFile?.ItemSpec ?? throw new UnreachableException(), + Namespace: Namespace, + Framework: framework, + Architecture: arch, + ModuleKind: moduleKind, + CoreLibPath: CoreLibPath?.ItemSpec, + RuntimePath: RuntimePath?.ItemSpec, + ImportItems: ImportItems.Select(item => item.ItemSpec).ToArray(), + PreprocessorItems: PreprocessorItems.Select(item => item.ItemSpec).ToArray() + ); + + return true; + } + + private IEnumerable CollectCommandLineArguments(ValidatedOptions options) + { + yield return options.CompilerExe; + yield return "--nologo"; + + if (options.Framework is { } framework) + { + yield return "--framework"; + yield return framework.ToString(); + } + + if (options.Architecture is { } arch) + { + yield return "--arch"; + yield return arch.ToString(); + } + + if (options.ModuleKind is { } moduleKind) + { + yield return "--modulekind"; + yield return moduleKind.ToString(); + } + + if (!string.IsNullOrWhiteSpace(options.Namespace)) + { + yield return "--namespace"; + yield return options.Namespace; + } + + foreach (var import in options.ImportItems) + { + yield return "--import"; + yield return import; + } + + if (!string.IsNullOrWhiteSpace(options.CoreLibPath)) + { + yield return "--corelib"; + yield return options.CoreLibPath; + } + + if (!string.IsNullOrWhiteSpace(options.RuntimePath)) + { + yield return "--runtime"; + yield return options.RuntimePath; + } + + foreach (var item in options.PreprocessorItems) + { + yield return "-D"; + yield return item; + } + + yield return "--out"; + yield return $"\"{options.OutputFile}\""; + + foreach (var input in options.InputItems) + { + yield return $"\"{input}\""; + } + } + + private void ReportValidationError(string code, string message) => + BuildEngine.LogErrorEvent(new BuildErrorEventArgs(nameof(CesiumCompile), code, string.Empty, -1, -1, -1, -1, message, string.Empty, nameof(CesiumCompile))); + + private void ReportValidationWarning(string code, string message) => + BuildEngine.LogWarningEvent(new BuildWarningEventArgs(nameof(CesiumCompile), code, string.Empty, -1, -1, -1, -1, message, string.Empty, nameof(CesiumCompile))); + + private enum FrameworkKind + { + Net, + NetFramework, + NetStandard + } + + private enum ArchitectureKind + { + Dynamic, + Bit32, + Bit64 + } + + private enum ModuleKind + { + Dll, + Console, + Windows, + NetModule + } + + private record ValidatedOptions( + string CompilerExe, + string[] InputItems, + string OutputFile, + string? Namespace, + FrameworkKind? Framework, + ArchitectureKind? Architecture, + ModuleKind? ModuleKind, + string? CoreLibPath, + string? RuntimePath, + string[] ImportItems, + string[] PreprocessorItems + ); +} diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props new file mode 100644 index 00000000..75e230c7 --- /dev/null +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -0,0 +1,29 @@ + + + + false + + + + + + false + Cesium.Compiler + 0.0.1 + + + + + + + + $(PkgCesium_Compiler) + + $(CesiumCompilerPackagePath)/tools/$(CesiumCompilerPackageName).exe + $(CesiumCompilerPath) + + + diff --git a/Cesium.Sdk/Sdk/Sdk.targets b/Cesium.Sdk/Sdk/Sdk.targets new file mode 100644 index 00000000..ae975a00 --- /dev/null +++ b/Cesium.Sdk/Sdk/Sdk.targets @@ -0,0 +1,17 @@ + + + + + + + + <_CompilerOutput>@(IntermediateAssembly->'%(FullPath)') + + + + + + diff --git a/Cesium.sln b/Cesium.sln index c79a3a7f..4438fc39 100644 --- a/Cesium.sln +++ b/Cesium.sln @@ -79,6 +79,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "perform-common-steps", "per EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cesium.Core", "Cesium.Core\Cesium.Core.csproj", "{C83A5A9A-5667-4574-B75C-EFF38FA0FE79}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cesium.Sdk", "Cesium.Sdk\Cesium.Sdk.csproj", "{736A7F26-F507-48C5-BF48-3726EA2399CB}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cesium.Runtime.Tests", "Cesium.Runtime.Tests\Cesium.Runtime.Tests.csproj", "{526D8E61-6143-490F-BB9D-E7CD78512E55}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cesium.Compiler.Tests", "Cesium.Compiler.Tests\Cesium.Compiler.Tests.csproj", "{A5E33E79-E710-4F2F-838F-20CD0A3142F3}" @@ -147,6 +149,10 @@ Global {3AF6A395-8B9C-4E97-9036-B7C03A62EC9D}.Debug|Any CPU.Build.0 = Debug|Any CPU {3AF6A395-8B9C-4E97-9036-B7C03A62EC9D}.Release|Any CPU.ActiveCfg = Release|Any CPU {3AF6A395-8B9C-4E97-9036-B7C03A62EC9D}.Release|Any CPU.Build.0 = Release|Any CPU + {736A7F26-F507-48C5-BF48-3726EA2399CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {736A7F26-F507-48C5-BF48-3726EA2399CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {736A7F26-F507-48C5-BF48-3726EA2399CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {736A7F26-F507-48C5-BF48-3726EA2399CB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Directory.Build.props b/Directory.Build.props index 028e277e..654f70da 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -7,4 +7,7 @@ nullable 12.0 + + + diff --git a/nuget.config b/nuget.config new file mode 100644 index 00000000..6fd055e8 --- /dev/null +++ b/nuget.config @@ -0,0 +1,10 @@ + + + + + + + + + + From 8d4fbfa9b61332e5f7e4508bb4fedada7fd0fa15 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sat, 22 Jul 2023 20:28:26 +0200 Subject: [PATCH 011/103] Add dry-run option to CesiumCompile Introduced a "DryRun" boolean to the CesiumCompile class. This option, when set to true, prevents the compiler process from actually starting. This can be used for testing purposes or to verify command line arguments without performing a full compilation. --- Cesium.Sdk/CesiumCompile.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Cesium.Sdk/CesiumCompile.cs b/Cesium.Sdk/CesiumCompile.cs index 0f272959..06bd4dac 100644 --- a/Cesium.Sdk/CesiumCompile.cs +++ b/Cesium.Sdk/CesiumCompile.cs @@ -41,6 +41,7 @@ public class CesiumCompile : Task public ITaskItem? RuntimePath { get; set; } public ITaskItem[] ImportItems { get; set; } = Array.Empty(); public ITaskItem[] PreprocessorItems { get; set; } = Array.Empty(); + public bool DryRun = false; [Output] public string? ResultingCommandLine { get; private set; } @@ -66,8 +67,11 @@ public override bool Execute() compilerProcess.StartInfo.ArgumentList.Add(arg); } - compilerProcess.Start(); - compilerProcess.WaitForExit(); + if (!DryRun) + { + compilerProcess.Start(); + compilerProcess.WaitForExit(); + } return true; } From af9bb8424c243831a7b0eda9ef29d44c1e99a1b6 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 23 Jul 2023 02:14:30 +0200 Subject: [PATCH 012/103] Add CommandArgumentsBuilder for argument escaping --- Cesium.Sdk/CesiumCompile.cs | 19 +++++-- Cesium.Sdk/CommandArgumentsBuilder.cs | 80 +++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 Cesium.Sdk/CommandArgumentsBuilder.cs diff --git a/Cesium.Sdk/CesiumCompile.cs b/Cesium.Sdk/CesiumCompile.cs index 06bd4dac..ecba7eff 100644 --- a/Cesium.Sdk/CesiumCompile.cs +++ b/Cesium.Sdk/CesiumCompile.cs @@ -52,21 +52,23 @@ public override bool Execute() return false; } - var args = CollectCommandLineArguments(options); + var argumentsBuilder = new CommandArgumentsBuilder(); + foreach (var argument in CollectCommandLineArguments(options)) + { + argumentsBuilder.Argument(argument); + } + var compilerProcess = new Process { StartInfo = { FileName = options.CompilerExe, + Arguments = argumentsBuilder.Build(), UseShellExecute = false, } }; - foreach (var arg in args) - { - compilerProcess.StartInfo.ArgumentList.Add(arg); - } - + ResultingCommandLine = $"{compilerProcess.StartInfo.FileName} {compilerProcess.StartInfo.Arguments}"; if (!DryRun) { compilerProcess.Start(); @@ -253,6 +255,11 @@ private void ReportValidationError(string code, string message) => private void ReportValidationWarning(string code, string message) => BuildEngine.LogWarningEvent(new BuildWarningEventArgs(nameof(CesiumCompile), code, string.Empty, -1, -1, -1, -1, message, string.Empty, nameof(CesiumCompile))); + private string GetResultingCommandLine(string executable, IReadOnlyCollection arguments) + { + return $"{executable} {string.Join(" ", arguments)}"; + } + private enum FrameworkKind { Net, diff --git a/Cesium.Sdk/CommandArgumentsBuilder.cs b/Cesium.Sdk/CommandArgumentsBuilder.cs new file mode 100644 index 00000000..9de668d2 --- /dev/null +++ b/Cesium.Sdk/CommandArgumentsBuilder.cs @@ -0,0 +1,80 @@ +using System.Linq; +using System.Text; + +namespace Cesium.Sdk; + +// Implementation reference: +// https://github.com/Tyrrrz/CliWrap/blob/417aaffe171b9897799ed2a28a6467c11d69c296/CliWrap/Builders/ArgumentsBuilder.cs +// MIT License, Oleksii Holub +public class CommandArgumentsBuilder +{ + private StringBuilder _builder = new StringBuilder(); + + public CommandArgumentsBuilder Argument(string argument) + { + _builder.Append(" "); + if (NeedsEscaping(argument)) + { + argument = Escape(argument); + } + _builder.Append(argument); + + return this; + } + + public string Build() => _builder.ToString(); + + private bool NeedsEscaping(string argument) => + argument.Length > 0 && argument.All(c => !char.IsWhiteSpace(c) && c != '"'); + + private static string Escape(string argument) + { + var buffer = new StringBuilder(); + + buffer.Append('"'); + + for (var i = 0; i < argument.Length;) + { + var c = argument[i++]; + + if (c == '\\') + { + var backslashCount = 1; + while (i < argument.Length && argument[i] == '\\') + { + backslashCount++; + i++; + } + + if (i == argument.Length) + { + buffer.Append('\\', backslashCount * 2); + } + else if (argument[i] == '"') + { + buffer + .Append('\\', backslashCount * 2 + 1) + .Append('"'); + + i++; + } + else + { + buffer.Append('\\', backslashCount); + } + } + else if (c == '"') + { + buffer.Append('\\').Append('"'); + } + else + { + buffer.Append(c); + } + } + + buffer.Append('"'); + + return buffer.ToString(); + } +} From 21f2d969b72e22bfb0826ba95dfcdbdd25de2b3d Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 23 Jul 2023 02:26:53 +0200 Subject: [PATCH 013/103] SDK: Start writing tests --- Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj | 26 +++++++++++++++++++ Cesium.Sdk.Tests/CesiumCompileTests.cs | 9 +++++++ .../TestProjects/ValidDefinition.msbuild | 6 +++++ Cesium.Sdk.Tests/Usings.cs | 1 + Cesium.sln | 6 +++++ 5 files changed, 48 insertions(+) create mode 100644 Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj create mode 100644 Cesium.Sdk.Tests/CesiumCompileTests.cs create mode 100644 Cesium.Sdk.Tests/TestProjects/ValidDefinition.msbuild create mode 100644 Cesium.Sdk.Tests/Usings.cs diff --git a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj new file mode 100644 index 00000000..d21167ef --- /dev/null +++ b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj @@ -0,0 +1,26 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + diff --git a/Cesium.Sdk.Tests/CesiumCompileTests.cs b/Cesium.Sdk.Tests/CesiumCompileTests.cs new file mode 100644 index 00000000..9c69a330 --- /dev/null +++ b/Cesium.Sdk.Tests/CesiumCompileTests.cs @@ -0,0 +1,9 @@ +namespace Cesium.Sdk.Tests; + +public class CesiumCompileTests +{ + [Fact] + public void Test1() + { + } +} diff --git a/Cesium.Sdk.Tests/TestProjects/ValidDefinition.msbuild b/Cesium.Sdk.Tests/TestProjects/ValidDefinition.msbuild new file mode 100644 index 00000000..32f34ae7 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/ValidDefinition.msbuild @@ -0,0 +1,6 @@ +namespace Cesium.Sdk.Tests.TestProjects; + +public class ValidDefinition_msbuild +{ + +} diff --git a/Cesium.Sdk.Tests/Usings.cs b/Cesium.Sdk.Tests/Usings.cs new file mode 100644 index 00000000..c802f448 --- /dev/null +++ b/Cesium.Sdk.Tests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; diff --git a/Cesium.sln b/Cesium.sln index 4438fc39..cd79cd1f 100644 --- a/Cesium.sln +++ b/Cesium.sln @@ -87,6 +87,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cesium.Compiler.Tests", "Ce EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cesium.TestFramework.Tests", "Cesium.TestFramework.Tests\Cesium.TestFramework.Tests.csproj", "{3AF6A395-8B9C-4E97-9036-B7C03A62EC9D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cesium.Sdk.Tests", "Cesium.Sdk.Tests\Cesium.Sdk.Tests.csproj", "{02C764E4-41C6-4E73-AD93-F3DD3E1E9630}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -153,6 +155,10 @@ Global {736A7F26-F507-48C5-BF48-3726EA2399CB}.Debug|Any CPU.Build.0 = Debug|Any CPU {736A7F26-F507-48C5-BF48-3726EA2399CB}.Release|Any CPU.ActiveCfg = Release|Any CPU {736A7F26-F507-48C5-BF48-3726EA2399CB}.Release|Any CPU.Build.0 = Release|Any CPU + {02C764E4-41C6-4E73-AD93-F3DD3E1E9630}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {02C764E4-41C6-4E73-AD93-F3DD3E1E9630}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02C764E4-41C6-4E73-AD93-F3DD3E1E9630}.Release|Any CPU.ActiveCfg = Release|Any CPU + {02C764E4-41C6-4E73-AD93-F3DD3E1E9630}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 1a62281f6eef4bba141ddfcad3e195da65c4ad93 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 17 Dec 2023 04:22:20 +0100 Subject: [PATCH 014/103] SDK: Propagate solution metadata from MSBuild, add test base --- Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj | 10 ++ Cesium.Sdk.Tests/CesiumCompileTests.cs | 12 +- Cesium.Sdk.Tests/SdkTestBase.cs | 170 ++++++++++++++++++ .../SimpleProject/SimpleProject.ceproj | 9 + .../TestProjects/SimpleProject/hello.c | 7 + .../TestProjects/ValidDefinition.msbuild | 6 - Cesium.Sdk/Cesium.Sdk.csproj | 4 +- Cesium.Sdk/TestTargets.targets | 10 ++ .../Cesium.Solution.Metadata.csproj | 16 ++ Cesium.Solution.Metadata/SolutionMetadata.cs | 14 ++ .../SolutionMetadataAttribute.cs | 13 ++ Cesium.sln | 6 + Directory.Build.props | 5 +- 13 files changed, 271 insertions(+), 11 deletions(-) create mode 100644 Cesium.Sdk.Tests/SdkTestBase.cs create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleProject/hello.c delete mode 100644 Cesium.Sdk.Tests/TestProjects/ValidDefinition.msbuild create mode 100644 Cesium.Sdk/TestTargets.targets create mode 100644 Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj create mode 100644 Cesium.Solution.Metadata/SolutionMetadata.cs create mode 100644 Cesium.Solution.Metadata/SolutionMetadataAttribute.cs diff --git a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj index d21167ef..12e140f4 100644 --- a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj +++ b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj @@ -10,6 +10,9 @@ + + + @@ -22,5 +25,12 @@ + + + + + + + diff --git a/Cesium.Sdk.Tests/CesiumCompileTests.cs b/Cesium.Sdk.Tests/CesiumCompileTests.cs index 9c69a330..b7d0f2cf 100644 --- a/Cesium.Sdk.Tests/CesiumCompileTests.cs +++ b/Cesium.Sdk.Tests/CesiumCompileTests.cs @@ -1,9 +1,15 @@ +using Xunit.Abstractions; + namespace Cesium.Sdk.Tests; -public class CesiumCompileTests +public class CesiumCompileTests : SdkTestBase { - [Fact] - public void Test1() + // [Theory] + // [InlineData()] + // public void CesiumCompile_ShouldSucceed(string projectPath) + // { + // } + public CesiumCompileTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } } diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs new file mode 100644 index 00000000..7ae43473 --- /dev/null +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -0,0 +1,170 @@ +using System.Reflection; +using Cesium.Solution.Metadata; +using Microsoft.Build.Execution; +using Microsoft.Build.Framework; +using Xunit.Abstractions; + +namespace Cesium.Sdk.Tests; + +public abstract class SdkTestBase +{ + private readonly ITestOutputHelper _testOutputHelper; + private readonly string _temporaryPath = Path.GetTempFileName(); + + public SdkTestBase(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + + File.Delete(_temporaryPath); + + _testOutputHelper.WriteLine($"Test projects folder: {_temporaryPath}"); + + var assemblyPath = Assembly.GetExecutingAssembly().Location; + var testDataPath = Path.Combine(Path.GetDirectoryName(assemblyPath)!, "TestProjects"); + CopyDirectoryRecursive(testDataPath, _temporaryPath); + + var nupkgPath = Path.GetFullPath(Path.Combine(SolutionMetadata.SourceRoot, "artifacts", "package", "debug")); + EmitNuGetConfig(Path.Combine(_temporaryPath, "NuGet.config"), nupkgPath); + EmitGlobalJson(Path.Combine(_temporaryPath, "global.json"), $"{SolutionMetadata.VersionPrefix}-dev"); + } + + protected BuildResult ExecuteTargets(string projectFile, params string[] targets) + { + var projectInstance = new ProjectInstance(projectFile); + var request = new BuildRequestData(projectInstance, targets); + var parameters = new BuildParameters + { + Loggers = new []{ new TestOutputLogger(_testOutputHelper) } + }; + var result = BuildManager.DefaultBuildManager.Build(parameters, request); + return result; + } + + private static void EmitNuGetConfig(string configFilePath, string packageSourcePath) + { + File.WriteAllText(configFilePath, $@" + + + + + + + +"); + } + + private static void EmitGlobalJson(string globalJsonPath, string packageVersion) + { + File.WriteAllText(globalJsonPath, $@"{{ + ""msbuild-sdks"": {{ + ""Cesium.Sdk"" : ""{packageVersion}"" + }} +}} +"); + } + + private static void CopyDirectoryRecursive(string source, string target) + { + Directory.CreateDirectory(target); + + foreach (var subDirPath in Directory.GetDirectories(source)) + { + var dirName = Path.GetFileName(subDirPath); + CopyDirectoryRecursive(subDirPath, Path.Combine(target, dirName)); + } + + foreach (var filePath in Directory.GetFiles(source)) + { + var fileName = Path.GetFileName(filePath); + File.Copy(filePath, Path.Combine(target, fileName)); + } + } + + private class TestOutputLogger : ILogger + { + public LoggerVerbosity Verbosity { get; set; } = LoggerVerbosity.Normal; + public string Parameters { get; set; } = string.Empty; + + private readonly ITestOutputHelper _testOutputHelper; + + public TestOutputLogger(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + + public void Initialize(IEventSource eventSource) + { + eventSource.AnyEventRaised += HandleEvent; + } + + public void Shutdown() + { + } + + private void HandleEvent(object sender, BuildEventArgs args) + { + var entry = args switch + { + TargetFinishedEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.TargetFinished, args.Message), + TargetStartedEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.TargetStarted, args.Message), + TaskFinishedEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.TaskFinished, args.Message), + TaskStartedEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.TaskStarted, args.Message), + BuildFinishedEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.BuildFinished, args.Message), + BuildStartedEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.BuildStarted, args.Message), + CustomBuildEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.CustomEventRaised, args.Message), + BuildErrorEventArgs => + new BuildLogEntry(BuildLogLevel.Error, BuildLogKind.ErrorRaised, args.Message), + BuildMessageEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.MessageRaised, args.Message), + ProjectFinishedEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.ProjectFinished, args.Message), + ProjectStartedEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.ProjectStarted, args.Message), + BuildStatusEventArgs => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.StatusEventRaised, args.Message), + BuildWarningEventArgs => + new BuildLogEntry(BuildLogLevel.Warning, BuildLogKind.WarningRaised, args.Message), + var other => + new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.AnyEventRaised, other.Message) + }; + + _testOutputHelper.WriteLine($"[{entry.Level.ToString()}]: {entry.Message}"); + } + } + + protected enum BuildLogLevel + { + Error, + Warning, + Info, + Verbose, + Trace, + } + + protected enum BuildLogKind + { + AnyEventRaised, + BuildFinished, + BuildStarted, + CustomEventRaised, + ErrorRaised, + MessageRaised, + ProjectFinished, + ProjectStarted, + StatusEventRaised, + TargetFinished, + TargetStarted, + TaskFinished, + TaskStarted, + WarningRaised + } + + protected record BuildLogEntry(BuildLogLevel Level, BuildLogKind Kind, string? Message); +} diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj new file mode 100644 index 00000000..805b6d58 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleProject/hello.c b/Cesium.Sdk.Tests/TestProjects/SimpleProject/hello.c new file mode 100644 index 00000000..2889672e --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleProject/hello.c @@ -0,0 +1,7 @@ +#include + +int main(int argc, char *argv[]) +{ + puts("Hello, world!"); + return 42; +} diff --git a/Cesium.Sdk.Tests/TestProjects/ValidDefinition.msbuild b/Cesium.Sdk.Tests/TestProjects/ValidDefinition.msbuild deleted file mode 100644 index 32f34ae7..00000000 --- a/Cesium.Sdk.Tests/TestProjects/ValidDefinition.msbuild +++ /dev/null @@ -1,6 +0,0 @@ -namespace Cesium.Sdk.Tests.TestProjects; - -public class ValidDefinition_msbuild -{ - -} diff --git a/Cesium.Sdk/Cesium.Sdk.csproj b/Cesium.Sdk/Cesium.Sdk.csproj index e4aea2c6..488e616a 100644 --- a/Cesium.Sdk/Cesium.Sdk.csproj +++ b/Cesium.Sdk/Cesium.Sdk.csproj @@ -11,9 +11,11 @@ - + + + diff --git a/Cesium.Sdk/TestTargets.targets b/Cesium.Sdk/TestTargets.targets new file mode 100644 index 00000000..fcddc5d8 --- /dev/null +++ b/Cesium.Sdk/TestTargets.targets @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj b/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj new file mode 100644 index 00000000..d31b65b1 --- /dev/null +++ b/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj @@ -0,0 +1,16 @@ + + + + net7.0 + enable + enable + + + + + <_Parameter1>$(CesiumSourceRoot) + <_Parameter2>$(VersionPrefix) + + + + diff --git a/Cesium.Solution.Metadata/SolutionMetadata.cs b/Cesium.Solution.Metadata/SolutionMetadata.cs new file mode 100644 index 00000000..050e2fd9 --- /dev/null +++ b/Cesium.Solution.Metadata/SolutionMetadata.cs @@ -0,0 +1,14 @@ +using System.Reflection; + +namespace Cesium.Solution.Metadata; + +public static class SolutionMetadata +{ + public static string SourceRoot => + Assembly.GetExecutingAssembly().GetCustomAttribute()?.SourceRoot + ?? throw new Exception($"Missing {nameof(SolutionMetadataAttribute)} metadata attribute."); + + public static string VersionPrefix => + Assembly.GetExecutingAssembly().GetCustomAttribute()?.VersionPrefix + ?? throw new Exception($"Missing {nameof(SolutionMetadataAttribute)} metadata attribute."); +} diff --git a/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs b/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs new file mode 100644 index 00000000..baa923e0 --- /dev/null +++ b/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs @@ -0,0 +1,13 @@ +namespace Cesium.Solution.Metadata; + +public class SolutionMetadataAttribute : Attribute +{ + public string SourceRoot { get; } + public string VersionPrefix { get; } + + public SolutionMetadataAttribute(string sourceRoot, string versionPrefix) + { + SourceRoot = sourceRoot; + VersionPrefix = versionPrefix; + } +} diff --git a/Cesium.sln b/Cesium.sln index cd79cd1f..aa9b32ee 100644 --- a/Cesium.sln +++ b/Cesium.sln @@ -89,6 +89,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cesium.TestFramework.Tests" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cesium.Sdk.Tests", "Cesium.Sdk.Tests\Cesium.Sdk.Tests.csproj", "{02C764E4-41C6-4E73-AD93-F3DD3E1E9630}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cesium.Solution.Metadata", "Cesium.Solution.Metadata\Cesium.Solution.Metadata.csproj", "{5B59ADD9-5C9D-482C-B238-F5EFD5E1F7CF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -159,6 +161,10 @@ Global {02C764E4-41C6-4E73-AD93-F3DD3E1E9630}.Debug|Any CPU.Build.0 = Debug|Any CPU {02C764E4-41C6-4E73-AD93-F3DD3E1E9630}.Release|Any CPU.ActiveCfg = Release|Any CPU {02C764E4-41C6-4E73-AD93-F3DD3E1E9630}.Release|Any CPU.Build.0 = Release|Any CPU + {5B59ADD9-5C9D-482C-B238-F5EFD5E1F7CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B59ADD9-5C9D-482C-B238-F5EFD5E1F7CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B59ADD9-5C9D-482C-B238-F5EFD5E1F7CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B59ADD9-5C9D-482C-B238-F5EFD5E1F7CF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Directory.Build.props b/Directory.Build.props index 654f70da..295e76e8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -8,6 +8,9 @@ 12.0 - + true + + + $(MSBuildThisFileDirectory) From f4def2adf24b8202a175c2aae02634f0aa760071 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Mon, 18 Dec 2023 05:02:07 +0100 Subject: [PATCH 015/103] SDK: WIP --- .../SimpleProject/SimpleProject.ceproj | 4 --- Cesium.Sdk/CesiumCompile.cs | 29 ++++++++++--------- Cesium.Sdk/Sdk/Sdk.props | 16 ++++++---- Cesium.Sdk/Sdk/Sdk.targets | 18 +++++++++++- 4 files changed, 43 insertions(+), 24 deletions(-) diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj index 805b6d58..b602a5a0 100644 --- a/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj +++ b/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj @@ -2,8 +2,4 @@ - - - - diff --git a/Cesium.Sdk/CesiumCompile.cs b/Cesium.Sdk/CesiumCompile.cs index ecba7eff..e2b077a7 100644 --- a/Cesium.Sdk/CesiumCompile.cs +++ b/Cesium.Sdk/CesiumCompile.cs @@ -27,18 +27,19 @@ namespace Cesium.Sdk; value pos. 0 */ +// ReSharper disable once UnusedType.Global public class CesiumCompile : Task { - [Required] public ITaskItem CompilerExe { get; set; } = null!; + [Required] public string CompilerExe { get; set; } = null!; [Required] public ITaskItem[] InputFiles { get; set; } = null!; - [Required] public ITaskItem OutputFile { get; set; } = null!; + [Required] public string OutputFile { get; set; } = null!; public string? Namespace { get; set; } public string? Framework { get; set; } public string? Architecture { get; set; } public string? ModuleType { get; set; } - public ITaskItem? CoreLibPath { get; set; } - public ITaskItem? RuntimePath { get; set; } + public string? CoreLibPath { get; set; } + public string? RuntimePath { get; set; } public ITaskItem[] ImportItems { get; set; } = Array.Empty(); public ITaskItem[] PreprocessorItems { get; set; } = Array.Empty(); public bool DryRun = false; @@ -112,9 +113,9 @@ private bool TryValidate(out ValidatedOptions? options) var success = true; - if (!string.IsNullOrWhiteSpace(CompilerExe.ItemSpec) && !File.Exists(CompilerExe.ItemSpec)) + if (!string.IsNullOrWhiteSpace(CompilerExe) && !File.Exists(CompilerExe)) { - ReportValidationError("CES1000", $"Compiler executable doesn't exist under path '{CompilerExe?.ItemSpec}'"); + ReportValidationError("CES1000", $"Compiler executable doesn't exist under path '{CompilerExe}'"); success = false; } @@ -149,15 +150,15 @@ private bool TryValidate(out ValidatedOptions? options) success = false; } - if (!string.IsNullOrWhiteSpace(CoreLibPath?.ItemSpec) && !File.Exists(CoreLibPath.ItemSpec)) + if (!string.IsNullOrWhiteSpace(CoreLibPath) && !File.Exists(CoreLibPath)) { - ReportValidationError("CES1002", $"CorLib doesn't exist under path '{CoreLibPath?.ItemSpec}'"); + ReportValidationError("CES1002", $"CorLib doesn't exist under path '{CoreLibPath}'"); success = false; } - if (!string.IsNullOrWhiteSpace(RuntimePath?.ItemSpec) && !File.Exists(RuntimePath.ItemSpec)) + if (!string.IsNullOrWhiteSpace(RuntimePath) && !File.Exists(RuntimePath)) { - ReportValidationError("CES1003", $"Cesium.Runtime doesn't exist under path '{RuntimePath.ItemSpec}'"); + ReportValidationError("CES1003", $"Cesium.Runtime doesn't exist under path '{RuntimePath}'"); success = false; } @@ -171,15 +172,15 @@ private bool TryValidate(out ValidatedOptions? options) if (!success) return false; options = new ValidatedOptions( - CompilerExe: CompilerExe?.ItemSpec ?? throw new UnreachableException(), + CompilerExe: CompilerExe ?? throw new UnreachableException(), InputItems: InputFiles.Select(item => item.ItemSpec).ToArray(), - OutputFile: OutputFile?.ItemSpec ?? throw new UnreachableException(), + OutputFile: OutputFile ?? throw new UnreachableException(), Namespace: Namespace, Framework: framework, Architecture: arch, ModuleKind: moduleKind, - CoreLibPath: CoreLibPath?.ItemSpec, - RuntimePath: RuntimePath?.ItemSpec, + CoreLibPath: CoreLibPath, + RuntimePath: RuntimePath, ImportItems: ImportItems.Select(item => item.ItemSpec).ToArray(), PreprocessorItems: PreprocessorItems.Select(item => item.ItemSpec).ToArray() ); diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index 75e230c7..3cd7c85c 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -9,21 +9,27 @@ false Cesium.Compiler - 0.0.1 + $(VersionPrefix) $(PkgCesium_Compiler) - - $(CesiumCompilerPackagePath)/tools/$(CesiumCompilerPackageName).exe - $(CesiumCompilerPath) + + $(CesiumCompilerPackagePath)/tools/$(CesiumCompilerPackageName) + + + $(CesiumCompilerPackagePath)/tools/$(CesiumCompilerPackageName).exe + + + diff --git a/Cesium.Sdk/Sdk/Sdk.targets b/Cesium.Sdk/Sdk/Sdk.targets index ae975a00..9a2b00e3 100644 --- a/Cesium.Sdk/Sdk/Sdk.targets +++ b/Cesium.Sdk/Sdk/Sdk.targets @@ -7,9 +7,25 @@ Outputs="@(IntermediateAssembly)"> - <_CompilerOutput>@(IntermediateAssembly->'%(FullPath)') + <_CompilerOutput>$(OutDir)$(AssemblyName) + + + From 601aafb21f80236d94a154d7259fa27f66a9cddd Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Wed, 20 Dec 2023 22:44:38 +0100 Subject: [PATCH 016/103] Use .NET 8 across the solution & toolset --- .github/workflows/perform-common-steps/action.yml | 4 ++-- Cesium.Ast/Cesium.Ast.csproj | 2 +- Cesium.Core/Cesium.Core.csproj | 2 +- Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj | 2 +- Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj | 2 +- global.json | 7 +++++++ 6 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 global.json diff --git a/.github/workflows/perform-common-steps/action.yml b/.github/workflows/perform-common-steps/action.yml index a9ba89e9..fdf54aa2 100644 --- a/.github/workflows/perform-common-steps/action.yml +++ b/.github/workflows/perform-common-steps/action.yml @@ -4,9 +4,9 @@ runs: using: "composite" steps: - name: ⚙ Setup .NET SDK ⚙ - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: - dotnet-version: '8.0.x' + global-json-file: global.json - name: ♻ NuGet Cache ♻ uses: actions/cache@v2 diff --git a/Cesium.Ast/Cesium.Ast.csproj b/Cesium.Ast/Cesium.Ast.csproj index fdc5611d..d2fdb902 100644 --- a/Cesium.Ast/Cesium.Ast.csproj +++ b/Cesium.Ast/Cesium.Ast.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable true diff --git a/Cesium.Core/Cesium.Core.csproj b/Cesium.Core/Cesium.Core.csproj index aa68acee..7d989800 100644 --- a/Cesium.Core/Cesium.Core.csproj +++ b/Cesium.Core/Cesium.Core.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable enable diff --git a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj index 12e140f4..fad9a01e 100644 --- a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj +++ b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable enable diff --git a/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj b/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj index d31b65b1..611eacd4 100644 --- a/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj +++ b/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable enable diff --git a/global.json b/global.json new file mode 100644 index 00000000..c65c9eac --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "8.0.0", + "rollForward": "latestMinor", + "allowPrerelease": true + } +} \ No newline at end of file From cb9a4463624dda0e8b5571b1f1ec7838b824f523 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Thu, 21 Dec 2023 04:18:42 +0100 Subject: [PATCH 017/103] SDK: WIP --- Cesium.Sdk.Tests/CesiumCompileTests.cs | 15 +- Cesium.Sdk.Tests/SdkTestBase.cs | 203 ++++++++---------- Cesium.Sdk/Cesium.Sdk.csproj | 1 + Cesium.Sdk/Sdk/Sdk.props | 2 +- .../Cesium.Solution.Metadata.csproj | 1 + Cesium.Solution.Metadata/SolutionMetadata.cs | 9 +- 6 files changed, 107 insertions(+), 124 deletions(-) diff --git a/Cesium.Sdk.Tests/CesiumCompileTests.cs b/Cesium.Sdk.Tests/CesiumCompileTests.cs index b7d0f2cf..3ef1f753 100644 --- a/Cesium.Sdk.Tests/CesiumCompileTests.cs +++ b/Cesium.Sdk.Tests/CesiumCompileTests.cs @@ -2,14 +2,15 @@ namespace Cesium.Sdk.Tests; -public class CesiumCompileTests : SdkTestBase +public class CesiumCompileTests(ITestOutputHelper testOutputHelper) : SdkTestBase(testOutputHelper) { - // [Theory] - // [InlineData()] - // public void CesiumCompile_ShouldSucceed(string projectPath) - // { - // } - public CesiumCompileTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) + [Theory] + [InlineData("SimpleProject")] + public void CesiumCompile_ShouldSucceed(string projectName) { + var result = ExecuteTargets(projectName, "Build"); + + Assert.True(result.ExitCode == 0); + ClearOutput(); } } diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index 7ae43473..d28995b3 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -1,7 +1,6 @@ +using System.Diagnostics; using System.Reflection; using Cesium.Solution.Metadata; -using Microsoft.Build.Execution; -using Microsoft.Build.Framework; using Xunit.Abstractions; namespace Cesium.Sdk.Tests; @@ -9,7 +8,10 @@ namespace Cesium.Sdk.Tests; public abstract class SdkTestBase { private readonly ITestOutputHelper _testOutputHelper; - private readonly string _temporaryPath = Path.GetTempFileName(); + private readonly string _temporaryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + + protected string NuGetConfigPath => Path.Combine(_temporaryPath, "NuGet.config"); + protected string GlobalJsonPath => Path.Combine(_temporaryPath, "global.json"); public SdkTestBase(ITestOutputHelper testOutputHelper) { @@ -21,46 +23,103 @@ public SdkTestBase(ITestOutputHelper testOutputHelper) var assemblyPath = Assembly.GetExecutingAssembly().Location; var testDataPath = Path.Combine(Path.GetDirectoryName(assemblyPath)!, "TestProjects"); + _testOutputHelper.WriteLine($"Copying TestProjects to {_temporaryPath}..."); CopyDirectoryRecursive(testDataPath, _temporaryPath); var nupkgPath = Path.GetFullPath(Path.Combine(SolutionMetadata.SourceRoot, "artifacts", "package", "debug")); - EmitNuGetConfig(Path.Combine(_temporaryPath, "NuGet.config"), nupkgPath); - EmitGlobalJson(Path.Combine(_temporaryPath, "global.json"), $"{SolutionMetadata.VersionPrefix}-dev"); + _testOutputHelper.WriteLine($"Local NuGet feed: {nupkgPath}."); + EmitNuGetConfig(NuGetConfigPath, nupkgPath); + EmitGlobalJson(GlobalJsonPath, $"{SolutionMetadata.VersionPrefix}"); } - protected BuildResult ExecuteTargets(string projectFile, params string[] targets) + protected BuildResult ExecuteTargets(string projectName, params string[] targets) { - var projectInstance = new ProjectInstance(projectFile); - var request = new BuildRequestData(projectInstance, targets); - var parameters = new BuildParameters + var projectFile = $"{projectName}/{projectName}.ceproj"; + var joinedTargets = string.Join(";", targets); + var testProjectFile = Path.GetFullPath(Path.Combine(_temporaryPath, projectFile)); + var testProjectFolder = Path.GetDirectoryName(testProjectFile) ?? throw new ArgumentNullException(nameof(testProjectFile)); + var startInfo = new ProcessStartInfo + { + WorkingDirectory = testProjectFolder, + FileName = "dotnet", + Arguments = $"build \"{testProjectFile}\" -t:{joinedTargets} -v:d /bl:build_result.binlog", + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true, + UseShellExecute = false, + }; + + using var process = new Process(); + process.StartInfo = startInfo; + + process.OutputDataReceived += (sender, e) => { - Loggers = new []{ new TestOutputLogger(_testOutputHelper) } + if (!string.IsNullOrEmpty(e.Data)) + { + _testOutputHelper.WriteLine($"[stdout]: {e.Data}"); + } + }; + + process.ErrorDataReceived += (sender, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + { + _testOutputHelper.WriteLine($"[stderr]: {e.Data}"); + } }; - var result = BuildManager.DefaultBuildManager.Build(parameters, request); - return result; + + process.Start(); + + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + + process.WaitForExit(); + + var success = process.ExitCode == 0; + + _testOutputHelper.WriteLine(success + ? "Build succeeded" + : $"Build failed with exit code {process.ExitCode}"); + + var binFolder = Path.Combine(testProjectFolder, "bin"); + var objFolder = Path.Combine(testProjectFolder, "obj"); + + var binArtifacts = CollectArtifacts(binFolder); + var objArtifacts = CollectArtifacts(objFolder); + + return new BuildResult(process.ExitCode, binArtifacts, objArtifacts); + + IReadOnlyCollection CollectArtifacts(string folder) => + Directory.Exists(folder) + ? Directory.GetFiles(folder, "*.*", SearchOption.AllDirectories) + .Select(path => Path.GetRelativePath(folder, path)) + .ToList() + : Array.Empty(); } private static void EmitNuGetConfig(string configFilePath, string packageSourcePath) { - File.WriteAllText(configFilePath, $@" - - - - - - - -"); + File.WriteAllText(configFilePath, $""" + + + + + + + + + """); } private static void EmitGlobalJson(string globalJsonPath, string packageVersion) { - File.WriteAllText(globalJsonPath, $@"{{ - ""msbuild-sdks"": {{ - ""Cesium.Sdk"" : ""{packageVersion}"" - }} -}} -"); + File.WriteAllText(globalJsonPath, $$""" + { + "msbuild-sdks": { + "Cesium.Sdk" : "{{packageVersion}}" + } + } + """); } private static void CopyDirectoryRecursive(string source, string target) @@ -80,91 +139,13 @@ private static void CopyDirectoryRecursive(string source, string target) } } - private class TestOutputLogger : ILogger - { - public LoggerVerbosity Verbosity { get; set; } = LoggerVerbosity.Normal; - public string Parameters { get; set; } = string.Empty; - - private readonly ITestOutputHelper _testOutputHelper; - - public TestOutputLogger(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } - - public void Initialize(IEventSource eventSource) - { - eventSource.AnyEventRaised += HandleEvent; - } - - public void Shutdown() - { - } - - private void HandleEvent(object sender, BuildEventArgs args) - { - var entry = args switch - { - TargetFinishedEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.TargetFinished, args.Message), - TargetStartedEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.TargetStarted, args.Message), - TaskFinishedEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.TaskFinished, args.Message), - TaskStartedEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.TaskStarted, args.Message), - BuildFinishedEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.BuildFinished, args.Message), - BuildStartedEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.BuildStarted, args.Message), - CustomBuildEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.CustomEventRaised, args.Message), - BuildErrorEventArgs => - new BuildLogEntry(BuildLogLevel.Error, BuildLogKind.ErrorRaised, args.Message), - BuildMessageEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.MessageRaised, args.Message), - ProjectFinishedEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.ProjectFinished, args.Message), - ProjectStartedEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.ProjectStarted, args.Message), - BuildStatusEventArgs => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.StatusEventRaised, args.Message), - BuildWarningEventArgs => - new BuildLogEntry(BuildLogLevel.Warning, BuildLogKind.WarningRaised, args.Message), - var other => - new BuildLogEntry(BuildLogLevel.Info, BuildLogKind.AnyEventRaised, other.Message) - }; - - _testOutputHelper.WriteLine($"[{entry.Level.ToString()}]: {entry.Message}"); - } - } + protected record BuildResult( + int ExitCode, + IReadOnlyCollection OutputArtifacts, + IReadOnlyCollection IntermediateArtifacts); - protected enum BuildLogLevel + protected void ClearOutput() { - Error, - Warning, - Info, - Verbose, - Trace, + Directory.Delete(_temporaryPath, true); } - - protected enum BuildLogKind - { - AnyEventRaised, - BuildFinished, - BuildStarted, - CustomEventRaised, - ErrorRaised, - MessageRaised, - ProjectFinished, - ProjectStarted, - StatusEventRaised, - TargetFinished, - TargetStarted, - TaskFinished, - TaskStarted, - WarningRaised - } - - protected record BuildLogEntry(BuildLogLevel Level, BuildLogKind Kind, string? Message); } diff --git a/Cesium.Sdk/Cesium.Sdk.csproj b/Cesium.Sdk/Cesium.Sdk.csproj index 488e616a..e9bd74b4 100644 --- a/Cesium.Sdk/Cesium.Sdk.csproj +++ b/Cesium.Sdk/Cesium.Sdk.csproj @@ -10,6 +10,7 @@ + diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index 3cd7c85c..f140a64a 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -29,7 +29,7 @@ - diff --git a/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj b/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj index 611eacd4..b5708b55 100644 --- a/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj +++ b/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + false diff --git a/Cesium.Solution.Metadata/SolutionMetadata.cs b/Cesium.Solution.Metadata/SolutionMetadata.cs index 050e2fd9..9408ea60 100644 --- a/Cesium.Solution.Metadata/SolutionMetadata.cs +++ b/Cesium.Solution.Metadata/SolutionMetadata.cs @@ -4,11 +4,10 @@ namespace Cesium.Solution.Metadata; public static class SolutionMetadata { - public static string SourceRoot => - Assembly.GetExecutingAssembly().GetCustomAttribute()?.SourceRoot - ?? throw new Exception($"Missing {nameof(SolutionMetadataAttribute)} metadata attribute."); + public static string SourceRoot => ResolvedAttribute.SourceRoot; + public static string VersionPrefix => ResolvedAttribute.VersionPrefix; - public static string VersionPrefix => - Assembly.GetExecutingAssembly().GetCustomAttribute()?.VersionPrefix + private static SolutionMetadataAttribute ResolvedAttribute => + Assembly.GetExecutingAssembly().GetCustomAttribute() ?? throw new Exception($"Missing {nameof(SolutionMetadataAttribute)} metadata attribute."); } From 51e184e8b2dae45e96e22ce2bff9a51789f57702 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Fri, 22 Dec 2023 01:25:36 +0100 Subject: [PATCH 018/103] SDK: WIP --- Cesium.Compiler/Cesium.Compiler.csproj | 1 + Cesium.Sdk.Tests/SdkTestBase.cs | 2 +- .../SimpleProject/SimpleProject.ceproj | 5 +- Cesium.Sdk/Sdk/Sdk.props | 2 +- Cesium.Sdk/Sdk/Sdk.targets | 70 +++++++++++++++---- 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/Cesium.Compiler/Cesium.Compiler.csproj b/Cesium.Compiler/Cesium.Compiler.csproj index 979c81d9..5f2ffe93 100644 --- a/Cesium.Compiler/Cesium.Compiler.csproj +++ b/Cesium.Compiler/Cesium.Compiler.csproj @@ -8,6 +8,7 @@ true true Major + true diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index d28995b3..822acc7d 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -42,7 +42,7 @@ protected BuildResult ExecuteTargets(string projectName, params string[] targets { WorkingDirectory = testProjectFolder, FileName = "dotnet", - Arguments = $"build \"{testProjectFile}\" -t:{joinedTargets} -v:d /bl:build_result.binlog", + Arguments = $"build \"{testProjectFile}\" -t:{joinedTargets} -v:diag /bl:build_result.binlog", RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj index b602a5a0..33d22c64 100644 --- a/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj +++ b/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj @@ -1,5 +1,8 @@ + + net6.0 + - + diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index f140a64a..9671dca7 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -9,7 +9,7 @@ false Cesium.Compiler - $(VersionPrefix) + 0.0.1 diff --git a/Cesium.Sdk/Sdk/Sdk.targets b/Cesium.Sdk/Sdk/Sdk.targets index 9a2b00e3..030331fa 100644 --- a/Cesium.Sdk/Sdk/Sdk.targets +++ b/Cesium.Sdk/Sdk/Sdk.targets @@ -2,32 +2,72 @@ - + <_CesiumModuleKind Condition="'$(OutputType)' == 'Exe'">Console + <_CesiumModuleKind Condition="'$(OutputType)' == 'WinExe'">Windows + <_CesiumModuleKind Condition="'$(OutputType)' == 'Dll'">Library + + + + + + + + <_CesiumFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion)' == 'v6.0'">net6.0 + <_CesiumFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework' AND '$(TargetFrameworkVersion)' == 'v4.8'">net48 + <_CesiumFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard' AND '$(TargetFrameworkVersion)' == 'v2.0'">netstandard2.0 + + + + + + + + <_CesiumArchitecture Condition="'$(Platform)' == 'AnyCPU'">Dynamic + <_CesiumArchitecture Condition="'$(Platform)' == 'x64'">Bit64 + <_CesiumArchitecture Condition="'$(Platform)' == 'x86'">Bit32 + + + + + + + + <_CompilerOutput>$(OutDir)$(AssemblyName) + + + + + + Outputs="@(ResultingCommandLine)"> - - <_CompilerOutput>$(OutDir)$(AssemblyName) - + + + + + - From 20b7a7160db33a84a62402878b621485c8a9860a Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sat, 23 Dec 2023 04:17:07 +0100 Subject: [PATCH 019/103] SDK: Work on compiler cross-platform packing --- Cesium.Compiler/Cesium.Compiler.csproj | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/Cesium.Compiler/Cesium.Compiler.csproj b/Cesium.Compiler/Cesium.Compiler.csproj index 5f2ffe93..7092d027 100644 --- a/Cesium.Compiler/Cesium.Compiler.csproj +++ b/Cesium.Compiler/Cesium.Compiler.csproj @@ -4,11 +4,11 @@ Exe net8.0 enable - true + true true true Major - true + win-x64;win-x86;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64 @@ -38,8 +38,24 @@ + + + <_PublishRuntimeIdentifier Include="$(RuntimeIdentifiers)" /> + + + + + + + + <_PackRuntimeIdentifier Include="$(RuntimeIdentifiers)" /> + + + + + - + true tools false From 0d5862a9e30d4f6dee9ed3c2daef7c7f2d38a49b Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 24 Dec 2023 03:42:33 +0100 Subject: [PATCH 020/103] SDK: Introduce Nuke for unified compiler packs packaging --- .config/dotnet-tools.json | 12 +++ .gitignore | 3 + .nuke/build.schema.json | 114 +++++++++++++++++++++++++ .nuke/parameters.json | 4 + Cesium.Compiler/Cesium.Compiler.csproj | 24 ------ Cesium.sln | 4 + build.cmd | 7 ++ build.ps1 | 74 ++++++++++++++++ build.sh | 67 +++++++++++++++ build/.editorconfig | 11 +++ build/Build.Sdk.cs | 99 +++++++++++++++++++++ build/Build.cs | 56 ++++++++++++ build/Configuration.cs | 16 ++++ build/Directory.Build.props | 8 ++ build/Directory.Build.targets | 8 ++ build/_build.csproj | 24 ++++++ build/_build.csproj.DotSettings | 28 ++++++ 17 files changed, 535 insertions(+), 24 deletions(-) create mode 100644 .config/dotnet-tools.json create mode 100644 .nuke/build.schema.json create mode 100644 .nuke/parameters.json create mode 100755 build.cmd create mode 100644 build.ps1 create mode 100755 build.sh create mode 100644 build/.editorconfig create mode 100644 build/Build.Sdk.cs create mode 100644 build/Build.cs create mode 100644 build/Configuration.cs create mode 100644 build/Directory.Build.props create mode 100644 build/Directory.Build.targets create mode 100644 build/_build.csproj create mode 100644 build/_build.csproj.DotSettings diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 00000000..b5c92636 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "nuke.globaltool": { + "version": "7.0.6", + "commands": [ + "nuke" + ] + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index d7e0a87f..7794c572 100644 --- a/.gitignore +++ b/.gitignore @@ -4,9 +4,12 @@ bin/ obj/ artifacts/ +/.nuke/temp *.dll *.exe *.runtimeconfig.json *.received.txt *.user + + diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json new file mode 100644 index 00000000..60a3e9fc --- /dev/null +++ b/.nuke/build.schema.json @@ -0,0 +1,114 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/build", + "title": "Build Schema", + "definitions": { + "build": { + "type": "object", + "properties": { + "Configuration": { + "type": "string", + "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)", + "enum": [ + "Debug", + "Release" + ] + }, + "Continue": { + "type": "boolean", + "description": "Indicates to continue a previously failed build attempt" + }, + "Help": { + "type": "boolean", + "description": "Shows the help text for this build assembly" + }, + "Host": { + "type": "string", + "description": "Host for execution. Default is 'automatic'", + "enum": [ + "AppVeyor", + "AzurePipelines", + "Bamboo", + "Bitbucket", + "Bitrise", + "GitHubActions", + "GitLab", + "Jenkins", + "Rider", + "SpaceAutomation", + "TeamCity", + "Terminal", + "TravisCI", + "VisualStudio", + "VSCode" + ] + }, + "NoLogo": { + "type": "boolean", + "description": "Disables displaying the NUKE logo" + }, + "Partition": { + "type": "string", + "description": "Partition to use on CI" + }, + "Plan": { + "type": "boolean", + "description": "Shows the execution plan (HTML)" + }, + "Profile": { + "type": "array", + "description": "Defines the profiles to load", + "items": { + "type": "string" + } + }, + "Root": { + "type": "string", + "description": "Root directory during build execution" + }, + "Skip": { + "type": "array", + "description": "List of targets to be skipped. Empty list skips all dependencies", + "items": { + "type": "string", + "enum": [ + "Clean", + "Compile", + "PackCompilerPacks", + "PublishCompilerPacks", + "Restore" + ] + } + }, + "Solution": { + "type": "string", + "description": "Path to a solution file that is automatically loaded" + }, + "Target": { + "type": "array", + "description": "List of targets to be invoked. Default is '{default_target}'", + "items": { + "type": "string", + "enum": [ + "Clean", + "Compile", + "PackCompilerPacks", + "PublishCompilerPacks", + "Restore" + ] + } + }, + "Verbosity": { + "type": "string", + "description": "Logging verbosity during build execution. Default is 'Normal'", + "enum": [ + "Minimal", + "Normal", + "Quiet", + "Verbose" + ] + } + } + } + } +} diff --git a/.nuke/parameters.json b/.nuke/parameters.json new file mode 100644 index 00000000..45c2a69b --- /dev/null +++ b/.nuke/parameters.json @@ -0,0 +1,4 @@ +{ + "$schema": "./build.schema.json", + "Solution": "Cesium.sln" +} diff --git a/Cesium.Compiler/Cesium.Compiler.csproj b/Cesium.Compiler/Cesium.Compiler.csproj index 7092d027..67a17e10 100644 --- a/Cesium.Compiler/Cesium.Compiler.csproj +++ b/Cesium.Compiler/Cesium.Compiler.csproj @@ -38,28 +38,4 @@ - - - <_PublishRuntimeIdentifier Include="$(RuntimeIdentifiers)" /> - - - - - - - - <_PackRuntimeIdentifier Include="$(RuntimeIdentifiers)" /> - - - - - - - - true - tools - false - - - diff --git a/Cesium.sln b/Cesium.sln index aa9b32ee..af719a7a 100644 --- a/Cesium.sln +++ b/Cesium.sln @@ -91,12 +91,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cesium.Sdk.Tests", "Cesium. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cesium.Solution.Metadata", "Cesium.Solution.Metadata\Cesium.Solution.Metadata.csproj", "{5B59ADD9-5C9D-482C-B238-F5EFD5E1F7CF}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{05416E66-3615-4ABB-A130-F37EC18785A2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {05416E66-3615-4ABB-A130-F37EC18785A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05416E66-3615-4ABB-A130-F37EC18785A2}.Release|Any CPU.ActiveCfg = Release|Any CPU {B85C397C-1F36-4A27-AB36-D03F55AE1A89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B85C397C-1F36-4A27-AB36-D03F55AE1A89}.Debug|Any CPU.Build.0 = Debug|Any CPU {B85C397C-1F36-4A27-AB36-D03F55AE1A89}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/build.cmd b/build.cmd new file mode 100755 index 00000000..b08cc590 --- /dev/null +++ b/build.cmd @@ -0,0 +1,7 @@ +:; set -eo pipefail +:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) +:; ${SCRIPT_DIR}/build.sh "$@" +:; exit $? + +@ECHO OFF +powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %* diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 00000000..c0c0e612 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,74 @@ +[CmdletBinding()] +Param( + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$BuildArguments +) + +Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)" + +Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 } +$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent + +########################################################################### +# CONFIGURATION +########################################################################### + +$BuildProjectFile = "$PSScriptRoot\build\_build.csproj" +$TempDirectory = "$PSScriptRoot\\.nuke\temp" + +$DotNetGlobalFile = "$PSScriptRoot\\global.json" +$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1" +$DotNetChannel = "STS" + +$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1 +$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 +$env:DOTNET_MULTILEVEL_LOOKUP = 0 + +########################################################################### +# EXECUTION +########################################################################### + +function ExecSafe([scriptblock] $cmd) { + & $cmd + if ($LASTEXITCODE) { exit $LASTEXITCODE } +} + +# If dotnet CLI is installed globally and it matches requested version, use for execution +if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and ` + $(dotnet --version) -and $LASTEXITCODE -eq 0) { + $env:DOTNET_EXE = (Get-Command "dotnet").Path +} +else { + # Download install script + $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" + New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) + + # If global.json exists, load expected version + if (Test-Path $DotNetGlobalFile) { + $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json) + if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) { + $DotNetVersion = $DotNetGlobal.sdk.version + } + } + + # Install by channel or version + $DotNetDirectory = "$TempDirectory\dotnet-win" + if (!(Test-Path variable:DotNetVersion)) { + ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath } + } else { + ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } + } + $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe" +} + +Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)" + +if (Test-Path env:NUKE_ENTERPRISE_TOKEN) { + & $env:DOTNET_EXE nuget remove source "nuke-enterprise" > $null + & $env:DOTNET_EXE nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password $env:NUKE_ENTERPRISE_TOKEN > $null +} + +ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet } +ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments } diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..d4a7e51e --- /dev/null +++ b/build.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +bash --version 2>&1 | head -n 1 + +set -eo pipefail +SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) + +########################################################################### +# CONFIGURATION +########################################################################### + +BUILD_PROJECT_FILE="$SCRIPT_DIR/build/_build.csproj" +TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp" + +DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" +DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh" +DOTNET_CHANNEL="STS" + +export DOTNET_CLI_TELEMETRY_OPTOUT=1 +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 +export DOTNET_MULTILEVEL_LOOKUP=0 + +########################################################################### +# EXECUTION +########################################################################### + +function FirstJsonValue { + perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}" +} + +# If dotnet CLI is installed globally and it matches requested version, use for execution +if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then + export DOTNET_EXE="$(command -v dotnet)" +else + # Download install script + DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" + mkdir -p "$TEMP_DIRECTORY" + curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" + chmod +x "$DOTNET_INSTALL_FILE" + + # If global.json exists, load expected version + if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then + DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")") + if [[ "$DOTNET_VERSION" == "" ]]; then + unset DOTNET_VERSION + fi + fi + + # Install by channel or version + DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" + if [[ -z ${DOTNET_VERSION+x} ]]; then + "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path + else + "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path + fi + export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" +fi + +echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)" + +if [[ ! -z ${NUKE_ENTERPRISE_TOKEN+x} && "NUKE_ENTERPRISE_TOKEN" != "" ]]; then + "$DOTNET_EXE" nuget remove source "nuke-enterprise" &>/dev/null || true + "$DOTNET_EXE" nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password "$NUKE_ENTERPRISE_TOKEN" --store-password-in-clear-text &>/dev/null || true +fi + +"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet +"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@" diff --git a/build/.editorconfig b/build/.editorconfig new file mode 100644 index 00000000..31e43dcd --- /dev/null +++ b/build/.editorconfig @@ -0,0 +1,11 @@ +[*.cs] +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning +dotnet_style_require_accessibility_modifiers = never:warning + +csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_accessors = true:warning diff --git a/build/Build.Sdk.cs b/build/Build.Sdk.cs new file mode 100644 index 00000000..37ff062a --- /dev/null +++ b/build/Build.Sdk.cs @@ -0,0 +1,99 @@ +using System.Collections.Generic; +using System.IO; +using NuGet.Packaging; +using NuGet.Versioning; +using Nuke.Common; +using Nuke.Common.ProjectModel; +using Nuke.Common.Tools.DotNet; +using Serilog; +using static Nuke.Common.Tools.DotNet.DotNetTasks; +using Project = Microsoft.Build.Evaluation.Project; + +public partial class Build +{ + Target PublishCompilerPacks => _ => _ + .DependsOn(Compile) + .Executes(() => + { + var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); + var runtimeIds = compilerProject.GetProperty("RuntimeIdentifiers").EvaluatedValue.Split(";"); + Log.Information( + $"Runtime identifiers defined in {Solution.Cesium_Compiler.Name}: {string.Join(", ", runtimeIds)}"); + + foreach (var runtimeId in runtimeIds) + { + Log.Information($"Publishing for {runtimeId}..."); + DotNetPublish(o => o + .SetConfiguration(Configuration) + .SetProject(compilerProject.ProjectFileLocation.File) + .SetRuntime(runtimeId) + .SetOutput(GetCompilerRuntimePublishFolder(compilerProject, runtimeId)) + .EnableNoBuild() + .EnableNoRestore()); + } + }); + + Target PackCompilerPacks => _ => _ + .Executes(() => + { + var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); + var runtimeIds = compilerProject.GetProperty("RuntimeIdentifiers").EvaluatedValue.Split(";"); + Log.Information( + $"Runtime identifiers defined in {Solution.Cesium_Compiler.Name}: {string.Join(", ", runtimeIds)}"); + + foreach (var runtimeId in runtimeIds) + { + Log.Information($"Packing compiler for {runtimeId}..."); + EmitCompilerPack(runtimeId, compilerProject); + } + }); + + static void EmitCompilerPack(string runtimeId, Project compilerProject) + { + var packageId = $"Cesium.Compiler.Pack.{runtimeId}"; + var packageFile = $"{packageId}.nupkg"; + var publishDirectory = GetCompilerRuntimePublishFolder(compilerProject, runtimeId); + var publishedFiles = Directory.GetFiles(publishDirectory, "*.*", SearchOption.AllDirectories); + var packageOutputPath = compilerProject.GetProperty("PackageOutputPath").EvaluatedValue; + + Log.Debug($"Source publish directory: {publishDirectory}"); + Log.Debug($"Target package ID: {packageId}"); + Log.Debug($"Target package output directory: {packageOutputPath}"); + + var builder = new PackageBuilder + { + Id = packageId, + Version = NuGetVersion.Parse(compilerProject.GetProperty("VersionPrefix").EvaluatedValue), + Description = $"Cesium compiler native executable pack for {runtimeId} platform.", + Authors = { "Cesium Team" } + }; + builder.Files.AddRange(GetPhysicalFiles(publishDirectory, publishedFiles)); + + var packageFileName = Path.Combine(packageOutputPath, packageFile); + Log.Information($"Package is ready, saving to {packageFileName}..."); + Directory.CreateDirectory(packageOutputPath); + using var outputStream = new FileStream(packageFileName, FileMode.Create); + builder.Save(outputStream); + return; + + IEnumerable GetPhysicalFiles(string publishDirectory, IEnumerable filePaths) + { + foreach (var filePath in filePaths) + { + yield return new PhysicalPackageFile + { + SourcePath = filePath, + TargetPath = $"tools/{Path.GetRelativePath(publishDirectory, filePath)}" + }; + } + } + } + + static string GetCompilerRuntimePublishFolder(Project compilerProject, string runtimeId) => + Path.Combine( + compilerProject.GetProperty("ArtifactsPath").EvaluatedValue, + compilerProject.GetProperty("ArtifactsPublishOutputName").EvaluatedValue, + GetRuntimeArtifactFolder(runtimeId)); + + static string GetRuntimeArtifactFolder(string runtimeId) => $"pack_{runtimeId}"; +} diff --git a/build/Build.cs b/build/Build.cs new file mode 100644 index 00000000..3797eab9 --- /dev/null +++ b/build/Build.cs @@ -0,0 +1,56 @@ +using System.Diagnostics; +using System.Threading; +using Nuke.Common; +using Nuke.Common.ProjectModel; +using Nuke.Common.Tools.DotNet; +using static Nuke.Common.Tools.DotNet.DotNetTasks; + +partial class Build : NukeBuild +{ + public static int Main() + { + // while (!Debugger.IsAttached) Thread.Sleep(100); + return Execute(x => x.Compile); + } + + [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] + readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; + + [Solution(GenerateProjects = true)] + readonly Solution Solution; + + Target Clean => _ => _ + .Before(Restore) + .Executes(() => + { + DotNetClean(); + }); + + Target Restore => _ => _ + .Executes(() => + { + DotNetRestore(_ => _ + .SetProjectFile(BuildProjectFile ?? Solution.FileName)); + }); + + Target Compile => _ => _ + .DependsOn(Restore) + .Executes(() => + { + DotNetBuild(_ => _ + .SetConfiguration(Configuration) + .SetProjectFile(BuildProjectFile ?? Solution.FileName) + .EnableNoRestore()); + }); + + Target Test => _ => _ + .DependsOn(Compile) + .Executes(() => + { + DotNetTest(_ => _ + .SetConfiguration(Configuration) + .SetProjectFile(BuildProjectFile ?? Solution.FileName) + .EnableNoBuild() + .EnableNoRestore()); + }); +} diff --git a/build/Configuration.cs b/build/Configuration.cs new file mode 100644 index 00000000..9c08b1ae --- /dev/null +++ b/build/Configuration.cs @@ -0,0 +1,16 @@ +using System; +using System.ComponentModel; +using System.Linq; +using Nuke.Common.Tooling; + +[TypeConverter(typeof(TypeConverter))] +public class Configuration : Enumeration +{ + public static Configuration Debug = new Configuration { Value = nameof(Debug) }; + public static Configuration Release = new Configuration { Value = nameof(Release) }; + + public static implicit operator string(Configuration configuration) + { + return configuration.Value; + } +} diff --git a/build/Directory.Build.props b/build/Directory.Build.props new file mode 100644 index 00000000..e147d635 --- /dev/null +++ b/build/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/build/Directory.Build.targets b/build/Directory.Build.targets new file mode 100644 index 00000000..25326095 --- /dev/null +++ b/build/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/build/_build.csproj b/build/_build.csproj new file mode 100644 index 00000000..9874fbb1 --- /dev/null +++ b/build/_build.csproj @@ -0,0 +1,24 @@ + + + + Exe + net8.0 + + CS0649;CS0169 + .. + .. + 1 + true + + + + + + + + + Build.cs + + + + diff --git a/build/_build.csproj.DotSettings b/build/_build.csproj.DotSettings new file mode 100644 index 00000000..eb3f4c27 --- /dev/null +++ b/build/_build.csproj.DotSettings @@ -0,0 +1,28 @@ + + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + Implicit + Implicit + ExpressionBody + 0 + NEXT_LINE + True + False + 120 + IF_OWNER_IS_SINGLE_LINE + WRAP_IF_LONG + False + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True + True + True + True + True + True + True + True From 124172c7e1bcce5d6fd126426027ff5d01a25b4b Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sat, 16 Mar 2024 17:47:22 +0100 Subject: [PATCH 021/103] SDK: Progress with packing and testing --- .nuke/build.schema.json | 30 +++++- Cesium.Compiler/Cesium.Compiler.csproj | 2 +- Cesium.Sdk.Tests/CesiumCompileTests.cs | 2 +- Cesium.Sdk.Tests/SdkTestBase.cs | 5 +- .../SimpleProject/SimpleProject.ceproj | 2 +- Cesium.Sdk/Cesium.Sdk.csproj | 2 +- Cesium.Sdk/CesiumCompile.cs | 19 ++-- Cesium.Sdk/CommandArgumentsBuilder.cs | 2 +- Cesium.Sdk/IsExternalInit.cs | 4 + Cesium.Sdk/Sdk/Sdk.props | 2 +- Cesium.Sdk/Sdk/Sdk.targets | 36 ++++--- build/Build.Sdk.cs | 96 ++++++++++++++++--- build/Build.Tests.cs | 42 ++++++++ build/Build.cs | 32 +++---- build/ProjectExtensions.cs | 25 +++++ build/_build.csproj | 3 + build/_build.csproj.DotSettings | 5 +- 17 files changed, 242 insertions(+), 67 deletions(-) create mode 100644 Cesium.Sdk/IsExternalInit.cs create mode 100644 build/Build.Tests.cs create mode 100644 build/ProjectExtensions.cs diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index 60a3e9fc..d5dbf8e0 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -73,13 +73,26 @@ "type": "string", "enum": [ "Clean", - "Compile", + "CompileAll", + "ForceClear", "PackCompilerPacks", + "PackSdk", "PublishCompilerPacks", - "Restore" + "RestoreAll", + "TestAll", + "TestCodeGen", + "TestCompiler", + "TestIntegration", + "TestParser", + "TestRuntime", + "TestSdk" ] } }, + "SkipCaches": { + "type": "boolean", + "description": "If set to true, ignores all cached build results. Default: false" + }, "Solution": { "type": "string", "description": "Path to a solution file that is automatically loaded" @@ -91,10 +104,19 @@ "type": "string", "enum": [ "Clean", - "Compile", + "CompileAll", + "ForceClear", "PackCompilerPacks", + "PackSdk", "PublishCompilerPacks", - "Restore" + "RestoreAll", + "TestAll", + "TestCodeGen", + "TestCompiler", + "TestIntegration", + "TestParser", + "TestRuntime", + "TestSdk" ] } }, diff --git a/Cesium.Compiler/Cesium.Compiler.csproj b/Cesium.Compiler/Cesium.Compiler.csproj index 67a17e10..3f80bfde 100644 --- a/Cesium.Compiler/Cesium.Compiler.csproj +++ b/Cesium.Compiler/Cesium.Compiler.csproj @@ -4,7 +4,7 @@ Exe net8.0 enable - true + true true Major diff --git a/Cesium.Sdk.Tests/CesiumCompileTests.cs b/Cesium.Sdk.Tests/CesiumCompileTests.cs index 3ef1f753..d2d4b4cb 100644 --- a/Cesium.Sdk.Tests/CesiumCompileTests.cs +++ b/Cesium.Sdk.Tests/CesiumCompileTests.cs @@ -8,7 +8,7 @@ public class CesiumCompileTests(ITestOutputHelper testOutputHelper) : SdkTestBas [InlineData("SimpleProject")] public void CesiumCompile_ShouldSucceed(string projectName) { - var result = ExecuteTargets(projectName, "Build"); + var result = ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); ClearOutput(); diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index 822acc7d..c4a2d837 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -7,6 +7,8 @@ namespace Cesium.Sdk.Tests; public abstract class SdkTestBase { + private const string _binLogFile = "build_result.binlog"; + private readonly ITestOutputHelper _testOutputHelper; private readonly string _temporaryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); @@ -42,13 +44,14 @@ protected BuildResult ExecuteTargets(string projectName, params string[] targets { WorkingDirectory = testProjectFolder, FileName = "dotnet", - Arguments = $"build \"{testProjectFile}\" -t:{joinedTargets} -v:diag /bl:build_result.binlog", + Arguments = $"msbuild \"{testProjectFile}\" /t:{joinedTargets} /restore /bl:{_binLogFile}", RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, UseShellExecute = false, }; + using var process = new Process(); process.StartInfo = startInfo; diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj index 33d22c64..793d194e 100644 --- a/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj +++ b/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj @@ -3,6 +3,6 @@ net6.0 - + diff --git a/Cesium.Sdk/Cesium.Sdk.csproj b/Cesium.Sdk/Cesium.Sdk.csproj index e9bd74b4..4c170d49 100644 --- a/Cesium.Sdk/Cesium.Sdk.csproj +++ b/Cesium.Sdk/Cesium.Sdk.csproj @@ -1,7 +1,7 @@ - net8.0 + netstandard2.0 enable true diff --git a/Cesium.Sdk/CesiumCompile.cs b/Cesium.Sdk/CesiumCompile.cs index e2b077a7..7cf34c15 100644 --- a/Cesium.Sdk/CesiumCompile.cs +++ b/Cesium.Sdk/CesiumCompile.cs @@ -45,6 +45,7 @@ public class CesiumCompile : Task public bool DryRun = false; [Output] public string? ResultingCommandLine { get; private set; } + [Output] public TaskItem[]? OutputFiles { get; private set; } public override bool Execute() { @@ -70,6 +71,8 @@ public override bool Execute() }; ResultingCommandLine = $"{compilerProcess.StartInfo.FileName} {compilerProcess.StartInfo.Arguments}"; + OutputFiles = [new TaskItem(OutputFile)]; + if (!DryRun) { compilerProcess.Start(); @@ -122,7 +125,7 @@ private bool TryValidate(out ValidatedOptions? options) var (isFrameworkValid, framework) = TryParseFramework(Framework); if (!isFrameworkValid) { - var validValues = Enum.GetValues().Select(kind => kind.ToString()); + var validValues = Enum.GetValues(typeof(FrameworkKind)).Cast().Select(kind => kind.ToString()); ReportValidationError("CES1004", $"Framework should be in range: '{string.Join(", ", validValues)}'"); success = false; } @@ -130,7 +133,7 @@ private bool TryValidate(out ValidatedOptions? options) var (isArchValid, arch) = TryParseArchitectureKind(Architecture); if (!isArchValid) { - var validValues = Enum.GetValues().Select(kind => kind.ToString()); + var validValues = Enum.GetValues(typeof(ArchitectureKind)).Cast().Select(kind => kind.ToString()); ReportValidationError("CES1005", $"Architecture should be in range: '{string.Join(", ", validValues)}'"); success = false; } @@ -138,7 +141,7 @@ private bool TryValidate(out ValidatedOptions? options) var (isModuleKindValid, moduleKind) = TryParseModuleKind(ModuleType); if (!isModuleKindValid) { - var validValues = Enum.GetValues().Select(kind => kind.ToString()); + var validValues = Enum.GetValues(typeof(ModuleKind)).Cast().Select(kind => kind.ToString()); ReportValidationError("CES1006", $"ModuleKind should be in range: '{string.Join(", ", validValues)}'"); success = false; } @@ -172,9 +175,9 @@ private bool TryValidate(out ValidatedOptions? options) if (!success) return false; options = new ValidatedOptions( - CompilerExe: CompilerExe ?? throw new UnreachableException(), + CompilerExe: CompilerExe, InputItems: InputFiles.Select(item => item.ItemSpec).ToArray(), - OutputFile: OutputFile ?? throw new UnreachableException(), + OutputFile: OutputFile, Namespace: Namespace, Framework: framework, Architecture: arch, @@ -214,7 +217,7 @@ private IEnumerable CollectCommandLineArguments(ValidatedOptions options if (!string.IsNullOrWhiteSpace(options.Namespace)) { yield return "--namespace"; - yield return options.Namespace; + yield return options.Namespace!; } foreach (var import in options.ImportItems) @@ -226,13 +229,13 @@ private IEnumerable CollectCommandLineArguments(ValidatedOptions options if (!string.IsNullOrWhiteSpace(options.CoreLibPath)) { yield return "--corelib"; - yield return options.CoreLibPath; + yield return options.CoreLibPath!; } if (!string.IsNullOrWhiteSpace(options.RuntimePath)) { yield return "--runtime"; - yield return options.RuntimePath; + yield return options.RuntimePath!; } foreach (var item in options.PreprocessorItems) diff --git a/Cesium.Sdk/CommandArgumentsBuilder.cs b/Cesium.Sdk/CommandArgumentsBuilder.cs index 9de668d2..28c13a92 100644 --- a/Cesium.Sdk/CommandArgumentsBuilder.cs +++ b/Cesium.Sdk/CommandArgumentsBuilder.cs @@ -12,7 +12,7 @@ public class CommandArgumentsBuilder public CommandArgumentsBuilder Argument(string argument) { - _builder.Append(" "); + _builder.Append(' '); if (NeedsEscaping(argument)) { argument = Escape(argument); diff --git a/Cesium.Sdk/IsExternalInit.cs b/Cesium.Sdk/IsExternalInit.cs new file mode 100644 index 00000000..eb2da113 --- /dev/null +++ b/Cesium.Sdk/IsExternalInit.cs @@ -0,0 +1,4 @@ +namespace System.Runtime.CompilerServices +{ + internal static class IsExternalInit {} +} diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index 9671dca7..288784bd 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -8,7 +8,7 @@ false - Cesium.Compiler + Cesium.Compiler.Pack.$(NETCoreSdkRuntimeIdentifier) 0.0.1 diff --git a/Cesium.Sdk/Sdk/Sdk.targets b/Cesium.Sdk/Sdk/Sdk.targets index 030331fa..e5b64ae2 100644 --- a/Cesium.Sdk/Sdk/Sdk.targets +++ b/Cesium.Sdk/Sdk/Sdk.targets @@ -2,10 +2,13 @@ + + + <_CesiumModuleKind Condition="'$(OutputType)' == 'Exe'">Console <_CesiumModuleKind Condition="'$(OutputType)' == 'WinExe'">Windows - <_CesiumModuleKind Condition="'$(OutputType)' == 'Dll'">Library + <_CesiumModuleKind Condition="'$(OutputType)' == 'Library'">Library @@ -36,24 +39,28 @@ - <_CompilerOutput>$(OutDir)$(AssemblyName) + <_CompilerOutput>$(IntermediateOutputPath)$(AssemblyName) - + Outputs="$(_CompilerOutput)"> - - - + + + + + + + + + + + PreprocessorItems="$(DefineConstants.Split(';'))"> + + + + + diff --git a/build/Build.Sdk.cs b/build/Build.Sdk.cs index 37ff062a..f4ce604c 100644 --- a/build/Build.Sdk.cs +++ b/build/Build.Sdk.cs @@ -11,8 +11,9 @@ public partial class Build { + const string _compilerPackPackagePrefix = "Cesium.Compiler.Pack"; + Target PublishCompilerPacks => _ => _ - .DependsOn(Compile) .Executes(() => { var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); @@ -22,48 +23,78 @@ public partial class Build foreach (var runtimeId in runtimeIds) { + Log.Information(SkipCaches+""); + if (!SkipCaches && !NeedPublishCompilerPack(compilerProject, runtimeId)) + { + Log.Information($"Skipping {runtimeId} because it was already published. Use '--skip-caches true' to re-publish."); + continue; + } + Log.Information($"Publishing for {runtimeId}..."); DotNetPublish(o => o .SetConfiguration(Configuration) .SetProject(compilerProject.ProjectFileLocation.File) .SetRuntime(runtimeId) - .SetOutput(GetCompilerRuntimePublishFolder(compilerProject, runtimeId)) - .EnableNoBuild() - .EnableNoRestore()); + .SetOutput(GetCompilerRuntimePublishFolder(compilerProject, runtimeId))); } }); Target PackCompilerPacks => _ => _ + .DependsOn(PublishCompilerPacks) .Executes(() => { var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); - var runtimeIds = compilerProject.GetProperty("RuntimeIdentifiers").EvaluatedValue.Split(";"); + var runtimeIds = compilerProject.GetRuntimeIds(); Log.Information( $"Runtime identifiers defined in {Solution.Cesium_Compiler.Name}: {string.Join(", ", runtimeIds)}"); foreach (var runtimeId in runtimeIds) { + if (!SkipCaches && !NeedPackageCompilerPack(compilerProject, runtimeId)) + { + Log.Information($"Skipping {runtimeId} because it was already packed. Use '--skip-caches true' to re-pack."); + continue; + } + Log.Information($"Packing compiler for {runtimeId}..."); EmitCompilerPack(runtimeId, compilerProject); } }); - static void EmitCompilerPack(string runtimeId, Project compilerProject) + Target PackSdk => _ => _ + .Executes(() => + { + var sdkProject = Solution.Cesium_Sdk.GetMSBuildProject(); + if (!SkipCaches && !NeedPackageSdk(sdkProject)) + { + Log.Information($"Skipping SDK packing because it was already packed. Use '--skip-caches true' to re-publish."); + return; + } + + Log.Information($"Packing SDK..."); + DotNetPack(o => o + .SetConfiguration(Configuration) + .SetProject(Solution.Cesium_Sdk.Path)); + }); + + void EmitCompilerPack(string runtimeId, Project compilerProject) { - var packageId = $"Cesium.Compiler.Pack.{runtimeId}"; - var packageFile = $"{packageId}.nupkg"; + var version = compilerProject.GetVersion(); + var runtimePackageId = GetRuntimePackId(runtimeId); + var packageFile = GetRuntimePackFileName(version, runtimeId); var publishDirectory = GetCompilerRuntimePublishFolder(compilerProject, runtimeId); + Directory.CreateDirectory(publishDirectory); var publishedFiles = Directory.GetFiles(publishDirectory, "*.*", SearchOption.AllDirectories); - var packageOutputPath = compilerProject.GetProperty("PackageOutputPath").EvaluatedValue; + var packageOutputPath = compilerProject.GetPackageOutputPath(); Log.Debug($"Source publish directory: {publishDirectory}"); - Log.Debug($"Target package ID: {packageId}"); + Log.Debug($"Target package ID: {runtimePackageId}"); Log.Debug($"Target package output directory: {packageOutputPath}"); var builder = new PackageBuilder { - Id = packageId, - Version = NuGetVersion.Parse(compilerProject.GetProperty("VersionPrefix").EvaluatedValue), + Id = runtimePackageId, + Version = NuGetVersion.Parse(compilerProject.GetVersion()), Description = $"Cesium compiler native executable pack for {runtimeId} platform.", Authors = { "Cesium Team" } }; @@ -89,11 +120,46 @@ IEnumerable GetPhysicalFiles(string publishDirectory, IEnumerable< } } - static string GetCompilerRuntimePublishFolder(Project compilerProject, string runtimeId) => + string GetCompilerRuntimePublishFolder(Project compilerProject, string runtimeId) => Path.Combine( compilerProject.GetProperty("ArtifactsPath").EvaluatedValue, compilerProject.GetProperty("ArtifactsPublishOutputName").EvaluatedValue, - GetRuntimeArtifactFolder(runtimeId)); + Solution.Cesium_Compiler.Name, + GetRuntimeArtifactFolder(compilerProject.GetVersion(), runtimeId)); + + static string GetRuntimeArtifactFolder(string version, string runtimeId) => + $"pack_{version}_{runtimeId}"; - static string GetRuntimeArtifactFolder(string runtimeId) => $"pack_{runtimeId}"; + static string GetRuntimePackId(string runtimeId) => + $"{_compilerPackPackagePrefix}.{runtimeId}"; + + static string GetRuntimePackFileName(string version, string runtimeId) => + $"{_compilerPackPackagePrefix}.{runtimeId}.{version}.nupkg"; + + bool NeedPublishCompilerPack(Project compiler, string runtimeId) + { + var folder = GetCompilerRuntimePublishFolder(compiler, runtimeId); + + return !Directory.Exists(folder) + || Directory.GetFiles(folder, "Cesium.Compiler*").Length == 0; + } + + bool NeedPackageCompilerPack(Project compiler, string runtimeId) + { + var version = compiler.GetVersion(); + var packageDirectory = compiler.GetPackageOutputPath(); + var packageFileName = GetRuntimePackFileName(version, runtimeId); + + return !File.Exists(Path.Combine(packageDirectory, packageFileName)); + } + + bool NeedPackageSdk(Project sdk) + { + var packageId = sdk.GetProperty("PackageVersion").EvaluatedValue; + var version = sdk.GetProperty("PackageId").EvaluatedValue; + var packageDirectory = sdk.GetPackageOutputPath(); + var packageFileName = $"{packageId}.{version}"; + + return !File.Exists(Path.Combine(packageDirectory, packageFileName)); + } } diff --git a/build/Build.Tests.cs b/build/Build.Tests.cs new file mode 100644 index 00000000..0a8a5747 --- /dev/null +++ b/build/Build.Tests.cs @@ -0,0 +1,42 @@ +using Nuke.Common; +using Nuke.Common.ProjectModel; +using Nuke.Common.Tools.DotNet; +using static Nuke.Common.Tools.DotNet.DotNetTasks; + +partial class Build +{ + Target TestCodeGen => _ => _ + .Executes(() => ExecuteTests(Solution.Cesium_CodeGen_Tests)); + + Target TestCompiler => _ => _ + .Executes(() => ExecuteTests(Solution.Cesium_Compiler_Tests)); + + Target TestIntegration => _ => _ + .Executes(() => ExecuteTests(Solution.Cesium_IntegrationTests)); + + Target TestParser => _ => _ + .Executes(() => ExecuteTests(Solution.Cesium_Parser_Tests)); + + Target TestRuntime => _ => _ + .Executes(() => ExecuteTests(Solution.Cesium_Runtime_Tests)); + + Target TestSdk => _ => _ + .DependsOn(PackCompilerPacks) + .DependsOn(PackSdk) + .Executes(() => ExecuteTests(Solution.Cesium_Sdk_Tests)); + + Target TestAll => _ => _ + .DependsOn(TestCodeGen) + .DependsOn(TestCompiler) + .DependsOn(TestIntegration) + .DependsOn(TestParser) + .DependsOn(TestRuntime) + .DependsOn(TestSdk); + + void ExecuteTests(Project project) + { + DotNetTest(_ => _ + .SetConfiguration(Configuration) + .SetProjectFile(project.GetMSBuildProject().ProjectFileLocation.File)); + } +} diff --git a/build/Build.cs b/build/Build.cs index 3797eab9..ab63eeaf 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -1,5 +1,3 @@ -using System.Diagnostics; -using System.Threading; using Nuke.Common; using Nuke.Common.ProjectModel; using Nuke.Common.Tools.DotNet; @@ -10,47 +8,43 @@ partial class Build : NukeBuild public static int Main() { // while (!Debugger.IsAttached) Thread.Sleep(100); - return Execute(x => x.Compile); + return Execute(x => x.CompileAll); } [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; + [Parameter("If set to true, ignores all cached build results. Default: false")] + readonly bool SkipCaches = false; + [Solution(GenerateProjects = true)] readonly Solution Solution; Target Clean => _ => _ - .Before(Restore) + .Before(RestoreAll) .Executes(() => { DotNetClean(); }); - Target Restore => _ => _ + Target RestoreAll => _ => _ .Executes(() => { DotNetRestore(_ => _ - .SetProjectFile(BuildProjectFile ?? Solution.FileName)); + .SetProjectFile(Solution.FileName)); }); - Target Compile => _ => _ - .DependsOn(Restore) + Target CompileAll => _ => _ + .DependsOn(RestoreAll) .Executes(() => { DotNetBuild(_ => _ .SetConfiguration(Configuration) - .SetProjectFile(BuildProjectFile ?? Solution.FileName) + .SetProjectFile(Solution.FileName) .EnableNoRestore()); }); - Target Test => _ => _ - .DependsOn(Compile) - .Executes(() => - { - DotNetTest(_ => _ - .SetConfiguration(Configuration) - .SetProjectFile(BuildProjectFile ?? Solution.FileName) - .EnableNoBuild() - .EnableNoRestore()); - }); + Target ForceClear => _ => _ + .OnlyWhenDynamic(() => SkipCaches) + .Before(RestoreAll); } diff --git a/build/ProjectExtensions.cs b/build/ProjectExtensions.cs new file mode 100644 index 00000000..88720be9 --- /dev/null +++ b/build/ProjectExtensions.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using Microsoft.Build.Evaluation; + +public static class ProjectExtensions +{ + public static IReadOnlyCollection GetRuntimeIds(this Project project) + { + return project.GetProperty("RuntimeIdentifiers").EvaluatedValue.Split(";"); + } + + public static string GetVersion(this Project project) + { + return project.GetProperty("VersionPrefix").EvaluatedValue; + } + + public static string GetPackageOutputPath(this Project project) + { + return project.GetProperty("PackageOutputPath").EvaluatedValue; + } + + public static string GetPublishDirectory(this Project project) + { + return project.GetProperty("PublishDir").EvaluatedValue; + } +} diff --git a/build/_build.csproj b/build/_build.csproj index 9874fbb1..0b05104a 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -19,6 +19,9 @@ Build.cs + + Build.cs + diff --git a/build/_build.csproj.DotSettings b/build/_build.csproj.DotSettings index eb3f4c27..c815d363 100644 --- a/build/_build.csproj.DotSettings +++ b/build/_build.csproj.DotSettings @@ -17,6 +17,8 @@ False <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> True True True @@ -25,4 +27,5 @@ True True True - True + True + True From dde2ebd962653efb7406e183fd47c9927e39e894 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 17 Mar 2024 03:00:13 +0100 Subject: [PATCH 022/103] SDK: Introduce option to publish & pack only specific RID --- build/Build.Sdk.cs | 27 +++++++++++++++++++++++++-- build/Build.cs | 9 ++++++++- build/ProjectExtensions.cs | 13 +++++++++---- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/build/Build.Sdk.cs b/build/Build.Sdk.cs index f4ce604c..bba696cb 100644 --- a/build/Build.Sdk.cs +++ b/build/Build.Sdk.cs @@ -18,16 +18,28 @@ public partial class Build { var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); var runtimeIds = compilerProject.GetProperty("RuntimeIdentifiers").EvaluatedValue.Split(";"); + + var runtimeIds = compilerProject.GetEvaluatedProperty("RuntimeIdentifiers").Split(";"); Log.Information( $"Runtime identifiers defined in {Solution.Cesium_Compiler.Name}: {string.Join(", ", runtimeIds)}"); + if (!string.IsNullOrEmpty(RuntimeId)) + { + Log.Information($"Executing only {RuntimeId} because it was specified explicitly."); + PublishCompiler(RuntimeId); + return; + } + foreach (var runtimeId in runtimeIds) + PublishCompiler(runtimeId); + + void PublishCompiler(string runtimeId) { Log.Information(SkipCaches+""); if (!SkipCaches && !NeedPublishCompilerPack(compilerProject, runtimeId)) { Log.Information($"Skipping {runtimeId} because it was already published. Use '--skip-caches true' to re-publish."); - continue; + return; } Log.Information($"Publishing for {runtimeId}..."); @@ -44,16 +56,27 @@ public partial class Build .Executes(() => { var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); + var runtimeIds = compilerProject.GetRuntimeIds(); Log.Information( $"Runtime identifiers defined in {Solution.Cesium_Compiler.Name}: {string.Join(", ", runtimeIds)}"); + if (!string.IsNullOrEmpty(RuntimeId)) + { + Log.Information($"Executing only {RuntimeId} because it was specified explicitly."); + PackCompiler(RuntimeId); + return; + } + foreach (var runtimeId in runtimeIds) + PackCompiler(runtimeId); + + void PackCompiler(string runtimeId) { if (!SkipCaches && !NeedPackageCompilerPack(compilerProject, runtimeId)) { Log.Information($"Skipping {runtimeId} because it was already packed. Use '--skip-caches true' to re-pack."); - continue; + return; } Log.Information($"Packing compiler for {runtimeId}..."); diff --git a/build/Build.cs b/build/Build.cs index ab63eeaf..3a745e49 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -1,5 +1,6 @@ using Nuke.Common; using Nuke.Common.ProjectModel; +using Nuke.Common.Tooling; using Nuke.Common.Tools.DotNet; using static Nuke.Common.Tools.DotNet.DotNetTasks; @@ -20,17 +21,22 @@ public static int Main() [Solution(GenerateProjects = true)] readonly Solution Solution; + [Parameter("If set, only executes targets for a specified runtime identifier. Provided RID must be included in property of Cesium.Compiler project.")] + readonly string RuntimeId = string.Empty; + Target Clean => _ => _ .Before(RestoreAll) .Executes(() => { - DotNetClean(); + DotNetClean(_ => _ + .Apply(settings => !string.IsNullOrEmpty(RuntimeId) ? settings.SetRuntime(RuntimeId) : settings)); }); Target RestoreAll => _ => _ .Executes(() => { DotNetRestore(_ => _ + .Apply(settings => !string.IsNullOrEmpty(RuntimeId) ? settings.SetRuntime(RuntimeId) : settings) .SetProjectFile(Solution.FileName)); }); @@ -39,6 +45,7 @@ public static int Main() .Executes(() => { DotNetBuild(_ => _ + .Apply(settings => !string.IsNullOrEmpty(RuntimeId) ? settings.SetRuntime(RuntimeId) : settings) .SetConfiguration(Configuration) .SetProjectFile(Solution.FileName) .EnableNoRestore()); diff --git a/build/ProjectExtensions.cs b/build/ProjectExtensions.cs index 88720be9..25577c9a 100644 --- a/build/ProjectExtensions.cs +++ b/build/ProjectExtensions.cs @@ -5,21 +5,26 @@ public static class ProjectExtensions { public static IReadOnlyCollection GetRuntimeIds(this Project project) { - return project.GetProperty("RuntimeIdentifiers").EvaluatedValue.Split(";"); + return project.GetEvaluatedProperty("RuntimeIdentifiers").Split(";"); } public static string GetVersion(this Project project) { - return project.GetProperty("VersionPrefix").EvaluatedValue; + return project.GetEvaluatedProperty("VersionPrefix"); } public static string GetPackageOutputPath(this Project project) { - return project.GetProperty("PackageOutputPath").EvaluatedValue; + return project.GetEvaluatedProperty("PackageOutputPath"); } public static string GetPublishDirectory(this Project project) { - return project.GetProperty("PublishDir").EvaluatedValue; + return project.GetEvaluatedProperty("PublishDir"); + } + + public static string GetEvaluatedProperty(this Project project, string name) + { + return project.GetProperty(name).EvaluatedValue; } } From ba36eff61faf6c147256ea5ec857155925573b0e Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 17 Mar 2024 03:00:46 +0100 Subject: [PATCH 023/103] SDK: Fix compilation after packages consolidation --- Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj | 14 +++++++------- Cesium.Sdk/Cesium.Sdk.csproj | 2 +- Directory.Packages.props | 4 ++++ build/Build.Sdk.cs | 1 - build/_build.csproj | 2 +- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj index fad9a01e..f91ea2ed 100644 --- a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj +++ b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj @@ -10,16 +10,16 @@ - - - - - - + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Cesium.Sdk/Cesium.Sdk.csproj b/Cesium.Sdk/Cesium.Sdk.csproj index 4c170d49..dc1b44cd 100644 --- a/Cesium.Sdk/Cesium.Sdk.csproj +++ b/Cesium.Sdk/Cesium.Sdk.csproj @@ -14,7 +14,7 @@ - + diff --git a/Directory.Packages.props b/Directory.Packages.props index 977c9a0c..e2deed85 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -21,5 +21,9 @@ + + + + diff --git a/build/Build.Sdk.cs b/build/Build.Sdk.cs index bba696cb..7977293a 100644 --- a/build/Build.Sdk.cs +++ b/build/Build.Sdk.cs @@ -17,7 +17,6 @@ public partial class Build .Executes(() => { var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); - var runtimeIds = compilerProject.GetProperty("RuntimeIdentifiers").EvaluatedValue.Split(";"); var runtimeIds = compilerProject.GetEvaluatedProperty("RuntimeIdentifiers").Split(";"); Log.Information( diff --git a/build/_build.csproj b/build/_build.csproj index 0b05104a..98f857ce 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -12,7 +12,7 @@ - + From 98a4f42bafd0b99f06f41daa42a0be8fb9c5d5d0 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 17 Mar 2024 03:01:24 +0100 Subject: [PATCH 024/103] SDK: Add missing build schema update --- .nuke/build.schema.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index d5dbf8e0..fe4add0c 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -66,6 +66,10 @@ "type": "string", "description": "Root directory during build execution" }, + "RuntimeId": { + "type": "string", + "description": "If set, only executes targets for a specified runtime identifier. Provided RID must be included in property of Cesium.Compiler project" + }, "Skip": { "type": "array", "description": "List of targets to be skipped. Empty list skips all dependencies", From 551897ed2f50a9eac93c52896cd3adf80e3ad2c0 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 17 Mar 2024 03:01:48 +0100 Subject: [PATCH 025/103] SDK: Add missing Self-contained option to compiler publishing --- build/Build.Sdk.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/build/Build.Sdk.cs b/build/Build.Sdk.cs index 7977293a..d374db47 100644 --- a/build/Build.Sdk.cs +++ b/build/Build.Sdk.cs @@ -46,6 +46,7 @@ void PublishCompiler(string runtimeId) .SetConfiguration(Configuration) .SetProject(compilerProject.ProjectFileLocation.File) .SetRuntime(runtimeId) + .SetSelfContained(true) .SetOutput(GetCompilerRuntimePublishFolder(compilerProject, runtimeId))); } }); From 758c481c1797116fe48da726c4aaa38d8d9e88f3 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 17 Mar 2024 03:02:25 +0100 Subject: [PATCH 026/103] SDK: Make enum-related compiler properties validation more self-descriptive --- Cesium.Sdk/CesiumCompile.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cesium.Sdk/CesiumCompile.cs b/Cesium.Sdk/CesiumCompile.cs index 7cf34c15..b366c2e3 100644 --- a/Cesium.Sdk/CesiumCompile.cs +++ b/Cesium.Sdk/CesiumCompile.cs @@ -126,7 +126,7 @@ private bool TryValidate(out ValidatedOptions? options) if (!isFrameworkValid) { var validValues = Enum.GetValues(typeof(FrameworkKind)).Cast().Select(kind => kind.ToString()); - ReportValidationError("CES1004", $"Framework should be in range: '{string.Join(", ", validValues)}'"); + ReportValidationError("CES1004", $"Framework should be in range: '{string.Join(", ", validValues)}', actual: '{Framework}'"); success = false; } @@ -134,7 +134,7 @@ private bool TryValidate(out ValidatedOptions? options) if (!isArchValid) { var validValues = Enum.GetValues(typeof(ArchitectureKind)).Cast().Select(kind => kind.ToString()); - ReportValidationError("CES1005", $"Architecture should be in range: '{string.Join(", ", validValues)}'"); + ReportValidationError("CES1005", $"Architecture should be in range: '{string.Join(", ", validValues)}', actual: '{Architecture}'"); success = false; } @@ -142,7 +142,7 @@ private bool TryValidate(out ValidatedOptions? options) if (!isModuleKindValid) { var validValues = Enum.GetValues(typeof(ModuleKind)).Cast().Select(kind => kind.ToString()); - ReportValidationError("CES1006", $"ModuleKind should be in range: '{string.Join(", ", validValues)}'"); + ReportValidationError("CES1006", $"ModuleKind should be in range: '{string.Join(", ", validValues)}', actual: '{ModuleType}'"); success = false; } From b5d945e1510019d94373ee1f1896a1f68170c519 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 17 Mar 2024 03:03:23 +0100 Subject: [PATCH 027/103] SDK: Fix issues with proper properties propagation from MSBuild targets to Task --- Cesium.Sdk.Tests/CesiumCompileTests.cs | 2 +- Cesium.Sdk/Sdk/Sdk.props | 11 ----------- Cesium.Sdk/Sdk/Sdk.targets | 22 ++++++++++++++++------ 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Cesium.Sdk.Tests/CesiumCompileTests.cs b/Cesium.Sdk.Tests/CesiumCompileTests.cs index d2d4b4cb..16d496dc 100644 --- a/Cesium.Sdk.Tests/CesiumCompileTests.cs +++ b/Cesium.Sdk.Tests/CesiumCompileTests.cs @@ -11,6 +11,6 @@ public void CesiumCompile_ShouldSucceed(string projectName) var result = ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); - ClearOutput(); + // ClearOutput(); } } diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index 288784bd..4de4e806 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -15,20 +15,9 @@ - - $(PkgCesium_Compiler) - - $(CesiumCompilerPackagePath)/tools/$(CesiumCompilerPackageName) - - - $(CesiumCompilerPackagePath)/tools/$(CesiumCompilerPackageName).exe - - - diff --git a/Cesium.Sdk/Sdk/Sdk.targets b/Cesium.Sdk/Sdk/Sdk.targets index e5b64ae2..ed277b6a 100644 --- a/Cesium.Sdk/Sdk/Sdk.targets +++ b/Cesium.Sdk/Sdk/Sdk.targets @@ -2,13 +2,23 @@ + + <_NuGetPackageRootNormalized Condition="$(CesiumCompilerPackagePath) == ''">$([MSBuild]::EnsureTrailingSlash('$(NuGetPackageRoot)')) + <_CesiumCompilerPackageFolderName Condition="$(CesiumCompilerPackagePath) == ''">$(CesiumCompilerPackageName.ToLower()) + <_CesiumCompilerPackagePath Condition="$(CesiumCompilerPackagePath) == ''">$(_NuGetPackageRootNormalized) + $([System.IO.Path]::Combine($(_CesiumCompilerPackagePath), $(_CesiumCompilerPackageFolderName), $(CesiumCompilerPackageVersion))) + $(CesiumCompilerPackagePath)/tools/Cesium.Compiler + $(CesiumCompilerPackagePath)/tools/Cesium.Compiler.exe + $([System.IO.File]::Exists('$(CesiumCompilerPath)')) + + <_CesiumModuleKind Condition="'$(OutputType)' == 'Exe'">Console <_CesiumModuleKind Condition="'$(OutputType)' == 'WinExe'">Windows - <_CesiumModuleKind Condition="'$(OutputType)' == 'Library'">Library + <_CesiumModuleKind Condition="'$(OutputType)' == 'Library'">Dll @@ -17,9 +27,9 @@ - <_CesiumFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion)' == 'v6.0'">net6.0 - <_CesiumFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework' AND '$(TargetFrameworkVersion)' == 'v4.8'">net48 - <_CesiumFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard' AND '$(TargetFrameworkVersion)' == 'v2.0'">netstandard2.0 + <_CesiumFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion)' == 'v6.0'">Net + <_CesiumFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework' AND '$(TargetFrameworkVersion)' == 'v4.8'">NetFramework + <_CesiumFramework Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard' AND '$(TargetFrameworkVersion)' == 'v2.0'">NetStandard @@ -71,8 +81,8 @@ ModuleType="$(_CesiumModuleKind)" RuntimePath="$(RuntimePath)" PreprocessorItems="$(DefineConstants.Split(';'))"> - - + + From 165bcaa716bbcdc158ce49272f612dcb27500fe3 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 17 Mar 2024 18:37:25 +0100 Subject: [PATCH 028/103] Compiler: Fix AOT-related exception from CommandLineParser --- Cesium.Compiler/Main.cs | 71 +++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/Cesium.Compiler/Main.cs b/Cesium.Compiler/Main.cs index 2ccd37d2..f7098266 100644 --- a/Cesium.Compiler/Main.cs +++ b/Cesium.Compiler/Main.cs @@ -1,43 +1,52 @@ +using System.Diagnostics.CodeAnalysis; using Cesium.CodeGen; -using Cesium.Compiler; using Cesium.Core; using Mono.Cecil; -await CommandLineParser.ParseCommandLineArgs(args, new CompilerReporter(), async args => +namespace Cesium.Compiler; + +public static class Program +{ + [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Arguments))] + public static async Task Main(string[] args) { - var targetArchitectureSet = args.TargetArchitectureSet; - var targetRuntime = args.Framework switch + return await CommandLineParser.ParseCommandLineArgs(args, new CompilerReporter(), async args => { - TargetFrameworkKind.NetFramework => TargetRuntimeDescriptor.Net48, - TargetFrameworkKind.NetStandard => TargetRuntimeDescriptor.NetStandard20, - _ => TargetRuntimeDescriptor.Net60 - }; + var targetArchitectureSet = args.TargetArchitectureSet; + var targetRuntime = args.Framework switch + { + TargetFrameworkKind.NetFramework => TargetRuntimeDescriptor.Net48, + TargetFrameworkKind.NetStandard => TargetRuntimeDescriptor.NetStandard20, + _ => TargetRuntimeDescriptor.Net60 + }; - var cesiumRuntime = args.CesiumCRuntime ?? Path.Combine(AppContext.BaseDirectory, "Cesium.Runtime.dll"); - var defaultImportsAssembly = args.DefaultImportAssemblies ?? Array.Empty(); + var cesiumRuntime = args.CesiumCRuntime ?? Path.Combine(AppContext.BaseDirectory, "Cesium.Runtime.dll"); + var defaultImportsAssembly = args.DefaultImportAssemblies ?? Array.Empty(); #pragma warning disable IL3000 // Automatic discovery of corelib is fallback option, if tooling do not pass that parameter - var corelibAssembly = args.CoreLib ?? typeof(Math).Assembly.Location; // System.Runtime.dll + var corelibAssembly = args.CoreLib ?? typeof(Math).Assembly.Location; // System.Runtime.dll #pragma warning restore IL3000 - var moduleKind = args.ProducePreprocessedFile ? ModuleKind.Console : args.ModuleKind ?? Path.GetExtension(args.OutputFilePath).ToLowerInvariant() switch - { - ".exe" => ModuleKind.Console, - ".dll" => ModuleKind.Dll, - var o => throw new CompilationException($"Unknown file extension: {o}. \"modulekind\" is not specified.") - }; - var compilationOptions = new CompilationOptions( - targetRuntime, - targetArchitectureSet, - moduleKind, - corelibAssembly, - cesiumRuntime, - defaultImportsAssembly, - args.Namespace, - args.GlobalClass, - args.DefineConstant.ToList(), - args.IncludeDirectories.ToList(), - args.ProducePreprocessedFile); - return await Compilation.Compile(args.InputFilePaths, args.OutputFilePath, compilationOptions); - }); + var moduleKind = args.ProducePreprocessedFile ? ModuleKind.Console : args.ModuleKind ?? Path.GetExtension(args.OutputFilePath).ToLowerInvariant() switch + { + ".exe" => ModuleKind.Console, + ".dll" => ModuleKind.Dll, + var o => throw new CompilationException($"Unknown file extension: {o}. \"modulekind\" is not specified.") + }; + var compilationOptions = new CompilationOptions( + targetRuntime, + targetArchitectureSet, + moduleKind, + corelibAssembly, + cesiumRuntime, + defaultImportsAssembly, + args.Namespace, + args.GlobalClass, + args.DefineConstant.ToList(), + args.IncludeDirectories.ToList(), + args.ProducePreprocessedFile); + return await Compilation.Compile(args.InputFilePaths, args.OutputFilePath, compilationOptions); + }); + } +} class CompilerReporter : ICompilerReporter { From 49445370eafdb613d8bb7cece0228bfd63751b7a Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 17 Mar 2024 18:58:20 +0100 Subject: [PATCH 029/103] SDK: Fix compilation task --- Cesium.Sdk/CesiumCompile.cs | 55 +++++++++++++-------------- Cesium.Sdk/CommandArgumentsBuilder.cs | 12 ++++-- Cesium.Sdk/Sdk/Sdk.targets | 30 ++++++++++----- 3 files changed, 55 insertions(+), 42 deletions(-) diff --git a/Cesium.Sdk/CesiumCompile.cs b/Cesium.Sdk/CesiumCompile.cs index b366c2e3..7201cee3 100644 --- a/Cesium.Sdk/CesiumCompile.cs +++ b/Cesium.Sdk/CesiumCompile.cs @@ -54,18 +54,12 @@ public override bool Execute() return false; } - var argumentsBuilder = new CommandArgumentsBuilder(); - foreach (var argument in CollectCommandLineArguments(options)) - { - argumentsBuilder.Argument(argument); - } - var compilerProcess = new Process { StartInfo = { FileName = options.CompilerExe, - Arguments = argumentsBuilder.Build(), + Arguments = CollectCommandLineArguments(options), UseShellExecute = false, } }; @@ -191,66 +185,69 @@ private bool TryValidate(out ValidatedOptions? options) return true; } - private IEnumerable CollectCommandLineArguments(ValidatedOptions options) + private string CollectCommandLineArguments(ValidatedOptions options) { - yield return options.CompilerExe; - yield return "--nologo"; + var builder = new CommandArgumentsBuilder(); + + builder.RawArgument("--nologo"); if (options.Framework is { } framework) { - yield return "--framework"; - yield return framework.ToString(); + builder.RawArgument("--framework"); + builder.RawArgument(framework.ToString()); } if (options.Architecture is { } arch) { - yield return "--arch"; - yield return arch.ToString(); + builder.RawArgument("--arch"); + builder.RawArgument(arch.ToString()); } if (options.ModuleKind is { } moduleKind) { - yield return "--modulekind"; - yield return moduleKind.ToString(); + builder.RawArgument("--modulekind"); + builder.RawArgument(moduleKind.ToString()); } if (!string.IsNullOrWhiteSpace(options.Namespace)) { - yield return "--namespace"; - yield return options.Namespace!; + builder.RawArgument("--namespace"); + builder.RawArgument(options.Namespace!); } foreach (var import in options.ImportItems) { - yield return "--import"; - yield return import; + builder.RawArgument("--import"); + builder.Argument(import); } if (!string.IsNullOrWhiteSpace(options.CoreLibPath)) { - yield return "--corelib"; - yield return options.CoreLibPath!; + builder.RawArgument("--corelib"); + builder.Argument(options.CoreLibPath!); } if (!string.IsNullOrWhiteSpace(options.RuntimePath)) { - yield return "--runtime"; - yield return options.RuntimePath!; + builder.RawArgument("--runtime"); + builder.Argument(options.RuntimePath!); } foreach (var item in options.PreprocessorItems) { - yield return "-D"; - yield return item; + builder.RawArgument("-D"); + builder.Argument(item); } - yield return "--out"; - yield return $"\"{options.OutputFile}\""; + builder.RawArgument("--out"); + builder.Argument(options.OutputFile); foreach (var input in options.InputItems) { - yield return $"\"{input}\""; + builder.Argument(input); } + + return builder.Build(); } private void ReportValidationError(string code, string message) => diff --git a/Cesium.Sdk/CommandArgumentsBuilder.cs b/Cesium.Sdk/CommandArgumentsBuilder.cs index 28c13a92..ffcc4077 100644 --- a/Cesium.Sdk/CommandArgumentsBuilder.cs +++ b/Cesium.Sdk/CommandArgumentsBuilder.cs @@ -10,13 +10,19 @@ public class CommandArgumentsBuilder { private StringBuilder _builder = new StringBuilder(); + public CommandArgumentsBuilder RawArgument(string value) + { + _builder.Append(' '); + _builder.Append(value); + + return this; + } + public CommandArgumentsBuilder Argument(string argument) { _builder.Append(' '); if (NeedsEscaping(argument)) - { argument = Escape(argument); - } _builder.Append(argument); return this; @@ -25,7 +31,7 @@ public CommandArgumentsBuilder Argument(string argument) public string Build() => _builder.ToString(); private bool NeedsEscaping(string argument) => - argument.Length > 0 && argument.All(c => !char.IsWhiteSpace(c) && c != '"'); + argument.Length > 0 && argument.Any(c => char.IsWhiteSpace(c) || c != '"'); private static string Escape(string argument) { diff --git a/Cesium.Sdk/Sdk/Sdk.targets b/Cesium.Sdk/Sdk/Sdk.targets index ed277b6a..c1ea306e 100644 --- a/Cesium.Sdk/Sdk/Sdk.targets +++ b/Cesium.Sdk/Sdk/Sdk.targets @@ -2,19 +2,30 @@ - - <_NuGetPackageRootNormalized Condition="$(CesiumCompilerPackagePath) == ''">$([MSBuild]::EnsureTrailingSlash('$(NuGetPackageRoot)')) + <_CesiumCompilerPackageFolderName Condition="$(CesiumCompilerPackagePath) == ''">$(CesiumCompilerPackageName.ToLower()) - <_CesiumCompilerPackagePath Condition="$(CesiumCompilerPackagePath) == ''">$(_NuGetPackageRootNormalized) - $([System.IO.Path]::Combine($(_CesiumCompilerPackagePath), $(_CesiumCompilerPackageFolderName), $(CesiumCompilerPackageVersion))) - $(CesiumCompilerPackagePath)/tools/Cesium.Compiler - $(CesiumCompilerPackagePath)/tools/Cesium.Compiler.exe - $([System.IO.File]::Exists('$(CesiumCompilerPath)')) + <_CesiumCompilerPackagePath>$([System.IO.Path]::Combine($(NuGetPackageRoot), $(_CesiumCompilerPackageFolderName), $(CesiumCompilerPackageVersion))) + $(_CesiumCompilerPackagePath)/tools/Cesium.Compiler + $(_CesiumCompilerPackagePath)\tools\Cesium.Compiler.exe + + + + + + + <_CoreLibAssembly Include="@(ReferencePath)" Condition="'%(AssemblyName)'=='System.Private.CoreLib' OR '%(AssemblyName)'=='mscorlib'" /> + + + %(_CoreLibAssembly.Identity) + + + <_CesiumModuleKind Condition="'$(OutputType)' == 'Exe'">Console <_CesiumModuleKind Condition="'$(OutputType)' == 'WinExe'">Windows @@ -68,18 +79,17 @@ - From 4dfe12097b84da6657e60b28796e3600c4405cc9 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 7 Apr 2024 05:48:45 +0200 Subject: [PATCH 030/103] CodeGen: Fix System.Runtime usage instead of System.Private.CoreLib --- Cesium.CodeGen/Contexts/AssemblyContext.cs | 2 +- Cesium.CodeGen/Ir/Types/InPlaceArrayType.cs | 10 +++++----- Cesium.CodeGen/Ir/Types/StructType.cs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cesium.CodeGen/Contexts/AssemblyContext.cs b/Cesium.CodeGen/Contexts/AssemblyContext.cs index 39b5951e..b90b57e4 100644 --- a/Cesium.CodeGen/Contexts/AssemblyContext.cs +++ b/Cesium.CodeGen/Contexts/AssemblyContext.cs @@ -299,7 +299,7 @@ private TypeReference GetStubType(int size) "", stubStructTypeName, TypeAttributes.Sealed | TypeAttributes.ExplicitLayout | TypeAttributes.NestedPrivate, - Module.ImportReference(MscorlibAssembly.GetType("System.ValueType"))) + Module.ImportReference(new TypeReference("System", "ValueType", MscorlibAssembly.MainModule, MscorlibAssembly.MainModule.TypeSystem.CoreLibrary))) { PackingSize = 1, ClassSize = size diff --git a/Cesium.CodeGen/Ir/Types/InPlaceArrayType.cs b/Cesium.CodeGen/Ir/Types/InPlaceArrayType.cs index 421eaad7..9965a11a 100644 --- a/Cesium.CodeGen/Ir/Types/InPlaceArrayType.cs +++ b/Cesium.CodeGen/Ir/Types/InPlaceArrayType.cs @@ -37,8 +37,8 @@ public FieldDefinition CreateFieldOfType(TranslationUnitContext context, TypeDef CustomAttribute GenerateCustomFieldAttribute() { - var typeType = context.Module.ImportReference(context.AssemblyContext.MscorlibAssembly.GetType("System.Type")); - var fixedBufferAttributeType = context.AssemblyContext.MscorlibAssembly.GetType("System.Runtime.CompilerServices.FixedBufferAttribute") ?? throw new AssertException( + var typeType = context.Module.ImportReference(new TypeReference("System", "Type", context.AssemblyContext.MscorlibAssembly.MainModule, context.AssemblyContext.MscorlibAssembly.MainModule.TypeSystem.CoreLibrary)); + var fixedBufferAttributeType = new TypeReference("System.Runtime.CompilerServices", "FixedBufferAttribute", context.AssemblyContext.MscorlibAssembly.MainModule, context.AssemblyContext.MscorlibAssembly.MainModule.TypeSystem.CoreLibrary) ?? throw new AssertException( "Cannot find a type System.Runtime.CompilerServices.FixedBufferAttribute."); var fixedBufferCtor = new MethodReference(".ctor", context.TypeSystem.Void, fixedBufferAttributeType); fixedBufferCtor.Parameters.Add(new ParameterDefinition(typeType)); @@ -104,12 +104,12 @@ private static TypeDefinition CreateFixedBufferType( // } ModuleDefinition module = context.Module; - var compilerGeneratedAttributeType = context.AssemblyContext.MscorlibAssembly.GetType("System.Runtime.CompilerServices.CompilerGeneratedAttribute") ?? throw new AssertException( + var compilerGeneratedAttributeType = new TypeReference("System.Runtime.CompilerServices", "CompilerGeneratedAttribute", context.AssemblyContext.MscorlibAssembly.MainModule, context.AssemblyContext.MscorlibAssembly.MainModule.TypeSystem.CoreLibrary) ?? throw new AssertException( "Cannot find a type System.Runtime.CompilerServices.CompilerGeneratedAttribute."); var compilerGeneratedCtor = new MethodReference(".ctor", context.TypeSystem.Void, compilerGeneratedAttributeType); var compilerGeneratedAttribute = new CustomAttribute(module.ImportReference(compilerGeneratedCtor)); - var unsafeValueTypeAttributeType = context.AssemblyContext.MscorlibAssembly.GetType("System.Runtime.CompilerServices.UnsafeValueTypeAttribute") ?? throw new AssertException( + var unsafeValueTypeAttributeType = new TypeReference("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute", context.AssemblyContext.MscorlibAssembly.MainModule, context.AssemblyContext.MscorlibAssembly.MainModule.TypeSystem.CoreLibrary) ?? throw new AssertException( "Cannot find a type System.Runtime.CompilerServices.UnsafeValueTypeAttribute."); var unsafeValueTypeCtor = new MethodReference(".ctor", context.TypeSystem.Void, unsafeValueTypeAttributeType); var unsafeValueTypeAttribute = new CustomAttribute(module.ImportReference(unsafeValueTypeCtor)); @@ -118,7 +118,7 @@ private static TypeDefinition CreateFixedBufferType( "", $"{fieldName}", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.SequentialLayout | TypeAttributes.NestedPublic, - module.ImportReference(context.AssemblyContext.MscorlibAssembly.GetType("System.ValueType"))) + module.ImportReference(new TypeReference("System", "ValueType", context.AssemblyContext.MscorlibAssembly.MainModule, context.AssemblyContext.MscorlibAssembly.MainModule.TypeSystem.CoreLibrary))) { PackingSize = 0, ClassSize = sizeInBytes, diff --git a/Cesium.CodeGen/Ir/Types/StructType.cs b/Cesium.CodeGen/Ir/Types/StructType.cs index 069af96a..71e9a47a 100644 --- a/Cesium.CodeGen/Ir/Types/StructType.cs +++ b/Cesium.CodeGen/Ir/Types/StructType.cs @@ -42,7 +42,7 @@ public TypeDefinition StartEmit(string name, TranslationUnitContext context) "", Identifier is null ? "" + name : Identifier, TypeAttributes.Sealed, - context.Module.ImportReference(context.AssemblyContext.MscorlibAssembly.GetType("System.ValueType"))); + context.Module.ImportReference(new TypeReference("System", "ValueType", context.AssemblyContext.MscorlibAssembly.MainModule, context.AssemblyContext.MscorlibAssembly.MainModule.TypeSystem.CoreLibrary))); switch (context.AssemblyContext.ArchitectureSet) { case TargetArchitectureSet.Dynamic: @@ -106,7 +106,7 @@ private void EmitAsAnonStructure(TranslationUnitContext context) string.Empty, CreateAnonIdentifier(Members, IsUnion), TypeAttributes.Public | TypeAttributes.Sealed, - context.Module.ImportReference(context.AssemblyContext.MscorlibAssembly.GetType("System.ValueType"))); + context.Module.ImportReference(new TypeReference("System", "ValueType", context.AssemblyContext.MscorlibAssembly.MainModule, context.AssemblyContext.MscorlibAssembly.MainModule.TypeSystem.CoreLibrary))); FinishEmit(type, type.Name, context); // emit fields From 614de2a0f7e130f42c7a5635966242a9432d2a46 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 7 Apr 2024 05:49:40 +0200 Subject: [PATCH 031/103] SDK: Add ability to publish non-AOT compiler pack --- .nuke/build.schema.json | 4 ++++ Directory.Packages.props | 4 ++-- build/Build.Sdk.cs | 5 ++++- build/Build.cs | 3 +++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index fe4add0c..e8ff42e1 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -62,6 +62,10 @@ "type": "string" } }, + "PublishAot": { + "type": "boolean", + "description": "If set to true, publishes compiler packs in AOT mode" + }, "Root": { "type": "string", "description": "Root directory during build execution" diff --git a/Directory.Packages.props b/Directory.Packages.props index e2deed85..2ca1f314 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -21,9 +21,9 @@ - + - + \ No newline at end of file diff --git a/build/Build.Sdk.cs b/build/Build.Sdk.cs index d374db47..c0de8de3 100644 --- a/build/Build.Sdk.cs +++ b/build/Build.Sdk.cs @@ -41,12 +41,15 @@ void PublishCompiler(string runtimeId) return; } - Log.Information($"Publishing for {runtimeId}..."); + Log.Information($"Publishing for {runtimeId}, AOT {(PublishAot ? "enabled" : "disabled")}..."); DotNetPublish(o => o .SetConfiguration(Configuration) .SetProject(compilerProject.ProjectFileLocation.File) .SetRuntime(runtimeId) .SetSelfContained(true) + .SetPublishTrimmed(PublishAot) + .SetPublishSingleFile(PublishAot) + .SetProperty("PublishAot", PublishAot) .SetOutput(GetCompilerRuntimePublishFolder(compilerProject, runtimeId))); } }); diff --git a/build/Build.cs b/build/Build.cs index 3a745e49..571627a2 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -24,6 +24,9 @@ public static int Main() [Parameter("If set, only executes targets for a specified runtime identifier. Provided RID must be included in property of Cesium.Compiler project.")] readonly string RuntimeId = string.Empty; + [Parameter("If set to true, publishes compiler packs in AOT mode.")] + readonly bool PublishAot = false; + Target Clean => _ => _ .Before(RestoreAll) .Executes(() => From 7b1c095478405d6811f51f3f50c7c97c17cac616 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 7 Apr 2024 05:50:40 +0200 Subject: [PATCH 032/103] SDK: Auto-publish Cesium.Runtime --- Cesium.Runtime/Cesium.Runtime.csproj | 1 + Cesium.Sdk/Sdk/Sdk.props | 10 +++++++++- Cesium.Sdk/Sdk/Sdk.targets | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Cesium.Runtime/Cesium.Runtime.csproj b/Cesium.Runtime/Cesium.Runtime.csproj index a8da8707..38cce558 100644 --- a/Cesium.Runtime/Cesium.Runtime.csproj +++ b/Cesium.Runtime/Cesium.Runtime.csproj @@ -6,6 +6,7 @@ enable true latest + true diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index 4de4e806..21406e78 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -8,6 +8,7 @@ false + false Cesium.Compiler.Pack.$(NETCoreSdkRuntimeIdentifier) 0.0.1 @@ -15,7 +16,14 @@ + PrivateAssets="all" + ExcludeAssets="runtime"/> + + + + - <_CoreLibAssembly Include="@(ReferencePath)" Condition="'%(AssemblyName)'=='System.Private.CoreLib' OR '%(AssemblyName)'=='mscorlib'" /> + <_CoreLibAssembly Include="@(ReferencePath)" Condition="'%(ReferencePath.AssemblyName)'=='System.Runtime' OR '%(ReferencePath.AssemblyName)'=='mscorlib'" /> %(_CoreLibAssembly.Identity) From 47dd8f22765e7eea57cdea5559b1e41856cdcb6f Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 7 Apr 2024 05:52:36 +0200 Subject: [PATCH 033/103] SDK: Add missing configuration & fixes - Skip ref asm copying - Generate .runtimeconfig.json - Fix missing .dll extension - Fix OutputType in test data --- .../TestProjects/SimpleProject/SimpleProject.ceproj | 1 + Cesium.Sdk/Sdk/Sdk.props | 1 + Cesium.Sdk/Sdk/Sdk.targets | 7 ++++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj index 793d194e..228362dd 100644 --- a/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj +++ b/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj @@ -1,6 +1,7 @@ net6.0 + Exe diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index 21406e78..0b681ff1 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -11,6 +11,7 @@ false Cesium.Compiler.Pack.$(NETCoreSdkRuntimeIdentifier) 0.0.1 + false diff --git a/Cesium.Sdk/Sdk/Sdk.targets b/Cesium.Sdk/Sdk/Sdk.targets index 22f16993..3008362c 100644 --- a/Cesium.Sdk/Sdk/Sdk.targets +++ b/Cesium.Sdk/Sdk/Sdk.targets @@ -2,6 +2,11 @@ + + true + false + + <_CesiumCompilerPackageFolderName Condition="$(CesiumCompilerPackagePath) == ''">$(CesiumCompilerPackageName.ToLower()) <_CesiumCompilerPackagePath>$([System.IO.Path]::Combine($(NuGetPackageRoot), $(_CesiumCompilerPackageFolderName), $(CesiumCompilerPackageVersion))) @@ -60,7 +65,7 @@ - <_CompilerOutput>$(IntermediateOutputPath)$(AssemblyName) + <_CompilerOutput>$(IntermediateOutputPath)$(AssemblyName).dll From a71e03230baa615d1eeba2fe89abd57f7ff4baf2 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 7 Apr 2024 22:45:24 +0200 Subject: [PATCH 034/103] SDK: Fix build for Exe and WinExe output types in netfx --- Cesium.Sdk/Sdk/Sdk.targets | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Cesium.Sdk/Sdk/Sdk.targets b/Cesium.Sdk/Sdk/Sdk.targets index 3008362c..c59669a6 100644 --- a/Cesium.Sdk/Sdk/Sdk.targets +++ b/Cesium.Sdk/Sdk/Sdk.targets @@ -65,7 +65,11 @@ - <_CompilerOutput>$(IntermediateOutputPath)$(AssemblyName).dll + <_CompilerOutputBase>$(IntermediateOutputPath)$(AssemblyName) + <_CompilerOutputExtenion>dll + + <_CompilerOutputExtenion Condition="$(_CesiumFramework) == 'NetFramework' AND $(OutputType) != 'Library'">exe + <_CompilerOutput>$(_CompilerOutputBase).$(_CompilerOutputExtenion) From c0840ccdd1abec37e6d29c176b60369742b31419 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 7 Apr 2024 22:46:44 +0200 Subject: [PATCH 035/103] SDK: Add more tests Including netfx tests --- Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj | 1 + Cesium.Sdk.Tests/CesiumCompileTests.cs | 92 ++++++++++++++++++- Cesium.Sdk.Tests/Framework/AssertEx.cs | 12 +++ .../IncludesAssertFailedException.cs | 8 ++ Cesium.Sdk.Tests/MSBuildCli.cs | 32 +++++++ Cesium.Sdk.Tests/SdkTestBase.cs | 29 ++++-- .../SimpleCoreExe.ceproj} | 0 .../{SimpleProject => SimpleCoreExe}/hello.c | 0 .../SimpleCoreLibrary.ceproj | 9 ++ .../TestProjects/SimpleCoreLibrary/library.c | 29 ++++++ .../SimpleNetStandardLibrary.ceproj | 9 ++ .../SimpleNetStandardLibrary/library.c | 29 ++++++ .../SimpleNetfxExe/SimpleNetfxExe.ceproj | 9 ++ .../TestProjects/SimpleNetfxExe/hello.c | 7 ++ .../SimpleNetfxLibrary.ceproj | 9 ++ .../TestProjects/SimpleNetfxLibrary/library.c | 29 ++++++ 16 files changed, 294 insertions(+), 10 deletions(-) create mode 100644 Cesium.Sdk.Tests/Framework/AssertEx.cs create mode 100644 Cesium.Sdk.Tests/Framework/IncludesAssertFailedException.cs create mode 100644 Cesium.Sdk.Tests/MSBuildCli.cs rename Cesium.Sdk.Tests/TestProjects/{SimpleProject/SimpleProject.ceproj => SimpleCoreExe/SimpleCoreExe.ceproj} (100%) rename Cesium.Sdk.Tests/TestProjects/{SimpleProject => SimpleCoreExe}/hello.c (100%) create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/SimpleCoreLibrary.ceproj create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/library.c create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/SimpleNetStandardLibrary.ceproj create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/library.c create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/SimpleNetfxExe.ceproj create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/hello.c create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/SimpleNetfxLibrary.ceproj create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/library.c diff --git a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj index f91ea2ed..eb98fcf5 100644 --- a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj +++ b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj @@ -10,6 +10,7 @@ + diff --git a/Cesium.Sdk.Tests/CesiumCompileTests.cs b/Cesium.Sdk.Tests/CesiumCompileTests.cs index 16d496dc..4a89d6c1 100644 --- a/Cesium.Sdk.Tests/CesiumCompileTests.cs +++ b/Cesium.Sdk.Tests/CesiumCompileTests.cs @@ -1,3 +1,5 @@ +using System.Runtime.InteropServices; +using Cesium.Sdk.Tests.Framework; using Xunit.Abstractions; namespace Cesium.Sdk.Tests; @@ -5,12 +7,96 @@ namespace Cesium.Sdk.Tests; public class CesiumCompileTests(ITestOutputHelper testOutputHelper) : SdkTestBase(testOutputHelper) { [Theory] - [InlineData("SimpleProject")] - public void CesiumCompile_ShouldSucceed(string projectName) + [InlineData("SimpleCoreExe")] + public void CesiumCompile_Core_Exe_ShouldSucceed(string projectName) { + HashSet expectedObjArtifacts = + [ + $"{projectName}.dll" + ]; + + var hostExeFile = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? $"{projectName}.exe" : projectName; + HashSet expectedBinArtifacts = + [ + $"{projectName}.dll", + hostExeFile, + "Cesium.Runtime.dll", + $"{projectName}.runtimeconfig.json", + $"{projectName}.deps.json", + ]; + + var result = ExecuteTargets(projectName, "Restore", "Build"); + + Assert.True(result.ExitCode == 0); + AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts); + AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts); + } + + [Theory] + [InlineData("SimpleNetfxExe")] + public void CesiumCompile_NetFx_Exe_ShouldSucceed(string projectName) + { + HashSet expectedObjArtifacts = + [ + $"{projectName}.exe" + ]; + + HashSet expectedBinArtifacts = + [ + $"{projectName}.exe", + "Cesium.Runtime.dll", + $"{projectName}.runtimeconfig.json" + ]; + + var result = ExecuteTargets(projectName, "Restore", "Build"); + + Assert.True(result.ExitCode == 0); + AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts); + AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts); + } + + [Theory] + [InlineData("SimpleCoreLibrary")] + [InlineData("SimpleNetStandardLibrary")] + public void CesiumCompile_Core_Library_ShouldSucceed(string projectName) + { + string[] expectedObjArtifacts = + [ + $"{projectName}.dll" + ]; + + string[] expectedBinArtifacts = + [ + $"{projectName}.dll", + $"{projectName}.deps.json", + ]; + + var result = ExecuteTargets(projectName, "Restore", "Build"); + + Assert.True(result.ExitCode == 0); + AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts); + AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts); + } + + [Theory] + [InlineData("SimpleNetfxLibrary")] + public void CesiumCompile_NetFxLibrary_ShouldSucceed(string projectName) + { + HashSet expectedObjArtifacts = + [ + $"{projectName}.dll" + ]; + + HashSet expectedBinArtifacts = + [ + $"{projectName}.dll", + "Cesium.Runtime.dll", + ]; + var result = ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); - // ClearOutput(); + AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts); + AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts); } } diff --git a/Cesium.Sdk.Tests/Framework/AssertEx.cs b/Cesium.Sdk.Tests/Framework/AssertEx.cs new file mode 100644 index 00000000..1bf223c7 --- /dev/null +++ b/Cesium.Sdk.Tests/Framework/AssertEx.cs @@ -0,0 +1,12 @@ +namespace Cesium.Sdk.Tests.Framework; + +public static class AssertEx +{ + public static void Includes(IReadOnlyCollection expected, IReadOnlyCollection all) + { + var foundItems = all.Where(expected.Contains).ToList(); + var remainingItems = expected.Except(foundItems).ToList(); + if (remainingItems.Count != 0) + throw new IncludesAssertFailedException(remainingItems); + } +} diff --git a/Cesium.Sdk.Tests/Framework/IncludesAssertFailedException.cs b/Cesium.Sdk.Tests/Framework/IncludesAssertFailedException.cs new file mode 100644 index 00000000..9306e719 --- /dev/null +++ b/Cesium.Sdk.Tests/Framework/IncludesAssertFailedException.cs @@ -0,0 +1,8 @@ +using Xunit.Sdk; + +namespace Cesium.Sdk.Tests.Framework; + +public class IncludesAssertFailedException( + IEnumerable expected, + Exception? innerException = null) + : XunitException($"Expected elements are missing: [{string.Join(", ", expected)}]", innerException); diff --git a/Cesium.Sdk.Tests/MSBuildCli.cs b/Cesium.Sdk.Tests/MSBuildCli.cs new file mode 100644 index 00000000..6de5291e --- /dev/null +++ b/Cesium.Sdk.Tests/MSBuildCli.cs @@ -0,0 +1,32 @@ +using System.Text.Json; +using Medallion.Shell; + +namespace Cesium.Sdk.Tests; + +public static class MSBuildCli +{ + public static string EvaluateProperty(string projectPath, string propertyName) + { + var command = Command.Run("dotnet", "msbuild", $"\"{projectPath}\"", $"-getProperty:{propertyName}"); + command.Wait(); + return command.Result.StandardOutput; + } + + public static IReadOnlyDictionary EvaluateProperties(string projectPath, params string[] propertyNames) + { + if (!propertyNames.Any()) + return new Dictionary(); + + var command = Command.Run("dotnet", "msbuild", $"\"{projectPath}\"", $"-getProperty:{string.Join(",", propertyNames)}"); + command.Wait(); + var resultString = command.Result.StandardOutput; + if (propertyNames.Length == 1) + return new Dictionary { { propertyNames[0], resultString } }; + + var resultJson = JsonDocument.Parse(resultString); + var propertiesJson = resultJson.RootElement.GetProperty("Properties").EnumerateObject().ToArray(); + + return propertiesJson + .ToDictionary(property => property.Name, property => property.Value.GetString() ?? string.Empty); + } +} diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index c4a2d837..84ec0a8a 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -1,11 +1,12 @@ using System.Diagnostics; using System.Reflection; +using System.Text.Json; using Cesium.Solution.Metadata; using Xunit.Abstractions; namespace Cesium.Sdk.Tests; -public abstract class SdkTestBase +public abstract class SdkTestBase : IDisposable { private const string _binLogFile = "build_result.binlog"; @@ -40,18 +41,22 @@ protected BuildResult ExecuteTargets(string projectName, params string[] targets var joinedTargets = string.Join(";", targets); var testProjectFile = Path.GetFullPath(Path.Combine(_temporaryPath, projectFile)); var testProjectFolder = Path.GetDirectoryName(testProjectFile) ?? throw new ArgumentNullException(nameof(testProjectFile)); + var binLogFile = Path.Combine(testProjectFolder, $"build_result_{projectName}_{DateTime.UtcNow:yyyy-dd-M_HH-mm-s}.binlog"); + + const string objFolderPropertyName = "IntermediateOutputPath"; + const string binFolderPropertyName = "OutDir"; + var startInfo = new ProcessStartInfo { WorkingDirectory = testProjectFolder, FileName = "dotnet", - Arguments = $"msbuild \"{testProjectFile}\" /t:{joinedTargets} /restore /bl:{_binLogFile}", + Arguments = $"msbuild \"{testProjectFile}\" /t:{joinedTargets} /restore /bl:{binLogFile}", RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, UseShellExecute = false, }; - using var process = new Process(); process.StartInfo = startInfo; @@ -84,13 +89,18 @@ protected BuildResult ExecuteTargets(string projectName, params string[] targets ? "Build succeeded" : $"Build failed with exit code {process.ExitCode}"); - var binFolder = Path.Combine(testProjectFolder, "bin"); - var objFolder = Path.Combine(testProjectFolder, "obj"); + var properties = MSBuildCli.EvaluateProperties(testProjectFile, objFolderPropertyName, binFolderPropertyName); + _testOutputHelper.WriteLine($"Properties request result: {JsonSerializer.Serialize(properties, new JsonSerializerOptions { WriteIndented = false })}"); + + var binFolder = Path.Combine(testProjectFolder, properties[binFolderPropertyName]); + var objFolder = Path.Combine(testProjectFolder, properties[objFolderPropertyName]); var binArtifacts = CollectArtifacts(binFolder); var objArtifacts = CollectArtifacts(objFolder); - return new BuildResult(process.ExitCode, binArtifacts, objArtifacts); + var result = new BuildResult(process.ExitCode, binArtifacts, objArtifacts); + _testOutputHelper.WriteLine($"Build result: {JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented = true })}"); + return result; IReadOnlyCollection CollectArtifacts(string folder) => Directory.Exists(folder) @@ -147,8 +157,13 @@ protected record BuildResult( IReadOnlyCollection OutputArtifacts, IReadOnlyCollection IntermediateArtifacts); - protected void ClearOutput() + private void ClearOutput() { Directory.Delete(_temporaryPath, true); } + + public void Dispose() + { + ClearOutput(); + } } diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleCoreExe/SimpleCoreExe.ceproj similarity index 100% rename from Cesium.Sdk.Tests/TestProjects/SimpleProject/SimpleProject.ceproj rename to Cesium.Sdk.Tests/TestProjects/SimpleCoreExe/SimpleCoreExe.ceproj diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleProject/hello.c b/Cesium.Sdk.Tests/TestProjects/SimpleCoreExe/hello.c similarity index 100% rename from Cesium.Sdk.Tests/TestProjects/SimpleProject/hello.c rename to Cesium.Sdk.Tests/TestProjects/SimpleCoreExe/hello.c diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/SimpleCoreLibrary.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/SimpleCoreLibrary.ceproj new file mode 100644 index 00000000..69513748 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/SimpleCoreLibrary.ceproj @@ -0,0 +1,9 @@ + + + net6.0 + Library + + + + + diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/library.c b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/library.c new file mode 100644 index 00000000..c6d65a06 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/library.c @@ -0,0 +1,29 @@ +#include + +void greet() +{ + puts("Hello World!\n"); +} + +int add(int a, int b) +{ + return a + b; +} + +int subtract(int a, int b) +{ + return a - b; +} + +float divide(int a, int b) +{ + if (b != 0) + return (float) a / b; + else + return 0; +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/SimpleNetStandardLibrary.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/SimpleNetStandardLibrary.ceproj new file mode 100644 index 00000000..06f876d5 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/SimpleNetStandardLibrary.ceproj @@ -0,0 +1,9 @@ + + + netstandard2.0 + Library + + + + + diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/library.c b/Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/library.c new file mode 100644 index 00000000..c6d65a06 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/library.c @@ -0,0 +1,29 @@ +#include + +void greet() +{ + puts("Hello World!\n"); +} + +int add(int a, int b) +{ + return a + b; +} + +int subtract(int a, int b) +{ + return a - b; +} + +float divide(int a, int b) +{ + if (b != 0) + return (float) a / b; + else + return 0; +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/SimpleNetfxExe.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/SimpleNetfxExe.ceproj new file mode 100644 index 00000000..7a2d6ae4 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/SimpleNetfxExe.ceproj @@ -0,0 +1,9 @@ + + + net48 + Exe + + + + + diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/hello.c b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/hello.c new file mode 100644 index 00000000..2889672e --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/hello.c @@ -0,0 +1,7 @@ +#include + +int main(int argc, char *argv[]) +{ + puts("Hello, world!"); + return 42; +} diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/SimpleNetfxLibrary.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/SimpleNetfxLibrary.ceproj new file mode 100644 index 00000000..c41fe5bd --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/SimpleNetfxLibrary.ceproj @@ -0,0 +1,9 @@ + + + net48 + Library + + + + + diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/library.c b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/library.c new file mode 100644 index 00000000..c6d65a06 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/library.c @@ -0,0 +1,29 @@ +#include + +void greet() +{ + puts("Hello World!\n"); +} + +int add(int a, int b) +{ + return a + b; +} + +int subtract(int a, int b) +{ + return a - b; +} + +float divide(int a, int b) +{ + if (b != 0) + return (float) a / b; + else + return 0; +} + +int multiply(int a, int b) +{ + return a * b; +} From aa6ef91b37566c79fbd602634af2984efc674d83 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Mon, 15 Apr 2024 00:28:13 +0200 Subject: [PATCH 036/103] Tests: Fix failing tests after local to global artifacts folder migration --- .../IntegrationTestContext.cs | 5 ++-- .../IntegrationTestRunner.cs | 15 ++++++------ .../Cesium.Solution.Metadata.csproj | 3 ++- Cesium.Solution.Metadata/SolutionMetadata.cs | 1 + .../SolutionMetadataAttribute.cs | 4 +++- Cesium.TestFramework/CSharpCompilationUtil.cs | 8 +++---- .../Cesium.TestFramework.csproj | 1 + Cesium.TestFramework/TestFileVerification.cs | 24 +++++++++++-------- Cesium.TestFramework/TestStructureUtil.cs | 23 ------------------ 9 files changed, 36 insertions(+), 48 deletions(-) delete mode 100644 Cesium.TestFramework/TestStructureUtil.cs diff --git a/Cesium.IntegrationTests/IntegrationTestContext.cs b/Cesium.IntegrationTests/IntegrationTestContext.cs index fc1cd10a..dc37fcf5 100644 --- a/Cesium.IntegrationTests/IntegrationTestContext.cs +++ b/Cesium.IntegrationTests/IntegrationTestContext.cs @@ -1,6 +1,7 @@ using Cesium.TestFramework; using JetBrains.Annotations; using AsyncKeyedLock; +using Cesium.Solution.Metadata; using Xunit.Abstractions; namespace Cesium.IntegrationTests; @@ -72,7 +73,7 @@ public async ValueTask DisposeAsync() private static async Task BuildRuntime(ITestOutputHelper output) { var runtimeProjectFile = Path.Combine( - TestStructureUtil.SolutionRootPath, + SolutionMetadata.SourceRoot, "Cesium.Runtime/Cesium.Runtime.csproj"); await DotNetCliHelper.BuildDotNetProject(output, BuildConfiguration, runtimeProjectFile); } @@ -80,7 +81,7 @@ private static async Task BuildRuntime(ITestOutputHelper output) private static async Task BuildCompiler(ITestOutputHelper output) { var compilerProjectFile = Path.Combine( - TestStructureUtil.SolutionRootPath, + SolutionMetadata.SourceRoot, "Cesium.Compiler/Cesium.Compiler.csproj"); await DotNetCliHelper.BuildDotNetProject(output, BuildConfiguration, compilerProjectFile); } diff --git a/Cesium.IntegrationTests/IntegrationTestRunner.cs b/Cesium.IntegrationTests/IntegrationTestRunner.cs index c012fbe3..a2ba15ca 100644 --- a/Cesium.IntegrationTests/IntegrationTestRunner.cs +++ b/Cesium.IntegrationTests/IntegrationTestRunner.cs @@ -1,3 +1,4 @@ +using Cesium.Solution.Metadata; using Cesium.TestFramework; using Xunit.Abstractions; @@ -20,7 +21,7 @@ public Task InitializeAsync() => public static IEnumerable TestCaseProvider() { - var testCaseDirectory = Path.Combine(TestStructureUtil.SolutionRootPath, "Cesium.IntegrationTests"); + var testCaseDirectory = Path.Combine(SolutionMetadata.SourceRoot, "Cesium.IntegrationTests"); var cFiles = Directory.EnumerateFileSystemEntries(testCaseDirectory, "*.c", SearchOption.AllDirectories); return cFiles .Where(file => !file.EndsWith(".ignore.c")) @@ -61,7 +62,7 @@ private async Task DoTest(string relativeSourcePath, TargetFramework targetFrame Directory.CreateDirectory(objDirPath); var sourceFilePath = Path.Combine( - TestStructureUtil.SolutionRootPath, + SolutionMetadata.SourceRoot, "Cesium.IntegrationTests", relativeSourcePath); @@ -179,7 +180,7 @@ private async Task BuildExecutableWithCesium( "run", "--no-build", "--configuration", IntegrationTestContext.BuildConfiguration, - "--project", Path.Combine(TestStructureUtil.SolutionRootPath, "Cesium.Compiler"), + "--project", Path.Combine(SolutionMetadata.SourceRoot, "Cesium.Compiler"), "--", "--nologo", sourceFilePath, @@ -192,10 +193,10 @@ private async Task BuildExecutableWithCesium( { var coreLibPath = WindowsEnvUtil.MsCorLibPath; var runtimeLibPath = Path.Combine( - TestStructureUtil.SolutionRootPath, - "Cesium.Runtime/bin", - IntegrationTestContext.BuildConfiguration, - "netstandard2.0/Cesium.Runtime.dll" + SolutionMetadata.ArtifactsRoot, + "bin/Cesium.Runtime", + $"{IntegrationTestContext.BuildConfiguration.ToLower()}_netstandard2.0", + "Cesium.Runtime.dll" ); args.AddRange(new[] { diff --git a/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj b/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj index b5708b55..099620c0 100644 --- a/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj +++ b/Cesium.Solution.Metadata/Cesium.Solution.Metadata.csproj @@ -10,7 +10,8 @@ <_Parameter1>$(CesiumSourceRoot) - <_Parameter2>$(VersionPrefix) + <_Parameter2>$(ArtifactsPath) + <_Parameter3>$(VersionPrefix) diff --git a/Cesium.Solution.Metadata/SolutionMetadata.cs b/Cesium.Solution.Metadata/SolutionMetadata.cs index 9408ea60..761c29a8 100644 --- a/Cesium.Solution.Metadata/SolutionMetadata.cs +++ b/Cesium.Solution.Metadata/SolutionMetadata.cs @@ -5,6 +5,7 @@ namespace Cesium.Solution.Metadata; public static class SolutionMetadata { public static string SourceRoot => ResolvedAttribute.SourceRoot; + public static string ArtifactsRoot => ResolvedAttribute.ArtifactsRoot; public static string VersionPrefix => ResolvedAttribute.VersionPrefix; private static SolutionMetadataAttribute ResolvedAttribute => diff --git a/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs b/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs index baa923e0..c11ac89f 100644 --- a/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs +++ b/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs @@ -3,11 +3,13 @@ namespace Cesium.Solution.Metadata; public class SolutionMetadataAttribute : Attribute { public string SourceRoot { get; } + public string ArtifactsRoot { get; } public string VersionPrefix { get; } - public SolutionMetadataAttribute(string sourceRoot, string versionPrefix) + public SolutionMetadataAttribute(string sourceRoot, string artifactsRoot, string versionPrefix) { SourceRoot = sourceRoot; + ArtifactsRoot = artifactsRoot; VersionPrefix = versionPrefix; } } diff --git a/Cesium.TestFramework/CSharpCompilationUtil.cs b/Cesium.TestFramework/CSharpCompilationUtil.cs index b6f87809..3775f015 100644 --- a/Cesium.TestFramework/CSharpCompilationUtil.cs +++ b/Cesium.TestFramework/CSharpCompilationUtil.cs @@ -2,6 +2,7 @@ using System.Xml.XPath; using AsyncKeyedLock; using Cesium.CodeGen; +using Cesium.Solution.Metadata; using Xunit.Abstractions; namespace Cesium.TestFramework; @@ -66,11 +67,10 @@ await ExecUtil.RunToSuccess( } public static readonly string CesiumRuntimeLibraryPath = Path.Combine( - TestStructureUtil.SolutionRootPath, - "Cesium.Runtime", + SolutionMetadata.ArtifactsRoot, "bin", - _configuration, - _cesiumRuntimeLibTargetRuntime, + "Cesium.Runtime", + $"{_configuration.ToLower()}_{_cesiumRuntimeLibTargetRuntime}", "Cesium.Runtime.dll"); private static Task CompileCSharpProject(ITestOutputHelper output, string directory, string projectName) => diff --git a/Cesium.TestFramework/Cesium.TestFramework.csproj b/Cesium.TestFramework/Cesium.TestFramework.csproj index a73f3be2..34cbc620 100644 --- a/Cesium.TestFramework/Cesium.TestFramework.csproj +++ b/Cesium.TestFramework/Cesium.TestFramework.csproj @@ -17,6 +17,7 @@ + diff --git a/Cesium.TestFramework/TestFileVerification.cs b/Cesium.TestFramework/TestFileVerification.cs index e04dc8f8..e73bac1c 100644 --- a/Cesium.TestFramework/TestFileVerification.cs +++ b/Cesium.TestFramework/TestFileVerification.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Text; +using Cesium.Solution.Metadata; namespace Cesium.TestFramework; @@ -49,16 +50,19 @@ private static Assembly GetTestAssembly(IEnumerable types) private static string GetTestProjectSourceDirectory(Assembly assembly) { - var currentPath = Path.GetDirectoryName(assembly.Location)!; - while (!Directory.EnumerateFileSystemEntries(currentPath, "*.csproj").Any()) - { - currentPath = Path.GetDirectoryName(currentPath); - if (currentPath == null) - throw new InvalidOperationException( - $"Could not find the test project source directory for assembly \"{assembly.Location}\"."); - } - - return currentPath; + // Assuming that output assembly name (AssemblyName MSBuild property) is equal to the project name + var projectName = assembly.GetName().Name; + if (projectName is null) + throw new InvalidOperationException( + $"Name is missing for an assembly at location \"{assembly.Location}\"."); + + var fullProjectFolderPath = Path.Combine(SolutionMetadata.SourceRoot, projectName); + var fullProjectFilePath = Path.Combine(fullProjectFolderPath, $"{projectName}.csproj"); + if (!File.Exists(fullProjectFilePath)) + throw new InvalidOperationException( + $"Could not find the test project source directory for assembly \"{assembly.Location}\"."); + + return fullProjectFolderPath; } private static IReadOnlySet GetAcceptedFilePaths(string sourceDirectory) diff --git a/Cesium.TestFramework/TestStructureUtil.cs b/Cesium.TestFramework/TestStructureUtil.cs deleted file mode 100644 index 0051d8df..00000000 --- a/Cesium.TestFramework/TestStructureUtil.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Reflection; - -namespace Cesium.TestFramework; - -public static class TestStructureUtil -{ - public static readonly string SolutionRootPath = GetSolutionRoot(); - - private static string GetSolutionRoot() - { - var assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var currentDirectory = assemblyDirectory; - while (currentDirectory != null) - { - if (File.Exists(Path.Combine(currentDirectory, "Cesium.sln"))) - return currentDirectory; - - currentDirectory = Path.GetDirectoryName(currentDirectory); - } - - throw new Exception($"Could not find the solution directory going up from directory \"{assemblyDirectory}\"."); - } -} From 8f6189852009c3f80b5d962df60ff9ca62b70ea4 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Mon, 15 Apr 2024 00:28:56 +0200 Subject: [PATCH 037/103] SDK: Include full path information for artifacts coming from build --- Cesium.Sdk.Tests/CesiumCompileTests.cs | 16 ++++++++-------- .../{MSBuildCli.cs => MSBuildCLI.cs} | 2 +- Cesium.Sdk.Tests/SdkTestBase.cs | 16 ++++++++++------ 3 files changed, 19 insertions(+), 15 deletions(-) rename Cesium.Sdk.Tests/{MSBuildCli.cs => MSBuildCLI.cs} (97%) diff --git a/Cesium.Sdk.Tests/CesiumCompileTests.cs b/Cesium.Sdk.Tests/CesiumCompileTests.cs index 4a89d6c1..e8a66b85 100644 --- a/Cesium.Sdk.Tests/CesiumCompileTests.cs +++ b/Cesium.Sdk.Tests/CesiumCompileTests.cs @@ -28,8 +28,8 @@ public void CesiumCompile_Core_Exe_ShouldSucceed(string projectName) var result = ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); - AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts); - AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts); + AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); + AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); } [Theory] @@ -51,8 +51,8 @@ public void CesiumCompile_NetFx_Exe_ShouldSucceed(string projectName) var result = ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); - AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts); - AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts); + AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); + AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); } [Theory] @@ -74,8 +74,8 @@ public void CesiumCompile_Core_Library_ShouldSucceed(string projectName) var result = ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); - AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts); - AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts); + AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); + AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); } [Theory] @@ -96,7 +96,7 @@ public void CesiumCompile_NetFxLibrary_ShouldSucceed(string projectName) var result = ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); - AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts); - AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts); + AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); + AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); } } diff --git a/Cesium.Sdk.Tests/MSBuildCli.cs b/Cesium.Sdk.Tests/MSBuildCLI.cs similarity index 97% rename from Cesium.Sdk.Tests/MSBuildCli.cs rename to Cesium.Sdk.Tests/MSBuildCLI.cs index 6de5291e..831aca90 100644 --- a/Cesium.Sdk.Tests/MSBuildCli.cs +++ b/Cesium.Sdk.Tests/MSBuildCLI.cs @@ -3,7 +3,7 @@ namespace Cesium.Sdk.Tests; -public static class MSBuildCli +public static class MSBuildCLI { public static string EvaluateProperty(string projectPath, string propertyName) { diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index 84ec0a8a..35ec1f5d 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -89,7 +89,7 @@ protected BuildResult ExecuteTargets(string projectName, params string[] targets ? "Build succeeded" : $"Build failed with exit code {process.ExitCode}"); - var properties = MSBuildCli.EvaluateProperties(testProjectFile, objFolderPropertyName, binFolderPropertyName); + var properties = MSBuildCLI.EvaluateProperties(testProjectFile, objFolderPropertyName, binFolderPropertyName); _testOutputHelper.WriteLine($"Properties request result: {JsonSerializer.Serialize(properties, new JsonSerializerOptions { WriteIndented = false })}"); var binFolder = Path.Combine(testProjectFolder, properties[binFolderPropertyName]); @@ -102,12 +102,12 @@ protected BuildResult ExecuteTargets(string projectName, params string[] targets _testOutputHelper.WriteLine($"Build result: {JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented = true })}"); return result; - IReadOnlyCollection CollectArtifacts(string folder) => + IReadOnlyCollection CollectArtifacts(string folder) => Directory.Exists(folder) ? Directory.GetFiles(folder, "*.*", SearchOption.AllDirectories) - .Select(path => Path.GetRelativePath(folder, path)) + .Select(path => new BuildArtifact(Path.GetRelativePath(folder, path), path)) .ToList() - : Array.Empty(); + : Array.Empty(); } private static void EmitNuGetConfig(string configFilePath, string packageSourcePath) @@ -154,8 +154,12 @@ private static void CopyDirectoryRecursive(string source, string target) protected record BuildResult( int ExitCode, - IReadOnlyCollection OutputArtifacts, - IReadOnlyCollection IntermediateArtifacts); + IReadOnlyCollection OutputArtifacts, + IReadOnlyCollection IntermediateArtifacts); + + protected record BuildArtifact( + string FileName, + string FullPath); private void ClearOutput() { From ebcc54fc5b5f4397dc84b8435e52992634154de3 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Mon, 15 Apr 2024 02:13:09 +0200 Subject: [PATCH 038/103] CI: Include SDK tests into build workflow --- .github/workflows/perform-common-steps/action.yml | 4 ++++ .github/workflows/run-build-and-unit-tests.yml | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/perform-common-steps/action.yml b/.github/workflows/perform-common-steps/action.yml index fdf54aa2..3f36ba61 100644 --- a/.github/workflows/perform-common-steps/action.yml +++ b/.github/workflows/perform-common-steps/action.yml @@ -14,6 +14,10 @@ runs: path: ${{ env.NUGET_PACKAGES }} key: ${{ runner.os }}.nuget.${{ hashFiles('**/*.csproj') }} + - name: 🛠️ Restore local .NET tools 🛠️ + shell: bash + run: dotnet tool restore + - name: 🔄 Restore Nuget Packages 🔄 shell: bash run: dotnet restore diff --git a/.github/workflows/run-build-and-unit-tests.yml b/.github/workflows/run-build-and-unit-tests.yml index 840fbba7..90c39bd7 100644 --- a/.github/workflows/run-build-and-unit-tests.yml +++ b/.github/workflows/run-build-and-unit-tests.yml @@ -34,6 +34,14 @@ jobs: shell: bash run: dotnet build + - name: 🚚 Publish Compiler Packs 🚚 + shell: bash + run: dotnet nuke PublishCompilerPacks + + - name: 📦 Pack Compiler Packs 📦 + shell: bash + run: dotnet nuke PackCompilerPacks + - name: ✅ Run Unit Tests ✅ shell: bash - run: dotnet test + run: dotnet nuke TestAll --configuration Debug From f6d1f9eaae833ef2d4cdd0c8967ad5c2d5369bcb Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Mon, 15 Apr 2024 02:13:52 +0200 Subject: [PATCH 039/103] CI: Fix different issues on CI because of SDK implementation --- .../{ => Framework}/MSBuildCLI.cs | 0 Cesium.Sdk.Tests/SdkTestBase.cs | 20 +++++++++++++++---- build/Build.Sdk.cs | 1 - global.json | 6 +++--- nuget.config | 1 - 5 files changed, 19 insertions(+), 9 deletions(-) rename Cesium.Sdk.Tests/{ => Framework}/MSBuildCLI.cs (100%) diff --git a/Cesium.Sdk.Tests/MSBuildCLI.cs b/Cesium.Sdk.Tests/Framework/MSBuildCLI.cs similarity index 100% rename from Cesium.Sdk.Tests/MSBuildCLI.cs rename to Cesium.Sdk.Tests/Framework/MSBuildCLI.cs diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index 35ec1f5d..f3669540 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Reflection; +using System.Runtime.InteropServices; using System.Text.Json; using Cesium.Solution.Metadata; using Xunit.Abstractions; @@ -92,8 +93,8 @@ protected BuildResult ExecuteTargets(string projectName, params string[] targets var properties = MSBuildCLI.EvaluateProperties(testProjectFile, objFolderPropertyName, binFolderPropertyName); _testOutputHelper.WriteLine($"Properties request result: {JsonSerializer.Serialize(properties, new JsonSerializerOptions { WriteIndented = false })}"); - var binFolder = Path.Combine(testProjectFolder, properties[binFolderPropertyName]); - var objFolder = Path.Combine(testProjectFolder, properties[objFolderPropertyName]); + var binFolder = NormalizePath(Path.GetFullPath(properties[binFolderPropertyName], testProjectFolder)); + var objFolder = NormalizePath(Path.GetFullPath(properties[objFolderPropertyName], testProjectFolder)); var binArtifacts = CollectArtifacts(binFolder); var objArtifacts = CollectArtifacts(objFolder); @@ -102,12 +103,15 @@ protected BuildResult ExecuteTargets(string projectName, params string[] targets _testOutputHelper.WriteLine($"Build result: {JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented = true })}"); return result; - IReadOnlyCollection CollectArtifacts(string folder) => - Directory.Exists(folder) + IReadOnlyCollection CollectArtifacts(string folder) + { + _testOutputHelper.WriteLine($"Collecting artifacts from '{folder}' folder"); + return Directory.Exists(folder) ? Directory.GetFiles(folder, "*.*", SearchOption.AllDirectories) .Select(path => new BuildArtifact(Path.GetRelativePath(folder, path), path)) .ToList() : Array.Empty(); + } } private static void EmitNuGetConfig(string configFilePath, string packageSourcePath) @@ -152,6 +156,14 @@ private static void CopyDirectoryRecursive(string source, string target) } } + private static string NormalizePath(string path) + { + var normalizedPath = new Uri(path).LocalPath; + return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? normalizedPath + : normalizedPath.Replace('\\', '/'); + } + protected record BuildResult( int ExitCode, IReadOnlyCollection OutputArtifacts, diff --git a/build/Build.Sdk.cs b/build/Build.Sdk.cs index c0de8de3..cdd93615 100644 --- a/build/Build.Sdk.cs +++ b/build/Build.Sdk.cs @@ -34,7 +34,6 @@ public partial class Build void PublishCompiler(string runtimeId) { - Log.Information(SkipCaches+""); if (!SkipCaches && !NeedPublishCompilerPack(compilerProject, runtimeId)) { Log.Information($"Skipping {runtimeId} because it was already published. Use '--skip-caches true' to re-publish."); diff --git a/global.json b/global.json index c65c9eac..36394634 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "sdk": { "version": "8.0.0", - "rollForward": "latestMinor", - "allowPrerelease": true + "rollForward": "latestFeature", + "allowPrerelease": false } -} \ No newline at end of file +} diff --git a/nuget.config b/nuget.config index 6fd055e8..32d08817 100644 --- a/nuget.config +++ b/nuget.config @@ -4,7 +4,6 @@ - From b148d8f3d29f2e939a88bb6f55989a0dfb9859d0 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Wed, 17 Apr 2024 20:50:12 +0200 Subject: [PATCH 040/103] SDK: Refactor compiler bundle producing, add docs - Add docs about MSBuild SDK - Add info about SDK tests - Use NUKE in tests docs - Rename compiler pack -> compiler bundle - Introduce CI-friendly single pack and publish compiler bundle targets --- .../workflows/perform-common-steps/action.yml | 2 +- .../workflows/run-build-and-unit-tests.yml | 12 +-- .nuke/build.schema.json | 14 ++- Cesium.Sdk/Sdk/Sdk.props | 2 +- Cesium.sln | 1 + README.md | 1 + build/Build.Sdk.cs | 99 ++++++++++--------- build/Build.Tests.cs | 2 +- build/Build.cs | 8 +- docs/msbuild-sdk.md | 64 ++++++++++++ docs/tests.md | 49 +++++++-- 11 files changed, 184 insertions(+), 70 deletions(-) create mode 100644 docs/msbuild-sdk.md diff --git a/.github/workflows/perform-common-steps/action.yml b/.github/workflows/perform-common-steps/action.yml index 3f36ba61..696bac90 100644 --- a/.github/workflows/perform-common-steps/action.yml +++ b/.github/workflows/perform-common-steps/action.yml @@ -20,4 +20,4 @@ runs: - name: 🔄 Restore Nuget Packages 🔄 shell: bash - run: dotnet restore + run: dotnet nuke RestoreAll diff --git a/.github/workflows/run-build-and-unit-tests.yml b/.github/workflows/run-build-and-unit-tests.yml index 90c39bd7..d4cc8566 100644 --- a/.github/workflows/run-build-and-unit-tests.yml +++ b/.github/workflows/run-build-and-unit-tests.yml @@ -32,16 +32,16 @@ jobs: - name: 🛠 Build Solution 🛠 shell: bash - run: dotnet build + run: dotnet nuke CompileAll - - name: 🚚 Publish Compiler Packs 🚚 + - name: 🚚 Publish Compiler Bundle 🚚 shell: bash - run: dotnet nuke PublishCompilerPacks + run: dotnet nuke PublishCompilerBundle - - name: 📦 Pack Compiler Packs 📦 + - name: 📦 Pack Compiler Bundle 📦 shell: bash - run: dotnet nuke PackCompilerPacks + run: dotnet nuke PackCompilerBundle - name: ✅ Run Unit Tests ✅ shell: bash - run: dotnet nuke TestAll --configuration Debug + run: dotnet nuke TestAll diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index e8ff42e1..ffb7d189 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -8,7 +8,7 @@ "properties": { "Configuration": { "type": "string", - "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)", + "description": "Configuration to build - Default is 'Debug' or 'Release'", "enum": [ "Debug", "Release" @@ -83,9 +83,11 @@ "Clean", "CompileAll", "ForceClear", - "PackCompilerPacks", + "PackAllCompilerBundles", + "PackCompilerBundle", "PackSdk", - "PublishCompilerPacks", + "PublishAllCompilerBundles", + "PublishCompilerBundle", "RestoreAll", "TestAll", "TestCodeGen", @@ -114,9 +116,11 @@ "Clean", "CompileAll", "ForceClear", - "PackCompilerPacks", + "PackAllCompilerBundles", + "PackCompilerBundle", "PackSdk", - "PublishCompilerPacks", + "PublishAllCompilerBundles", + "PublishCompilerBundle", "RestoreAll", "TestAll", "TestCodeGen", diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index 0b681ff1..e8e643e6 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -9,7 +9,7 @@ false false - Cesium.Compiler.Pack.$(NETCoreSdkRuntimeIdentifier) + Cesium.Compiler.Bundle.$(NETCoreSdkRuntimeIdentifier) 0.0.1 false diff --git a/Cesium.sln b/Cesium.sln index af719a7a..cc4bd6c6 100644 --- a/Cesium.sln +++ b/Cesium.sln @@ -64,6 +64,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{986C6A13-2 docs\tests.md = docs\tests.md docs\type-system.md = docs\type-system.md docs\design-notes.md = docs\design-notes.md + docs\msbuild-sdk.md = docs\msbuild-sdk.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cesium.Preprocessor", "Cesium.Preprocessor\Cesium.Preprocessor.csproj", "{0CDF730D-2A2A-437F-B27F-2BB04770C709}" diff --git a/README.md b/README.md index deb212e4..eda2cbc2 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ Documentation - [Contributor Guide][docs.contributing] - [Cesium Tests][docs.tests] - [Cesium Type System][docs.type-system] +- [Cesium SDK][docs.msbuild-sdk] - [Architecture Sets][docs.architecture-sets] - [CLI-Related Language Extensions][docs.language-extensions] - [Built-in Functions][docs.builtins] diff --git a/build/Build.Sdk.cs b/build/Build.Sdk.cs index cdd93615..c158a46b 100644 --- a/build/Build.Sdk.cs +++ b/build/Build.Sdk.cs @@ -11,9 +11,9 @@ public partial class Build { - const string _compilerPackPackagePrefix = "Cesium.Compiler.Pack"; + const string _compilerPackPackagePrefix = "Cesium.Compiler.Bundle"; - Target PublishCompilerPacks => _ => _ + Target PublishAllCompilerBundles => _ => _ .Executes(() => { var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); @@ -22,39 +22,18 @@ public partial class Build Log.Information( $"Runtime identifiers defined in {Solution.Cesium_Compiler.Name}: {string.Join(", ", runtimeIds)}"); - if (!string.IsNullOrEmpty(RuntimeId)) - { - Log.Information($"Executing only {RuntimeId} because it was specified explicitly."); - PublishCompiler(RuntimeId); - return; - } - foreach (var runtimeId in runtimeIds) PublishCompiler(runtimeId); + }); - void PublishCompiler(string runtimeId) - { - if (!SkipCaches && !NeedPublishCompilerPack(compilerProject, runtimeId)) - { - Log.Information($"Skipping {runtimeId} because it was already published. Use '--skip-caches true' to re-publish."); - return; - } - - Log.Information($"Publishing for {runtimeId}, AOT {(PublishAot ? "enabled" : "disabled")}..."); - DotNetPublish(o => o - .SetConfiguration(Configuration) - .SetProject(compilerProject.ProjectFileLocation.File) - .SetRuntime(runtimeId) - .SetSelfContained(true) - .SetPublishTrimmed(PublishAot) - .SetPublishSingleFile(PublishAot) - .SetProperty("PublishAot", PublishAot) - .SetOutput(GetCompilerRuntimePublishFolder(compilerProject, runtimeId))); - } + Target PublishCompilerBundle => _ => _ + .Executes(() => + { + PublishCompiler(EffectiveRuntimeId); }); - Target PackCompilerPacks => _ => _ - .DependsOn(PublishCompilerPacks) + Target PackAllCompilerBundles => _ => _ + .DependsOn(PublishAllCompilerBundles) .Executes(() => { var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); @@ -63,27 +42,15 @@ void PublishCompiler(string runtimeId) Log.Information( $"Runtime identifiers defined in {Solution.Cesium_Compiler.Name}: {string.Join(", ", runtimeIds)}"); - if (!string.IsNullOrEmpty(RuntimeId)) - { - Log.Information($"Executing only {RuntimeId} because it was specified explicitly."); - PackCompiler(RuntimeId); - return; - } - foreach (var runtimeId in runtimeIds) PackCompiler(runtimeId); + }); - void PackCompiler(string runtimeId) - { - if (!SkipCaches && !NeedPackageCompilerPack(compilerProject, runtimeId)) - { - Log.Information($"Skipping {runtimeId} because it was already packed. Use '--skip-caches true' to re-pack."); - return; - } - - Log.Information($"Packing compiler for {runtimeId}..."); - EmitCompilerPack(runtimeId, compilerProject); - } + Target PackCompilerBundle => _ => _ + .DependsOn(PublishCompilerBundle) + .Executes(() => + { + PackCompiler(EffectiveRuntimeId); }); Target PackSdk => _ => _ @@ -145,6 +112,42 @@ IEnumerable GetPhysicalFiles(string publishDirectory, IEnumerable< } } + void PublishCompiler(string runtimeId) + { + var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); + + if (!SkipCaches && !NeedPublishCompilerPack(compilerProject, runtimeId)) + { + Log.Information($"Skipping {runtimeId} because it was already published. Use '--skip-caches true' to re-publish."); + return; + } + + Log.Information($"Publishing for {runtimeId}, AOT {(PublishAot ? "enabled" : "disabled")}..."); + DotNetPublish(o => o + .SetConfiguration(Configuration) + .SetProject(compilerProject.ProjectFileLocation.File) + .SetRuntime(runtimeId) + .SetSelfContained(true) + .SetPublishTrimmed(PublishAot) + .SetPublishSingleFile(PublishAot) + .SetProperty("PublishAot", PublishAot) + .SetOutput(GetCompilerRuntimePublishFolder(compilerProject, runtimeId))); + } + + void PackCompiler(string runtimeId) + { + var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); + + if (!SkipCaches && !NeedPackageCompilerPack(compilerProject, runtimeId)) + { + Log.Information($"Skipping {runtimeId} because it was already packed. Use '--skip-caches true' to re-pack."); + return; + } + + Log.Information($"Packing compiler for {runtimeId}..."); + EmitCompilerPack(runtimeId, compilerProject); + } + string GetCompilerRuntimePublishFolder(Project compilerProject, string runtimeId) => Path.Combine( compilerProject.GetProperty("ArtifactsPath").EvaluatedValue, diff --git a/build/Build.Tests.cs b/build/Build.Tests.cs index 0a8a5747..b31bde9a 100644 --- a/build/Build.Tests.cs +++ b/build/Build.Tests.cs @@ -21,7 +21,7 @@ partial class Build .Executes(() => ExecuteTests(Solution.Cesium_Runtime_Tests)); Target TestSdk => _ => _ - .DependsOn(PackCompilerPacks) + .DependsOn(PackCompilerBundle) .DependsOn(PackSdk) .Executes(() => ExecuteTests(Solution.Cesium_Sdk_Tests)); diff --git a/build/Build.cs b/build/Build.cs index 571627a2..303ba6f8 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -12,8 +12,8 @@ public static int Main() return Execute(x => x.CompileAll); } - [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] - readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; + [Parameter("Configuration to build - Default is 'Debug' or 'Release'")] + readonly Configuration Configuration = Configuration.Debug; [Parameter("If set to true, ignores all cached build results. Default: false")] readonly bool SkipCaches = false; @@ -24,6 +24,10 @@ public static int Main() [Parameter("If set, only executes targets for a specified runtime identifier. Provided RID must be included in property of Cesium.Compiler project.")] readonly string RuntimeId = string.Empty; + string EffectiveRuntimeId => !string.IsNullOrEmpty(RuntimeId) + ? RuntimeId + : Solution.Cesium_Compiler.GetProperty("DefaultAppHostRuntimeIdentifier") ?? string.Empty; + [Parameter("If set to true, publishes compiler packs in AOT mode.")] readonly bool PublishAot = false; diff --git a/docs/msbuild-sdk.md b/docs/msbuild-sdk.md new file mode 100644 index 00000000..f5fce3bb --- /dev/null +++ b/docs/msbuild-sdk.md @@ -0,0 +1,64 @@ +Cesium MSBuild Project SDK +-------------------------- + +Cesium provides it's own project SDK that could be used to simplify building of Cesium programs and libraries. + +Cesium MSBuild SDK inherits default behavior from a `Microsoft.NET.Sdk` SDK and tries to integrate with it the same way as C# does. + +Cesium MSBuild SDK only supports SDK-style projects. + +> Note: Some of the common MSBuild properties and items those are not stated in this document could be also used in Cesium project files. Not all of them are tested so something may not work as expected. + +### Source files +Source files are defined with `` items, very similar to other .NET languages: +```xml + + + + +``` +> Note: In the current SDK implementation, compile units should be defined explicitly, in opposite to C# `` items. + +### References + +#### Packages +Not supported yet. + +#### Projects +Not supported yet. + +#### Assemblies +Not supported yet. + +### Preprocessor directives +`` property is directly mapped to a list of preprocessor items. So, you could define such constants in .csproj: +```xml + + $(DefineConstants);FOO;BAR + +``` + +And then use it in your .c code: +```c++ +#ifdef FOO +int foo() { return 0; } +#endif + +#ifdef BAR +int bar() { return 1; } +#endif +``` + +### Output files +Output assembly and additional artifacts will be placed in `bin` folder. Depending on the target framework, output type and a platform you're compiling on, `.runtimeconfig.json` and `.deps.json` files will also be generated. + +### Properties +- `SkipCesiumCompilerInstallation`: if set to `true`, doesn't automatically install a compiler bundle package. In that case it should be explicitly provided by `CesiumCompilerPackageName` and `CesiumCompilerPackageVersion` properties. Default: `false` +- `SkipCesiumRuntimeInstallation`: if set to `true`, doesn't automatically install a `Cesium.Runtime` package. In that case it should be explicitly installed. Default: `false` +- `CesiumCompilerPackageName`: an optional platform-specific compiler bundle package name. Should be specified if `SkipCesiumCompilerInstallation` set to `true`. Default: `Cesium.Compiler.Pack.{RID}` +- `CesiumCompilerPackageName`: an optional platform-specific compiler bundle package version. Should be specified if `SkipCesiumCompilerInstallation` set to `true`. Default: Cesium SDK version +- `CesiumCompilerPath`: an optional path to compiler executable. Use this property to specify a path to the compiler not coming from a compiler package. +- `CesiumCoreLibAssemblyPath`: an optional path to .NET runtime assembly: `System.Runtime` or `mscorlib`, depending on the target framework. + +### Items +- `Compile`: a C source file to be included into compiler execution command diff --git a/docs/tests.md b/docs/tests.md index f27e486d..30781b70 100644 --- a/docs/tests.md +++ b/docs/tests.md @@ -3,16 +3,32 @@ Cesium Tests Being a compiler, Cesium requires a complicated test suite checking every feature. -There are two kinds of tests in Cesium: unit tests (directly calling various internal APIs in the compiler) and integration tests (interacting with the compiler executable and comparing the resulting programs' behavior with programs compiled by other compilers). +There are three kinds of tests in Cesium: unit tests (directly calling various internal APIs in the compiler), integration tests (interacting with the compiler executable and comparing the resulting programs' behavior with programs compiled by other compilers) and SDK tests (testing integration with MSBuild via MSBuild project SDK). -Unit Tests ----------- -Unit tests in Cesium are normal .NET tests, so they are runnable by the following shell command: -s +Running Tests +------------- +To run all tests from solution, make sure to restore locally installed tools: +```console +dotnet tool restore +``` + +Then, run `TestAll` target using NUKE: ```console -$ dotnet test +dotnet nuke TestAll ``` +You could also execute test from specific corresponding test projects: +- `dotnet nuke TestParser` +- `dotnet nuke TestCompiler` +- `dotnet nuke TestCodeGen` +- `dotnet nuke TestRuntime` +- `dotnet nuke TestIntegration` +- `dotnet nuke TestSdk` + +Unit Tests +---------- +Unit tests in Cesium are normal .NET tests. + There are two kinds of unit tests: a few of "the real" unit tests (e.g. `Cesium.Parser.Tests.LexerTests.IdentifierTests`) and a set of [characterization tests][wiki.characterization-tests]. The real unit tests verify certain facts using assertions of the Xunit testing framework, but their usage in the compiler is small. The characterization tests, on the other hand, invoke parts of the compiler on various sources, and then dump the results (e.g. a full parse tree of a code fragment, or a whole compiled assembly). The characterization tests comprise the biggest part of the compiler test suite, and it helps us to thoroughly verify the most aspects of the compiler behavior. @@ -53,3 +69,24 @@ There are two categories of integration tests: .NET interop tests and compiler v [wiki.characterization-tests]: https://en.wikipedia.org/wiki/Characterization_test +SDK Tests +--------- +#### How SDK tests work +SDK tests check correctness of integration with MSBuild. They are focused on build output, including artifacts existence asserting. + +SDK tests (and Cesium Project SDK itself) require compiler bundle to be built and packed. A compiler bundle is a special platform-specific NuGet package containing a published compiler executable with dependencies. It is not intended to be used as a runtime dependency and only used while building project. + +Compiler packing is done by 2 NUKE targets: +- `PublishCompilerBundle`: a target that make platform-specific `dotnet publish` of compiler bundle to corresponding artifacts' folder. +- `PackCompilerBundle`: a target that wraps a published compiler bundle into a NuGet package which is then used by SDK to deliver compiler to user's project + +Both targets are called automatically when `TestSdk` target is invoked. + +SDK itself should also be built to be used in test projects. This is done by dependent target `PackSdk` which produces `Cesium.Sdk` NuGet package, suitable as Project SDK. + +Having all necessary dependencies, SDK tests are invoking `dotnet build` CLI with test projects, representing different layouts and configurations. Test result is determined by MSBuild output and artifacts presence. + +#### Adding new tests +Adding new tests is quite straightforward. +1. Add a test project if needed to the `TestProjects` directory. All items from that folder will be automatically included into temporary test execution directory. +2. Write a test with the new test project in use. Look for the examples at `CesiumCompileTests.cs`. From 51b095e02c0bf47deb766afe06ad356d98d70da6 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Thu, 18 Apr 2024 15:26:05 +0200 Subject: [PATCH 041/103] SDK: Fix missing reference about MSBuild SDK docs in README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index eda2cbc2..ebbb3369 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ If you're interested in certain project areas, check the per-area issue labels: [docs.builtins]: docs/builtins.md [docs.contributing]: CONTRIBUTING.md [docs.design-notes]: docs/design-notes.md +[docs.msbuild-sdk]: docs/msbuild-sdk.md [docs.exceptions]: docs/exceptions.md [docs.language-extensions]: docs/language-extensions.md [docs.license]: LICENSE.md From ce1f14abface1816b9a6652c8da1bbe7717d8fa1 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Thu, 18 Apr 2024 16:08:51 +0200 Subject: [PATCH 042/103] SDK: Fix line endings in NUKE build.sh script --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..73e5a20a --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +build.sh eol=lf From 852a05baaa8372697c12bf7d43823aa3ef8f15fe Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Fri, 19 Apr 2024 22:18:06 +0200 Subject: [PATCH 043/103] SDK: Move SDK helpers into TestFramework --- Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj | 2 +- Cesium.Sdk.Tests/CesiumCompileTests.cs | 34 +++++++++---------- Cesium.Sdk.Tests/Framework/MSBuildCLI.cs | 32 ----------------- Cesium.Sdk.Tests/SdkTestBase.cs | 7 ++-- .../AssertCollection.cs | 6 ++-- Cesium.TestFramework/DotNetCliHelper.cs | 24 +++++++++++++ .../IncludesAssertFailedException.cs | 2 +- 7 files changed, 50 insertions(+), 57 deletions(-) delete mode 100644 Cesium.Sdk.Tests/Framework/MSBuildCLI.cs rename Cesium.Sdk.Tests/Framework/AssertEx.cs => Cesium.TestFramework/AssertCollection.cs (76%) rename {Cesium.Sdk.Tests/Framework => Cesium.TestFramework/Exceptions}/IncludesAssertFailedException.cs (84%) diff --git a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj index eb98fcf5..2d715572 100644 --- a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj +++ b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj @@ -31,7 +31,7 @@ - + diff --git a/Cesium.Sdk.Tests/CesiumCompileTests.cs b/Cesium.Sdk.Tests/CesiumCompileTests.cs index e8a66b85..11bf5c45 100644 --- a/Cesium.Sdk.Tests/CesiumCompileTests.cs +++ b/Cesium.Sdk.Tests/CesiumCompileTests.cs @@ -1,5 +1,5 @@ using System.Runtime.InteropServices; -using Cesium.Sdk.Tests.Framework; +using Cesium.TestFramework; using Xunit.Abstractions; namespace Cesium.Sdk.Tests; @@ -8,7 +8,7 @@ public class CesiumCompileTests(ITestOutputHelper testOutputHelper) : SdkTestBas { [Theory] [InlineData("SimpleCoreExe")] - public void CesiumCompile_Core_Exe_ShouldSucceed(string projectName) + public async Task CesiumCompile_Core_Exe_ShouldSucceed(string projectName) { HashSet expectedObjArtifacts = [ @@ -25,16 +25,16 @@ public void CesiumCompile_Core_Exe_ShouldSucceed(string projectName) $"{projectName}.deps.json", ]; - var result = ExecuteTargets(projectName, "Restore", "Build"); + var result = await ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); - AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); - AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); + AssertCollection.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); + AssertCollection.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); } [Theory] [InlineData("SimpleNetfxExe")] - public void CesiumCompile_NetFx_Exe_ShouldSucceed(string projectName) + public async Task CesiumCompile_NetFx_Exe_ShouldSucceed(string projectName) { HashSet expectedObjArtifacts = [ @@ -48,17 +48,17 @@ public void CesiumCompile_NetFx_Exe_ShouldSucceed(string projectName) $"{projectName}.runtimeconfig.json" ]; - var result = ExecuteTargets(projectName, "Restore", "Build"); + var result = await ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); - AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); - AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); + AssertCollection.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); + AssertCollection.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); } [Theory] [InlineData("SimpleCoreLibrary")] [InlineData("SimpleNetStandardLibrary")] - public void CesiumCompile_Core_Library_ShouldSucceed(string projectName) + public async Task CesiumCompile_Core_Library_ShouldSucceed(string projectName) { string[] expectedObjArtifacts = [ @@ -71,16 +71,16 @@ public void CesiumCompile_Core_Library_ShouldSucceed(string projectName) $"{projectName}.deps.json", ]; - var result = ExecuteTargets(projectName, "Restore", "Build"); + var result = await ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); - AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); - AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); + AssertCollection.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); + AssertCollection.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); } [Theory] [InlineData("SimpleNetfxLibrary")] - public void CesiumCompile_NetFxLibrary_ShouldSucceed(string projectName) + public async Task CesiumCompile_NetFxLibrary_ShouldSucceed(string projectName) { HashSet expectedObjArtifacts = [ @@ -93,10 +93,10 @@ public void CesiumCompile_NetFxLibrary_ShouldSucceed(string projectName) "Cesium.Runtime.dll", ]; - var result = ExecuteTargets(projectName, "Restore", "Build"); + var result = await ExecuteTargets(projectName, "Restore", "Build"); Assert.True(result.ExitCode == 0); - AssertEx.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); - AssertEx.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); + AssertCollection.Includes(expectedObjArtifacts, result.IntermediateArtifacts.Select(a => a.FileName).ToList()); + AssertCollection.Includes(expectedBinArtifacts, result.OutputArtifacts.Select(a => a.FileName).ToList()); } } diff --git a/Cesium.Sdk.Tests/Framework/MSBuildCLI.cs b/Cesium.Sdk.Tests/Framework/MSBuildCLI.cs deleted file mode 100644 index 831aca90..00000000 --- a/Cesium.Sdk.Tests/Framework/MSBuildCLI.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Text.Json; -using Medallion.Shell; - -namespace Cesium.Sdk.Tests; - -public static class MSBuildCLI -{ - public static string EvaluateProperty(string projectPath, string propertyName) - { - var command = Command.Run("dotnet", "msbuild", $"\"{projectPath}\"", $"-getProperty:{propertyName}"); - command.Wait(); - return command.Result.StandardOutput; - } - - public static IReadOnlyDictionary EvaluateProperties(string projectPath, params string[] propertyNames) - { - if (!propertyNames.Any()) - return new Dictionary(); - - var command = Command.Run("dotnet", "msbuild", $"\"{projectPath}\"", $"-getProperty:{string.Join(",", propertyNames)}"); - command.Wait(); - var resultString = command.Result.StandardOutput; - if (propertyNames.Length == 1) - return new Dictionary { { propertyNames[0], resultString } }; - - var resultJson = JsonDocument.Parse(resultString); - var propertiesJson = resultJson.RootElement.GetProperty("Properties").EnumerateObject().ToArray(); - - return propertiesJson - .ToDictionary(property => property.Name, property => property.Value.GetString() ?? string.Empty); - } -} diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index f3669540..1cf09d62 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -3,14 +3,13 @@ using System.Runtime.InteropServices; using System.Text.Json; using Cesium.Solution.Metadata; +using Cesium.TestFramework; using Xunit.Abstractions; namespace Cesium.Sdk.Tests; public abstract class SdkTestBase : IDisposable { - private const string _binLogFile = "build_result.binlog"; - private readonly ITestOutputHelper _testOutputHelper; private readonly string _temporaryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); @@ -36,7 +35,7 @@ public SdkTestBase(ITestOutputHelper testOutputHelper) EmitGlobalJson(GlobalJsonPath, $"{SolutionMetadata.VersionPrefix}"); } - protected BuildResult ExecuteTargets(string projectName, params string[] targets) + protected async Task ExecuteTargets(string projectName, params string[] targets) { var projectFile = $"{projectName}/{projectName}.ceproj"; var joinedTargets = string.Join(";", targets); @@ -90,7 +89,7 @@ protected BuildResult ExecuteTargets(string projectName, params string[] targets ? "Build succeeded" : $"Build failed with exit code {process.ExitCode}"); - var properties = MSBuildCLI.EvaluateProperties(testProjectFile, objFolderPropertyName, binFolderPropertyName); + var properties = await DotNetCliHelper.EvaluateMSBuildProperties(_testOutputHelper, testProjectFile, objFolderPropertyName, binFolderPropertyName); _testOutputHelper.WriteLine($"Properties request result: {JsonSerializer.Serialize(properties, new JsonSerializerOptions { WriteIndented = false })}"); var binFolder = NormalizePath(Path.GetFullPath(properties[binFolderPropertyName], testProjectFolder)); diff --git a/Cesium.Sdk.Tests/Framework/AssertEx.cs b/Cesium.TestFramework/AssertCollection.cs similarity index 76% rename from Cesium.Sdk.Tests/Framework/AssertEx.cs rename to Cesium.TestFramework/AssertCollection.cs index 1bf223c7..ab29b7fd 100644 --- a/Cesium.Sdk.Tests/Framework/AssertEx.cs +++ b/Cesium.TestFramework/AssertCollection.cs @@ -1,6 +1,8 @@ -namespace Cesium.Sdk.Tests.Framework; +using Cesium.TestFramework.Exceptions; -public static class AssertEx +namespace Cesium.TestFramework; + +public static class AssertCollection { public static void Includes(IReadOnlyCollection expected, IReadOnlyCollection all) { diff --git a/Cesium.TestFramework/DotNetCliHelper.cs b/Cesium.TestFramework/DotNetCliHelper.cs index d945fda6..587f9a8e 100644 --- a/Cesium.TestFramework/DotNetCliHelper.cs +++ b/Cesium.TestFramework/DotNetCliHelper.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using Medallion.Shell; using Xunit.Abstractions; @@ -25,6 +26,29 @@ await RunToSuccess(output, "dotnet", Path.GetDirectoryName(projectFilePath)!, ne }); } + public static async Task EvaluateMSBuildProperty(ITestOutputHelper output, string projectPath, string propertyName) + { + var result = await ExecUtil.Run(output, "dotnet", Environment.CurrentDirectory, [ "msbuild", $"\"{projectPath}\"", $"-getProperty:{propertyName}" ]); + return result.StandardOutput; + } + + public static async Task> EvaluateMSBuildProperties(ITestOutputHelper output, string projectPath, params string[] propertyNames) + { + if (!propertyNames.Any()) + return new Dictionary(); + + var result = await ExecUtil.Run(output, "dotnet", Environment.CurrentDirectory, [ "msbuild", $"\"{projectPath}\"", $"-getProperty:{string.Join(",", propertyNames)}" ]); + var resultString = result.StandardOutput; + if (propertyNames.Length == 1) + return new Dictionary { { propertyNames[0], resultString } }; + + var resultJson = JsonDocument.Parse(resultString); + var propertiesJson = resultJson.RootElement.GetProperty("Properties").EnumerateObject().ToArray(); + + return propertiesJson + .ToDictionary(property => property.Name, property => property.Value.GetString() ?? string.Empty); + } + public static Task RunDotNetDll( ITestOutputHelper output, string workingDirectoryPath, diff --git a/Cesium.Sdk.Tests/Framework/IncludesAssertFailedException.cs b/Cesium.TestFramework/Exceptions/IncludesAssertFailedException.cs similarity index 84% rename from Cesium.Sdk.Tests/Framework/IncludesAssertFailedException.cs rename to Cesium.TestFramework/Exceptions/IncludesAssertFailedException.cs index 9306e719..48a8d4dd 100644 --- a/Cesium.Sdk.Tests/Framework/IncludesAssertFailedException.cs +++ b/Cesium.TestFramework/Exceptions/IncludesAssertFailedException.cs @@ -1,6 +1,6 @@ using Xunit.Sdk; -namespace Cesium.Sdk.Tests.Framework; +namespace Cesium.TestFramework.Exceptions; public class IncludesAssertFailedException( IEnumerable expected, From 63d7023e6d577490364dcf3d406920baea6723a0 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sat, 20 Apr 2024 17:37:57 +0200 Subject: [PATCH 044/103] (#80) Docs: document how to run the SDK tests --- docs/tests.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/tests.md b/docs/tests.md index 30781b70..0ce7cd13 100644 --- a/docs/tests.md +++ b/docs/tests.md @@ -80,6 +80,11 @@ Compiler packing is done by 2 NUKE targets: - `PublishCompilerBundle`: a target that make platform-specific `dotnet publish` of compiler bundle to corresponding artifacts' folder. - `PackCompilerBundle`: a target that wraps a published compiler bundle into a NuGet package which is then used by SDK to deliver compiler to user's project +If you want to run these tests separately, run the targets using a shell command: +```console +$ dotnet nuke PackCompilerBundle +``` + Both targets are called automatically when `TestSdk` target is invoked. SDK itself should also be built to be used in test projects. This is done by dependent target `PackSdk` which produces `Cesium.Sdk` NuGet package, suitable as Project SDK. From 785050b454f2377239d911277fb6573554964c4f Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sat, 20 Apr 2024 17:40:25 +0200 Subject: [PATCH 045/103] (#80) Add documentation on the solution metadata attribute --- Cesium.Solution.Metadata/SolutionMetadataAttribute.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs b/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs index c11ac89f..ecf3e7eb 100644 --- a/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs +++ b/Cesium.Solution.Metadata/SolutionMetadataAttribute.cs @@ -1,5 +1,6 @@ namespace Cesium.Solution.Metadata; +/// This attribute is only used by the Cesium test infrastructure. public class SolutionMetadataAttribute : Attribute { public string SourceRoot { get; } From fc1681455927809a32fe1bb84c3acc7a327fc789 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sat, 20 Apr 2024 18:48:01 +0200 Subject: [PATCH 046/103] (#80) Docs: more info on running tests --- CONTRIBUTING.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cb9d2cc9..448f2dfb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,8 @@ There are two kinds of tests in Cesium: unit tests and integration tests. Run the unit and integration tests using this shell command: ```console -$ dotnet test +$ dotnet restore +$ dotnet nuke TestAll ``` Publishing From 84321e0122fee1390407071ec733af201173b99d Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sat, 20 Apr 2024 18:48:33 +0200 Subject: [PATCH 047/103] (#80) SDK: self-written code for process argument passing --- Cesium.Sdk.Tests/ArgumentUtilTests.cs | 17 +++++ Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj | 1 + Cesium.Sdk/ArgumentUtil.cs | 73 ++++++++++++++++++++ Cesium.Sdk/CesiumCompile.cs | 44 ++++++------ Cesium.Sdk/CommandArgumentsBuilder.cs | 86 ------------------------ 5 files changed, 113 insertions(+), 108 deletions(-) create mode 100644 Cesium.Sdk.Tests/ArgumentUtilTests.cs create mode 100644 Cesium.Sdk/ArgumentUtil.cs delete mode 100644 Cesium.Sdk/CommandArgumentsBuilder.cs diff --git a/Cesium.Sdk.Tests/ArgumentUtilTests.cs b/Cesium.Sdk.Tests/ArgumentUtilTests.cs new file mode 100644 index 00000000..7df90d99 --- /dev/null +++ b/Cesium.Sdk.Tests/ArgumentUtilTests.cs @@ -0,0 +1,17 @@ +namespace Cesium.Sdk.Tests; + +public class ArgumentUtilTests +{ + [Fact] + public void PerformTests() + { + Assert.Equal("\"\"", ArgumentUtil.ToCommandLineString([""])); + Assert.Equal("a b c", ArgumentUtil.ToCommandLineString(["a", "b", "c"])); + Assert.Equal("\"a b\" c", ArgumentUtil.ToCommandLineString(["a b", "c"])); + Assert.Equal("a\\b c", ArgumentUtil.ToCommandLineString([@"a\b", "c"])); + Assert.Equal("\"\\\"\"", ArgumentUtil.ToCommandLineString(["\""])); + Assert.Equal("\"a \\\"b\\\"\"", ArgumentUtil.ToCommandLineString(["a \"b\""])); + Assert.Equal("\"\\\\\\\"\"", ArgumentUtil.ToCommandLineString(["\\\""])); + Assert.Equal("\"a\\ \\\\\\\"b\\\"\"", ArgumentUtil.ToCommandLineString(["a\\ \\\"b\""])); + } +} diff --git a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj index 2d715572..bc129dc3 100644 --- a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj +++ b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj @@ -31,6 +31,7 @@ + diff --git a/Cesium.Sdk/ArgumentUtil.cs b/Cesium.Sdk/ArgumentUtil.cs new file mode 100644 index 00000000..8df5dd0c --- /dev/null +++ b/Cesium.Sdk/ArgumentUtil.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Cesium.Sdk; + +public static class ArgumentUtil +{ + public static string ToCommandLineString(IEnumerable args) + { + var result = new StringBuilder(); + var first = true; + foreach (var a in args) + { + if (first) + { + first = false; + } + else + { + result.Append(' '); + } + if (a.Length == 0 || a.Any(c => char.IsWhiteSpace(c) || c == '"')) + { + result.Append(Quoted(a)); + } + else + { + result.Append(a); + } + } + return result.ToString(); + } + + private static string Quoted(string arg) + { + // The simplified rules: + // 1. Every quote should be escaped by \ + // 2. Slashes preceding the quotes should be escaped by \ + // + // Meaning any amount of slashes following a quote should be converted to twice as many slashes + slash + quote. + // The final quote (not part of the argument per se) also counts as quote for this purpose. + var result = new StringBuilder(arg.Length + 2); + result.Append('"'); + var slashes = 0; + foreach (var c in arg) + { + switch (c) + { + case '\\': + slashes++; + break; + case '"': + result.Append('\\', slashes * 2); + slashes = 0; + + result.Append("\\\""); + break; + default: + result.Append('\\', slashes); + slashes = 0; + + result.Append(c); + break; + } + } + + result.Append('\\', slashes * 2); + result.Append('"'); + + return result.ToString(); + } +} diff --git a/Cesium.Sdk/CesiumCompile.cs b/Cesium.Sdk/CesiumCompile.cs index 7201cee3..cc756379 100644 --- a/Cesium.Sdk/CesiumCompile.cs +++ b/Cesium.Sdk/CesiumCompile.cs @@ -187,67 +187,67 @@ private bool TryValidate(out ValidatedOptions? options) private string CollectCommandLineArguments(ValidatedOptions options) { - var builder = new CommandArgumentsBuilder(); + var args = new List(); - builder.RawArgument("--nologo"); + args.Add("--nologo"); if (options.Framework is { } framework) { - builder.RawArgument("--framework"); - builder.RawArgument(framework.ToString()); + args.Add("--framework"); + args.Add(framework.ToString()); } if (options.Architecture is { } arch) { - builder.RawArgument("--arch"); - builder.RawArgument(arch.ToString()); + args.Add("--arch"); + args.Add(arch.ToString()); } if (options.ModuleKind is { } moduleKind) { - builder.RawArgument("--modulekind"); - builder.RawArgument(moduleKind.ToString()); + args.Add("--modulekind"); + args.Add(moduleKind.ToString()); } if (!string.IsNullOrWhiteSpace(options.Namespace)) { - builder.RawArgument("--namespace"); - builder.RawArgument(options.Namespace!); + args.Add("--namespace"); + args.Add(options.Namespace!); } foreach (var import in options.ImportItems) { - builder.RawArgument("--import"); - builder.Argument(import); + args.Add("--import"); + args.Add(import); } if (!string.IsNullOrWhiteSpace(options.CoreLibPath)) { - builder.RawArgument("--corelib"); - builder.Argument(options.CoreLibPath!); + args.Add("--corelib"); + args.Add(options.CoreLibPath!); } if (!string.IsNullOrWhiteSpace(options.RuntimePath)) { - builder.RawArgument("--runtime"); - builder.Argument(options.RuntimePath!); + args.Add("--runtime"); + args.Add(options.RuntimePath!); } foreach (var item in options.PreprocessorItems) { - builder.RawArgument("-D"); - builder.Argument(item); + args.Add("-D"); + args.Add(item); } - builder.RawArgument("--out"); - builder.Argument(options.OutputFile); + args.Add("--out"); + args.Add(options.OutputFile); foreach (var input in options.InputItems) { - builder.Argument(input); + args.Add(input); } - return builder.Build(); + return ArgumentUtil.ToCommandLineString(args); } private void ReportValidationError(string code, string message) => diff --git a/Cesium.Sdk/CommandArgumentsBuilder.cs b/Cesium.Sdk/CommandArgumentsBuilder.cs deleted file mode 100644 index ffcc4077..00000000 --- a/Cesium.Sdk/CommandArgumentsBuilder.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Linq; -using System.Text; - -namespace Cesium.Sdk; - -// Implementation reference: -// https://github.com/Tyrrrz/CliWrap/blob/417aaffe171b9897799ed2a28a6467c11d69c296/CliWrap/Builders/ArgumentsBuilder.cs -// MIT License, Oleksii Holub -public class CommandArgumentsBuilder -{ - private StringBuilder _builder = new StringBuilder(); - - public CommandArgumentsBuilder RawArgument(string value) - { - _builder.Append(' '); - _builder.Append(value); - - return this; - } - - public CommandArgumentsBuilder Argument(string argument) - { - _builder.Append(' '); - if (NeedsEscaping(argument)) - argument = Escape(argument); - _builder.Append(argument); - - return this; - } - - public string Build() => _builder.ToString(); - - private bool NeedsEscaping(string argument) => - argument.Length > 0 && argument.Any(c => char.IsWhiteSpace(c) || c != '"'); - - private static string Escape(string argument) - { - var buffer = new StringBuilder(); - - buffer.Append('"'); - - for (var i = 0; i < argument.Length;) - { - var c = argument[i++]; - - if (c == '\\') - { - var backslashCount = 1; - while (i < argument.Length && argument[i] == '\\') - { - backslashCount++; - i++; - } - - if (i == argument.Length) - { - buffer.Append('\\', backslashCount * 2); - } - else if (argument[i] == '"') - { - buffer - .Append('\\', backslashCount * 2 + 1) - .Append('"'); - - i++; - } - else - { - buffer.Append('\\', backslashCount); - } - } - else if (c == '"') - { - buffer.Append('\\').Append('"'); - } - else - { - buffer.Append(c); - } - } - - buffer.Append('"'); - - return buffer.ToString(); - } -} From a704a98e50f476ee5ddb206c7f3b52233a0cd677 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sat, 20 Apr 2024 18:49:45 +0200 Subject: [PATCH 048/103] (#80) SDK: add a TODO note --- Cesium.Sdk/Sdk/Sdk.props | 1 + 1 file changed, 1 insertion(+) diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index e8e643e6..ceac26d6 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -10,6 +10,7 @@ false false Cesium.Compiler.Bundle.$(NETCoreSdkRuntimeIdentifier) + 0.0.1 false From 9d47b36d0b9009424270aab0c8a56541971aa723 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 21 Apr 2024 14:55:01 +0200 Subject: [PATCH 049/103] SDK: Fix minor issues in documentation --- docs/msbuild-sdk.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/msbuild-sdk.md b/docs/msbuild-sdk.md index f5fce3bb..c7258b74 100644 --- a/docs/msbuild-sdk.md +++ b/docs/msbuild-sdk.md @@ -14,10 +14,10 @@ Source files are defined with `` items, very similar to other .NET lang ```xml - + ``` -> Note: In the current SDK implementation, compile units should be defined explicitly, in opposite to C# `` items. +> Note: In the current SDK implementation, source files will not be included into compilation implicitly. They should be defined in `` items, in opposite to SDK-style C# projects, where all C# source files are implicitly added to the compilation. ### References @@ -31,7 +31,7 @@ Not supported yet. Not supported yet. ### Preprocessor directives -`` property is directly mapped to a list of preprocessor items. So, you could define such constants in .csproj: +`` property is directly mapped to a list of preprocessor items. So, you could define such constants in `.ceproj`: ```xml $(DefineConstants);FOO;BAR @@ -39,7 +39,7 @@ Not supported yet. ``` And then use it in your .c code: -```c++ +```c #ifdef FOO int foo() { return 0; } #endif From 36a5ff0b9eed4bb8a30611f408b753ac9660df56 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 21 Apr 2024 15:03:31 +0200 Subject: [PATCH 050/103] SDK: Remove unnecessary lines --- Cesium.Compiler/Cesium.Compiler.csproj | 1 - Cesium.Sdk/Cesium.Sdk.csproj | 2 -- build/Build.cs | 1 - 3 files changed, 4 deletions(-) diff --git a/Cesium.Compiler/Cesium.Compiler.csproj b/Cesium.Compiler/Cesium.Compiler.csproj index 3f80bfde..be7246ac 100644 --- a/Cesium.Compiler/Cesium.Compiler.csproj +++ b/Cesium.Compiler/Cesium.Compiler.csproj @@ -4,7 +4,6 @@ Exe net8.0 enable - true true Major diff --git a/Cesium.Sdk/Cesium.Sdk.csproj b/Cesium.Sdk/Cesium.Sdk.csproj index dc1b44cd..4e8d3843 100644 --- a/Cesium.Sdk/Cesium.Sdk.csproj +++ b/Cesium.Sdk/Cesium.Sdk.csproj @@ -2,8 +2,6 @@ netstandard2.0 - - enable true diff --git a/build/Build.cs b/build/Build.cs index 303ba6f8..b6701f73 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -8,7 +8,6 @@ partial class Build : NukeBuild { public static int Main() { - // while (!Debugger.IsAttached) Thread.Sleep(100); return Execute(x => x.CompileAll); } From 6123ff267aa02ca901c906ea0351f2bf441e3d0e Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 21 Apr 2024 15:04:12 +0200 Subject: [PATCH 051/103] SDK: Fix naming of methods those are referencing the old "pack" term instead of "bundle" --- build/Build.Sdk.cs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/build/Build.Sdk.cs b/build/Build.Sdk.cs index c158a46b..66838adf 100644 --- a/build/Build.Sdk.cs +++ b/build/Build.Sdk.cs @@ -11,7 +11,7 @@ public partial class Build { - const string _compilerPackPackagePrefix = "Cesium.Compiler.Bundle"; + const string _compilerBundlePackagePrefix = "Cesium.Compiler.Bundle"; Target PublishAllCompilerBundles => _ => _ .Executes(() => @@ -63,17 +63,17 @@ public partial class Build return; } - Log.Information($"Packing SDK..."); + Log.Information("Packing SDK..."); DotNetPack(o => o .SetConfiguration(Configuration) .SetProject(Solution.Cesium_Sdk.Path)); }); - void EmitCompilerPack(string runtimeId, Project compilerProject) + void EmitCompilerBundle(string runtimeId, Project compilerProject) { var version = compilerProject.GetVersion(); - var runtimePackageId = GetRuntimePackId(runtimeId); - var packageFile = GetRuntimePackFileName(version, runtimeId); + var runtimePackageId = GetRuntimeBundleId(runtimeId); + var packageFile = GetRuntimeBundleFileName(version, runtimeId); var publishDirectory = GetCompilerRuntimePublishFolder(compilerProject, runtimeId); Directory.CreateDirectory(publishDirectory); var publishedFiles = Directory.GetFiles(publishDirectory, "*.*", SearchOption.AllDirectories); @@ -116,7 +116,7 @@ void PublishCompiler(string runtimeId) { var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); - if (!SkipCaches && !NeedPublishCompilerPack(compilerProject, runtimeId)) + if (!SkipCaches && !NeedPublishCompilerBundle(compilerProject, runtimeId)) { Log.Information($"Skipping {runtimeId} because it was already published. Use '--skip-caches true' to re-publish."); return; @@ -138,14 +138,14 @@ void PackCompiler(string runtimeId) { var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); - if (!SkipCaches && !NeedPackageCompilerPack(compilerProject, runtimeId)) + if (!SkipCaches && !NeedPackageCompilerBundle(compilerProject, runtimeId)) { Log.Information($"Skipping {runtimeId} because it was already packed. Use '--skip-caches true' to re-pack."); return; } Log.Information($"Packing compiler for {runtimeId}..."); - EmitCompilerPack(runtimeId, compilerProject); + EmitCompilerBundle(runtimeId, compilerProject); } string GetCompilerRuntimePublishFolder(Project compilerProject, string runtimeId) => @@ -158,13 +158,13 @@ string GetCompilerRuntimePublishFolder(Project compilerProject, string runtimeId static string GetRuntimeArtifactFolder(string version, string runtimeId) => $"pack_{version}_{runtimeId}"; - static string GetRuntimePackId(string runtimeId) => - $"{_compilerPackPackagePrefix}.{runtimeId}"; + static string GetRuntimeBundleId(string runtimeId) => + $"{_compilerBundlePackagePrefix}.{runtimeId}"; - static string GetRuntimePackFileName(string version, string runtimeId) => - $"{_compilerPackPackagePrefix}.{runtimeId}.{version}.nupkg"; + static string GetRuntimeBundleFileName(string version, string runtimeId) => + $"{_compilerBundlePackagePrefix}.{runtimeId}.{version}.nupkg"; - bool NeedPublishCompilerPack(Project compiler, string runtimeId) + bool NeedPublishCompilerBundle(Project compiler, string runtimeId) { var folder = GetCompilerRuntimePublishFolder(compiler, runtimeId); @@ -172,11 +172,11 @@ bool NeedPublishCompilerPack(Project compiler, string runtimeId) || Directory.GetFiles(folder, "Cesium.Compiler*").Length == 0; } - bool NeedPackageCompilerPack(Project compiler, string runtimeId) + bool NeedPackageCompilerBundle(Project compiler, string runtimeId) { var version = compiler.GetVersion(); var packageDirectory = compiler.GetPackageOutputPath(); - var packageFileName = GetRuntimePackFileName(version, runtimeId); + var packageFileName = GetRuntimeBundleFileName(version, runtimeId); return !File.Exists(Path.Combine(packageDirectory, packageFileName)); } From 5a9a904ca209ccb1f3371844bd6dcbdc80c4a4b1 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sun, 21 Apr 2024 15:04:41 +0200 Subject: [PATCH 052/103] SDK: Use ArgumentsList instead of Arguments when running MSBuild process --- Cesium.Sdk.Tests/SdkTestBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index 1cf09d62..37ade95e 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -50,7 +50,7 @@ protected async Task ExecuteTargets(string projectName, params stri { WorkingDirectory = testProjectFolder, FileName = "dotnet", - Arguments = $"msbuild \"{testProjectFile}\" /t:{joinedTargets} /restore /bl:{binLogFile}", + ArgumentList = { "msbuild", testProjectFile, $"/t:{joinedTargets}", "/restore", $"/bl:{binLogFile}" }, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, From da09cdb753f207d249e6c181799421ff8f384544 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sun, 21 Apr 2024 23:19:23 +0200 Subject: [PATCH 053/103] (#80) Docs: improve the test explanation --- docs/tests.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/tests.md b/docs/tests.md index 0ce7cd13..be231734 100644 --- a/docs/tests.md +++ b/docs/tests.md @@ -80,10 +80,11 @@ Compiler packing is done by 2 NUKE targets: - `PublishCompilerBundle`: a target that make platform-specific `dotnet publish` of compiler bundle to corresponding artifacts' folder. - `PackCompilerBundle`: a target that wraps a published compiler bundle into a NuGet package which is then used by SDK to deliver compiler to user's project -If you want to run these tests separately, run the targets using a shell command: +If you want to run these tests without Nuke (e.g. from the IDE), run the targets using a shell command: ```console $ dotnet nuke PackCompilerBundle ``` +After that, run the tests in your preferred way. Both targets are called automatically when `TestSdk` target is invoked. From f6ab861744b1094abd41a92a7b8e5537290e2df2 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sun, 21 Apr 2024 23:22:22 +0200 Subject: [PATCH 054/103] (#80, #196, #571) TODO processing --- Cesium.CodeGen.Tests/CodeGenMethodTests.cs | 2 +- Cesium.IntegrationTests/function_ptr.c | 2 +- Cesium.Sdk/Sdk/Sdk.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cesium.CodeGen.Tests/CodeGenMethodTests.cs b/Cesium.CodeGen.Tests/CodeGenMethodTests.cs index cc786ee3..842d975c 100644 --- a/Cesium.CodeGen.Tests/CodeGenMethodTests.cs +++ b/Cesium.CodeGen.Tests/CodeGenMethodTests.cs @@ -502,7 +502,7 @@ int console_read(struct struct1* s) { return s->x; }"); - // TODO [#196] + // TODO[#196] /* [Fact] public Task VarargFunctionPointerCallTest() => DoTest(@"int foo(int a, ...) { return a; } diff --git a/Cesium.IntegrationTests/function_ptr.c b/Cesium.IntegrationTests/function_ptr.c index b5fc9d11..29632475 100644 --- a/Cesium.IntegrationTests/function_ptr.c +++ b/Cesium.IntegrationTests/function_ptr.c @@ -17,7 +17,7 @@ int main(void) return x(40); - // TODO [#196] + // TODO[#196] // foov_t y = &foov; // return (x(40) + y(40, 123, 456, "foo")) / 2; } diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index ceac26d6..6cb6f3d8 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -10,7 +10,7 @@ false false Cesium.Compiler.Bundle.$(NETCoreSdkRuntimeIdentifier) - + 0.0.1 false From cbdf280372a32c687adfce81993fd5fb0c9d4179 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Apr 2024 16:10:16 +0000 Subject: [PATCH 055/103] Bump actions/checkout from 2 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/run-build-and-unit-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-build-and-unit-tests.yml b/.github/workflows/run-build-and-unit-tests.yml index d4cc8566..68aeda4d 100644 --- a/.github/workflows/run-build-and-unit-tests.yml +++ b/.github/workflows/run-build-and-unit-tests.yml @@ -25,7 +25,7 @@ jobs: NUGET_PACKAGES: ${{ github.workspace }}/.github/nuget-packages steps: - name: 📝 Fetch Sources 📝 - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: 💡 Perform Common Steps 💡 uses: ./.github/workflows/perform-common-steps From 8d3f20778c72c7d97ca513479e0a2a54792a4db5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:35:23 +0000 Subject: [PATCH 056/103] Bump xunit.runner.visualstudio from 2.4.3 to 2.5.8 Bumps [xunit.runner.visualstudio](https://github.com/xunit/visualstudio.xunit) from 2.4.3 to 2.5.8. - [Release notes](https://github.com/xunit/visualstudio.xunit/releases) - [Commits](https://github.com/xunit/visualstudio.xunit/compare/v2.4.3...2.5.8) --- updated-dependencies: - dependency-name: xunit.runner.visualstudio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 2ca1f314..b47bf4f1 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,7 +14,7 @@ - + From 435865fb6cf3c14d3cd3699133dd3020e0b5ff4d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:34:29 +0000 Subject: [PATCH 057/103] Bump coverlet.collector from 3.1.2 to 6.0.2 Bumps [coverlet.collector](https://github.com/coverlet-coverage/coverlet) from 3.1.2 to 6.0.2. - [Release notes](https://github.com/coverlet-coverage/coverlet/releases) - [Commits](https://github.com/coverlet-coverage/coverlet/commits/v6.0.2) --- updated-dependencies: - dependency-name: coverlet.collector dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b47bf4f1..627968ef 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,7 @@ - + From 3cecfb5dbf234782987c0a72aa437b0cba789ebc Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sun, 21 Apr 2024 23:54:26 +0200 Subject: [PATCH 058/103] Tests: drop coverlet.collector We don't use it here anyway. --- Cesium.CodeGen.Tests/Cesium.CodeGen.Tests.csproj | 4 ---- Cesium.Compiler.Tests/Cesium.Compiler.Tests.csproj | 4 ---- Cesium.Parser.Tests/Cesium.Parser.Tests.csproj | 4 ---- Cesium.Runtime.Tests/Cesium.Runtime.Tests.csproj | 4 ---- Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj | 4 ---- Cesium.TestFramework.Tests/Cesium.TestFramework.Tests.csproj | 4 ---- Directory.Packages.props | 1 - 7 files changed, 25 deletions(-) diff --git a/Cesium.CodeGen.Tests/Cesium.CodeGen.Tests.csproj b/Cesium.CodeGen.Tests/Cesium.CodeGen.Tests.csproj index 1f0ee832..c47f9872 100644 --- a/Cesium.CodeGen.Tests/Cesium.CodeGen.Tests.csproj +++ b/Cesium.CodeGen.Tests/Cesium.CodeGen.Tests.csproj @@ -16,10 +16,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/Cesium.Compiler.Tests/Cesium.Compiler.Tests.csproj b/Cesium.Compiler.Tests/Cesium.Compiler.Tests.csproj index 297bb799..5667e066 100644 --- a/Cesium.Compiler.Tests/Cesium.Compiler.Tests.csproj +++ b/Cesium.Compiler.Tests/Cesium.Compiler.Tests.csproj @@ -15,10 +15,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/Cesium.Parser.Tests/Cesium.Parser.Tests.csproj b/Cesium.Parser.Tests/Cesium.Parser.Tests.csproj index 83d11c7f..ae428d01 100644 --- a/Cesium.Parser.Tests/Cesium.Parser.Tests.csproj +++ b/Cesium.Parser.Tests/Cesium.Parser.Tests.csproj @@ -15,10 +15,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/Cesium.Runtime.Tests/Cesium.Runtime.Tests.csproj b/Cesium.Runtime.Tests/Cesium.Runtime.Tests.csproj index 17108c41..82928fd8 100644 --- a/Cesium.Runtime.Tests/Cesium.Runtime.Tests.csproj +++ b/Cesium.Runtime.Tests/Cesium.Runtime.Tests.csproj @@ -16,10 +16,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj index bc129dc3..f4c8f60f 100644 --- a/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj +++ b/Cesium.Sdk.Tests/Cesium.Sdk.Tests.csproj @@ -20,10 +20,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/Cesium.TestFramework.Tests/Cesium.TestFramework.Tests.csproj b/Cesium.TestFramework.Tests/Cesium.TestFramework.Tests.csproj index 33440b6f..f4dd9c6b 100644 --- a/Cesium.TestFramework.Tests/Cesium.TestFramework.Tests.csproj +++ b/Cesium.TestFramework.Tests/Cesium.TestFramework.Tests.csproj @@ -16,10 +16,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/Directory.Packages.props b/Directory.Packages.props index 627968ef..2dd7318e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,6 @@ - From 1a27d3339cc04989102eb311ed40e4126d76f193 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Apr 2024 17:15:51 +0000 Subject: [PATCH 059/103] Bump Mono.Cecil from 0.11.4 to 0.11.5 Bumps [Mono.Cecil](https://github.com/jbevain/cecil) from 0.11.4 to 0.11.5. - [Release notes](https://github.com/jbevain/cecil/releases) - [Commits](https://github.com/jbevain/cecil/compare/0.11.4...0.11.5) --- updated-dependencies: - dependency-name: Mono.Cecil dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 2dd7318e..1675348a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -9,7 +9,7 @@ - + From 52fbd7fe67543b60ed03b536d21ac71c8437ce12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:55:07 +0000 Subject: [PATCH 060/103] Bump xunit from 2.4.2 to 2.7.1 Bumps [xunit](https://github.com/xunit/xunit) from 2.4.2 to 2.7.1. - [Commits](https://github.com/xunit/xunit/compare/2.4.2...2.7.1) --- updated-dependencies: - dependency-name: xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1675348a..e46041fa 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + From 3da636c7608f11353ec8ed460144705b2dc4c417 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Apr 2024 22:18:40 +0000 Subject: [PATCH 061/103] Bump Verify.Xunit from 16.3.5 to 24.1.0 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 16.3.5 to 24.1.0. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/16.3.5...24.1.0) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index e46041fa..9c161665 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,7 +11,7 @@ - + From 090d6256b3ebf206d9a6f68e58604e78cad38753 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Mon, 22 Apr 2024 00:54:09 +0200 Subject: [PATCH 062/103] Update to new Verify.Xunit --- Cesium.TestFramework/Cesium.TestFramework.csproj | 2 ++ Cesium.TestFramework/TestFileVerification.cs | 2 +- Cesium.TestFramework/VerifyTestBase.cs | 1 - Directory.Packages.props | 2 ++ 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Cesium.TestFramework/Cesium.TestFramework.csproj b/Cesium.TestFramework/Cesium.TestFramework.csproj index 34cbc620..816fed19 100644 --- a/Cesium.TestFramework/Cesium.TestFramework.csproj +++ b/Cesium.TestFramework/Cesium.TestFramework.csproj @@ -8,7 +8,9 @@ + + diff --git a/Cesium.TestFramework/TestFileVerification.cs b/Cesium.TestFramework/TestFileVerification.cs index e73bac1c..8aa8977d 100644 --- a/Cesium.TestFramework/TestFileVerification.cs +++ b/Cesium.TestFramework/TestFileVerification.cs @@ -30,7 +30,7 @@ List Relativize(IEnumerable paths) => public static void VerifyAllTestsFromAssembly(Assembly assembly) { - var testClasses = assembly.GetTypes().Where(t => t.GetCustomAttributes().Any()).ToList(); + var testClasses = assembly.GetTypes().Where(t => t.IsAssignableTo(typeof(VerifyTestBase))).ToList(); Verify(testClasses); } diff --git a/Cesium.TestFramework/VerifyTestBase.cs b/Cesium.TestFramework/VerifyTestBase.cs index 2b1172fc..be97c9a1 100644 --- a/Cesium.TestFramework/VerifyTestBase.cs +++ b/Cesium.TestFramework/VerifyTestBase.cs @@ -1,6 +1,5 @@ namespace Cesium.TestFramework; -[UsesVerify] public abstract class VerifyTestBase { static VerifyTestBase() diff --git a/Directory.Packages.props b/Directory.Packages.props index 9c161665..e1f32fbd 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,9 +10,11 @@ + + From 2ab82a7756271397d3f3455b4c79a59795cacaf9 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Mon, 22 Apr 2024 00:54:27 +0200 Subject: [PATCH 063/103] Preprocessor: more diagnostic in case a file is not found --- Cesium.Compiler/FileSystemIncludeContext.cs | 24 ++++++++++++++------- Cesium.Preprocessor/CPreprocessor.cs | 2 +- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Cesium.Compiler/FileSystemIncludeContext.cs b/Cesium.Compiler/FileSystemIncludeContext.cs index cdb7aebb..970a42d0 100644 --- a/Cesium.Compiler/FileSystemIncludeContext.cs +++ b/Cesium.Compiler/FileSystemIncludeContext.cs @@ -1,23 +1,31 @@ using System.Collections.Immutable; +using System.Text; using Cesium.Preprocessor; namespace Cesium.Compiler; -public sealed class FileSystemIncludeContext : IIncludeContext +public sealed class FileSystemIncludeContext(string stdLibDirectory, IEnumerable currentDirectory) + : IIncludeContext { - private readonly string _stdLibDirectory; - private readonly ImmutableArray _userIncludeDirectories; + private readonly ImmutableArray _userIncludeDirectories = [..currentDirectory]; private readonly List _guardedIncludedFiles = new(); - public FileSystemIncludeContext(string stdLibDirectory, IEnumerable currentDirectory) + public override string ToString() { - _stdLibDirectory = stdLibDirectory; - _userIncludeDirectories = currentDirectory.ToImmutableArray(); + var result = new StringBuilder(); + result.AppendLine($"Standard library directory: \"{stdLibDirectory}\""); + result.Append("User include directories: [\n"); + foreach (var dir in _userIncludeDirectories) + { + result.Append($"\"{dir}\"\n"); + } + result.Append("]"); + return result.ToString(); } public string LookUpAngleBracedIncludeFile(string filePath) { - var path = Path.Combine(_stdLibDirectory, filePath); + var path = Path.Combine(stdLibDirectory, filePath); if (File.Exists(path)) return Path.GetFullPath(path); @@ -41,7 +49,7 @@ public string LookUpQuotedIncludeFile(string filePath) return Path.GetFullPath(path); } - path = Path.Combine(_stdLibDirectory, filePath); + path = Path.Combine(stdLibDirectory, filePath); return Path.GetFullPath(path); } diff --git a/Cesium.Preprocessor/CPreprocessor.cs b/Cesium.Preprocessor/CPreprocessor.cs index 66d7e4b9..6be1ab68 100644 --- a/Cesium.Preprocessor/CPreprocessor.cs +++ b/Cesium.Preprocessor/CPreprocessor.cs @@ -83,7 +83,7 @@ private async IAsyncEnumerable> ProcessGroupPart( { throw new PreprocessorException( filePathToken.Location, - $"Cannot find file {filePath} for include directive."); + $"Cannot find file {filePath} for include directive. Include context: {IncludeContext}"); } await foreach (var token in ProcessInclude(includeFilePath, reader)) { From 14c5977c9400d00a7275ff47eee3a3b0fbc80b0d Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Mon, 22 Apr 2024 00:57:43 +0200 Subject: [PATCH 064/103] CI: should include Directory.Packages.props into cache key calculation --- .github/workflows/perform-common-steps/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/perform-common-steps/action.yml b/.github/workflows/perform-common-steps/action.yml index 696bac90..11d9598c 100644 --- a/.github/workflows/perform-common-steps/action.yml +++ b/.github/workflows/perform-common-steps/action.yml @@ -12,7 +12,7 @@ runs: uses: actions/cache@v2 with: path: ${{ env.NUGET_PACKAGES }} - key: ${{ runner.os }}.nuget.${{ hashFiles('**/*.csproj') }} + key: ${{ runner.os }}.nuget.${{ hashFiles('**/*.csproj', 'Directory.Packages.props') }} - name: 🛠️ Restore local .NET tools 🛠️ shell: bash From b8fcca649455ddb7b16b5d0cf0663be774cc6ea7 Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Mon, 22 Apr 2024 16:17:18 +0200 Subject: [PATCH 065/103] [sdk]: Possible fix missing/outdated artifacts before compiler packing --- build/Build.Sdk.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/Build.Sdk.cs b/build/Build.Sdk.cs index 66838adf..dee4259a 100644 --- a/build/Build.Sdk.cs +++ b/build/Build.Sdk.cs @@ -14,6 +14,7 @@ public partial class Build const string _compilerBundlePackagePrefix = "Cesium.Compiler.Bundle"; Target PublishAllCompilerBundles => _ => _ + .DependsOn(CompileAll) .Executes(() => { var compilerProject = Solution.Cesium_Compiler.GetMSBuildProject(); @@ -27,6 +28,7 @@ public partial class Build }); Target PublishCompilerBundle => _ => _ + .DependsOn(CompileAll) .Executes(() => { PublishCompiler(EffectiveRuntimeId); @@ -54,6 +56,7 @@ public partial class Build }); Target PackSdk => _ => _ + .DependsOn(CompileAll) .Executes(() => { var sdkProject = Solution.Cesium_Sdk.GetMSBuildProject(); From f75e7c6255e07355f760eb9f1dac7e03edeeefb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 21:29:28 +0000 Subject: [PATCH 066/103] Bump Microsoft.NET.Test.Sdk from 17.1.0 to 17.9.0 Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.1.0 to 17.9.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md) - [Commits](https://github.com/microsoft/vstest/compare/v17.1.0...v17.9.0) --- updated-dependencies: - dependency-name: Microsoft.NET.Test.Sdk dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index e1f32fbd..47dbdd59 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,7 +8,7 @@ - + From 226df1f0c9d2fa32c55f9260011a22458ae88260 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 21:35:07 +0000 Subject: [PATCH 067/103] Bump Microsoft.Build.Tasks.Core and Microsoft.Build.Utilities.Core Bumps [Microsoft.Build.Tasks.Core](https://github.com/dotnet/msbuild) and [Microsoft.Build.Utilities.Core](https://github.com/dotnet/msbuild). These dependencies needed to be updated together. Updates `Microsoft.Build.Tasks.Core` from 17.8.3 to 17.9.5 - [Release notes](https://github.com/dotnet/msbuild/releases) - [Changelog](https://github.com/dotnet/msbuild/blob/main/documentation/Changelog.md) - [Commits](https://github.com/dotnet/msbuild/compare/v17.8.3...v17.9.5) Updates `Microsoft.Build.Utilities.Core` from 17.8.3 to 17.9.5 - [Release notes](https://github.com/dotnet/msbuild/releases) - [Changelog](https://github.com/dotnet/msbuild/blob/main/documentation/Changelog.md) - [Commits](https://github.com/dotnet/msbuild/compare/v17.8.3...v17.9.5) --- updated-dependencies: - dependency-name: Microsoft.Build.Tasks.Core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: Microsoft.Build.Utilities.Core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 47dbdd59..783214a7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -24,7 +24,7 @@ - - + + \ No newline at end of file From 779188a289f2f717b7904152a66119b872f54e1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 21:45:32 +0000 Subject: [PATCH 068/103] Bump nuke.globaltool from 7.0.6 to 8.0.0 Bumps [nuke.globaltool](https://github.com/nuke-build/nuke) from 7.0.6 to 8.0.0. - [Release notes](https://github.com/nuke-build/nuke/releases) - [Changelog](https://github.com/nuke-build/nuke/blob/develop/CHANGELOG.md) - [Commits](https://github.com/nuke-build/nuke/compare/7.0.6...8.0.0) --- updated-dependencies: - dependency-name: nuke.globaltool dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .config/dotnet-tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index b5c92636..91343641 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "nuke.globaltool": { - "version": "7.0.6", + "version": "8.0.0", "commands": [ "nuke" ] From 67d2c81c8d06db59f8448f160a9cf63f8a607b75 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 21:55:43 +0000 Subject: [PATCH 069/103] Bump Microsoft.Build from 17.8.3 to 17.9.5 Bumps [Microsoft.Build](https://github.com/dotnet/msbuild) from 17.8.3 to 17.9.5. - [Release notes](https://github.com/dotnet/msbuild/releases) - [Changelog](https://github.com/dotnet/msbuild/blob/main/documentation/Changelog.md) - [Commits](https://github.com/dotnet/msbuild/compare/v17.8.3...v17.9.5) --- updated-dependencies: - dependency-name: Microsoft.Build dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 783214a7..db566e8a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,7 +23,7 @@ - + From f2d3692644f18fabb40d033d6acf280955c7315a Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Tue, 30 Apr 2024 23:34:04 +0200 Subject: [PATCH 070/103] fprintf: correctly process long prefix --- Cesium.IntegrationTests/stdlib/printf.c | 8 ++-- Cesium.Runtime.Tests/StdIoFunctionTests.cs | 29 +++++++++++--- Cesium.Runtime/StdIoFunctions.cs | 46 +++++++++++++++++----- 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/Cesium.IntegrationTests/stdlib/printf.c b/Cesium.IntegrationTests/stdlib/printf.c index bce03742..a53ca1dc 100644 --- a/Cesium.IntegrationTests/stdlib/printf.c +++ b/Cesium.IntegrationTests/stdlib/printf.c @@ -21,9 +21,11 @@ int main(int argc, char *argv[]) return -4; } - if (printf("%lu\n", -1) != 11) { - return -5; - } + // TODO: This test is not portable: on Windows, Cesium and MSVC use different sizes for long. + // int maxULongLengthInChars = sizeof(long) == 4 ? 10 : 20; + // if (printf("%lu\n", -1L) != maxULongLengthInChars + 1) { // + 1 for \n + // return -5; + // } if (printf("%i\n", -1) != 3) { return -6; diff --git a/Cesium.Runtime.Tests/StdIoFunctionTests.cs b/Cesium.Runtime.Tests/StdIoFunctionTests.cs index 25ff7ce7..82f90c7a 100644 --- a/Cesium.Runtime.Tests/StdIoFunctionTests.cs +++ b/Cesium.Runtime.Tests/StdIoFunctionTests.cs @@ -7,10 +7,28 @@ public class StdIoFunctionTests [Theory] [InlineData(9, "0x09")] [InlineData(32, "0x20")] - public unsafe void FPrintFHex(long input, string expectedResult) + public void FPrintFHex(long input, string expectedResult) { - var format = Encoding.UTF8.GetBytes("0x%02x"); + var (exitCode, result) = TestFPrintF("0x%02x", input); + Assert.Equal(expectedResult, result); + Assert.Equal(4, exitCode); + } + + [Theory] + [InlineData(-1L, "%li", 2, "-1")] + [InlineData(-1L, "%lu", 20, "18446744073709551615")] + public void FPrintFLong(long input, string format, int expectedExitCode, string expectedResult) + { + var (exitCode, result) = TestFPrintF(format, input); + Assert.Equal(expectedResult, result); + Assert.Equal(expectedExitCode, exitCode); + } + private static unsafe (int, string) TestFPrintF(string format, long input) + { + var formatEncoded = Encoding.UTF8.GetBytes(format); + + int exitCode; using var buffer = new MemoryStream(); var handleIndex = StdIoFunctions.Handles.Count; try @@ -24,9 +42,9 @@ public unsafe void FPrintFHex(long input, string expectedResult) }; StdIoFunctions.Handles.Add(handle); - fixed (byte* formatPtr = format) + fixed (byte* formatPtr = formatEncoded) { - Assert.Equal(4, StdIoFunctions.FPrintF((void*)handleIndex, formatPtr, &input)); + exitCode = StdIoFunctions.FPrintF((void*)handleIndex, formatPtr, &input); } } finally @@ -34,7 +52,6 @@ public unsafe void FPrintFHex(long input, string expectedResult) StdIoFunctions.Handles.RemoveAt(handleIndex); } - var result = Encoding.UTF8.GetString(buffer.ToArray()); - Assert.Equal(expectedResult, result); + return (exitCode, Encoding.UTF8.GetString(buffer.ToArray())); } } diff --git a/Cesium.Runtime/StdIoFunctions.cs b/Cesium.Runtime/StdIoFunctions.cs index 4ecac607..9f7ac05d 100644 --- a/Cesium.Runtime/StdIoFunctions.cs +++ b/Cesium.Runtime/StdIoFunctions.cs @@ -298,7 +298,6 @@ public static int FPrintF(void* stream, byte* str, void* varargs) case "d": case "ld": case "i": - case "li": int intValue = (int)((long*)varargs)[consumedArgs]; var intValueString = intValue.ToString(); if (alwaysSign && intValue > 0) @@ -319,16 +318,45 @@ public static int FPrintF(void* stream, byte* str, void* varargs) consumedBytes += intValueString.Length; consumedArgs++; break; - case "u": - case "lu": + case "li": + long longValue = ((long*)varargs)[consumedArgs]; + var longValueString = longValue.ToString(); + if (alwaysSign && longValue > 0) { - uint uintValue = (uint)((long*)varargs)[consumedArgs]; - var uintValueString = uintValue.ToString(); - streamWriter.Write(uintValueString); - consumedBytes += uintValueString.Length; - consumedArgs++; - break; + streamWriter.Write('+'); + } + + if (longValueString.Length < precision) + { + streamWriter.Write(new string('0', precision - longValueString.Length)); + } + + if (precision != 0 || longValue != 0) + { + streamWriter.Write(longValueString); } + + consumedBytes += longValueString.Length; + consumedArgs++; + break; + case "u": + { + uint uintValue = (uint)((long*)varargs)[consumedArgs]; + var uintValueString = uintValue.ToString(); + streamWriter.Write(uintValueString); + consumedBytes += uintValueString.Length; + consumedArgs++; + break; + } + case "lu": + { + ulong ulongValue = (ulong)((long*)varargs)[consumedArgs]; + var ulongValueString = ulongValue.ToString(); + streamWriter.Write(ulongValueString); + consumedBytes += ulongValueString.Length; + consumedArgs++; + break; + } case "f": { var floatNumber = ((double*)varargs)[consumedArgs]; From 54706ae22719c8ee2502d4e7ae6743a75207de46 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Wed, 1 May 2024 00:00:16 +0200 Subject: [PATCH 071/103] (#586) Connect a TODO with the issue --- Cesium.IntegrationTests/stdlib/printf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cesium.IntegrationTests/stdlib/printf.c b/Cesium.IntegrationTests/stdlib/printf.c index a53ca1dc..9f99888b 100644 --- a/Cesium.IntegrationTests/stdlib/printf.c +++ b/Cesium.IntegrationTests/stdlib/printf.c @@ -21,7 +21,7 @@ int main(int argc, char *argv[]) return -4; } - // TODO: This test is not portable: on Windows, Cesium and MSVC use different sizes for long. + // TODO[#586]: This test is not portable: on Windows, Cesium and MSVC use different sizes for long. // int maxULongLengthInChars = sizeof(long) == 4 ? 10 : 20; // if (printf("%lu\n", -1L) != maxULongLengthInChars + 1) { // + 1 for \n // return -5; From 875206bc4dee5d445a90f7bf63aa29f630be8054 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 22:15:16 +0000 Subject: [PATCH 072/103] Bump xunit.assert from 2.7.1 to 2.8.0 Bumps [xunit.assert](https://github.com/xunit/xunit) from 2.7.1 to 2.8.0. - [Commits](https://github.com/xunit/xunit/compare/2.7.1...2.8.0) --- updated-dependencies: - dependency-name: xunit.assert dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index db566e8a..e5658bf7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,7 +14,7 @@ - + From 2053a32073ee97e16264dcd46ae7af45f42e3d5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 20:23:18 +0000 Subject: [PATCH 073/103] Bump xunit.runner.visualstudio from 2.5.8 to 2.8.0 Bumps [xunit.runner.visualstudio](https://github.com/xunit/visualstudio.xunit) from 2.5.8 to 2.8.0. - [Release notes](https://github.com/xunit/visualstudio.xunit/releases) - [Commits](https://github.com/xunit/visualstudio.xunit/compare/2.5.8...2.8.0) --- updated-dependencies: - dependency-name: xunit.runner.visualstudio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index e5658bf7..2752473c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,7 +15,7 @@ - + From 2618ceb8397f90920b7c55c7b2006c5ae062296e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 20:24:32 +0000 Subject: [PATCH 074/103] Bump xunit from 2.7.1 to 2.8.0 Bumps [xunit](https://github.com/xunit/xunit) from 2.7.1 to 2.8.0. - [Commits](https://github.com/xunit/xunit/compare/2.7.1...2.8.0) --- updated-dependencies: - dependency-name: xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 2752473c..d8aa1b00 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -13,7 +13,7 @@ - + From 28e02d12ed987f458595268a610344c988890858 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 21:56:30 +0000 Subject: [PATCH 075/103] Bump Verify.Xunit from 24.1.0 to 24.2.0 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 24.1.0 to 24.2.0. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/commits) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index d8aa1b00..8953351a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + From 5a375ccc19a8df1acc6ff1a7ae6d13557b3d414f Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Wed, 1 May 2024 00:25:38 +0200 Subject: [PATCH 076/103] [templates]: Introduce App & Library templates --- .../Cesium.Templates.CSharp.csproj | 19 ++++++++ .../.template.config/template.json | 40 +++++++++++++++++ .../MyProject.Name.ceproj | 9 ++++ .../Cesium.Template.App.CSharp/program.c | 7 +++ .../.template.config/template.json | 44 +++++++++++++++++++ .../MyProject.Name.ceproj | 9 ++++ .../Cesium.Template.Library.CSharp/lib.c | 4 ++ Cesium.sln | 9 ++++ 8 files changed, 141 insertions(+) create mode 100644 Cesium.Templates.CSharp/Cesium.Templates.CSharp.csproj create mode 100644 Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/.template.config/template.json create mode 100644 Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/MyProject.Name.ceproj create mode 100644 Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/program.c create mode 100644 Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/.template.config/template.json create mode 100644 Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/MyProject.Name.ceproj create mode 100644 Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/lib.c diff --git a/Cesium.Templates.CSharp/Cesium.Templates.CSharp.csproj b/Cesium.Templates.CSharp/Cesium.Templates.CSharp.csproj new file mode 100644 index 00000000..803aa64f --- /dev/null +++ b/Cesium.Templates.CSharp/Cesium.Templates.CSharp.csproj @@ -0,0 +1,19 @@ + + + Cesium .NET Templates + Templates to use when creating a Cesium applications or libraries. + Template + netstandard2.0 + true + false + content + + $(NoWarn);NU5128 + Cesium.Templates.CSharp + + + + + + + diff --git a/Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/.template.config/template.json b/Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/.template.config/template.json new file mode 100644 index 00000000..d0241951 --- /dev/null +++ b/Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/.template.config/template.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Cesium Team", + "classifications": [ "Console" ], + "identity": "Cesium.Template.App.CSharp", + "name": "Cesium Console Application", + "shortName": "cesiumapp", + "tags": { + "language": "C", + "type":"project" + }, + "sourceName": "MyProject.Name", + "preferNameDirectory": true, + "symbols": { + "CesiumVersion": { + "type": "generated", + "generator": "constant", + "parameters": { + "value": "0.0.1" + }, + "replaces": "CesiumVersion" + }, + "tfm": { + "type": "parameter", + "datatype": "choice", + "defaultValue": "net6.0", + "choices": [ + { + "choice": "net6.0", + "description": ".NET 6.0 target framework" + }, + { + "choice": "net48", + "description": ".NET Framework 4.8 target framework" + } + ], + "replaces":"Tfm" + } + } +} diff --git a/Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/MyProject.Name.ceproj b/Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/MyProject.Name.ceproj new file mode 100644 index 00000000..20a785f2 --- /dev/null +++ b/Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/MyProject.Name.ceproj @@ -0,0 +1,9 @@ + + + Tfm + Exe + + + + + diff --git a/Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/program.c b/Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/program.c new file mode 100644 index 00000000..2889672e --- /dev/null +++ b/Cesium.Templates.CSharp/content/Cesium.Template.App.CSharp/program.c @@ -0,0 +1,7 @@ +#include + +int main(int argc, char *argv[]) +{ + puts("Hello, world!"); + return 42; +} diff --git a/Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/.template.config/template.json b/Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/.template.config/template.json new file mode 100644 index 00000000..0cb9d45d --- /dev/null +++ b/Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/.template.config/template.json @@ -0,0 +1,44 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Cesium Team", + "classifications": [ "Console" ], + "identity": "Cesium.Template.Library.CSharp", + "name": "Cesium Library", + "shortName": "cesiumlib", + "tags": { + "language": "C", + "type":"project" + }, + "sourceName": "MyProject.Name", + "preferNameDirectory": true, + "symbols": { + "CesiumVersion": { + "type": "generated", + "generator": "constant", + "parameters": { + "value": "0.0.1" + }, + "replaces": "CesiumVersion" + }, + "tfm": { + "type": "parameter", + "datatype": "choice", + "defaultValue": "net6.0", + "choices": [ + { + "choice": "net6.0", + "description": ".NET 6.0 target framework" + }, + { + "choice": "netstandard2.0", + "description": ".NET Standard 2.0 target framework" + }, + { + "choice": "net48", + "description": ".NET Framework 4.8 target framework" + } + ], + "replaces":"Tfm" + } + } +} diff --git a/Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/MyProject.Name.ceproj b/Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/MyProject.Name.ceproj new file mode 100644 index 00000000..989b06b8 --- /dev/null +++ b/Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/MyProject.Name.ceproj @@ -0,0 +1,9 @@ + + + Tfm + Library + + + + + diff --git a/Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/lib.c b/Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/lib.c new file mode 100644 index 00000000..be1e084f --- /dev/null +++ b/Cesium.Templates.CSharp/content/Cesium.Template.Library.CSharp/lib.c @@ -0,0 +1,4 @@ +int add(int a, int b) +{ + return a + b; +} diff --git a/Cesium.sln b/Cesium.sln index cc4bd6c6..3e4e9144 100644 --- a/Cesium.sln +++ b/Cesium.sln @@ -94,6 +94,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cesium.Solution.Metadata", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{05416E66-3615-4ABB-A130-F37EC18785A2}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Templates", "Templates", "{F59EF607-B888-4FC2-8148-43B019F33C7E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cesium.Templates.CSharp", "Cesium.Templates.CSharp\Cesium.Templates.CSharp.csproj", "{D26ED37B-1F41-4001-8755-47026763A32A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -170,6 +174,10 @@ Global {5B59ADD9-5C9D-482C-B238-F5EFD5E1F7CF}.Debug|Any CPU.Build.0 = Debug|Any CPU {5B59ADD9-5C9D-482C-B238-F5EFD5E1F7CF}.Release|Any CPU.ActiveCfg = Release|Any CPU {5B59ADD9-5C9D-482C-B238-F5EFD5E1F7CF}.Release|Any CPU.Build.0 = Release|Any CPU + {D26ED37B-1F41-4001-8755-47026763A32A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D26ED37B-1F41-4001-8755-47026763A32A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D26ED37B-1F41-4001-8755-47026763A32A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D26ED37B-1F41-4001-8755-47026763A32A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -177,6 +185,7 @@ Global GlobalSection(NestedProjects) = preSolution {C08E4851-DE2E-490E-970D-4F6A0A902A98} = {720F6830-E724-4B3A-BFDC-3FA1301A59D0} {BDB20BB2-0C0E-4EEA-8D65-AF53A3E65837} = {C08E4851-DE2E-490E-970D-4F6A0A902A98} + {D26ED37B-1F41-4001-8755-47026763A32A} = {F59EF607-B888-4FC2-8148-43B019F33C7E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4EAC8E60-2623-4A2D-B08C-4326184915E7} From b8c1c2ff4db7c604c6d7b9d5e64782ddb531c0fc Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Wed, 1 May 2024 00:26:19 +0200 Subject: [PATCH 077/103] [templates]: Add NUKE target for template packing --- .nuke/build.schema.json | 2 ++ build/Build.Templates.cs | 18 ++++++++++++++++++ build/_build.csproj | 3 +++ 3 files changed, 23 insertions(+) create mode 100644 build/Build.Templates.cs diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index ffb7d189..309bbb5e 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -86,6 +86,7 @@ "PackAllCompilerBundles", "PackCompilerBundle", "PackSdk", + "PackTemplates", "PublishAllCompilerBundles", "PublishCompilerBundle", "RestoreAll", @@ -119,6 +120,7 @@ "PackAllCompilerBundles", "PackCompilerBundle", "PackSdk", + "PackTemplates", "PublishAllCompilerBundles", "PublishCompilerBundle", "RestoreAll", diff --git a/build/Build.Templates.cs b/build/Build.Templates.cs new file mode 100644 index 00000000..0de5b747 --- /dev/null +++ b/build/Build.Templates.cs @@ -0,0 +1,18 @@ +using Nuke.Common; +using Nuke.Common.Tooling; +using Nuke.Common.Tools.DotNet; +using static Nuke.Common.Tools.DotNet.DotNetTasks; + +partial class Build +{ + Target PackTemplates => _ => _ + .DependsOn(CompileAll) + .Executes(() => + { + DotNetPack(_ => _ + .Apply(settings => !string.IsNullOrEmpty(RuntimeId) ? settings.SetRuntime(RuntimeId) : settings) + .SetConfiguration(Configuration) + .SetProject(Solution.Templates.Cesium_Templates_CSharp) + .EnableNoRestore()); + }); +} diff --git a/build/_build.csproj b/build/_build.csproj index 98f857ce..b14ba09a 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -22,6 +22,9 @@ Build.cs + + Build.cs + From 9040555a7d969ffb548d4b509e2685ff19d801ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 22:02:01 +0000 Subject: [PATCH 078/103] Bump Microsoft.Build.Tasks.Core and Microsoft.Build.Utilities.Core Bumps [Microsoft.Build.Tasks.Core](https://github.com/dotnet/msbuild) and [Microsoft.Build.Utilities.Core](https://github.com/dotnet/msbuild). These dependencies needed to be updated together. Updates `Microsoft.Build.Tasks.Core` from 17.9.5 to 17.10.4 - [Release notes](https://github.com/dotnet/msbuild/releases) - [Changelog](https://github.com/dotnet/msbuild/blob/main/documentation/Changelog.md) - [Commits](https://github.com/dotnet/msbuild/compare/v17.9.5...v17.10.4) Updates `Microsoft.Build.Utilities.Core` from 17.9.5 to 17.10.4 - [Release notes](https://github.com/dotnet/msbuild/releases) - [Changelog](https://github.com/dotnet/msbuild/blob/main/documentation/Changelog.md) - [Commits](https://github.com/dotnet/msbuild/compare/v17.9.5...v17.10.4) --- updated-dependencies: - dependency-name: Microsoft.Build.Tasks.Core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: Microsoft.Build.Utilities.Core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 8953351a..a0af9f48 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -24,7 +24,7 @@ - - + + \ No newline at end of file From 38fde569c15469288bc8b7eb38fe80f223a4eec8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 22:03:52 +0000 Subject: [PATCH 079/103] Bump Microsoft.NET.Test.Sdk from 17.9.0 to 17.10.0 Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.9.0 to 17.10.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md) - [Commits](https://github.com/microsoft/vstest/compare/v17.9.0...v17.10.0) --- updated-dependencies: - dependency-name: Microsoft.NET.Test.Sdk dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a0af9f48..30d2a66b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,7 +8,7 @@ - + From d1ffce8546120fe3d691cdc716cb5ad86e3647e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 25 May 2024 21:15:38 +0000 Subject: [PATCH 080/103] Bump Microsoft.Build from 17.9.5 to 17.10.4 Bumps [Microsoft.Build](https://github.com/dotnet/msbuild) from 17.9.5 to 17.10.4. - [Release notes](https://github.com/dotnet/msbuild/releases) - [Changelog](https://github.com/dotnet/msbuild/blob/main/documentation/Changelog.md) - [Commits](https://github.com/dotnet/msbuild/compare/v17.9.5...v17.10.4) --- updated-dependencies: - dependency-name: Microsoft.Build dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 30d2a66b..1778bf32 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,7 +23,7 @@ - + From e4412046a1de421662c5c82cd89b353dccdc46f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 21:43:07 +0000 Subject: [PATCH 081/103] Bump xunit.runner.visualstudio from 2.8.0 to 2.8.1 Bumps [xunit.runner.visualstudio](https://github.com/xunit/visualstudio.xunit) from 2.8.0 to 2.8.1. - [Release notes](https://github.com/xunit/visualstudio.xunit/releases) - [Commits](https://github.com/xunit/visualstudio.xunit/compare/2.8.0...2.8.1) --- updated-dependencies: - dependency-name: xunit.runner.visualstudio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1778bf32..0933a425 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,7 +15,7 @@ - + From 848cbb9a97e345d94930699388dfdf2a78266ccd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 20:47:09 +0000 Subject: [PATCH 082/103] Bump xunit.assert from 2.8.0 to 2.8.1 Bumps [xunit.assert](https://github.com/xunit/xunit) from 2.8.0 to 2.8.1. - [Commits](https://github.com/xunit/xunit/compare/2.8.0...2.8.1) --- updated-dependencies: - dependency-name: xunit.assert dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 0933a425..c6d9dc65 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,7 +14,7 @@ - + From 7cac9e8467192a87335cfe517bd69996c10e0dd7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 21:00:55 +0000 Subject: [PATCH 083/103] Bump xunit from 2.8.0 to 2.8.1 Bumps [xunit](https://github.com/xunit/xunit) from 2.8.0 to 2.8.1. - [Commits](https://github.com/xunit/xunit/compare/2.8.0...2.8.1) --- updated-dependencies: - dependency-name: xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index c6d9dc65..b8ca05d7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -13,7 +13,7 @@ - + From 01a993170776b498ac2eed2cadcbe340725e6c51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 21:44:54 +0000 Subject: [PATCH 084/103] Bump Meziantou.Xunit.ParallelTestFramework from 2.1.0 to 2.2.0 Bumps [Meziantou.Xunit.ParallelTestFramework](https://github.com/meziantou/Meziantou.Xunit.ParallelTestFramework) from 2.1.0 to 2.2.0. - [Commits](https://github.com/meziantou/Meziantou.Xunit.ParallelTestFramework/commits) --- updated-dependencies: - dependency-name: Meziantou.Xunit.ParallelTestFramework dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b8ca05d7..35e73f45 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,7 +7,7 @@ - + From d0d87b472fce2623231c09de66b60301de9f67aa Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sun, 9 Jun 2024 22:38:54 +0200 Subject: [PATCH 085/103] (#599) Tests: override NUGET_PACKAGES for SDK tests --- Cesium.Sdk.Tests/SdkTestBase.cs | 19 ++++++++++--------- Cesium.sln.DotSettings | 1 + 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index 37ade95e..afe05703 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -13,10 +13,10 @@ public abstract class SdkTestBase : IDisposable private readonly ITestOutputHelper _testOutputHelper; private readonly string _temporaryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - protected string NuGetConfigPath => Path.Combine(_temporaryPath, "NuGet.config"); - protected string GlobalJsonPath => Path.Combine(_temporaryPath, "global.json"); + private string NuGetConfigPath => Path.Combine(_temporaryPath, "NuGet.config"); + private string GlobalJsonPath => Path.Combine(_temporaryPath, "global.json"); - public SdkTestBase(ITestOutputHelper testOutputHelper) + protected SdkTestBase(ITestOutputHelper testOutputHelper) { _testOutputHelper = testOutputHelper; @@ -55,12 +55,16 @@ protected async Task ExecuteTargets(string projectName, params stri RedirectStandardError = true, CreateNoWindow = true, UseShellExecute = false, + Environment = + { + ["NUGET_PACKAGES"] = Path.Combine(_temporaryPath, "package-cache") + } }; using var process = new Process(); process.StartInfo = startInfo; - process.OutputDataReceived += (sender, e) => + process.OutputDataReceived += (_, e) => { if (!string.IsNullOrEmpty(e.Data)) { @@ -68,7 +72,7 @@ protected async Task ExecuteTargets(string projectName, params stri } }; - process.ErrorDataReceived += (sender, e) => + process.ErrorDataReceived += (_, e) => { if (!string.IsNullOrEmpty(e.Data)) { @@ -81,7 +85,7 @@ protected async Task ExecuteTargets(string projectName, params stri process.BeginOutputReadLine(); process.BeginErrorReadLine(); - process.WaitForExit(); + await process.WaitForExitAsync(); var success = process.ExitCode == 0; @@ -117,9 +121,6 @@ private static void EmitNuGetConfig(string configFilePath, string packageSourceP { File.WriteAllText(configFilePath, $""" - - - diff --git a/Cesium.sln.DotSettings b/Cesium.sln.DotSettings index 21660cf8..5d0eed08 100644 --- a/Cesium.sln.DotSettings +++ b/Cesium.sln.DotSettings @@ -2,6 +2,7 @@ True True + True True True True From af53de27a80a46c8c6cef9083b361a0bc95f645c Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sat, 1 Jun 2024 01:27:15 +0200 Subject: [PATCH 086/103] [sdk]: Include .c and .h files as compile items by default (cherry picked from commit d3721cca9cc0764890ee73f66b702702789076e9) --- Cesium.Sdk/Sdk/Sdk.props | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Cesium.Sdk/Sdk/Sdk.props b/Cesium.Sdk/Sdk/Sdk.props index 6cb6f3d8..9c1afd11 100644 --- a/Cesium.Sdk/Sdk/Sdk.props +++ b/Cesium.Sdk/Sdk/Sdk.props @@ -1,7 +1,13 @@ - false + true + true + false + false + false + false + .c @@ -15,6 +21,11 @@ false + + + + + Date: Sat, 1 Jun 2024 01:28:07 +0200 Subject: [PATCH 087/103] [sdk]: Adjust existing and add new tests for .c and .h default items evaluation (cherry picked from commit 42d4a7da13f4c320625864ff1c3b91d8c8a98512) --- Cesium.Sdk.Tests/EvaluationTests.cs | 32 +++++++++++++++++++ Cesium.Sdk.Tests/SdkTestBase.cs | 9 ++++++ .../SimpleCoreExe/SimpleCoreExe.ceproj | 3 -- .../SimpleCoreLibrary.ceproj | 3 -- .../SimpleDisableDefaultCompileItems.ceproj | 10 ++++++ .../SimpleDisableDefaultCompileItems/hello.c | 7 ++++ .../SimpleNetStandardLibrary.ceproj | 3 -- .../SimpleNetfxExe/SimpleNetfxExe.ceproj | 3 -- .../SimpleNetfxLibrary.ceproj | 3 -- Cesium.TestFramework/DotNetCliHelper.cs | 11 +++++++ 10 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 Cesium.Sdk.Tests/EvaluationTests.cs create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/SimpleDisableDefaultCompileItems.ceproj create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/hello.c diff --git a/Cesium.Sdk.Tests/EvaluationTests.cs b/Cesium.Sdk.Tests/EvaluationTests.cs new file mode 100644 index 00000000..fc6d6cfa --- /dev/null +++ b/Cesium.Sdk.Tests/EvaluationTests.cs @@ -0,0 +1,32 @@ +using Xunit.Abstractions; + +namespace Cesium.Sdk.Tests; + +/// +/// Tests that proper MSBuild items and properties are populated and set for the Cesium project +/// +/// +public class EvaluationTests(ITestOutputHelper testOutputHelper) : SdkTestBase(testOutputHelper) +{ + [Theory] + [InlineData("SimpleCoreExe")] + public async Task Evaluation_EnableDefaultCompileItems(string projectName) + { + HashSet expectedCompileItems = ["hello.c"]; + + var items = await ListItems(projectName, "Compile"); + + Assert.Equal(expectedCompileItems, items.ToHashSet()); + } + + [Theory] + [InlineData("SimpleDisableDefaultCompileItems")] + public async Task Evaluation_DisableDefaultCompileItems(string projectName) + { + HashSet expectedCompileItems = ["hello.c"]; + + var items = await ListItems(projectName, "Compile"); + + Assert.Equal(expectedCompileItems, items.ToHashSet()); + } +} diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index afe05703..6ed585e7 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -117,6 +117,15 @@ IReadOnlyCollection CollectArtifacts(string folder) } } + protected async Task> ListItems(string projectName, string itemName) + { + var projectFile = $"{projectName}/{projectName}.ceproj"; + var testProjectFile = Path.GetFullPath(Path.Combine(_temporaryPath, projectFile)); + var items = await DotNetCliHelper.EvaluateMSBuildItem(_testOutputHelper, testProjectFile, itemName); + + return items.Select(i => i.identity); + } + private static void EmitNuGetConfig(string configFilePath, string packageSourcePath) { File.WriteAllText(configFilePath, $""" diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleCoreExe/SimpleCoreExe.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleCoreExe/SimpleCoreExe.ceproj index 228362dd..b359b970 100644 --- a/Cesium.Sdk.Tests/TestProjects/SimpleCoreExe/SimpleCoreExe.ceproj +++ b/Cesium.Sdk.Tests/TestProjects/SimpleCoreExe/SimpleCoreExe.ceproj @@ -3,7 +3,4 @@ net6.0 Exe - - - diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/SimpleCoreLibrary.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/SimpleCoreLibrary.ceproj index 69513748..fa9b0e83 100644 --- a/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/SimpleCoreLibrary.ceproj +++ b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibrary/SimpleCoreLibrary.ceproj @@ -3,7 +3,4 @@ net6.0 Library - - - diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/SimpleDisableDefaultCompileItems.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/SimpleDisableDefaultCompileItems.ceproj new file mode 100644 index 00000000..d9380112 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/SimpleDisableDefaultCompileItems.ceproj @@ -0,0 +1,10 @@ + + + net6.0 + Exe + false + + + + + diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/hello.c b/Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/hello.c new file mode 100644 index 00000000..2889672e --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/hello.c @@ -0,0 +1,7 @@ +#include + +int main(int argc, char *argv[]) +{ + puts("Hello, world!"); + return 42; +} diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/SimpleNetStandardLibrary.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/SimpleNetStandardLibrary.ceproj index 06f876d5..d034cadc 100644 --- a/Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/SimpleNetStandardLibrary.ceproj +++ b/Cesium.Sdk.Tests/TestProjects/SimpleNetStandardLibrary/SimpleNetStandardLibrary.ceproj @@ -3,7 +3,4 @@ netstandard2.0 Library - - - diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/SimpleNetfxExe.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/SimpleNetfxExe.ceproj index 7a2d6ae4..06eaf71d 100644 --- a/Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/SimpleNetfxExe.ceproj +++ b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxExe/SimpleNetfxExe.ceproj @@ -3,7 +3,4 @@ net48 Exe - - - diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/SimpleNetfxLibrary.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/SimpleNetfxLibrary.ceproj index c41fe5bd..324bb982 100644 --- a/Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/SimpleNetfxLibrary.ceproj +++ b/Cesium.Sdk.Tests/TestProjects/SimpleNetfxLibrary/SimpleNetfxLibrary.ceproj @@ -3,7 +3,4 @@ net48 Library - - - diff --git a/Cesium.TestFramework/DotNetCliHelper.cs b/Cesium.TestFramework/DotNetCliHelper.cs index 587f9a8e..bfa347f2 100644 --- a/Cesium.TestFramework/DotNetCliHelper.cs +++ b/Cesium.TestFramework/DotNetCliHelper.cs @@ -49,6 +49,17 @@ public static async Task> EvaluateMSBuildPro .ToDictionary(property => property.Name, property => property.Value.GetString() ?? string.Empty); } + public static async Task> EvaluateMSBuildItem(ITestOutputHelper output, string projectPath, string itemName) + { + var result = await ExecUtil.Run(output, "dotnet", Environment.CurrentDirectory, [ "msbuild", $"\"{projectPath}\"", $"-getItem:{itemName}" ]); + var resultString = result.StandardOutput; + var resultJson = JsonDocument.Parse(resultString); + var itemsJson = resultJson.RootElement.GetProperty("Items").EnumerateObject().ToArray(); + var itemsDict = itemsJson.ToDictionary(item => item.Name, item => item.Value.EnumerateArray()); + + return itemsDict[itemName].Select(meta => (meta.GetProperty("Identity").GetString()!, meta.GetProperty("FullPath").GetString())); + } + public static Task RunDotNetDll( ITestOutputHelper output, string workingDirectoryPath, From 9f65d901928d6ccdb45d2d2c0772f5a9d491415c Mon Sep 17 00:00:00 2001 From: Andrii Rublov Date: Sat, 1 Jun 2024 14:43:49 +0200 Subject: [PATCH 088/103] [sdk]: Add tests to check .h default items --- Cesium.Sdk.Tests/CesiumCompileTests.cs | 1 + Cesium.Sdk.Tests/EvaluationTests.cs | 6 ++-- .../SimpleCoreLibraryWithHeader.ceproj | 6 ++++ .../SimpleCoreLibraryWithHeader/library.c | 30 +++++++++++++++++++ .../SimpleCoreLibraryWithHeader/library.h | 10 +++++++ .../SimpleExplicitCompileItems.ceproj} | 0 .../hello.c | 0 7 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/SimpleCoreLibraryWithHeader.ceproj create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/library.c create mode 100644 Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/library.h rename Cesium.Sdk.Tests/TestProjects/{SimpleDisableDefaultCompileItems/SimpleDisableDefaultCompileItems.ceproj => SimpleExplicitCompileItems/SimpleExplicitCompileItems.ceproj} (100%) rename Cesium.Sdk.Tests/TestProjects/{SimpleDisableDefaultCompileItems => SimpleExplicitCompileItems}/hello.c (100%) diff --git a/Cesium.Sdk.Tests/CesiumCompileTests.cs b/Cesium.Sdk.Tests/CesiumCompileTests.cs index 11bf5c45..e9156037 100644 --- a/Cesium.Sdk.Tests/CesiumCompileTests.cs +++ b/Cesium.Sdk.Tests/CesiumCompileTests.cs @@ -58,6 +58,7 @@ public async Task CesiumCompile_NetFx_Exe_ShouldSucceed(string projectName) [Theory] [InlineData("SimpleCoreLibrary")] [InlineData("SimpleNetStandardLibrary")] + [InlineData("SimpleCoreLibraryWithHeader")] public async Task CesiumCompile_Core_Library_ShouldSucceed(string projectName) { string[] expectedObjArtifacts = diff --git a/Cesium.Sdk.Tests/EvaluationTests.cs b/Cesium.Sdk.Tests/EvaluationTests.cs index fc6d6cfa..39ef319b 100644 --- a/Cesium.Sdk.Tests/EvaluationTests.cs +++ b/Cesium.Sdk.Tests/EvaluationTests.cs @@ -9,10 +9,10 @@ namespace Cesium.Sdk.Tests; public class EvaluationTests(ITestOutputHelper testOutputHelper) : SdkTestBase(testOutputHelper) { [Theory] - [InlineData("SimpleCoreExe")] + [InlineData("SimpleCoreLibraryWithHeader")] public async Task Evaluation_EnableDefaultCompileItems(string projectName) { - HashSet expectedCompileItems = ["hello.c"]; + HashSet expectedCompileItems = ["library.c", "library.h"]; var items = await ListItems(projectName, "Compile"); @@ -20,7 +20,7 @@ public async Task Evaluation_EnableDefaultCompileItems(string projectName) } [Theory] - [InlineData("SimpleDisableDefaultCompileItems")] + [InlineData("SimpleExplicitCompileItems")] public async Task Evaluation_DisableDefaultCompileItems(string projectName) { HashSet expectedCompileItems = ["hello.c"]; diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/SimpleCoreLibraryWithHeader.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/SimpleCoreLibraryWithHeader.ceproj new file mode 100644 index 00000000..fa9b0e83 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/SimpleCoreLibraryWithHeader.ceproj @@ -0,0 +1,6 @@ + + + net6.0 + Library + + diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/library.c b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/library.c new file mode 100644 index 00000000..c1075b29 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/library.c @@ -0,0 +1,30 @@ +#include "library.h" +#include + +void greet() +{ + puts("Hello World!\n"); +} + +int add(int a, int b) +{ + return a + b; +} + +int subtract(int a, int b) +{ + return a - b; +} + +float divide(int a, int b) +{ + if (b != 0) + return (float) a / b; + else + return 0; +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/library.h b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/library.h new file mode 100644 index 00000000..9651f0f8 --- /dev/null +++ b/Cesium.Sdk.Tests/TestProjects/SimpleCoreLibraryWithHeader/library.h @@ -0,0 +1,10 @@ +#ifndef LIBRARY_H +#define LIBRARY_H + +void greet(void); +int add(int a, int b); +int subtract(int a, int b); +float divide(int a, int b); +int multiply(int a, int b); + +#endif // LIBRARY_H diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/SimpleDisableDefaultCompileItems.ceproj b/Cesium.Sdk.Tests/TestProjects/SimpleExplicitCompileItems/SimpleExplicitCompileItems.ceproj similarity index 100% rename from Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/SimpleDisableDefaultCompileItems.ceproj rename to Cesium.Sdk.Tests/TestProjects/SimpleExplicitCompileItems/SimpleExplicitCompileItems.ceproj diff --git a/Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/hello.c b/Cesium.Sdk.Tests/TestProjects/SimpleExplicitCompileItems/hello.c similarity index 100% rename from Cesium.Sdk.Tests/TestProjects/SimpleDisableDefaultCompileItems/hello.c rename to Cesium.Sdk.Tests/TestProjects/SimpleExplicitCompileItems/hello.c From 89965c779300bcc8703abd6574dfcb8f44a38217 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sun, 9 Jun 2024 22:58:16 +0200 Subject: [PATCH 089/103] (#599) Tests: pass additional env vars --- Cesium.Sdk.Tests/SdkTestBase.cs | 19 ++++++++++++------ Cesium.TestFramework/DotNetCliHelper.cs | 26 +++++++++++++++++++++---- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/Cesium.Sdk.Tests/SdkTestBase.cs b/Cesium.Sdk.Tests/SdkTestBase.cs index 6ed585e7..d6a3989a 100644 --- a/Cesium.Sdk.Tests/SdkTestBase.cs +++ b/Cesium.Sdk.Tests/SdkTestBase.cs @@ -12,6 +12,7 @@ public abstract class SdkTestBase : IDisposable { private readonly ITestOutputHelper _testOutputHelper; private readonly string _temporaryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + private readonly Dictionary _dotNetEnvVars; private string NuGetConfigPath => Path.Combine(_temporaryPath, "NuGet.config"); private string GlobalJsonPath => Path.Combine(_temporaryPath, "global.json"); @@ -19,6 +20,7 @@ public abstract class SdkTestBase : IDisposable protected SdkTestBase(ITestOutputHelper testOutputHelper) { _testOutputHelper = testOutputHelper; + _dotNetEnvVars = new() { ["NUGET_PACKAGES"] = Path.Combine(_temporaryPath, "package-cache") }; File.Delete(_temporaryPath); @@ -55,11 +57,11 @@ protected async Task ExecuteTargets(string projectName, params stri RedirectStandardError = true, CreateNoWindow = true, UseShellExecute = false, - Environment = - { - ["NUGET_PACKAGES"] = Path.Combine(_temporaryPath, "package-cache") - } }; + foreach (var (name, var) in _dotNetEnvVars) + { + startInfo.Environment[name] = var; + } using var process = new Process(); process.StartInfo = startInfo; @@ -93,7 +95,12 @@ protected async Task ExecuteTargets(string projectName, params stri ? "Build succeeded" : $"Build failed with exit code {process.ExitCode}"); - var properties = await DotNetCliHelper.EvaluateMSBuildProperties(_testOutputHelper, testProjectFile, objFolderPropertyName, binFolderPropertyName); + var properties = await DotNetCliHelper.EvaluateMSBuildProperties( + _testOutputHelper, + testProjectFile, + env: _dotNetEnvVars, + objFolderPropertyName, + binFolderPropertyName); _testOutputHelper.WriteLine($"Properties request result: {JsonSerializer.Serialize(properties, new JsonSerializerOptions { WriteIndented = false })}"); var binFolder = NormalizePath(Path.GetFullPath(properties[binFolderPropertyName], testProjectFolder)); @@ -121,7 +128,7 @@ protected async Task> ListItems(string projectName, string i { var projectFile = $"{projectName}/{projectName}.ceproj"; var testProjectFile = Path.GetFullPath(Path.Combine(_temporaryPath, projectFile)); - var items = await DotNetCliHelper.EvaluateMSBuildItem(_testOutputHelper, testProjectFile, itemName); + var items = await DotNetCliHelper.EvaluateMSBuildItem(_testOutputHelper, testProjectFile, itemName, env: _dotNetEnvVars); return items.Select(i => i.identity); } diff --git a/Cesium.TestFramework/DotNetCliHelper.cs b/Cesium.TestFramework/DotNetCliHelper.cs index bfa347f2..21d32032 100644 --- a/Cesium.TestFramework/DotNetCliHelper.cs +++ b/Cesium.TestFramework/DotNetCliHelper.cs @@ -32,12 +32,21 @@ public static async Task EvaluateMSBuildProperty(ITestOutputHelper outpu return result.StandardOutput; } - public static async Task> EvaluateMSBuildProperties(ITestOutputHelper output, string projectPath, params string[] propertyNames) + public static async Task> EvaluateMSBuildProperties( + ITestOutputHelper output, + string projectPath, + IReadOnlyDictionary? env = null, + params string[] propertyNames) { if (!propertyNames.Any()) return new Dictionary(); - var result = await ExecUtil.Run(output, "dotnet", Environment.CurrentDirectory, [ "msbuild", $"\"{projectPath}\"", $"-getProperty:{string.Join(",", propertyNames)}" ]); + var result = await ExecUtil.Run( + output, + "dotnet", + Environment.CurrentDirectory, + [ "msbuild", $"\"{projectPath}\"", $"-getProperty:{string.Join(",", propertyNames)}" ], + env); var resultString = result.StandardOutput; if (propertyNames.Length == 1) return new Dictionary { { propertyNames[0], resultString } }; @@ -49,9 +58,18 @@ public static async Task> EvaluateMSBuildPro .ToDictionary(property => property.Name, property => property.Value.GetString() ?? string.Empty); } - public static async Task> EvaluateMSBuildItem(ITestOutputHelper output, string projectPath, string itemName) + public static async Task> EvaluateMSBuildItem( + ITestOutputHelper output, + string projectPath, + string itemName, + IReadOnlyDictionary? env = null) { - var result = await ExecUtil.Run(output, "dotnet", Environment.CurrentDirectory, [ "msbuild", $"\"{projectPath}\"", $"-getItem:{itemName}" ]); + var result = await ExecUtil.Run( + output, + "dotnet", + Environment.CurrentDirectory, + [ "msbuild", $"\"{projectPath}\"", $"-getItem:{itemName}" ], + env); var resultString = result.StandardOutput; var resultJson = JsonDocument.Parse(resultString); var itemsJson = resultJson.RootElement.GetProperty("Items").EnumerateObject().ToArray(); From c2fd3cd0864d7768a92013d016789303bf2c8aa3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 21:28:26 +0000 Subject: [PATCH 090/103] Bump Verify.Xunit from 24.2.0 to 25.0.1 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 24.2.0 to 25.0.1. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/commits/25.0.1) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 35e73f45..9f31256a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + From 81b8db675dab18f9a84e68227d86e468ec60a54a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Jun 2024 22:08:03 +0000 Subject: [PATCH 091/103] Bump Verify.Xunit from 25.0.1 to 25.0.3 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 25.0.1 to 25.0.3. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/25.0.1...25.0.3) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 9f31256a..5b220c97 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + From 1779a31069d5d8c39f6fa81a7e8f7cd09814638a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 21:48:22 +0000 Subject: [PATCH 092/103] Bump Verify.Xunit from 25.0.3 to 25.0.4 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 25.0.3 to 25.0.4. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/25.0.3...25.0.4) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 5b220c97..1e88c04b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + From b32f8aefe3ae0047736fb8ad6b05d10cb2804ee7 Mon Sep 17 00:00:00 2001 From: Ndiaye Pape ngagne Date: Sat, 15 Jun 2024 06:46:21 +0200 Subject: [PATCH 093/103] Issue-475 : Using the unsigned operations where it s available on PrimitiveType --- Cesium.CodeGen.Tests/CodeGenArrayTests.cs | 18 +++++++++ ...rrayTests.SignedByteArrayTest.verified.txt | 37 +++++++++++++++++++ ...yTests.UnSignedByteArrayTest2.verified.txt | 37 +++++++++++++++++++ Cesium.CodeGen/Ir/Types/PrimitiveType.cs | 4 +- 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 Cesium.CodeGen.Tests/verified/CodeGenArrayTests.SignedByteArrayTest.verified.txt create mode 100644 Cesium.CodeGen.Tests/verified/CodeGenArrayTests.UnSignedByteArrayTest2.verified.txt diff --git a/Cesium.CodeGen.Tests/CodeGenArrayTests.cs b/Cesium.CodeGen.Tests/CodeGenArrayTests.cs index f7f318e8..2d27961e 100644 --- a/Cesium.CodeGen.Tests/CodeGenArrayTests.cs +++ b/Cesium.CodeGen.Tests/CodeGenArrayTests.cs @@ -170,6 +170,24 @@ int main() { } """); + [Fact] + public Task SignedByteArrayTest() => DoTest(@" +int main() { + signed char x[1] = { -1 }; + signed char y = x[0]; + int z = (int)y; + return z; +}"); + + [Fact] + public Task UnSignedByteArrayTest2() => DoTest(@" +int main() { + unsigned char a[1] = { 255 }; + unsigned char b = a[0]; + int c = (int)b; + return c; +}"); + [Fact] public Task PointerAsArray() => DoTest(""" int main(void) diff --git a/Cesium.CodeGen.Tests/verified/CodeGenArrayTests.SignedByteArrayTest.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenArrayTests.SignedByteArrayTest.verified.txt new file mode 100644 index 00000000..9793ad88 --- /dev/null +++ b/Cesium.CodeGen.Tests/verified/CodeGenArrayTests.SignedByteArrayTest.verified.txt @@ -0,0 +1,37 @@ +System.Int32 ::main() + Locals: + System.SByte* V_0 + System.SByte V_1 + System.Int32 V_2 + IL_0000: ldc.i4.1 + IL_0001: conv.u + IL_0002: localloc + IL_0004: stloc.0 + IL_0005: ldsflda / ::ConstDataBuffer0 + IL_000a: ldloc V_0 + IL_000e: ldc.i4.1 + IL_000f: conv.u + IL_0010: call System.Void Cesium.Runtime.RuntimeHelpers::InitializeCompound(System.Void*,System.Void*,System.UInt32) + IL_0015: ldloc.0 + IL_0016: ldc.i4.0 + IL_0017: conv.i + IL_0018: ldc.i4 1 + IL_001d: mul + IL_001e: add + IL_001f: ldind.i1 + IL_0020: stloc.1 + IL_0021: ldloc.1 + IL_0022: conv.i4 + IL_0023: stloc.2 + IL_0024: ldloc.2 + IL_0025: ret + +System.Int32 ::() + Locals: + System.Int32 V_0 + IL_0000: call System.Int32 ::main() + IL_0005: stloc.s V_0 + IL_0007: ldloc.s V_0 + IL_0009: call System.Void Cesium.Runtime.RuntimeHelpers::Exit(System.Int32) + IL_000e: ldloc.s V_0 + IL_0010: ret diff --git a/Cesium.CodeGen.Tests/verified/CodeGenArrayTests.UnSignedByteArrayTest2.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenArrayTests.UnSignedByteArrayTest2.verified.txt new file mode 100644 index 00000000..8950ed17 --- /dev/null +++ b/Cesium.CodeGen.Tests/verified/CodeGenArrayTests.UnSignedByteArrayTest2.verified.txt @@ -0,0 +1,37 @@ +System.Int32 ::main() + Locals: + System.Byte* V_0 + System.Byte V_1 + System.Int32 V_2 + IL_0000: ldc.i4.1 + IL_0001: conv.u + IL_0002: localloc + IL_0004: stloc.0 + IL_0005: ldsflda / ::ConstDataBuffer0 + IL_000a: ldloc V_0 + IL_000e: ldc.i4.1 + IL_000f: conv.u + IL_0010: call System.Void Cesium.Runtime.RuntimeHelpers::InitializeCompound(System.Void*,System.Void*,System.UInt32) + IL_0015: ldloc.0 + IL_0016: ldc.i4.0 + IL_0017: conv.i + IL_0018: ldc.i4 1 + IL_001d: mul + IL_001e: add + IL_001f: ldind.u1 + IL_0020: stloc.1 + IL_0021: ldloc.1 + IL_0022: conv.i4 + IL_0023: stloc.2 + IL_0024: ldloc.2 + IL_0025: ret + +System.Int32 ::() + Locals: + System.Int32 V_0 + IL_0000: call System.Int32 ::main() + IL_0005: stloc.s V_0 + IL_0007: ldloc.s V_0 + IL_0009: call System.Void Cesium.Runtime.RuntimeHelpers::Exit(System.Int32) + IL_000e: ldloc.s V_0 + IL_0010: ret diff --git a/Cesium.CodeGen/Ir/Types/PrimitiveType.cs b/Cesium.CodeGen/Ir/Types/PrimitiveType.cs index 7a2c3686..bd4e2fe0 100644 --- a/Cesium.CodeGen/Ir/Types/PrimitiveType.cs +++ b/Cesium.CodeGen/Ir/Types/PrimitiveType.cs @@ -188,9 +188,9 @@ internal static class PrimitiveTypeInfo { PrimitiveTypeKind.SignedChar, (OpCodes.Ldind_I1, OpCodes.Stind_I1) }, { PrimitiveTypeKind.UnsignedChar, (OpCodes.Ldind_U1, OpCodes.Stind_I1) }, { PrimitiveTypeKind.Short, (OpCodes.Ldind_I2, OpCodes.Stind_I2) }, - { PrimitiveTypeKind.UnsignedShort, (OpCodes.Ldind_I2, OpCodes.Stind_I2) }, + { PrimitiveTypeKind.UnsignedShort, (OpCodes.Ldind_U2, OpCodes.Stind_I2) }, { PrimitiveTypeKind.Int, (OpCodes.Ldind_I4, OpCodes.Stind_I4) }, - { PrimitiveTypeKind.UnsignedInt, (OpCodes.Ldind_I4, OpCodes.Stind_I4) }, + { PrimitiveTypeKind.UnsignedInt, (OpCodes.Ldind_U4, OpCodes.Stind_I4) }, { PrimitiveTypeKind.Float, (OpCodes.Ldind_R4, OpCodes.Stind_R4) }, { PrimitiveTypeKind.Long, (OpCodes.Ldind_I8, OpCodes.Stind_I8) }, { PrimitiveTypeKind.UnsignedLong, (OpCodes.Ldind_I8, OpCodes.Stind_I8) }, From 53a9d4dba59f4f7f7ab7f759ea7c120d163bffb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:14:55 +0000 Subject: [PATCH 094/103] Bump Verify.Xunit from 25.0.4 to 25.2.0 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 25.0.4 to 25.2.0. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/25.0.4...25.2.0) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1e88c04b..81a7544e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + From d55b9a2da15c4c129e9470cfc17606960348c1c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 21:35:30 +0000 Subject: [PATCH 095/103] Bump Verify.Xunit from 25.2.0 to 25.3.0 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 25.2.0 to 25.3.0. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/25.2.0...25.3.0) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 81a7544e..efe9804a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + From 645145ed85dd8efbb1cee6d7cffdbefcb69bbc9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:22:12 +0000 Subject: [PATCH 096/103] Bump xunit from 2.8.1 to 2.9.0 Bumps xunit from 2.8.1 to 2.9.0. --- updated-dependencies: - dependency-name: xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index efe9804a..76517f39 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -13,8 +13,8 @@ - - + + From 516e7f7635befb4c0808d50d45cd5e42f0c46cf3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:26:35 +0000 Subject: [PATCH 097/103] Bump JetBrains.Annotations from 2023.3.0 to 2024.2.0 Bumps JetBrains.Annotations from 2023.3.0 to 2024.2.0. --- updated-dependencies: - dependency-name: JetBrains.Annotations dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 76517f39..92a379b6 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,7 @@ - + From 36c31b6f898ef539d912a06fef35b9d5ac9b3f1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:43:22 +0000 Subject: [PATCH 098/103] Bump xunit.runner.visualstudio from 2.8.1 to 2.8.2 Bumps xunit.runner.visualstudio from 2.8.1 to 2.8.2. --- updated-dependencies: - dependency-name: xunit.runner.visualstudio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 92a379b6..1b0221b7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,7 +15,7 @@ - + From 8fb7da6f2264eb084aff78bda4347cb250389bc4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 21:15:52 +0000 Subject: [PATCH 099/103] Bump Verify.Xunit from 25.3.0 to 25.3.1 Bumps Verify.Xunit from 25.3.0 to 25.3.1. --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1b0221b7..474c96c0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + From 298d192bc73f262f301de060d3523b0c15fc89bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 21:13:18 +0000 Subject: [PATCH 100/103] Bump Verify.Xunit from 25.3.1 to 25.3.2 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 25.3.1 to 25.3.2. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/25.3.1...25.3.2) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 474c96c0..fbf5a9ec 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + From b974c1f307cfb7fad6029629f294ce3e0b42a875 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 21:55:34 +0000 Subject: [PATCH 101/103] Bump AsyncKeyedLock from 6.4.2 to 7.0.0 Bumps [AsyncKeyedLock](https://github.com/MarkCiliaVincenti/AsyncKeyedLock) from 6.4.2 to 7.0.0. - [Release notes](https://github.com/MarkCiliaVincenti/AsyncKeyedLock/releases) - [Commits](https://github.com/MarkCiliaVincenti/AsyncKeyedLock/compare/6.4.2...7.0.0) --- updated-dependencies: - dependency-name: AsyncKeyedLock dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index fbf5a9ec..8be26108 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,7 +3,7 @@ true - + From 4a616d38a3d690e06581460d23adc2649057f7f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 21:56:20 +0000 Subject: [PATCH 102/103] Bump Verify.Xunit from 25.3.2 to 26.0.0 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 25.3.2 to 26.0.0. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/25.3.2...26.0.0) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 8be26108..67e7d1c7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + From 3e0ecd72cc7d696c0308887ad2d0405cc2ed7f13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 21:52:59 +0000 Subject: [PATCH 103/103] Bump Verify.Xunit from 26.0.0 to 26.0.1 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 26.0.0 to 26.0.1. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/26.0.0...26.0.1) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 67e7d1c7..b3882c53 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - +