Skip to content

Commit a02f8e5

Browse files
fix: BuildProperty-Generator and AOT compilation detection (#4333)
--------- Co-authored-by: James Crosswell <jamescrosswell@users.noreply.github.com>
1 parent cc613c9 commit a02f8e5

18 files changed

+760
-556
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- Sentry now decompresses Request bodies in ASP.NET Core when RequestDecompression middleware is enabled ([#4315](https://github.com/getsentry/sentry-dotnet/pull/4315))
1717
- Custom ISentryEventProcessors are now run for native iOS events ([#4318](https://github.com/getsentry/sentry-dotnet/pull/4318))
1818
- Crontab validation when capturing checkins ([#4314](https://github.com/getsentry/sentry-dotnet/pull/4314))
19+
- Fixed an issue with the way Sentry detects build settings. This was causing Sentry to produce code that could fail at runtime in AOT compiled applications. ([#4333](https://github.com/getsentry/sentry-dotnet/pull/4333))
1920
- Native AOT: link to static `lzma` on Linux/MUSL ([#4326](https://github.com/getsentry/sentry-dotnet/pull/4326))
2021
- AppDomain.CurrentDomain.ProcessExit hook is now removed on shutdown ([#4323](https://github.com/getsentry/sentry-dotnet/pull/4323))
2122

samples/Sentry.Samples.Android/Sentry.Samples.Android.csproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,4 @@
4343
<AndroidLinkMode>full</AndroidLinkMode>
4444
</PropertyGroup>
4545

46-
<!--In order to test our analyzers with this project, we manually reference our targets file. User do not need to do this-->
47-
<Import Project="..\..\src\Sentry\buildTransitive\Sentry.SourceGenerators.targets" />
4846
</Project>

samples/Sentry.Samples.Ios/Sentry.Samples.Ios.csproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,4 @@
4949
ReferenceOutputAssembly="false"/>
5050
</ItemGroup>
5151

52-
<!--In order to test our analyzers with this project, we manually reference our targets file. User do not need to do this-->
53-
<Import Project="..\..\src\Sentry\buildTransitive\Sentry.SourceGenerators.targets" />
5452
</Project>

samples/Sentry.Samples.MacCatalyst/Sentry.Samples.MacCatalyst.csproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,4 @@
4949
ReferenceOutputAssembly="false"/>
5050
</ItemGroup>
5151

52-
<!--In order to test our analyzers with this project, we manually reference our targets file. User do not need to do this-->
53-
<Import Project="..\..\src\Sentry\buildTransitive\Sentry.SourceGenerators.targets" />
5452
</Project>

samples/Sentry.Samples.Maui/Sentry.Samples.Maui.csproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,4 @@
115115
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
116116
</ItemGroup>
117117

118-
<!--In order to test our analyzers with this project, we manually reference our targets file. User do not need to do this-->
119-
<Import Project="..\..\src\Sentry\buildTransitive\Sentry.SourceGenerators.targets" />
120118
</Project>

src/Sentry.SourceGenerators/BuildPropertySourceGenerator.cs

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44

55
namespace Sentry.SourceGenerators;
66

7-
87
/// <summary>
98
/// Generates the necessary msbuild variables
109
/// </summary>
1110
[Generator(LanguageNames.CSharp)]
12-
public class BuildPropertySourceGenerator : ISourceGenerator
11+
public sealed class BuildPropertySourceGenerator : ISourceGenerator
1312
{
1413
/// <summary>
1514
/// Initialize the source gen
@@ -23,6 +22,8 @@ public void Initialize(GeneratorInitializationContext context)
2322
/// </summary>
2423
public void Execute(GeneratorExecutionContext context)
2524
{
25+
const string tabString = " ";
26+
2627
var opts = context.AnalyzerConfigOptions.GlobalOptions;
2728
var properties = opts.Keys.Where(x => x.StartsWith("build_property.")).ToList();
2829
if (properties.Count == 0)
@@ -37,36 +38,34 @@ public void Execute(GeneratorExecutionContext context)
3738
}
3839

3940
// we only want to generate code where host setup takes place
40-
if (!opts.TryGetValue("build_property.outputtype", out var outputType))
41-
{
42-
return;
43-
}
44-
45-
if (!outputType.Equals("exe", StringComparison.InvariantCultureIgnoreCase))
41+
if (!context.Compilation.Options.OutputKind.IsExe())
4642
{
4743
return;
4844
}
4945

5046
var sb = new StringBuilder();
5147
sb
5248
.Append(
53-
"""
49+
$$"""
5450
// <auto-generated>
55-
// Code generated by Sentry Source Generators
56-
// Changes may cause incorrect behavior and will be lost if the code is
57-
// regenerated.
51+
// This code was generated by Sentry.SourceGenerators.
52+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
5853
// </auto-generated>
5954
60-
#if NET8_0_OR_GREATER
61-
namespace Sentry;
55+
#if NET5_0_OR_GREATER
56+
57+
#nullable enable
6258
63-
[global::System.Runtime.CompilerServices.CompilerGenerated]
64-
public static class BuildVariableInitializer
59+
namespace Sentry.Generated
6560
{
66-
[global::System.Runtime.CompilerServices.ModuleInitializer]
67-
public static void Initialize()
61+
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{GeneratedCodeText.Tool}}", "{{GeneratedCodeText.Version}}")]
62+
internal static class BuildPropertyInitializer
6863
{
69-
global::Sentry.CompilerServices.BuildProperties.Initialize(new global::System.Collections.Generic.Dictionary<string, string> {
64+
[global::System.Runtime.CompilerServices.ModuleInitializerAttribute]
65+
internal static void Initialize()
66+
{
67+
global::Sentry.CompilerServices.BuildProperties.Initialize(new global::System.Collections.Generic.Dictionary<string, string>(global::System.StringComparer.OrdinalIgnoreCase)
68+
{
7069
7170
"""
7271
);
@@ -78,21 +77,21 @@ public static void Initialize()
7877
var pn = EscapeString(property.Replace("build_property.", ""));
7978
var ev = EscapeString(value);
8079
sb
81-
.Append("\t\t\t{")
80+
.Append($"{tabString}{tabString}{tabString}{tabString}{{")
8281
.Append($"\"{pn}\", \"{ev}\"")
8382
.AppendLine("},");
8483
}
8584
}
8685

8786
sb
88-
.AppendLine("\t\t});") // close dictionary
89-
.AppendLine("\t}")
87+
.AppendLine($"{tabString}{tabString}{tabString}}});") // close dictionary
88+
.AppendLine($"{tabString}{tabString}}}")
89+
.AppendLine($"{tabString}}}")
9090
.AppendLine("}")
9191
.AppendLine("#endif");
9292

93-
context.AddSource("__BuildProperties.g.cs", sb.ToString());
93+
context.AddSource("Sentry.Generated.BuildPropertyInitializer.g.cs", sb.ToString());
9494
}
9595

96-
9796
private static string EscapeString(string value) => value.Replace("\\", "\\\\");
9897
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Sentry.SourceGenerators;
2+
3+
internal static class GeneratedCodeText
4+
{
5+
public static string? Tool { get; } = typeof(BuildPropertySourceGenerator).Assembly.GetName().Name;
6+
public static string? Version { get; } = typeof(BuildPropertySourceGenerator).Assembly.GetName().Version?.ToString();
7+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Microsoft.CodeAnalysis;
2+
3+
namespace Sentry.SourceGenerators;
4+
5+
internal static class OutputKindExtensions
6+
{
7+
internal static bool IsExe(this OutputKind outputKind)
8+
{
9+
return outputKind switch
10+
{
11+
OutputKind.ConsoleApplication => true,
12+
OutputKind.WindowsApplication => true,
13+
OutputKind.DynamicallyLinkedLibrary => false,
14+
OutputKind.NetModule => false,
15+
OutputKind.WindowsRuntimeMetadata => false,
16+
OutputKind.WindowsRuntimeApplication => true,
17+
_ => false,
18+
};
19+
}
20+
}

src/Sentry/Internal/AotHelper.cs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
using System;
12
using Sentry.CompilerServices;
3+
using Sentry.Extensibility;
24

35
namespace Sentry.Internal;
46

@@ -13,31 +15,41 @@ static AotHelper()
1315
IsTrimmed = CheckIsTrimmed();
1416
}
1517

16-
1718
[UnconditionalSuppressMessage("Trimming", "IL2026: RequiresUnreferencedCode", Justification = AvoidAtRuntime)]
18-
private static bool CheckIsTrimmed()
19+
internal static bool CheckIsTrimmed(IDiagnosticLogger? logger = null)
1920
{
20-
if (TryGetBoolean("publishtrimmed", out var trimmed))
21+
if (TryGetBoolean("_IsPublishing", out var isPublishing) && isPublishing)
2122
{
22-
return trimmed;
23-
}
23+
logger?.LogDebug("Detected _IsPublishing");
24+
if (TryGetBoolean("PublishSelfContained", out var selfContained) && selfContained)
25+
{
26+
logger?.LogDebug("Detected PublishSelfContained");
27+
if (TryGetBoolean("PublishTrimmed", out var trimmed))
28+
{
29+
logger?.LogDebug("Detected PublishTrimmed");
30+
return trimmed;
31+
}
32+
}
2433

25-
if (TryGetBoolean("publishaot", out var aot))
26-
{
27-
return aot;
34+
if (TryGetBoolean("PublishAot", out var aot))
35+
{
36+
logger?.LogDebug($"Detected PublishAot: {aot}");
37+
return aot;
38+
}
2839
}
2940

3041
// fallback check
42+
logger?.LogDebug("Stacktrace fallback");
3143
var stackTrace = new StackTrace(false);
3244
return stackTrace.GetFrame(0)?.GetMethod() is null;
3345
}
3446

3547
private static bool TryGetBoolean(string key, out bool value)
3648
{
3749
value = false;
38-
if (BuildProperties.Values?.TryGetValue(key, out var aotValue) ?? false)
50+
if (BuildProperties.Values?.TryGetValue(key, out string? stringValue) ?? false)
3951
{
40-
if (bool.TryParse(aotValue, out var result))
52+
if (bool.TryParse(stringValue, out var result))
4153
{
4254
value = result;
4355
return true;

src/Sentry/Sentry.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,6 @@
188188
<None Include="buildTransitive\Sentry.props" Pack="true" PackagePath="build\Sentry.props" />
189189
<None Include="buildTransitive\Sentry.targets" Pack="true" PackagePath="buildTransitive\Sentry.targets" />
190190
<None Include="buildTransitive\Sentry.targets" Pack="true" PackagePath="build\Sentry.targets" />
191-
<None Include="buildTransitive\Sentry.SourceGenerators.targets" Pack="true" PackagePath="buildTransitive\Sentry.SourceGenerators.targets" />
192-
<None Include="buildTransitive\Sentry.SourceGenerators.targets" Pack="true" PackagePath="build\Sentry.SourceGenerators.targets" />
193191
</ItemGroup>
194192

195193
<ItemGroup>
@@ -198,4 +196,5 @@
198196
PackagePath="analyzers/dotnet/cs"
199197
Visible="false" />
200198
</ItemGroup>
199+
201200
</Project>

0 commit comments

Comments
 (0)