Skip to content

Commit 4a25401

Browse files
authored
fix: Native AOT for linux-musl-arm64 (#4365)
1 parent 3119a4b commit 4a25401

File tree

8 files changed

+113
-23
lines changed

8 files changed

+113
-23
lines changed

.github/alpine/setup-node.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/sh
2+
3+
[ -n "$1" ] || { echo "Usage: $0 <path>"; exit 1; }
4+
5+
# A workaround for "JavaScript Actions in Alpine containers are only supported on x64 Linux runners."
6+
# https://github.com/actions/runner/blob/8a9b96806d12343f7d123c669e29c629138023dd/src/Runner.Worker/Handlers/StepHost.cs#L283-L290
7+
if [ "$(uname -m)" != "x86_64" ]; then
8+
mkdir -p $1
9+
ln -s /usr/bin/node $1
10+
ln -s /usr/bin/npm $1
11+
sed -i 's/ID=alpine/ID=unknown/' /usr/lib/os-release
12+
fi

.github/workflows/build.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ jobs:
2727
rid: linux-musl-x64
2828
container:
2929
image: ghcr.io/getsentry/sentry-dotnet-alpine:3.21
30+
- os: ubuntu-24.04-arm
31+
rid: linux-musl-arm64
32+
container:
33+
image: ghcr.io/getsentry/sentry-dotnet-alpine:3.21
34+
volumes:
35+
- /tmp/node20:/__e/node20
3036
- os: macos-15 # Pin macos to get the version of Xcode that we need: https://github.com/actions/runner-images/issues/10703
3137
rid: macos # universal (osx-arm64 + osx-x64)
3238
- os: windows-latest
@@ -35,6 +41,11 @@ jobs:
3541
rid: win-arm64
3642

3743
steps:
44+
- name: Initialize Alpine Linux
45+
if: ${{ contains(matrix.container.image, 'alpine') }}
46+
run: |
47+
curl -sSL https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/.github/alpine/setup-node.sh | sudo bash /dev/stdin /__e/node20/bin/
48+
3849
- name: Checkout
3950
uses: actions/checkout@v4
4051

@@ -83,6 +94,14 @@ jobs:
8394
image: ghcr.io/getsentry/sentry-dotnet-alpine:3.21
8495
volumes:
8596
- /var/run/docker.sock:/var/run/docker.sock
97+
- os: ubuntu-24.04-arm
98+
rid: linux-musl-arm64
99+
slnf: Sentry-CI-Build-Linux-musl.slnf
100+
container:
101+
image: ghcr.io/getsentry/sentry-dotnet-alpine:3.21
102+
volumes:
103+
- /tmp/node20:/__e/node20
104+
- /var/run/docker.sock:/var/run/docker.sock
86105
- os: macos-15 # Pin macos to get the version of Xcode that we need: https://github.com/actions/runner-images/issues/10703
87106
rid: macos # universal (osx-arm64 + osx-x64)
88107
slnf: Sentry-CI-Build-macOS.slnf
@@ -94,6 +113,11 @@ jobs:
94113
slnf: Sentry-CI-Build-Windows-arm64.slnf
95114

96115
steps:
116+
- name: Initialize Alpine Linux
117+
if: ${{ contains(matrix.container.image, 'alpine') }}
118+
run: |
119+
curl -sSL https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/.github/alpine/setup-node.sh | sudo bash /dev/stdin /__e/node20/bin/
120+
97121
- name: Cancel Previous Runs
98122
if: github.ref_name != 'main' && !startsWith(github.ref_name, 'release/')
99123
uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # Tag: 0.12.1
@@ -140,6 +164,14 @@ jobs:
140164
key: sentry-native-linux-musl-x64-${{ hashFiles('scripts/build-sentry-native.ps1') }}-${{ hashFiles('.git/modules/modules/sentry-native/HEAD') }}
141165
fail-on-cache-miss: true
142166

167+
- name: Download sentry-native (linux-musl-arm64)
168+
if: ${{ (env.CI_PUBLISHING_BUILD == 'true') || (matrix.rid == 'linux-musl-arm64') }}
169+
uses: actions/cache/restore@v4
170+
with:
171+
path: src/Sentry/Platforms/Native/sentry-native
172+
key: sentry-native-linux-musl-arm64-${{ hashFiles('scripts/build-sentry-native.ps1') }}-${{ hashFiles('.git/modules/modules/sentry-native/HEAD') }}
173+
fail-on-cache-miss: true
174+
143175
- name: Download sentry-native (macos)
144176
if: ${{ (env.CI_PUBLISHING_BUILD == 'true') || (matrix.rid == 'macos') }}
145177
uses: actions/cache/restore@v4

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- Native AOT: don't load SentryNative on unsupported platforms ([#4347](https://github.com/getsentry/sentry-dotnet/pull/4347))
1313
- Fixed issue introduced in release 5.12.0 that might prevent other middleware or user code from reading request bodies ([#4373](https://github.com/getsentry/sentry-dotnet/pull/4373))
1414
- SentryTunnelMiddleware overwrites the X-Forwarded-For header ([#4375](https://github.com/getsentry/sentry-dotnet/pull/4375))
15+
- Native AOT support for `linux-musl-arm64` ([#4365](https://github.com/getsentry/sentry-dotnet/pull/4365))
1516

1617
### Dependencies
1718

integration-test/runtime.Tests.ps1

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,17 @@ internal class FakeTransport : ITransport
6060
}
6161
else
6262
{
63-
if ("Arm64".Equals([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString()))
63+
$musl = (ldd --version 2>&1) -match 'musl'
64+
$arm64 = "Arm64".Equals([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString())
65+
if ($musl -and $arm64)
66+
{
67+
return "./console-app/bin/Release/$framework/linux-musl-arm64/publish/console-app"
68+
}
69+
elseif ($arm64)
6470
{
6571
return "./console-app/bin/Release/$framework/linux-arm64/publish/console-app"
6672
}
67-
elseif ((ldd --version 2>&1) -match 'musl')
73+
elseif ($musl)
6874
{
6975
return "./console-app/bin/Release/$framework/linux-musl-x64/publish/console-app"
7076
}

scripts/build-sentry-native.ps1

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,17 @@ try
3737
}
3838
elseif ($IsLinux)
3939
{
40-
if ("Arm64".Equals([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString()))
40+
$musl = (ldd --version 2>&1) -match 'musl'
41+
$arm64 = "Arm64".Equals([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString())
42+
if ($musl -and $arm64)
43+
{
44+
$outDir += '/linux-musl-arm64'
45+
}
46+
elseif ($arm64)
4147
{
4248
$outDir += '/linux-arm64'
4349
}
44-
elseif ((ldd --version 2>&1) -match 'musl')
50+
elseif ($musl)
4551
{
4652
$outDir += '/linux-musl-x64'
4753
}

src/Sentry/Platforms/Native/CFunctions.cs

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ internal static void SetValueIfNotNull(sentry_value_t obj, string key, double? v
8181

8282
public static bool Init(SentryOptions options)
8383
{
84-
_isWindows = System.OperatingSystem.IsWindows();
8584
var cOptions = sentry_options_new();
8685

8786
// Note: DSN is not null because options.IsValid() must have returned true for this to be called.
@@ -441,7 +440,8 @@ private static void nativeTransportFree(IntPtr state)
441440

442441
// The logger we should forward native messages to. This is referenced by nativeLog() which in turn for.
443442
private static IDiagnosticLogger? _logger;
444-
private static bool _isWindows = false;
443+
private static bool _isWindows = System.OperatingSystem.IsWindows();
444+
private static bool _isArm64 = RuntimeInformation.OSArchitecture == Architecture.Arm64;
445445

446446
// This method is called from the C library and forwards incoming messages to the currently set _logger.
447447
// [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] // error CS3016: Arrays as attribute arguments is not CLS-complian
@@ -495,21 +495,14 @@ private static void nativeLogImpl(int cLevel, IntPtr format, IntPtr args, IntPtr
495495
message = Marshal.PtrToStringAnsi(buffer);
496496
});
497497
}
498+
// For Linux/macOS, we must make a copy of the VaList to be able to pass it back...
499+
else if (_isArm64)
500+
{
501+
message = FormatWithVaList<VaListArm64>(format, args);
502+
}
498503
else
499504
{
500-
// For Linux/macOS, we must make a copy of the VaList to be able to pass it back...
501-
var argsStruct = Marshal.PtrToStructure<VaListLinux64>(args);
502-
var formattedLength = 0;
503-
WithMarshalledStruct(argsStruct, argsPtr =>
504-
formattedLength = 1 + vsnprintf_linux(IntPtr.Zero, UIntPtr.Zero, format, argsPtr)
505-
);
506-
507-
WithAllocatedPtr(formattedLength, buffer =>
508-
WithMarshalledStruct(argsStruct, argsPtr =>
509-
{
510-
vsnprintf_linux(buffer, (UIntPtr)formattedLength, format, argsPtr);
511-
message = Marshal.PtrToStringAnsi(buffer);
512-
}));
505+
message = FormatWithVaList<VaListX64>(format, args);
513506
}
514507
}
515508
catch (Exception err)
@@ -534,14 +527,25 @@ private static void nativeLogImpl(int cLevel, IntPtr format, IntPtr args, IntPtr
534527

535528
// https://stackoverflow.com/a/4958507/2386130
536529
[StructLayout(LayoutKind.Sequential, Pack = 4)]
537-
private struct VaListLinux64
530+
private struct VaListX64
538531
{
539532
private uint _gp_offset;
540533
private uint _fp_offset;
541534
private IntPtr _overflow_arg_area;
542535
private IntPtr _reg_save_area;
543536
}
544537

538+
// https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#definition-of-va-list
539+
[StructLayout(LayoutKind.Sequential)]
540+
private struct VaListArm64
541+
{
542+
private IntPtr __stack;
543+
private IntPtr __gr_top;
544+
private IntPtr __vr_top;
545+
private int __gr_offs;
546+
private int __vr_offs;
547+
}
548+
545549
private static void WithAllocatedPtr(int size, Action<IntPtr> action)
546550
{
547551
var ptr = IntPtr.Zero;
@@ -562,4 +566,23 @@ private static void WithMarshalledStruct<T>(T structure, Action<IntPtr> action)
562566
Marshal.StructureToPtr(structure, ptr, false);
563567
action(ptr);
564568
});
569+
570+
private static string? FormatWithVaList<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>(IntPtr format, IntPtr args) where T : struct
571+
{
572+
string? message = null;
573+
var argsStruct = Marshal.PtrToStructure<T>(args);
574+
var formattedLength = 0;
575+
WithMarshalledStruct(argsStruct, argsPtr =>
576+
formattedLength = 1 + vsnprintf_linux(IntPtr.Zero, UIntPtr.Zero, format, argsPtr)
577+
);
578+
579+
WithAllocatedPtr(formattedLength, buffer =>
580+
WithMarshalledStruct(argsStruct, argsPtr =>
581+
{
582+
vsnprintf_linux(buffer, (UIntPtr)formattedLength, format, argsPtr);
583+
message = Marshal.PtrToStringAnsi(buffer);
584+
}));
585+
586+
return message;
587+
}
565588
}

src/Sentry/Platforms/Native/Sentry.Native.targets

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717
<SentryNativeOutputDirectory-linux-musl-x64>$(SentryNativeOutputDirectory)$(NativeLibRelativePath-linux-musl-x64)\</SentryNativeOutputDirectory-linux-musl-x64>
1818
<NativeLibRelativePath-linux-arm64>linux-arm64</NativeLibRelativePath-linux-arm64>
1919
<SentryNativeOutputDirectory-linux-arm64>$(SentryNativeOutputDirectory)$(NativeLibRelativePath-linux-arm64)\</SentryNativeOutputDirectory-linux-arm64>
20+
<NativeLibRelativePath-linux-musl-arm64>linux-musl-arm64</NativeLibRelativePath-linux-musl-arm64>
21+
<SentryNativeOutputDirectory-linux-musl-arm64>$(SentryNativeOutputDirectory)$(NativeLibRelativePath-linux-musl-arm64)\</SentryNativeOutputDirectory-linux-musl-arm64>
2022
<NativeLibRelativePath-osx>osx</NativeLibRelativePath-osx>
2123
<SentryNativeOutputDirectory-osx>$(SentryNativeOutputDirectory)$(NativeLibRelativePath-osx)\</SentryNativeOutputDirectory-osx>
2224
<SentryNativeBuildOutputs Condition="'$(RuntimeIdentifier)' == 'win-x64'">$(SentryNativeOutputDirectory-win-x64)lib$(SentryNativeLibraryName).lib</SentryNativeBuildOutputs>
2325
<SentryNativeBuildOutputs Condition="'$(RuntimeIdentifier)' == 'win-arm64'">$(SentryNativeOutputDirectory-win-arm64)lib$(SentryNativeLibraryName).lib</SentryNativeBuildOutputs>
2426
<SentryNativeBuildOutputs Condition="'$(RuntimeIdentifier)' == 'linux-x64'">$(SentryNativeOutputDirectory-linux-x64)lib$(SentryNativeLibraryName).a</SentryNativeBuildOutputs>
2527
<SentryNativeBuildOutputs Condition="'$(RuntimeIdentifier)' == 'linux-musl-x64'">$(SentryNativeOutputDirectory-linux-musl-x64)lib$(SentryNativeLibraryName).a</SentryNativeBuildOutputs>
2628
<SentryNativeBuildOutputs Condition="'$(RuntimeIdentifier)' == 'linux-arm64'">$(SentryNativeOutputDirectory-linux-arm64)lib$(SentryNativeLibraryName).a</SentryNativeBuildOutputs>
29+
<SentryNativeBuildOutputs Condition="'$(RuntimeIdentifier)' == 'linux-musl-arm64'">$(SentryNativeOutputDirectory-linux-musl-arm64)lib$(SentryNativeLibraryName).a</SentryNativeBuildOutputs>
2730
<SentryNativeBuildOutputs Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(SentryNativeOutputDirectory-osx)lib$(SentryNativeLibraryName).a</SentryNativeBuildOutputs>
2831
</PropertyGroup>
2932

@@ -69,6 +72,13 @@
6972
</None>
7073
</ItemGroup>
7174

75+
<ItemGroup Condition="'$(CI_PUBLISHING_BUILD)' == 'true' or '$(NETCoreSdkRuntimeIdentifier)' == 'linux-musl-arm64'">
76+
<None Include="$(SentryNativeOutputDirectory-linux-musl-arm64)lib$(SentryNativeLibraryName).a">
77+
<Pack>true</Pack>
78+
<PackagePath>\sentry-native\$(NativeLibRelativePath-linux-musl-arm64)</PackagePath>
79+
</None>
80+
</ItemGroup>
81+
7282
<ItemGroup Condition="'$(CI_PUBLISHING_BUILD)' == 'true' or $([MSBuild]::IsOsPlatform('OSX'))">
7383
<None Include="$(SentryNativeOutputDirectory-osx)lib$(SentryNativeLibraryName).a">
7484
<Pack>true</Pack>

src/Sentry/Platforms/Native/buildTransitive/Sentry.Native.targets

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<!-- Windows -->
2020
<FrameworkSupportsNative Condition="'$(RuntimeIdentifier)' == 'win-x64' or '$(RuntimeIdentifier)' == 'win-arm64'">true</FrameworkSupportsNative>
2121
<!-- Linux -->
22-
<FrameworkSupportsNative Condition="'$(RuntimeIdentifier)' == 'linux-x64' or '$(RuntimeIdentifier)' == 'linux-arm64' or '$(RuntimeIdentifier)' == 'linux-musl-x64'">true</FrameworkSupportsNative>
22+
<FrameworkSupportsNative Condition="'$(RuntimeIdentifier)' == 'linux-x64' or '$(RuntimeIdentifier)' == 'linux-arm64' or '$(RuntimeIdentifier)' == 'linux-musl-x64' or '$(RuntimeIdentifier)' == 'linux-musl-arm64'">true</FrameworkSupportsNative>
2323
<!-- macOS -->
2424
<FrameworkSupportsNative Condition="'$(RuntimeIdentifier)' == 'osx-x64' or '$(RuntimeIdentifier)' == 'osx-arm64'">true</FrameworkSupportsNative>
2525
<!-- net8.0 or greater -->
@@ -52,11 +52,11 @@
5252
<NativeLibrary Include="$(MSBuildThisFileDirectory)..\sentry-native\$(RuntimeIdentifier)\libsentry-native.a" />
5353
</ItemGroup>
5454

55-
<ItemGroup Condition="'$(FrameworkSupportsNative)' == 'true' and '$(RuntimeIdentifier)' == 'linux-musl-x64'">
55+
<ItemGroup Condition="'$(FrameworkSupportsNative)' == 'true' and ('$(RuntimeIdentifier)' == 'linux-musl-x64' or '$(RuntimeIdentifier)' == 'linux-musl-arm64')">
5656
<DirectPInvoke Include="sentry-native" />
5757
<!-- When musl is detected, static sentry-native links to static libunwind, which depends on liblzma -->
5858
<LinkerArg Include="-Wl,-Bstatic -Wl,--whole-archive -lunwind -Wl,--no-whole-archive -llzma -Wl,-Bdynamic" />
59-
<NativeLibrary Include="$(MSBuildThisFileDirectory)..\sentry-native\linux-musl-x64\libsentry-native.a" />
59+
<NativeLibrary Include="$(MSBuildThisFileDirectory)..\sentry-native\$(RuntimeIdentifier)\libsentry-native.a" />
6060
</ItemGroup>
6161

6262
<ItemGroup Condition="'$(FrameworkSupportsNative)' == 'true' and ('$(RuntimeIdentifier)' == 'osx-x64' or '$(RuntimeIdentifier)' == 'osx-arm64')">

0 commit comments

Comments
 (0)