1 /**
2  * Defines the help texts for the CLI options offered by DMD.
3  *
4  * This file is not shared with other compilers which use the DMD front-end.
5  * However, this file will be used to generate the
6  * $(LINK2 https://dlang.org/dmd-linux.html, online documentation) and MAN pages.
7  *
8  * Copyright:   Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
9  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
10  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
11  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cli.d, _cli.d)
12  * Documentation:  https://dlang.org/phobos/dmd_cli.html
13  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/cli.d
14  */
15 module dmd.cli;
16 
17 /* The enum TargetOS is an exact copy of the one in dmd.globals.
18  * Duplicated here because this file is stand-alone.
19  */
20 
21 /// Bit decoding of the TargetOS
22 enum TargetOS : ubyte
23 {
24     /* These are mutually exclusive; one and only one is set.
25      * Match spelling and casing of corresponding version identifiers
26      */
27     linux        = 1,
28     Windows      = 2,
29     OSX          = 4,
30     OpenBSD      = 8,
31     FreeBSD      = 0x10,
32     Solaris      = 0x20,
33     DragonFlyBSD = 0x40,
34 
35     // Combination masks
36     all = linux | Windows | OSX | OpenBSD | FreeBSD | Solaris | DragonFlyBSD,
37     Posix = linux | OSX | OpenBSD | FreeBSD | Solaris | DragonFlyBSD,
38 }
39 
40 // Detect the current TargetOS
41 version (linux)
42 {
43     private enum targetOS = TargetOS.linux;
44 }
45 else version(Windows)
46 {
47     private enum targetOS = TargetOS.Windows;
48 }
49 else version(OSX)
50 {
51     private enum targetOS = TargetOS.OSX;
52 }
53 else version(OpenBSD)
54 {
55     private enum targetOS = TargetOS.OpenBSD;
56 }
57 else version(FreeBSD)
58 {
59     private enum targetOS = TargetOS.FreeBSD;
60 }
61 else version(DragonFlyBSD)
62 {
63     private enum targetOS = TargetOS.DragonFlyBSD;
64 }
65 else version(Solaris)
66 {
67     private enum targetOS = TargetOS.Solaris;
68 }
69 else
70 {
71     private enum targetOS = TargetOS.all;
72 }
73 
74 /**
75 Checks whether `os` is the current $(LREF TargetOS).
76 For `TargetOS.all` it will always return true.
77 
78 Params:
79     os = $(LREF TargetOS) to check
80 
81 Returns: true iff `os` contains the current targetOS.
82 */
83 bool isCurrentTargetOS(TargetOS os) @safe
84 {
85     return (os & targetOS) > 0;
86 }
87 
88 /**
89 Capitalize a the first character of a ASCII string.
90 Params:
91     w = ASCII i string to capitalize
92 Returns: capitalized string
93 */
94 static string capitalize(string w)
95 {
96     char[] result = cast(char[]) w;
97     char c1 = w.length ? w[0] : '\0';
98 
99     if (c1 >= 'a' && c1 <= 'z')
100     {
101         enum adjustment = 'A' - 'a';
102 
103         result = new char[] (w.length);
104         result[0] = cast(char) (c1 + adjustment);
105         result[1 .. $] = w[1 .. $];
106     }
107 
108     return cast(string) result;
109 }
110 
111 /**
112 Contains all available CLI $(LREF Usage.Option)s.
113 
114 See_Also: $(LREF Usage.Option)
115 */
116 struct Usage
117 {
118     /**
119     * Representation of a CLI `Option`
120     *
121     * The DDoc description `ddoxText` is only available when compiled with `-version=DdocOptions`.
122     */
123     struct Option
124     {
125         string flag; /// The CLI flag without leading `-`, e.g. `color`
126         string helpText; /// A detailed description of the flag
127         TargetOS os = TargetOS.all; /// For which `TargetOS` the flags are applicable
128         bool documented = true; // whether this option should be shown in the documentation
129 
130         // Needs to be version-ed to prevent the text ending up in the binary
131         // See also: https://issues.dlang.org/show_bug.cgi?id=18238
132         version(DdocOptions) string ddocText; /// Detailed description of the flag (in Ddoc)
133 
134         /**
135         * Params:
136         *  flag = CLI flag without leading `-`, e.g. `color`
137         *  helpText = detailed description of the flag
138         *  os = for which `TargetOS` the flags are applicable
139         *  ddocText = detailed description of the flag (in Ddoc)
140         *  documented = whether this option should be shown in the documentation
141         */
142         this(string flag, string helpText, TargetOS os = TargetOS.all, bool documented = true) @safe
143         {
144             this.flag = flag;
145             this.helpText = helpText;
146             version(DdocOptions) this.ddocText = helpText;
147             this.os = os;
148             this.documented = documented;
149         }
150 
151         /// ditto
152         this(string flag, string helpText, string ddocText, TargetOS os = TargetOS.all, bool documented = true) @safe
153         {
154             this.flag = flag;
155             this.helpText = helpText;
156             version(DdocOptions) this.ddocText = ddocText;
157             this.os = os;
158             this.documented = documented;
159         }
160     }
161 
162     /// Returns all available CLI options
163     static immutable options = [
164         Option("allinst",
165             "generate code for all template instantiations"
166         ),
167         Option("betterC",
168             "omit generating some runtime information and helper functions",
169             "Adjusts the compiler to implement D as a $(LINK2 $(ROOT_DIR)spec/betterc.html, better C):
170             $(UL
171                 $(LI Predefines `D_BetterC` $(LINK2 $(ROOT_DIR)spec/version.html#predefined-versions, version).)
172                 $(LI $(LINK2 $(ROOT_DIR)spec/expression.html#AssertExpression, Assert Expressions), when they fail,
173                 call the C runtime library assert failure function
174                 rather than a function in the D runtime.)
175                 $(LI $(LINK2 $(ROOT_DIR)spec/arrays.html#bounds, Array overflows)
176                 call the C runtime library assert failure function
177                 rather than a function in the D runtime.)
178                 $(LI $(LINK2 spec/statement.html#final-switch-statement/, Final switch errors)
179                 call the C runtime library assert failure function
180                 rather than a function in the D runtime.)
181                 $(LI Does not automatically link with phobos runtime library.)
182                 $(UNIX
183                 $(LI Does not generate Dwarf `eh_frame` with full unwinding information, i.e. exception tables
184                 are not inserted into `eh_frame`.)
185                 )
186                 $(LI Module constructors and destructors are not generated meaning that
187                 $(LINK2 $(ROOT_DIR)spec/class.html#StaticConstructor, static) and
188                 $(LINK2 $(ROOT_DIR)spec/class.html#SharedStaticConstructor, shared static constructors) and
189                 $(LINK2 $(ROOT_DIR)spec/class.html#StaticDestructor, destructors)
190                 will not get called.)
191                 $(LI `ModuleInfo` is not generated.)
192                 $(LI $(LINK2 $(ROOT_DIR)phobos/object.html#.TypeInfo, `TypeInfo`)
193                 instances will not be generated for structs.)
194             )",
195         ),
196         Option("boundscheck=[on|safeonly|off]",
197             "bounds checks on, in @safe only, or off",
198             `Controls if bounds checking is enabled.
199                 $(UL
200                     $(LI $(I on): Bounds checks are enabled for all code. This is the default.)
201                     $(LI $(I safeonly): Bounds checks are enabled only in $(D @safe) code.
202                                         This is the default for $(SWLINK -release) builds.)
203                     $(LI $(I off): Bounds checks are disabled completely (even in $(D @safe)
204                                    code). This option should be used with caution and as a
205                                    last resort to improve performance. Confirm turning off
206                                    $(D @safe) bounds checks is worthwhile by benchmarking.)
207                 )`
208         ),
209         Option("c",
210             "compile only, do not link"
211         ),
212         Option("check=[assert|bounds|in|invariant|out|switch][=[on|off]]",
213             "enable or disable specific checks",
214             `Overrides default, -boundscheck, -release and -unittest options to enable or disable specific checks.
215                 $(UL
216                     $(LI $(B assert): assertion checking)
217                     $(LI $(B bounds): array bounds)
218                     $(LI $(B in): in contracts)
219                     $(LI $(B invariant): class/struct invariants)
220                     $(LI $(B out): out contracts)
221                     $(LI $(B switch): $(D final switch) failure checking)
222                 )
223                 $(UL
224                     $(LI $(B on) or not specified: specified check is enabled.)
225                     $(LI $(B off): specified check is disabled.)
226                 )`
227         ),
228         Option("check=[h|help|?]",
229             "list information on all available checks"
230         ),
231         Option("checkaction=[D|C|halt|context]",
232             "behavior on assert/boundscheck/finalswitch failure",
233             `Sets behavior when an assert or an array bounds check fails,
234              or a $(D final switch) errors.
235                 $(UL
236                     $(LI $(B D): Default behavior, which throws an unrecoverable $(D AssertError).)
237                     $(LI $(B C): Calls the C runtime library assert failure function.)
238                     $(LI $(B halt): Executes a halt instruction, terminating the program.)
239                     $(LI $(B context): Prints the error context as part of the unrecoverable $(D AssertError).)
240                 )`
241         ),
242         Option("checkaction=[h|help|?]",
243             "list information on all available check actions"
244         ),
245         Option("color",
246             "turn colored console output on"
247         ),
248         Option("color=[on|off|auto]",
249             "force colored console output on or off, or only when not redirected (default)",
250             `Show colored console output. The default depends on terminal capabilities.
251             $(UL
252                 $(LI $(B auto): use colored output if a tty is detected (default))
253                 $(LI $(B on): always use colored output.)
254                 $(LI $(B off): never use colored output.)
255             )`
256         ),
257         Option("conf=<filename>",
258             "use config file at filename"
259         ),
260         Option("cov",
261             "do code coverage analysis"
262         ),
263         Option("cov=ctfe", "Include code executed during CTFE in coverage report"),
264         Option("cov=<nnn>",
265             "require at least nnn% code coverage",
266             `Perform $(LINK2 $(ROOT_DIR)code_coverage.html, code coverage analysis) and generate
267             $(TT .lst) file with report.)
268 ---
269 dmd -cov -unittest myprog.d
270 ---
271             `,
272         ),
273         Option("cpp=<filename>",
274             "use filename as the name of the C preprocessor to use for ImportC files",
275             `Normally the C preprocessor used by the associated C compiler is used to
276             preprocess ImportC files,
277             this is overridden by the $(TT -cpp) switch.`
278         ),
279         Option("D",
280             "generate documentation",
281             `$(P Generate $(LINK2 $(ROOT_DIR)spec/ddoc.html, documentation) from source.)
282             $(P Note: mind the $(LINK2 $(ROOT_DIR)spec/ddoc.html#security, security considerations).)
283             `,
284         ),
285         Option("Dd<directory>",
286             "write documentation file to directory",
287             `Write documentation file to $(I directory) . $(SWLINK -op)
288             can be used if the original package hierarchy should
289             be retained`,
290         ),
291         Option("Df<filename>",
292             "write documentation file to filename"
293         ),
294         Option("d",
295             "silently allow deprecated features and symbols",
296             `Silently allow $(DDLINK deprecate,deprecate,deprecated features) and use of symbols with
297             $(DDSUBLINK $(ROOT_DIR)spec/attribute, deprecated, deprecated attributes).`,
298         ),
299         Option("de",
300             "issue an error when deprecated features or symbols are used (halt compilation)"
301         ),
302         Option("dw",
303             "issue a message when deprecated features or symbols are used (default)"
304         ),
305         Option("debug",
306             "compile in debug code",
307             `Compile in $(LINK2 spec/version.html#debug, debug) code`,
308         ),
309         Option("debug=<level>",
310             "compile in debug code <= level",
311             `Compile in $(LINK2 spec/version.html#debug, debug level) &lt;= $(I level)`,
312         ),
313         Option("debug=<ident>",
314             "compile in debug code identified by ident",
315             `Compile in $(LINK2 spec/version.html#debug, debug identifier) $(I ident)`,
316         ),
317         Option("debuglib=<name>",
318             "set symbolic debug library to name",
319             `Link in $(I libname) as the default library when
320             compiling for symbolic debugging instead of $(B $(LIB)).
321             If $(I libname) is not supplied, then no default library is linked in.`
322         ),
323         Option("defaultlib=<name>",
324             "set default library to name",
325             `Link in $(I libname) as the default library when
326             not compiling for symbolic debugging instead of $(B $(LIB)).
327             If $(I libname) is not supplied, then no default library is linked in.`,
328         ),
329         Option("deps",
330             "print module dependencies (imports/file/version/debug/lib)"
331         ),
332         Option("deps=<filename>",
333             "write module dependencies to filename (only imports)",
334             `Without $(I filename), print module dependencies
335             (imports/file/version/debug/lib).
336             With $(I filename), write module dependencies as text to $(I filename)
337             (only imports).`,
338         ),
339         Option("extern-std=<standard>",
340             "set C++ name mangling compatibility with <standard>",
341             "Standards supported are:
342             $(UL
343                 $(LI $(I c++98): Use C++98 name mangling,
344                     Sets `__traits(getTargetInfo, \"cppStd\")` to `199711`)
345                 $(LI $(I c++11) (default): Use C++11 name mangling,
346                     Sets `__traits(getTargetInfo, \"cppStd\")` to `201103`)
347                 $(LI $(I c++14): Use C++14 name mangling,
348                     Sets `__traits(getTargetInfo, \"cppStd\")` to `201402`)
349                 $(LI $(I c++17): Use C++17 name mangling,
350                     Sets `__traits(getTargetInfo, \"cppStd\")` to `201703`)
351                 $(LI $(I c++20): Use C++20 name mangling,
352                     Sets `__traits(getTargetInfo, \"cppStd\")` to `202002`)
353             )",
354         ),
355         Option("extern-std=[h|help|?]",
356             "list all supported standards"
357         ),
358         Option("fIBT",
359             "generate Indirect Branch Tracking code"
360         ),
361         Option("fPIC",
362             "generate position independent code",
363             cast(TargetOS) (TargetOS.all & ~(TargetOS.Windows | TargetOS.OSX))
364         ),
365         Option("fPIE",
366             "generate position independent executables",
367             cast(TargetOS) (TargetOS.all & ~(TargetOS.Windows | TargetOS.OSX))
368         ),
369         Option("g",
370             "add symbolic debug info",
371             `$(WINDOWS
372                 Add CodeView symbolic debug info. See
373                 $(LINK2 https://dlang.org/windbg.html, Debugging on Windows).
374             )
375             $(UNIX
376                 Add symbolic debug info in DWARF format
377                 for debuggers such as
378                 $(D gdb)
379             )`,
380         ),
381         Option("gdwarf=<version>",
382             "add DWARF symbolic debug info",
383             "The value of version may be 3, 4 or 5, defaulting to 3.",
384             cast(TargetOS) (TargetOS.all & ~cast(uint)TargetOS.Windows)
385         ),
386         Option("gf",
387             "emit debug info for all referenced types",
388             `Symbolic debug info is emitted for all types referenced by the compiled code,
389              even if the definition is in an imported file not currently being compiled.`,
390         ),
391         Option("gs",
392             "always emit stack frame"
393         ),
394         Option("gx",
395             "add stack stomp code",
396             `Adds stack stomp code, which overwrites the stack frame memory upon function exit.`,
397         ),
398         Option("H",
399             "generate 'header' file",
400             `Generate $(RELATIVE_LINK2 $(ROOT_DIR)interface-files, D interface file)`,
401         ),
402         Option("Hd=<directory>",
403             "write 'header' file to directory",
404             `Write D interface file to $(I directory). $(SWLINK -op)
405             can be used if the original package hierarchy should
406             be retained.`,
407         ),
408         Option("Hf=<filename>",
409             "write 'header' file to filename"
410         ),
411         Option("HC[=[silent|verbose]]",
412             "generate C++ 'header' file",
413             `Generate C++ 'header' files using the given configuration:",
414             $(DL
415             $(DT silent)$(DD only list extern(C[++]) declarations (default))
416             $(DT verbose)$(DD also add comments for ignored declarations (e.g. extern(D)))
417             )`,
418         ),
419         Option("HC=[?|h|help]",
420             "list available modes for C++ 'header' file generation"
421         ),
422         Option("HCd=<directory>",
423             "write C++ 'header' file to directory"
424         ),
425         Option("HCf=<filename>",
426             "write C++ 'header' file to filename"
427         ),
428         Option("-help",
429             "print help and exit"
430         ),
431         Option("I=<directory>",
432             "look for imports also in directory"
433         ),
434         Option("i[=<pattern>]",
435             "include imported modules in the compilation",
436             q"{$(P Enables "include imports" mode, where the compiler will include imported
437              modules in the compilation, as if they were given on the command line. By default, when
438              this option is enabled, all imported modules are included except those in
439              druntime/phobos. This behavior can be overridden by providing patterns via `-i=<pattern>`.
440              A pattern of the form `-i=<package>` is an "inclusive pattern", whereas a pattern
441              of the form `-i=-<package>` is an "exclusive pattern". Inclusive patterns will include
442              all module's whose names match the pattern, whereas exclusive patterns will exclude them.
443              For example. all modules in the package `foo.bar` can be included using `-i=foo.bar` or excluded
444              using `-i=-foo.bar`. Note that each component of the fully qualified name must match the
445              pattern completely, so the pattern `foo.bar` would not match a module named `foo.barx`.)
446 
447              $(P The default behavior of excluding druntime/phobos is accomplished by internally adding a
448              set of standard exclusions, namely, `-i=-std -i=-core -i=-etc -i=-object`. Note that these
449              can be overridden with `-i=std -i=core -i=etc -i=object`.)
450 
451              $(P When a module matches multiple patterns, matches are prioritized by their component length, where
452              a match with more components takes priority (i.e. pattern `foo.bar.baz` has priority over `foo.bar`).)
453 
454              $(P By default modules that don't match any pattern will be included. However, if at
455              least one inclusive pattern is given, then modules not matching any pattern will
456              be excluded. This behavior can be overridden by usig `-i=.` to include by default or `-i=-.` to
457              exclude by default.)
458 
459              $(P Note that multiple `-i=...` options are allowed, each one adds a pattern.)}"
460         ),
461         Option("ignore",
462             "ignore unsupported pragmas"
463         ),
464         Option("inline",
465             "do function inlining",
466             `Inline functions at the discretion of the compiler.
467             This can improve performance, at the expense of making
468             it more difficult to use a debugger on it.`,
469         ),
470         Option("J=<directory>",
471             "look for string imports also in directory",
472             `Where to look for files for
473             $(LINK2 $(ROOT_DIR)spec/expression.html#ImportExpression, $(I ImportExpression))s.
474             This switch is required in order to use $(I ImportExpression)s.
475             $(I path) is a ; separated
476             list of paths. Multiple $(B -J)'s can be used, and the paths
477             are searched in the same order.`,
478         ),
479         Option("L=<linkerflag>",
480             "pass linkerflag to link",
481             `Pass $(I linkerflag) to the
482             $(WINDOWS linker $(OPTLINK))
483             $(UNIX linker), for example, ld`,
484         ),
485         Option("lib",
486             "generate library rather than object files",
487             `Generate library file as output instead of object file(s).
488             All compiled source files, as well as object files and library
489             files specified on the command line, are inserted into
490             the output library.
491             Compiled source modules may be partitioned into several object
492             modules to improve granularity.
493             The name of the library is taken from the name of the first
494             source module to be compiled. This name can be overridden with
495             the $(SWLINK -of) switch.`,
496         ),
497         Option("lowmem",
498             "enable garbage collection for the compiler",
499             `Enable the garbage collector for the compiler, reducing the
500             compiler memory requirements but increasing compile times.`,
501         ),
502         Option("m32",
503             "generate 32 bit code",
504             `$(UNIX Compile a 32 bit executable. This is the default for the 32 bit dmd.)`,
505             cast(TargetOS) (TargetOS.all & ~cast(uint)TargetOS.DragonFlyBSD)  // available on all OS'es except DragonFly, which does not support 32-bit binaries
506         ),
507         Option("m32mscoff",
508             "generate 32 bit code and write MS-COFF object files (deprecated use -m32)",
509             TargetOS.Windows
510         ),
511         Option("m32omf",
512             "(deprecated) generate 32 bit code and write OMF object files",
513             `$(WINDOWS Compile a 32 bit executable. The generated object code is in OMF and is meant to be used with the
514                $(LINK2 http://www.digitalmars.com/download/freecompiler.html, Digital Mars C/C++ compiler)).`,
515             TargetOS.Windows
516         ),
517         Option("m64",
518             "generate 64 bit code",
519             `$(UNIX Compile a 64 bit executable. This is the default for the 64 bit dmd.)
520             $(WINDOWS The generated object code is in MS-COFF and is meant to be used with the
521             $(LINK2 https://msdn.microsoft.com/en-us/library/dd831853(v=vs.100).aspx, Microsoft Visual Studio 10)
522             or later compiler.`,
523         ),
524         Option("main",
525             "add default main() if not present already (e.g. for unittesting)",
526             `Add a default $(D main()) function when compiling. This is useful when
527             unittesting a library, as it enables running the unittests
528             in a library without having to manually define an entry-point function.`,
529         ),
530         Option("makedeps[=<filename>]",
531             "print dependencies in Makefile compatible format to filename or stdout.",
532             `Print dependencies in Makefile compatible format.
533             If filename is omitted, it prints to stdout.
534             The emitted targets are the compiled artifacts (executable, object files, libraries).
535             The emitted dependencies are imported modules and imported string files (via $(B -J) switch).
536             Special characters in a dependency or target filename are escaped in the GNU Make manner.
537             `,
538         ),
539         Option("man",
540             "open web browser on manual page",
541             `$(WINDOWS
542                 Open default browser on this page
543             )
544             $(LINUX
545                 Open browser specified by the $(B BROWSER)
546                 environment variable on this page. If $(B BROWSER) is
547                 undefined, $(B x-www-browser) is assumed.
548             )
549             $(FREEBSD
550                 Open browser specified by the $(B BROWSER)
551                 environment variable on this page. If $(B BROWSER) is
552                 undefined, $(B x-www-browser) is assumed.
553             )
554             $(OSX
555                 Open browser specified by the $(B BROWSER)
556                 environment variable on this page. If $(B BROWSER) is
557                 undefined, $(B Safari) is assumed.
558             )`,
559         ),
560         Option("map",
561             "generate linker .map file",
562             `Generate a $(TT .map) file`,
563         ),
564         Option("mcpu=<id>",
565             "generate instructions for architecture identified by 'id'",
566             `Set the target architecture for code generation,
567             where:
568             $(DL
569             $(DT help)$(DD list alternatives)
570             $(DT baseline)$(DD the minimum architecture for the target platform (default))
571             $(DT avx)$(DD
572             generate $(LINK2 https://en.wikipedia.org/wiki/Advanced_Vector_Extensions, AVX)
573             instructions instead of $(LINK2 https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions, SSE)
574             instructions for vector and floating point operations.
575             Not available for 32 bit memory models other than OSX32.
576             )
577             $(DT native)$(DD use the architecture the compiler is running on)
578             )`,
579         ),
580         Option("mcpu=[h|help|?]",
581             "list all architecture options"
582         ),
583         Option("mixin=<filename>",
584             "expand and save mixins to file specified by <filename>"
585         ),
586         Option("mscrtlib=<libname>",
587             "MS C runtime library to reference from main/WinMain/DllMain",
588             "If building MS-COFF object files when targeting Windows, embed a reference to
589             the given C runtime library $(I libname) into the object file containing `main`,
590             `DllMain` or `WinMain` for automatic linking. The default is $(TT libcmt)
591             (release version with static linkage), the other usual alternatives are
592             $(TT libcmtd), $(TT msvcrt) and $(TT msvcrtd).
593             If no Visual C installation is detected, a wrapper for the redistributable
594             VC2010 dynamic runtime library and mingw based platform import libraries will
595             be linked instead using the LLD linker provided by the LLVM project.
596             The detection can be skipped explicitly if $(TT msvcrt120) is specified as
597             $(I libname).
598             If $(I libname) is empty, no C runtime library is automatically linked in.",
599             TargetOS.Windows,
600         ),
601         Option("mv=<package.module>=<filespec>",
602             "use <filespec> as source file for <package.module>",
603             `Use $(I path/filename) as the source file for $(I package.module).
604             This is used when the source file path and names are not the same
605             as the package and module hierarchy.
606             The rightmost components of the  $(I path/filename) and $(I package.module)
607             can be omitted if they are the same.`,
608         ),
609         Option("noboundscheck",
610             "no array bounds checking (deprecated, use -boundscheck=off)",
611             `Turns off all array bounds checking, even for safe functions. $(RED Deprecated
612             (use $(TT $(SWLINK -boundscheck)=off) instead).)`,
613         ),
614         Option("nothrow",
615             "assume no Exceptions will be thrown",
616             `Turns off generation of exception stack unwinding code, enables
617             more efficient code for RAII objects.`,
618         ),
619         Option("O",
620             "optimize",
621             `Optimize generated code. For fastest executables, compile
622             with the $(TT $(SWLINK -O) $(SWLINK -release) $(SWLINK -inline) $(SWLINK -boundscheck)=off)
623             switches together.`,
624         ),
625         Option("o-",
626             "do not write object file",
627             `Suppress generation of object file. Useful in
628             conjuction with $(SWLINK -D) or $(SWLINK -H) flags.`
629         ),
630         Option("od=<directory>",
631             "write object & library files to directory",
632             `Write object files relative to directory $(I objdir)
633             instead of to the current directory. $(SWLINK -op)
634             can be used if the original package hierarchy should
635             be retained`,
636         ),
637         Option("of=<filename>",
638             "name output file to filename",
639             `Set output file name to $(I filename) in the output
640             directory. The output file can be an object file,
641             executable file, or library file depending on the other
642             switches.`
643         ),
644         Option("op",
645             "preserve source path for output files",
646             `Normally the path for $(B .d) source files is stripped
647             off when generating an object, interface, or Ddoc file
648             name. $(SWLINK -op) will leave it on.`,
649         ),
650         Option("os=<os>",
651             "sets target operating system to <os>",
652             `Set the target operating system as other than the host.
653                 $(UL
654                     $(LI $(I host): Target the host operating system (default).)
655                     $(LI $(I dragonflybsd): DragonFlyBSD)
656                     $(LI $(I freebsd): FreeBSD)
657                     $(LI $(I linux): Linux)
658                     $(LI $(I openbsd): OpenBSD)
659                     $(LI $(I osx): OSX)
660                     $(LI $(I solaris): Solaris)
661                     $(LI $(I windows): Windows)
662                 )`
663         ),
664         Option("P=<preprocessorflag>",
665             "pass preprocessorflag to C preprocessor",
666             `Pass $(I preprocessorflag) to
667             $(WINDOWS sppn.exe or cl.exe)
668             $(UNIX cpp)`,
669         ),
670         Option("preview=<name>",
671             "enable an upcoming language change identified by 'name'",
672             `Preview an upcoming language change identified by $(I id)`,
673         ),
674         Option("preview=[h|help|?]",
675             "list all upcoming language changes"
676         ),
677         Option("profile",
678             "profile runtime performance of generated code",
679             `Instrument the generated code so that runtime performance data is collected
680             when the generated program is run.
681             Upon completion of the generated program, the files $(TT trace.log) and $(TT trace.def)
682             are generated. $(TT trace.log) has two sections,
683             $(OL
684             $(LI Fan in and fan out for each profiled function. The name of the function is left-justified,
685             the functions immediately preceding it are the other functions that call it (fan in) and how many times
686             it is called. The functions immediately following are the functions that are called (fan out) and how
687             many times it calls that function. The function itself has 3 numbers appended: the aggregate of the fan in counts,
688             the tree time used by the function which is the function time plus the tree times of all the functions it calls,
689             and the time used excluding
690             the time used by fan out.
691             )
692             $(LI Timing data for each function, sorted from most used to least.)
693             )
694             The $(TT trace.def) file contains linker commands to associate functions which are strongly coupled
695             so they appear adjacent in the resulting executable file.
696             For more information see $(LINK2 https://www.digitalmars.com/ctg/trace.html, profile)
697             `,
698         ),
699         Option("profile=gc",
700             "profile runtime allocations",
701             `$(UL
702                 $(LI $(B gc): Instrument calls to GC memory allocation and
703                 write a report to the file $(TT profilegc.log) upon program
704                 termination.  $(B Note:) Only instrumented calls will be
705                 logged. These include:
706                    $(UL
707                        $(LI Language constructs that allocate memory)
708                        $(LI Phobos functions that allocate GC memory)
709                        $(LI GC allocations via core.memory.GC)
710                    )
711                    Allocations made by other means will not be logged,
712                    including direct calls to the GC's C API.)
713             )`,
714         ),
715         Option("release",
716             "contracts and asserts are not emitted, and bounds checking is performed only in @safe functions",
717             `Compile release version, which means not emitting run-time
718             checks for contracts and asserts. Array bounds checking is not
719             done for system and trusted functions, and assertion failures
720             are undefined behaviour.`
721         ),
722         Option("revert=<name>",
723             "revert language change identified by 'name'",
724             `Revert language change identified by $(I id)`,
725         ),
726         Option("revert=[h|help|?]",
727             "list all revertable language changes"
728         ),
729         Option("run <srcfile>",
730             "compile, link, and run the program srcfile",
731             `Compile, link, and run the program $(I srcfile) with the
732             rest of the
733             command line, $(I args...), as the arguments to the program.
734             No .$(OBJEXT) or executable file is left behind.`
735         ),
736         Option("shared",
737             "generate shared library (DLL)",
738             `$(UNIX Generate shared library)
739              $(WINDOWS Generate DLL library)`,
740         ),
741         Option("target=<triple>",
742                "use <triple> as <arch>-[<vendor>-]<os>[-<cenv>[-<cppenv]]",
743                "$(I arch) is the architecture: either `x86`, `x64`, `x86_64` or `x32`,
744                $(I vendor) is always ignored, but supported for easier interoperability,
745                $(I os) is the operating system, this may have a trailing version number:
746                `freestanding` for no operating system,
747                `darwin` or `osx` for MacOS, `dragonfly` or `dragonflybsd` for DragonflyBSD,
748                `freebsd`, `openbsd`, `linux`, `solaris` or `windows` for their respective operating systems.
749                $(I cenv) is the C runtime environment and is optional: `musl` for musl-libc,
750                `msvc` for the MSVC runtime (the default for windows with this option),
751                `bionic` for the Andriod libc, `digital_mars` for the Digital Mars runtime for Windows
752                `gnu` or `glibc` for the GCC C runtime, `newlib` or `uclibc` for their respective C runtimes.
753                ($ I cppenv) is the C++ runtime environment: `clang` for the LLVM C++ runtime
754                `gcc` for GCC's C++ runtime, `msvc` for microsoft's MSVC C++ runtime (the default for windows with this switch),
755                `sun` for Sun's C++ runtime and `digital_mars` for the Digital Mars C++ runtime for windows.
756                "
757         ),
758         Option("transition=<name>",
759             "help with language change identified by 'name'",
760             `Show additional info about language change identified by $(I id)`,
761         ),
762         Option("transition=[h|help|?]",
763             "list all language changes"
764         ),
765         Option("unittest",
766             "compile in unit tests",
767             `Compile in $(LINK2 spec/unittest.html, unittest) code, turns on asserts, and sets the
768              $(D unittest) $(LINK2 spec/version.html#PredefinedVersions, version identifier)`,
769         ),
770         Option("v",
771             "verbose",
772             `Enable verbose output for each compiler pass`,
773         ),
774         Option("vasm",
775             "list generated assembler for each function"
776         ),
777         Option("vcolumns",
778             "print character (column) numbers in diagnostics"
779         ),
780         Option("verror-style=[digitalmars|gnu]",
781             "set the style for file/line number annotations on compiler messages",
782             `Set the style for file/line number annotations on compiler messages,
783             where:
784             $(DL
785             $(DT digitalmars)$(DD 'file(line[,column]): message'. This is the default.)
786             $(DT gnu)$(DD 'file:line[:column]: message', conforming to the GNU standard used by gcc and clang.)
787             )`,
788         ),
789         Option("verror-supplements=<num>",
790             "limit the number of supplemental messages for each error (0 means unlimited)"
791         ),
792         Option("verrors=<num>",
793             "limit the number of error messages (0 means unlimited)"
794         ),
795         Option("verrors=context",
796             "show error messages with the context of the erroring source line"
797         ),
798         Option("verrors=spec",
799             "show errors from speculative compiles such as __traits(compiles,...)"
800         ),
801         Option("-version",
802             "print compiler version and exit"
803         ),
804         Option("version=<level>",
805             "compile in version code >= level",
806             `Compile in $(LINK2 $(ROOT_DIR)spec/version.html#version, version level) >= $(I level)`,
807         ),
808         Option("version=<ident>",
809             "compile in version code identified by ident",
810             `Compile in $(LINK2 $(ROOT_DIR)spec/version.html#version, version identifier) $(I ident)`
811         ),
812         Option("vgc",
813             "list all gc allocations including hidden ones"
814         ),
815         Option("vtls",
816             "list all variables going into thread local storage"
817         ),
818         Option("vtemplates=[list-instances]",
819             "list statistics on template instantiations",
820             `An optional argument determines extra diagnostics,
821             where:
822             $(DL
823             $(DT list-instances)$(DD Also shows all instantiation contexts for each template.)
824             )`,
825         ),
826         Option("w",
827             "warnings as errors (compilation will halt)",
828             `Enable $(LINK2 $(ROOT_DIR)articles/warnings.html, warnings)`
829         ),
830         Option("wi",
831             "warnings as messages (compilation will continue)",
832             `Enable $(LINK2 $(ROOT_DIR)articles/warnings.html, informational warnings (i.e. compilation
833             still proceeds normally))`,
834         ),
835         Option("wo",
836             "warnings about use of obsolete features (compilation will continue)",
837             `Enable warnings about use of obsolete features that may be problematic (compilation
838             still proceeds normally)`, TargetOS.all, false,
839         ),
840         Option("X",
841             "generate JSON file"
842         ),
843         Option("Xf=<filename>",
844             "write JSON file to filename"
845         ),
846         Option("Xcc=<driverflag>",
847             "pass driverflag to linker driver (cc)",
848             "Pass $(I driverflag) to the linker driver (`$CC` or `cc`)",
849             cast(TargetOS) (TargetOS.all & ~cast(uint)TargetOS.Windows)
850         ),
851     ];
852 
853     /// Representation of a CLI feature
854     struct Feature
855     {
856         string name; /// name of the feature
857         string paramName; // internal transition parameter name
858         string helpText; // detailed description of the feature
859         bool documented = true; // whether this option should be shown in the documentation
860         bool deprecated_; /// whether the feature is still in use
861     }
862 
863     /// Returns all available transitions
864     static immutable transitions = [
865         Feature("field", "v.field",
866             "list all non-mutable fields which occupy an object instance"),
867         Feature("complex", "v.complex",
868             "give deprecation messages about all usages of complex or imaginary types", true, true),
869         Feature("tls", "v.tls",
870             "list all variables going into thread local storage"),
871         Feature("in", "v.vin",
872             "list all usages of 'in' on parameter"),
873     ];
874 
875     /// Returns all available reverts
876     static immutable reverts = [
877         Feature("dip25", "useDIP25", "revert DIP25 changes https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md", true, true),
878         Feature("dip1000", "useDIP1000",
879                 "revert DIP1000 changes https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md (Scoped Pointers)"),
880         Feature("intpromote", "fix16997", "revert integral promotions for unary + - ~ operators"),
881         Feature("dtorfields", "dtorFields", "don't destruct fields of partially constructed objects"),
882     ];
883 
884     /// Returns all available previews
885     static immutable previews = [
886         Feature("dip25", "useDIP25",
887             "implement https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md (Sealed references)", true, true),
888         Feature("dip1000", "useDIP1000",
889             "implement https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md (Scoped Pointers)"),
890         Feature("dip1008", "ehnogc",
891             "implement https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md (@nogc Throwable)"),
892         Feature("dip1021", "useDIP1021",
893             "implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md (Mutable function arguments)"),
894         Feature("bitfields", "bitfields", "add bitfields https://github.com/dlang/dlang.org/pull/3190"),
895         Feature("fieldwise", "fieldwise", "use fieldwise comparisons for struct equality"),
896         Feature("fixAliasThis", "fixAliasThis",
897             "when a symbol is resolved, check alias this scope before going to upper scopes"),
898         Feature("intpromote", "fix16997",
899             "fix integral promotions for unary + - ~ operators", false, true),
900         Feature("dtorfields", "dtorFields",
901             "destruct fields of partially constructed objects", false, false),
902         Feature("rvaluerefparam", "rvalueRefParam",
903             "enable rvalue arguments to ref parameters"),
904         Feature("nosharedaccess", "noSharedAccess",
905             "disable access to shared memory objects"),
906         Feature("in", "previewIn",
907             "`in` on parameters means `scope const [ref]` and accepts rvalues"),
908         Feature("inclusiveincontracts", "inclusiveInContracts",
909             "'in' contracts of overridden methods must be a superset of parent contract"),
910         Feature("shortenedMethods", "shortenedMethods",
911             "allow use of => for methods and top-level functions in addition to lambdas", false, true),
912         Feature("fixImmutableConv", "fixImmutableConv",
913             "disallow unsound immutable conversions that were formerly incorrectly permitted"),
914         Feature("systemVariables", "systemVariables",
915             "disable access to variables marked '@system' from @safe code"),
916     ];
917 }
918 
919 /**
920 Formats the `Options` for CLI printing.
921 */
922 struct CLIUsage
923 {
924     /**
925     Returns a string of all available CLI options for the current targetOS.
926     Options are separated by newlines.
927     */
928     static string usage() @safe
929     {
930         enum maxFlagLength = 18;
931         enum s = () {
932             char[] buf;
933             foreach (option; Usage.options)
934             {
935                 if (!option.documented)
936                     continue;
937                 if (option.os.isCurrentTargetOS)
938                 {
939                     buf ~= "  -" ~ option.flag;
940                     // create new lines if the flag name is too long
941                     if (option.flag.length >= 17)
942                     {
943                             buf ~= "\n                    ";
944                     }
945                     else if (option.flag.length <= maxFlagLength)
946                     {
947                         const spaces = maxFlagLength - option.flag.length - 1;
948                         buf.length += spaces;
949                         buf[$ - spaces .. $] = ' ';
950                     }
951                     else
952                     {
953                             buf ~= "  ";
954                     }
955                     buf ~= option.helpText;
956                     buf ~= "\n";
957                 }
958             }
959             return cast(string) buf;
960         }();
961         return s;
962     }
963 
964     /// CPU architectures supported -mcpu=id
965     enum mcpuUsage = "CPU architectures supported by -mcpu=id:
966   =[h|help|?]    list information on all available choices
967   =baseline      use default architecture as determined by target
968   =avx           use AVX 1 instructions
969   =avx2          use AVX 2 instructions
970   =native        use CPU architecture that this compiler is running on
971 ";
972 
973     static string generateFeatureUsage(const Usage.Feature[] features, string flagName, string description)
974     {
975         enum maxFlagLength = 20;
976         auto buf = description.capitalize ~ " listed by -"~flagName~"=name:
977 ";
978         auto allTransitions = [Usage.Feature("all", null,
979             "Enables all available " ~ description)] ~ features;
980         foreach (t; allTransitions)
981         {
982             if (!t.documented)
983                 continue;
984             buf ~= "  =";
985             buf ~= t.name;
986             buf ~= " "; // at least one separating space
987             auto lineLength = "  =".length + t.name.length + " ".length;
988             foreach (i; lineLength .. maxFlagLength)
989                 buf ~= " ";
990             buf ~= t.helpText;
991             if (t.deprecated_)
992                 buf ~= " [DEPRECATED]";
993             buf ~= "\n";
994         }
995         return buf;
996     }
997 
998     /// Language changes listed by -transition=id
999     enum transitionUsage = generateFeatureUsage(Usage.transitions, "transition", "language transitions");
1000 
1001     /// Language changes listed by -revert
1002     enum revertUsage = generateFeatureUsage(Usage.reverts, "revert", "revertable language changes");
1003 
1004     /// Language previews listed by -preview
1005     enum previewUsage = generateFeatureUsage(Usage.previews, "preview", "upcoming language changes");
1006 
1007     /// Options supported by -checkaction=
1008     enum checkActionUsage = "Behavior on assert/boundscheck/finalswitch failure:
1009   =[h|help|?]    List information on all available choices
1010   =D             Usual D behavior of throwing an AssertError
1011   =C             Call the C runtime library assert failure function
1012   =halt          Halt the program execution (very lightweight)
1013   =context       Use D assert with context information (when available)
1014 ";
1015 
1016     /// Options supported by -check
1017     enum checkUsage = "Enable or disable specific checks:
1018   =[h|help|?]           List information on all available choices
1019   =assert[=[on|off]]    Assertion checking
1020   =bounds[=[on|off]]    Array bounds checking
1021   =in[=[on|off]]        Generate In contracts
1022   =invariant[=[on|off]] Class/struct invariants
1023   =out[=[on|off]]       Out contracts
1024   =switch[=[on|off]]    Final switch failure checking
1025   =on                   Enable all assertion checking
1026                         (default for non-release builds)
1027   =off                  Disable all assertion checking
1028 ";
1029 
1030     /// Options supported by -extern-std
1031     enum externStdUsage = "Available C++ standards:
1032   =[h|help|?]           List information on all available choices
1033   =c++98                Sets `__traits(getTargetInfo, \"cppStd\")` to `199711`
1034   =c++11                Sets `__traits(getTargetInfo, \"cppStd\")` to `201103`
1035   =c++14                Sets `__traits(getTargetInfo, \"cppStd\")` to `201402`
1036   =c++17                Sets `__traits(getTargetInfo, \"cppStd\")` to `201703`
1037   =c++20                Sets `__traits(getTargetInfo, \"cppStd\")` to `202002`
1038 ";
1039 
1040     /// Options supported by -HC
1041     enum hcUsage = "Available header generation modes:
1042   =[h|help|?]           List information on all available choices
1043   =silent               Silently ignore non-extern(C[++]) declarations
1044   =verbose              Add a comment for ignored non-extern(C[++]) declarations
1045 ";
1046 
1047     /// Options supported by -gdwarf
1048     enum gdwarfUsage = "Available DWARF versions:
1049   =[h|help|?]           List information on choices
1050   =3                    Emit DWARF version 3 debug information
1051   =4                    Emit DWARF version 4 debug information
1052   =5                    Emit DWARF version 5 debug information
1053 ";
1054 
1055 }