Argu 不支持 AOT,不过用 F# 的话可以看整个 .NET 的生态,我看了一下 C# 的 CommandLineParser:
https://github.com/commandlineparser

在这个 PR 中支持了 Native AOT
https://github.com/commandlineparser/commandline/pull/913

除此之外,还有一个更加精巧的 F# 库可以用,只有两百多行:
https://github.com/B2R2-org/FsOptParse/

AOT 后的大小很可观,并且支持 full trim.

用例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
(** defines a state to pass to the option parser *)
type opts =
{
optX : int;
optY : bool;
optZ : string;
}

(** default option state *)
let defaultOpts =
{
optX = 0;
optY = false;
optZ = "";
}

(*
An example command line specification, which is a list of Options.
Each Option describes a command line option (switch) that is specified with
either a short (a single-dash option) or long option (a double-dash option).
*)
let spec =
[
(* This option can be specified with -x <NUM>. There is an extra argument to
specify a value in integer. *)
Option ((* description of the option *)
descr="this is a testing param X",
(* how many extra argument must be provided by a user? *)
extra=1,
(* callback sets up the option and returns it *)
callback=(fun opts arg -> {opts with optX=(int) arg.[0]}),
(* use a short option style -x *)
short="-x"
);

(* This option can be specified with -y. There is no extra argument. This
option just sets a flag, optY. *)
Option ((* description of the option *)
descr="this is a testing param Y",
(* set the option to be true *)
callback=(fun opts _ -> {opts with optY=true}),
(* use a short option style (-y) *)
short="-y",
(* also use a long option style (--yoohoo) *)
long="--yoohoo"
);

(* A dummy option to pretty-print the usage *)
Option ((* description of the option *)
descr="",
dummy=true
);
Option ((* description of the option *)
descr="[Required Options]",
descrColor=System.ConsoleColor.DarkCyan,
dummy=true
);

(* The third option is a required option. In other words, option parsing
will raise an exception if this option is not given by a user. This
option takes in an additional integer argument, and set it to the global
variable z. *)
Option ((* description of the option *)
descr="required parameter <STRING> with an integer option",
(* callback to set the optZ value *)
callback=(fun opts arg -> {opts with optZ=arg.[0]}),
(* specifying this is a required option *)
required=true,
(* one additional argument to specify an integer value *)
extra=1,
(* use only a long option style *)
long="--req"
);
]

let _ =
let prog = "opttest.fsx"
let args = System.Environment.GetCommandLineArgs ()
let usageGetter () = "[Usage]\n %p %o"
try
let left, opts = optParse spec usageGetter prog args defaultOpts
printfn "Rest args: %A, x: %d, y: %b, z: %s"
left opts.optX opts.optY opts.optZ
0
with
| SpecErr msg ->
eprintfn "Invalid spec: %s" msg
exit 1
| RuntimeErr msg ->
eprintfn "Invalid args given by user: %s" msg
usagePrint spec prog usageGetter (fun () -> exit 1)