GDC(1)

πŸ“¦
version 15.3.0 Β· 2 versions
, in ubuntu stonking

πŸŽ€ GDC(1) πŸŽ€

okay bestie, welcome to gdc from the GNU girlies β€” this is the manual page for the compiler, and we're gonna go through it together, no skimming, no skipping, every single flag accounted for. πŸ’…

✨ NAME ✨

gdc β€” a GCC-based compiler for the D language. literally that's the whole vibe. πŸ¦‹

✨ SYNOPSIS ✨

gdc [-c|-S] [-g] [-pg]
    [-Olevel] [-Wwarn...]
    [-Idir...] [-Ldir...]
    [-foption...] [-mmachine-option...]
    [-o outfile] [@file] infile...

no cap, this is only the most useful options β€” the rest are hanging out further down, so keep scrolling bestie πŸ‘‘.

✨ DESCRIPTION ✨

The gdc command is the GNU compiler for the D language, and she supports so many of the same options as gcc β€” like, the family resemblance is real. But heads up: this manual only documents the options that are specific to gdc. So if you're looking for the generic GCC stuff, wrong page, go find gcc(1). 🫢


✨ OPTIONS ✨

🌸 Input and Output files 🌸

okay so for any given input file, the suffix of the file name decides what kind of compilation happens. like a vibe check by extension, iykyk. here's what's supported:

  • file.d β€” D source files. the classic. πŸ’–
  • file.dd β€” Ddoc source files.
  • file.di β€” D interface files.

You can absolutely put more than one input file on the gdc command line, bestie β€” each one gets compiled separately during the compilation process. and if you hand her a -o file option, then all the input files get compiled together, producing one single output file, named file. This is allowed even when you're using -S or -c. slay. ✨

A D interface file contains only what an import of the module needs β€” not the whole entire implementation of that module, just the essentials. she's giving minimalist queen. You can create them with gdc from a D source file by using the -H option. When the compiler resolves an import declaration, it searches for matching .di files first, then for .d.

A Ddoc source file contains code in the D macro processor language. It is primarily designed for use in producing user documentation from embedded comments, with a slight affinity towards HTML generation. and here's the tea: if a .d source file starts with the string "Ddoc" then it is treated as general purpose documentation, not as a D source file. plot twist 😭

🌈 Runtime Options 🌈

These options affect the runtime behavior of programs compiled with gdc. so like, not how your code compiles β€” how it lives its life once it's running. πŸ’€

  • -fall-instantiations β€” Generate code for all template instantiations. The default template emission strategy is to not generate code for declarations that were either instantiated speculatively, such as from __traits(compiles, ...), or that come from an imported module not being compiled.
  • -fno-assert β€” Turn off code generation for assert contracts. gone. deleted. πŸ™ˆ
  • -fno-bounds-check β€” Turns off array bounds checking for all functions, which can improve performance for code that uses arrays extensively.
⚠️ bestie listen to me: this can result in unpredictable behavior if the code in question actually does violate array bounds constraints. It is safe to use this option if you are sure that your code never throws a RangeError. are you sure? like sure sure? 🫣
  • -fbounds-check=value β€” An alternative to -fbounds-check that allows more control as to where bounds checking is turned on or off. The following values are supported:
    • on β€” Turns on array bounds checking for all functions.
    • safeonly β€” Turns on array bounds checking only for @safe functions.
    • off β€” Turns off array bounds checking completely.
  • -fno-builtin β€” Don't recognize built-in functions unless they begin with the prefix __builtin_. By default, the compiler will recognize when a function in the core.stdc package is a built-in function.
  • -fcheckaction=value β€” This option controls what code is generated on an assertion, bounds check, or final switch failure. The following values are supported:
    • context β€” Throw an AssertError with extra context information.
    • halt β€” Halt the program execution.
    • throw β€” Throw an AssertError (the default).
  • -fdebug, -fdebug=value β€” Turn on compilation of conditional debug code into the program. The -fdebug option itself sets the debug level to 1, while -fdebug= enables debug code that are identified by any of the following values:
    • ident β€” Turns on compilation of any debug code identified by ident.
  • -fno-druntime β€” Implements <https://dlang.org/spec/betterc.html>. Assumes that compilation targets an environment without a D runtime library. 🧚

This is equivalent to compiling with the following options:

gdc -nophoboslib -fno-exceptions -fno-moduleinfo -fno-rtti
  • -fextern-std=standard β€” Sets the C++ name mangling compatibility to the version identified by standard. The following values are supported:
    • c++98, c++03 β€” Sets __traits(getTargetInfo, "cppStd") to 199711.
    • c++11 β€” Sets __traits(getTargetInfo, "cppStd") to 201103.
    • c++14 β€” Sets __traits(getTargetInfo, "cppStd") to 201402.
    • c++17 β€” Sets __traits(getTargetInfo, "cppStd") to 201703. This is the default.
    • c++20 β€” Sets __traits(getTargetInfo, "cppStd") to 202002.
    • c++23 β€” Sets __traits(getTargetInfo, "cppStd") to 202302.
  • -finclude-imports β€” Include imported modules in the compilation, as if they were given on the command line. When this option is enabled, all imported modules are compiled except those that are part of libphobos.
  • -fno-invariants β€” Turns off code generation for class invariant contracts. bye girl πŸ‘‹
  • -fmain β€” Generates a default main() function when compiling. This is useful when unittesting a library, as it enables running the unittests in a library without having to manually define an entry-point function. This option does nothing when main is already defined in user code.
  • -fno-moduleinfo β€” Turns off generation of the ModuleInfo and related functions that would become unreferenced without it, which may allow linking to programs not written in D. Functions that are not be generated include module constructors and destructors (static this and static ~this), unittest code, and DSO registry functions for dynamically linked code.
  • -fonly=filename β€” Tells the compiler to parse and run semantic analysis on all modules on the command line, but only generate code for the module specified by filename. selective queen. πŸ‘‘
  • -fno-postconditions β€” Turns off code generation for postcondition out contracts.
  • -fno-preconditions β€” Turns off code generation for precondition in contracts.
  • -fpreview=id β€” Turns on an upcoming D language change identified by id. The following values are supported:
    • all β€” Turns on all upcoming D language features.
    • bitfields β€” Implements bit-fields in D.
    • dip1000 β€” Implements <https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md> (Scoped pointers).
    • dip1008 β€” Implements <https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md> (Allow exceptions in @nogc code).
    • dip1021 β€” Implements <https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md> (Mutable function arguments).
    • dip25 β€” Implements <https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md> (Sealed references).
    • dtorfields β€” Turns on generation for destructing fields of partially constructed objects.
    • fieldwise β€” Turns on generation of struct equality to use field-wise comparisons.
    • fixaliasthis β€” Implements new lookup rules that check the current scope for alias this before searching in upper scopes.
    • fiximmutableconv β€” Disallows unsound immutable conversions that were formerly incorrectly permitted.
    • in β€” Implements in parameters to mean scope const [ref] and accepts rvalues.
    • inclusiveincontracts β€” Implements in contracts of overridden methods to be a superset of parent contract.
    • nosharedaccess β€” Turns off and disallows all access to shared memory objects.
    • rvaluerefparam β€” Implements rvalue arguments to ref parameters.
    • systemvariables β€” Disables access to variables marked @system from @safe code.
  • -frelease β€” Turns on compiling in release mode, which means not emitting runtime checks for contracts and asserts. Array bounds checking is not done for @system and @trusted functions, and assertion failures are undefined behavior.
⚠️ say it with me: undefined behavior. not a vibe. be careful out there. πŸ’€

This is equivalent to compiling with the following options:

gdc -fno-assert -fbounds-check=safe -fno-invariants \
    -fno-postconditions -fno-preconditions -fno-switch-errors
  • -frevert= β€” Turns off a D language feature identified by id. The following values are supported:
  • -fno-rtti β€” Turns off generation of run-time type information for all user defined types. Any code that uses features of the language that require access to this information will result in an error. 😭
  • -fno-switch-errors β€” This option controls what code is generated when no case is matched in a final switch statement. The default run time behavior is to throw a SwitchError. Turning off -fswitch-errors means that instead the execution of the program is immediately halted.
  • -funittest β€” Turns on compilation of unittest code, and turns on the version(unittest) identifier. This implies -fassert. test girlies rise 🫢
  • -fversion=value β€” Turns on compilation of conditional version code into the program identified by any of the following values:
    • ident β€” Turns on compilation of version code identified by ident.
  • -fno-weak-templates β€” Turns off emission of declarations that can be defined in multiple objects as weak symbols. The default is to emit all public symbols as weak, unless the target lacks support for weak symbols. Disabling this option means that common symbols are instead put in COMDAT or become private.

These options specify directories to search for files, libraries, and other parts of the compiler:


(and that's where part 1 leaves us bestie β€” hold that thought, more is coming πŸ’–)

  • -Idir β€” okay bestie, this is your import-path plug πŸ” you hand it a dir to search when it's hunting down imported modules at compile time. Stack up as many -I options as you like, and the paths get searched in exactly the order you listed them.
  • -Jdir β€” same energy, different job 🌸 say what dir to search for files that show up in string imports at compile time. This switch is required if you wanna use import(file) expressions, no way around it. Multiple -J options? yes ma'am, and the paths are searched in the same order.
  • -Ldir β€” when it's linking, this names a library search directory, literally as with gcc.
  • -Bdir β€” this one tells the compiler where to find its own executables, libraries, source files, and data files, as with gcc. It's pointing at the compiler's own stuff, not yours πŸ’…
  • -fmodule-file=module=spec β€” this one messes with the file paths of imported modules 🧚 if an imported module matches all of module or the leftmost chunk of it, then the file path in spec is what gets used as the place to search for D sources. You want this when the source file paths and names don't line up with the package and module hierarchy. Check the examples:
gdc test.d -fmodule-file=A.B=foo.d -fmodule-file=C=bar

So that's telling the compiler: when importing A.B, search all the import paths for the source file foo.d; when importing C, search the directory bar/. Like the D code below annotates:

module test;
import A.B;     // Matches A.B, searches for foo.d
import C.D.E;   // Matches C, searches for bar/D/E.d
import A.B.C;   // No match, searches for A/B/C.d
  • -imultilib dir β€” use dir as a subdirectory of the gcc directory where the target-specific D sources and interfaces live.
  • -iprefix prefix β€” set prefix as the prefix for the gcc directory that holds the target-specific D sources and interfaces. Heads up 🫢 if the prefix is a directory, you gotta include the final /.
  • -nostdinc β€” do not search the standard system directories for D source and interface files. Only the directories you named with -I options get searched (plus the directory of the current file, if that applies).

✨ Code Generation ✨

On top of the many gcc options that control code generation, gdc has several options that are its own thing entirely πŸŽ€

  • -H β€” generates D interface files for every module being compiled. The compiler figures out the output file from the name of the input file: it strips any directory components and the suffix, then slaps a .di suffix on it.
  • -Hd dir β€” same as -H, but the interface files get written to directory dir. You can pair this with -Hf file so you set the output file and the directory path independently.
  • -Hf file β€” same as -H but writes the interface files to file. Pair it with -Hd dir to set the output file and the directory path independently, together.
  • -M β€” spits out the module dependencies of all the source files being compiled, in a format that make can eat. The compiler outputs one make rule holding the object file name for that source file, a colon, and the names of all the imported files.
  • -MM β€” like -M but it does not mention imported modules from the D standard library package directories.
  • -MF file β€” when you use it with -M or -MM, it names a file to write the dependencies to. When you use it with the driver options -MD or -MMD, -MF overrides the default dependency output file.
  • -MG β€” this exists for compatibility with gcc, and the compiler straight up ignores it πŸ™ˆ
  • -MP β€” outputs a phony target for each dependency other than the modules being compiled, which makes each one depend on nothing.
  • -MT target β€” changes the target of the rule emitted by dependency generation to be exactly the string you specify. Want multiple targets? Pass them as a single argument to -MT, or just use multiple -MT options. Either works πŸ’–
  • -MQ target β€” same as -MT, except it quotes any characters that are special to make.
  • -MD β€” equivalent to -M -MF file. The driver works out file by removing any directory components and the suffix from the input file, then adding a .deps suffix.
  • -MMD β€” like -MD but does not mention imported modules from the D standard library package directories.
  • -X β€” outputs info describing the contents of all source files being compiled, in JSON format, to a file. The driver gets file by removing any directory components and suffix from the input file and adding a .json suffix.
  • -Xf file β€” same as -X, but writes all the JSON contents to the specified file.
  • -fdoc β€” generates "Ddoc" documentation and writes it to a file. The compiler determines file by removing any directory components and suffix from the input file, then adding a .html suffix.
  • -fdoc-dir=dir β€” same as -fdoc, but writes the documentation to directory dir. Works alongside -fdoc-file=file so you can set the output file and directory path independently.
  • -fdoc-file=file β€” same as -fdoc, but writes documentation to file. Works alongside -fdoc-dir=dir to set the output file and directory path independently.
  • -fdoc-inc=file β€” names file as a Ddoc macro file to be read. Multiple -fdoc-inc options are allowed, and the files get read and processed in the same order.
  • -fdump-c++-spec=file β€” for D source files, generates the corresponding C++ declarations in file.
  • -fdump-c++-spec-verbose β€” used with -fdump-c++-spec= above, it adds comments for ignored declarations in the generated C++ header.
  • -fsave-mixins=file β€” generates code expanded from D "mixin" statements and writes the processed sources to file. This one is genuinely useful for debugging compilation errors, and it gives debuggers source to show when they're asked πŸ‘‘

🩷 Warnings 🩷

Warnings are diagnostic messages that report constructions that aren't inherently erroneous but are risky or suggest there's probably a bug in the program. Unless -Werror is specified, they do not stop the program from compiling.

  • -Wall β€” turns on all warning messages. Warnings are not a defined part of the D language, and every construct that this might generate a warning for is valid code.
  • -Walloca β€” warns on all uses of "alloca" in the source.
  • -Walloca-larger-than=n β€” warns on unbounded uses of alloca, and on bounded uses of alloca whose bound can be larger than n bytes. -Wno-alloca-larger-than disables the -Walloca-larger-than warning and is equivalent to -Walloca-larger-than=SIZE_MAX or larger.
  • -Wno-builtin-declaration-mismatch β€” warns if a built-in function is declared with an incompatible signature.
  • -Wcast-result β€” warns about casts that will produce a null or zero result. Right now this is only done for casting between an imaginary and non-imaginary data type, or casting between a D and C++ class.
  • -Wno-deprecated β€” do not warn about usage of deprecated features and symbols with "deprecated" attributes.
  • -Werror β€” turns all warnings into errors 😭
  • -Wextra β€” enables some extra warning flags that -Wall doesn't enable:

-Waddress -Wcast-result -Wmismatched-special-enum -Wunknown-pragmas

  • -Wmismatched-special-enum β€” warns when an enum the compiler recognizes as special is declared with a different size than the built-in type it represents.
  • -Wspeculative β€” lists all error messages from speculative compiles, like __traits(compiles, ...). This option doesn't report messages as warnings, so these messages never become errors, even when -Werror is also used.
  • -Wunknown-pragmas β€” warns when a pragma() shows up that gdc doesn't understand. This differs from -fignore-unknown-pragmas: with that one, a pragma that's part of the D language but not implemented by the compiler won't get reported.
  • -Wno-varargs β€” do not warn on questionable usage of the macros used to handle variable arguments like "va_start".
  • -fno-ignore-unknown-pragmas β€” do not recognize unsupported pragmas. Any pragma() encountered that isn't part of the D language results in an error. Heads up though: this option is now deprecated and will be removed in a future release πŸ’€
  • -fmax-errors=n β€” caps the maximum number of error messages at n, and at that point gdc bails out instead of trying to keep processing the source code. If n is 0 (the default), there's no limit on how many error messages get produced.
  • -fsyntax-only β€” checks the code for syntax errors but doesn't actually compile it. You can use this with -fdoc or -H to generate files for each module present on the command line, with no other output file.
  • -ftransition=id β€” reports extra info about D language changes identified by id. The supported values are:
    • all β€” list information on all D language transitions.
    • complex β€” list all usages of complex or imaginary types.
    • field β€” list all non-mutable fields which occupy an object instance.
    • in β€” list all usages of "in" on parameter.
    • nogc β€” list all hidden GC allocations.
    • templates β€” list statistics on template instantiations.
    • tls β€” list all variables going into thread local storage.

πŸ”— Options for Linking πŸ”—

These options come into play when the compiler links object files into an executable output file. They're meaningless if the compiler isn't doing a link step, just so you know ✨

  • -defaultlib=libname β€” names the library to use instead of libphobos when linking. Options that specify the linkage of libphobos, like -static-libphobos or -shared-libphobos, get ignored.
  • -debuglib=libname β€” names the debug library to use instead of libphobos when linking. This one has no effect unless -g was also given on the command line. Options specifying the linkage of libphobos, like -static-libphobos or -shared-libphobos, are ignored.
  • -nophoboslib β€” do not use the Phobos or D runtime library when linking. Options specifying the linkage of libphobos, like -static-libphobos or -shared-libphobos, are ignored. The standard system libraries do get used normally, unless -nostdlib or -nodefaultlibs is used.
  • -shared-libphobos β€” on systems that provide libgphobos and libgdruntime as both a shared and a static library, this option forces the shared version to be used. If no shared version was built when the compiler was configured, this option does nothing at all 🫠
  • -static-libphobos β€” okay so some systems out here ship libgphobos and libgdruntime in both a shared flavor and a static one 🌸 and this flag is you saying "static please, bestie." ✨ But real talk: if the compiler was configured without a static version ever being built in the first place? This option literally does nothing. It has no effect. Zero. Nada. πŸ’…

πŸ› οΈ Developer Options πŸ› οΈ

This bit is for the devs and the language-tooling girlies β€” options that are primarily of interest to developers or language tooling. 🧚 You probably don't need these unless you're literally working on the compiler itself, iykyk.

  • -fdump-d-original β€” dumps out the internal front-end AST after the "semantic3" stage 🫢 This one is only useful for debugging the GNU D compiler itself β€” like, it's for the compiler's own glow-up, not yours. πŸ™ˆ
  • -v β€” shows you all the compiler language processing stages while your source program is getting compiled πŸ”₯ This includes listing:
    • every module that gets processed through the "parse", "semantic", "semantic2", and "semantic3" stages
    • all "import" modules and their file paths
    • and all "function" bodies that are being compiled

It's giving full transparency, no secrets, we're all main characters here πŸ’–


πŸ”— SEE ALSO πŸ”—

Go read these next, bestie, they're part of the lore:

…plus the Info entries for gdc and gcc πŸ‘‘


Copyright (c) 2006-2025 Free Software Foundation, Inc. πŸ’œ

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation β€” with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. 🌈 A copy of the license is included in the man page gfdl(7). Slay. ✨

fr fr that's the whole page πŸ’– go compile something iconic πŸŽ€

And that's a wrap on GDC(1), babes 🫢 this was v gcc-15.3.0, dated 2026-06-12. Go forth and D your little heart out πŸ‘‘πŸ’…βœ¨

πŸ“¦ where this page comes from