Skip to content

Commit 56e8ba7

Browse files
committed
Fix NativeAOT compatibility for assembly location and PtrToStructure
Use AppContext.BaseDirectory instead of Assembly.Location on NET6_0_OR_GREATER to avoid IL3000 in AOT/single-file deployments. Add DynamicallyAccessedMembers annotation to PtrToStructure<T> so the trimmer preserves struct constructors needed by Marshal. Add IsAotCompatible=true in Directory.Build.props for all net6.0+ TFMs so the Roslyn trim/AOT analyzer runs on every library project during dotnet build without needing a full AOT publish. Add an AOT compatibility test app with PublishAot=true that acts as a regression guard: building it will error with IL2091 if the DynamicallyAccessedMembers annotation is ever removed.
1 parent c38ccd6 commit 56e8ba7

7 files changed

Lines changed: 78 additions & 4 deletions

File tree

src/Directory.Build.props

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
<PropertyGroup Condition="'$(Configuration)' == 'Win32Release'">
4141
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
4242
</PropertyGroup>
43+
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0'))">
44+
<IsAotCompatible>true</IsAotCompatible>
45+
</PropertyGroup>
46+
4347
<PropertyGroup>
4448
<NeutralLanguage>en</NeutralLanguage>
4549
<LangVersion>9.0</LangVersion>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<!-- PublishAot enables NativeAOT compilation on publish AND activates the
7+
Roslyn trim/AOT analyzer during dotnet build, so issues are caught early
8+
without needing a native toolchain. -->
9+
<PublishAot>true</PublishAot>
10+
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
11+
<GenerateDocumentationFile>false</GenerateDocumentationFile>
12+
</PropertyGroup>
13+
<ItemGroup>
14+
<ProjectReference Include="..\LibVLCSharp\LibVLCSharp.csproj" />
15+
</ItemGroup>
16+
</Project>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using LibVLCSharp.Shared;
3+
4+
// AOT Compatibility test for LibVLCSharp core.
5+
//
6+
// Build-time trim analysis (no native toolchain needed):
7+
// dotnet build
8+
//
9+
// Full NativeAOT publish (requires MSVC on Windows, clang on Linux/macOS):
10+
// dotnet publish -r win-x64 -c Release
11+
// dotnet publish -r linux-x64 -c Release
12+
13+
// Reference all public types so the linker includes them in analysis.
14+
_ = typeof(LibVLC);
15+
_ = typeof(MediaPlayer);
16+
_ = typeof(Media);
17+
_ = typeof(MediaList);
18+
_ = typeof(MediaDiscoverer);
19+
_ = typeof(RendererDiscoverer);
20+
_ = typeof(Equalizer);
21+
_ = typeof(MediaInput);
22+
_ = typeof(StreamMediaInput);
23+
24+
Console.WriteLine("LibVLCSharp AOT compatibility OK");

src/LibVLCSharp.Uno/PlaybackControlsBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ private void AddAspectRatioMenu(Button? zoomButton)
680680
var menuItems = menuFlyout.Items;
681681
var mediaPlayer = MediaPlayer;
682682
var currentAspectRatio = Manager.Get<AspectRatioManager>().AspectRatio;
683-
foreach (AspectRatio aspectRatio in Enum.GetValues(typeof(AspectRatio)))
683+
foreach (AspectRatio aspectRatio in Enum.GetValues<AspectRatio>())
684684
{
685685
var menuItem = new ToggleMenuFlyoutItem
686686
{

src/LibVLCSharp.slnx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,22 @@
446446
<BuildType Solution="Ad-Hoc|*" Project="Debug" />
447447
<BuildType Solution="AppStore|*" Project="Debug" />
448448
</Project>
449+
<Project Path="LibVLCSharp.AOTCompatibility.TestApp/LibVLCSharp.AOTCompatibility.TestApp.csproj">
450+
<BuildType Solution="Ad-Hoc|Any CPU" Project="Release" />
451+
<BuildType Solution="Ad-Hoc|ARM" Project="Debug" />
452+
<BuildType Solution="Ad-Hoc|ARM64" Project="Debug" />
453+
<BuildType Solution="Ad-Hoc|iPhone" Project="Release" />
454+
<BuildType Solution="Ad-Hoc|iPhoneSimulator" Project="Release" />
455+
<BuildType Solution="Ad-Hoc|x64" Project="Release" />
456+
<BuildType Solution="Ad-Hoc|x86" Project="Release" />
457+
<BuildType Solution="AppStore|Any CPU" Project="Release" />
458+
<BuildType Solution="AppStore|ARM" Project="Debug" />
459+
<BuildType Solution="AppStore|ARM64" Project="Debug" />
460+
<BuildType Solution="AppStore|iPhone" Project="Release" />
461+
<BuildType Solution="AppStore|iPhoneSimulator" Project="Release" />
462+
<BuildType Solution="AppStore|x64" Project="Release" />
463+
<BuildType Solution="AppStore|x86" Project="Release" />
464+
</Project>
449465
<Project Path="LibVLCSharp.Tests/LibVLCSharp.Tests.csproj">
450466
<BuildType Solution="Ad-Hoc|Any CPU" Project="Release" />
451467
<BuildType Solution="Ad-Hoc|ARM" Project="Debug" />

src/LibVLCSharp/Shared/Core/Core.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,16 @@ static internal bool LibVLCLoaded
8282
arch = PlatformHelper.IsX64BitProcess ? ArchitectureNames.Win64 : ArchitectureNames.Win86;
8383
}
8484

85+
#if NET6_0_OR_GREATER
86+
var libvlcAssemblyLocation = AppContext.BaseDirectory;
87+
#else
8588
var libvlcAssemblyLocation = typeof(LibVLC).Assembly.Location;
86-
8789
#if !NET40
88-
if (string.IsNullOrEmpty(libvlcAssemblyLocation)) /* .NET 5 (single file / self contained) and later */
90+
if (string.IsNullOrEmpty(libvlcAssemblyLocation))
8991
{
9092
libvlcAssemblyLocation = AppContext.BaseDirectory;
9193
}
94+
#endif
9295
#endif
9396
var libvlcDirPath1 = Path.Combine(Path.GetDirectoryName(libvlcAssemblyLocation)!,
9497
Constants.LibrariesRepositoryFolderName, arch);
@@ -98,7 +101,11 @@ static internal bool LibVLCLoaded
98101
var libvlcPath1 = LibVLCPath(libvlcDirPath1);
99102
paths.Add((libvlccorePath1, libvlcPath1));
100103

104+
#if NET6_0_OR_GREATER
105+
var assemblyLocation = AppContext.BaseDirectory;
106+
#else
101107
var assemblyLocation = Assembly.GetEntryAssembly()?.Location ?? Assembly.GetExecutingAssembly()?.Location;
108+
#endif
102109
if(!string.IsNullOrEmpty(assemblyLocation))
103110
{
104111
var libvlcDirPath2 = Path.Combine(Path.GetDirectoryName(assemblyLocation)!,

src/LibVLCSharp/Shared/Helpers/MarshalUtils.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System;
22
using System.Collections.Generic;
3+
#if NET6_0_OR_GREATER
4+
using System.Diagnostics.CodeAnalysis;
5+
#endif
36
using System.Runtime.InteropServices;
47
using System.Text;
58

@@ -508,7 +511,11 @@ internal static IntPtr[] ToUtf8(this string[]? args)
508511
/// <typeparam name="T"></typeparam>
509512
/// <param name="ptr"></param>
510513
/// <returns></returns>
511-
internal static T PtrToStructure<T>(IntPtr ptr)
514+
internal static T PtrToStructure<
515+
#if NET6_0_OR_GREATER
516+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
517+
#endif
518+
T>(IntPtr ptr)
512519
{
513520
#if NETSTANDARD1_1 || NET40
514521
return (T)Marshal.PtrToStructure(ptr, typeof(T));

0 commit comments

Comments
 (0)