diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 8047c4f..d90b7c8 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -8,6 +8,7 @@
* Add `Argu.Samples.Introspect` sample [#298](https://github.com/fsprojects/Argu/pull/298) [@dimension-zero](https://github.com/dimension-zero)
* Add `ArgumentParser.Parse(ParseConfig)` [#307](https://github.com/fsprojects/Argu/pull/307) [@dimension-zero](https://github.com/dimension-zero)
* Add `ArgumentParser.PrintUsage(..., ?UsageStrings)` for localization support [#303](https://github.com/fsprojects/Argu/pull/303) [@dimension-zero](https://github.com/dimension-zero)
+* Add AOT annotations on [#314](https://github.com/fsprojects/Argu/pull/314) [@dimension-zero](https://github.com/dimension-zero)
* Obsolete `EqualsAssignmentAttribute`, `ColonAssignmentAttribute`, `CustomAssignmentAttribute`, `EqualsAssignmentOrSpacedAttribute`, `ColonAssignmentOrSpacedAttribute` and `CustomAssignmentOrSpacedAttribute` [#315](https://github.com/fsprojects/Argu/pull/315) [@dimension-zero](https://github.com/dimension-zero)
* Obsolete `PostProcessResult`, `PostProcessResults`, `TryPostProcessResult` [#296](https://github.com/fsprojects/Argu/pull/296) [@dimension-zero](https://github.com/dimension-zero)
diff --git a/src/Argu/Argu.fsproj b/src/Argu/Argu.fsproj
index 45d8999..2e93b9d 100644
--- a/src/Argu/Argu.fsproj
+++ b/src/Argu/Argu.fsproj
@@ -5,8 +5,15 @@
true
logo.png
enable
+
+ true
+ false
+
diff --git a/src/Argu/ArgumentParser.fs b/src/Argu/ArgumentParser.fs
index ff2b194..9da0f5e 100644
--- a/src/Argu/ArgumentParser.fs
+++ b/src/Argu/ArgumentParser.fs
@@ -1,6 +1,8 @@
namespace Argu
open FSharp.Quotations
+open System.Diagnostics.CodeAnalysis
+
open Argu.UnionArgInfo
/// Configuration record for .
@@ -32,6 +34,14 @@ type ParseConfig =
IgnoreUnrecognized = false
RaiseOnUsage = true }
+module internal TrimMessages =
+ []
+ let aot =
+ "Argu reflects over the supplied F# discriminated union via MakeGenericType / Activator.CreateInstance to build its schema. This is not safe under publish-AOT; consider a hand-written parser for AOT scenarios."
+ []
+ let trim =
+ "Argu walks the union schema via System.Reflection (FSharpType.GetUnionCases and friends). The trimmer cannot keep referenced union cases unless the consumer's root sees them; pin the template type with DynamicDependency or DynamicallyAccessedMembers attributes when trimming."
+
/// The Argu type generates an argument parser given a type argument
/// that is an F# discriminated union. It can then be used to parse command line arguments
/// or XML configuration.
@@ -135,6 +145,8 @@ and []
/// Text width used when formatting the usage string. Defaults to 80 chars.
/// The implementation of IExiter used for error handling. Exception is default.
/// Indicate if the structure of the arguments discriminated union should be checked for errors.
+ []
+ []
new (?programName : string, ?helpTextMessage : string, ?usageStringCharacterWidth : int, ?errorHandler : IExiter, ?checkStructure: bool) =
let usageStringCharacterWidth = usageStringCharacterWidth |> Option.defaultWith getDefaultCharacterWidthSafeMin80
let programName = programName |> Option.defaultWith currentProgramName
@@ -150,6 +162,8 @@ and []
member val ProgramName = _programName
/// Force a check of the discriminated union structure.
+ []
+ []
static member CheckStructure() =
argInfoWithCheck.Value |> ignore
@@ -313,6 +327,8 @@ type ArgumentParser with
/// Text width used when formatting the usage string. Defaults to 80 chars.
/// The implementation of IExiter used for error handling. Exception is default.
/// Indicate if the structure of the arguments discriminated union should be checked for errors.
+ []
+ []
static member Create<'Template when 'Template :> IArgParserTemplate>(?programName : string, ?helpTextMessage : string, ?usageStringCharacterWidth : int, ?errorHandler : IExiter, ?checkStructure: bool) =
new ArgumentParser<'Template>(?programName = programName, ?helpTextMessage = helpTextMessage, ?errorHandler = errorHandler, ?usageStringCharacterWidth = usageStringCharacterWidth, ?checkStructure = checkStructure)
@@ -327,9 +343,13 @@ module ArgumentParserUtils =
r.CharacterWidth, r.ErrorHandler)
/// converts a sequence of inputs to a ParseResults instance
+ []
+ []
let toParseResults (inputs : seq<'Template>) : ParseResults<'Template> =
ArgumentParser.Create<'Template>().ToParseResults(inputs)
/// gets the F# union tag representation of given argument instance
+ []
+ []
let tagOf (input : 'Template) : int =
ArgumentParser.Create<'Template>().GetTag input
diff --git a/src/Argu/TrimAnnotations.fs b/src/Argu/TrimAnnotations.fs
new file mode 100644
index 0000000..a78464c
--- /dev/null
+++ b/src/Argu/TrimAnnotations.fs
@@ -0,0 +1,40 @@
+// Polyfills for AOT/trim diagnostic attributes so that
+// netstandard2.0 builds can carry the same metadata as .NET 7+ targets.
+// The .NET trimmer / publish-AOT pipeline matches by full type name,
+// not by assembly, so internal copies are picked up.
+namespace System.Diagnostics.CodeAnalysis
+
+open System
+
+#if !NET7_0_OR_GREATER
+
+///
+/// Marker indicating that the annotated method requires dynamic-code
+/// generation at runtime (e.g. MakeGenericType +
+/// Activator.CreateInstance) and is therefore not safe under
+/// publish-AOT. Callers that opt into AOT will see an IL3050
+/// warning when invoking the annotated member.
+///
+[]
+type internal RequiresDynamicCodeAttribute(message : string) =
+ inherit Attribute()
+ /// Reason the method requires dynamic code.
+ member _.Message = message
+ /// Optional URL pointing at extended documentation.
+ member val Url : string = null with get, set
+
+///
+/// Marker indicating that the annotated method uses reflection in a
+/// way the trimmer cannot statically analyse (e.g. arbitrary type
+/// reads via FSharpType.GetUnionCases). Callers that enable
+/// trimming will see an IL2026 warning.
+///
+[]
+type internal RequiresUnreferencedCodeAttribute(message : string) =
+ inherit Attribute()
+ /// Reason the method holds unreferenced-code requirements.
+ member _.Message = message
+ /// Optional URL pointing at extended documentation.
+ member val Url : string = null with get, set
+
+#endif