GDC(1)

πŸ“¦ version 13.5.0+git10516, in opensuse-leap 16.0

🌸 GDC(1) β€” GNU 🌸

okay bestie, welcome to the GDC manual page β€” that's gdc from the GNU fam, section 1 of the manual set. grab a snack, this one's a ride πŸ’…


✨ NAME ✨

gdc β€” a GCC-based compiler for the D language πŸ¦‹

✨ SYNOPSIS ✨

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

fr fr only the most useful options are listed up there β€” the rest of them are living further down this page, see below πŸ‘€

✨ DESCRIPTION ✨

So gdc is the GNU compiler for the D language, and it's lowkey built different β€” it supports a whole bunch of the same options as gcc does. But heads up: this manual page only documents the options that are specific to gdc. everything else? that's a gcc thing, iykyk 🌈

✨ OPTIONS ✨

πŸŽ€ Input and Output files πŸŽ€

okay so for any given input file, the file name suffix is what decides what kind of compilation gets done. here's the whole lineup of supported input file names πŸ‘‘

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

You can absolutely specify more than one input file on the gdc command line β€” each one gets compiled separately in the compilation process. and if you pass a -o file option, then all the input files are 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, rather than the whole implementation of that module. They can be created by 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. If a .d source file starts with the string Ddoc then it is treated as general purpose documentation, not as a D source file. πŸ¦‹

🌸 Runtime Options 🌸

These options affect the runtime behavior of programs compiled with gdc. periodt 🫢

  • -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. πŸ™ˆ
  • -fno-bounds-check β€” Turns off array bounds checking for all functions, which can improve performance for code that uses arrays extensively. Note that 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. 😭
  • -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.
  • -fno-invariants β€” Turns off code generation for class invariant contracts. πŸ’€
  • -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. πŸŽ€
  • -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. 😭

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. 🧚
  • -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 πŸ‘‘

  • -Idir β€” Specify a directory to use when searching for imported modules at compile time. Multiple -I options can be used, and the paths are searched in the same order. πŸ’–
  • -Jdir β€” Specify a directory to use when searching for files in string imports at compile time. This switch is required in order to use import(file) expressions. Multiple -J options can be used, and the paths are searched in the same order. ✨
  • -Ldir β€” when the compiler is linking, this tells it to also look in dir for libraries, exactly like the same flag in gcc. πŸ’–
  • -Bdir β€” this one tells the compiler where to find its own stuff: the executables, libraries, source files and data files that make up the compiler itself. Same deal as with gcc. ✨
  • -fmodule-file=module=spec β€” okay so this is the module-path-rewriter, and it's lowkey iconic. It messes with the file paths of imported modules so that if an imported module matches all of module, or just the leftmost chunk of it, then the path in spec becomes the place to go hunting for D sources. You reach for this when your source file paths and names don't line up with the package/module hierarchy. Peep these examples:
gdc test.d -fmodule-file=A.B=foo.d -fmodule-file=C=bar

That tells the compiler: whenever anything imports A.B, search every import path for the source file foo.d; and whenever anything imports C, search the directory bar/. Here's the D code it's annotating, bestie:

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, the one holding target-specific D sources and interfaces. πŸŽ€
  • -iprefix prefix β€” sets prefix as the prefix of that gcc directory containing the target-specific D sources and interfaces. If your prefix is a directory, include the final /, okay? Don't forget it. πŸ’…
  • -nostdinc β€” nope, no standard system directories for D source and interface files. Only the directories you explicitly handed over with -I options (plus the directory of the current file, if that applies) get searched. Bye standard paths πŸ‘‹

πŸ’» Code Generation πŸ’»

So besides the metric ton of gcc options that control code generation, gdc has a few of its very own. Main character options only. ✨

  • -H β€” generates D interface files for every module being compiled. The compiler figures out the output filename from the name of the input file: strip any directory components and the suffix, then slap .di on the end. 🫢
  • -Hd dir β€” same as -H but drops the interface files into directory dir. You can pair it with -Hf file to set the output file and the directory path independently. 🌸
  • -Hf file β€” same as -H but writes interface files to file. Pair with -Hd dir when you want to set the output file and the directory path independently. πŸ¦‹
  • -M β€” outputs the module dependencies of all the source files being compiled, formatted so make can actually use it. The compiler spits out one make rule: the object file name for that source file, a colon, and then the names of all the imported files. Chef's kiss for build systems. πŸ”₯
  • -MM β€” like -M, but it stays quiet about imported modules that come from the D standard library package directories.
  • -MF file β€” when you're using -M or -MM, this picks file as the place to write the dependencies to. And when it's used with the driver options -MD or -MMD, -MF overrides the default dependency output file. πŸ’–
  • -MG β€” purely there for compatibility with gcc. The compiler ignores it. It's just vibing. πŸ’€
  • -MP β€” outputs a phony target for each dependency other than the modules being compiled, so each one depends on nothing. Peak "I need no one" energy.
  • -MT target β€” changes the target of the rule emitted by dependency generation to be exactly the string you give it. Want multiple targets? Either pass them all as a single argument to -MT, or just use -MT multiple times. πŸŽ€
  • -MQ target β€” same as -MT, except it quotes any characters that are special to make. Protect those special little characters 🫢
  • -MD β€” equivalent to -M -MF file. The driver works out file by stripping any directory components and the suffix from the input file, then adding a .deps suffix.
  • -MMD β€” like -MD, but it doesn't mention imported modules from the D standard library package directories.
  • -X β€” outputs info describing the contents of all the source files being compiled, in JSON format, to a file. The driver works out file by stripping any directory components and the suffix from the input file, then adding a .json suffix. JSON girlies rise 🌈
  • -Xf file β€” same as -X, but writes all the JSON contents to the file you specify.
  • -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 an .html suffix. Docs era ✨
  • -fdoc-dir=dir β€” same as -fdoc, but writes the documentation into directory dir. Can be used together with -fdoc-file=file to set the output file and directory path independently.
  • -fdoc-file=file β€” same as -fdoc, but writes the documentation to file. Can be used together with -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. You can stack multiple -fdoc-inc options, and the files get read and processed in the same order you gave them. Order matters, bestie. πŸŽ€
  • -fdump-c++-spec=file β€” for D source files, generates the corresponding C++ declarations into file.
  • -fdump-c++-spec-verbose β€” used together with -fdump-c++-spec= above, this adds comments for ignored declarations in the generated C++ header. Receipts for everything πŸ™ˆ
  • -fsave-mixins=file β€” generates code expanded from D "mixin" statements and writes the processed sources to file. Genuinely useful for debugging compilation errors, and it gives debuggers actual source to show when they ask for it. So helpful it's giving main character energy πŸ’…

⚠️ Warnings ⚠️

Okay so warnings are these diagnostic messages that report constructions which aren't inherently erroneous but are risky, or which suggest there's probably a bug lurking in the program. Unless you specify -Werror, they do not stop the program from compiling. They're just the compiler going "bestie… are you sure?" 😭

  • -Wall β€” turns on all warning messages. Important vibe check: warnings are not a defined part of the D language, and every construct that might trigger one is valid code. So nothing here is "illegal", it's just sus. πŸ’…
  • -Walloca β€” warns on every single use of "alloca" in the source.
  • -Walloca-larger-than=n β€” warns on unbounded uses of alloca, and also on bounded uses of alloca whose bound could be bigger than n bytes. And -Wno-alloca-larger-than disables the -Walloca-larger-than warning β€” it's equivalent to -Walloca-larger-than=SIZE_MAX or larger. πŸ“
  • -Wno-builtin-declaration-mismatch β€” warns if a built-in function gets declared with an incompatible signature. Not the vibe.
  • -Wcast-result β€” warns about casts that will produce a null or zero result. Right now this only fires for casting between an imaginary and a non-imaginary data type, or casting between a D and a C++ class. πŸŒ€
  • -Wno-deprecated β€” don't warn about usage of deprecated features and symbols that have "deprecated" attributes. Let them live their truth.
  • -Werror β€” turns all warnings into errors. Everything is serious now. No more "just a warning" excuses πŸ’€
  • -Wextra β€” enables some extra warning flags that -Wall doesn't turn on:
    • -Waddress
    • -Wcast-result
    • -Wmismatched-special-enum
    • -Wunknown-pragmas
  • -Wmismatched-special-enum β€” warns when an enum that the compiler recognises as special is declared with a different size than the built-in type it's representing. Mismatch detected, red flag 🚩
  • -Wspeculative β€” lists all error messages from speculative compiles, like "__traits(compiles, ...)". Heads up though: this option does not report those messages as warnings, which means they never turn into errors even when -Werror is also in play. Important distinction, don't get it twisted 🫢
  • -Wunknown-pragmas β€” warns when a pragma() shows up that gdc doesn't understand. Note the difference from -fignore-unknown-pragmas: here, a pragma that's part of the D language but simply not implemented by the compiler won't get reported. ✨
  • -Wno-varargs β€” don't warn on questionable usage of the macros used to handle variable arguments, like "va_start". πŸ™ˆ
  • -fignore-unknown-pragmas β€” turns off errors for unsupported pragmas. Ignorance is bliss, officially supported.
  • -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 (which is the default), there's no limit at all on how many error messages get produced. Brace yourself. 😭
  • -fsyntax-only β€” checks the code for syntax errors but doesn't actually compile it. Fabulous combo with -fdoc or -H to generate files for each module on the command line, while producing no other output file. Just vibes and validation πŸ’…
  • -ftransition=id β€” reports extra info about D language changes identified by id. These are the supported values:
    • 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 ones only matter when the compiler is actually linking object files into an executable output file. If there's no link step happening, they're meaningless. Literally zero thoughts, head empty. πŸ¦‹

  • -defaultlib=libname β€” picks the library to use instead of libphobos when linking. Any options that specify the linkage of libphobos, like -static-libphobos or -shared-libphobos, get ignored. Sorry not sorry πŸ’…
  • -debuglib=libname β€” picks the debug library to use instead of libphobos when linking. It has no effect unless the -g option was also given on the command line. And again, options specifying the linkage of libphobos, like -static-libphobos or -shared-libphobos, are ignored. πŸŽ€
  • -nophoboslib β€” don't 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 still get used like normal, unless -nostdlib or -nodefaultlibs is used. DIY era ✨
  • -shared-libphobos β€” on systems that ship libgphobos and libgdruntime as both a shared and a static library, this forces the shared version. If no shared version was built when the compiler was configured, this option has no effect. πŸ’œ
  • -static-libphobos β€” on systems that ship libgphobos and libgdruntime as both a shared and a static library, this forces the static version. If no static version was built when the compiler was configured, this option has no effect. Snug and self-contained 🫢

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

This section is for the options that are mainly of interest to developers or to language tooling. Nerds only, respectfully. πŸ‘‘

  • -fdump-d-original β€” outputs the internal front-end AST after the "semantic3" stage. This one is only useful for debugging the GNU D compiler itself. You're not gonna need it unless you're in the compiler, iykyk 🧚
  • -v β€” bestie this one is a whole vibe check on your compiler πŸ’… it dumps info about the language processing stages while your source program is getting compiled. What's in the dump, you ask? everything: every module that goes through the "parse", "semantic", "semantic2", and "semantic3" stages, all the "import" modules plus their file paths, and all the "function" bodies that are being compiled. it's giving backstage pass energy fr fr πŸŽ€

✨ SEE ALSO ✨

okay so if you wanna go deeper (and you know you do πŸ¦‹), go check out:


Copyright (c) 2006-2023 Free Software Foundation, Inc.

so here's the legal tea, and it's actually kind of iconic 🌸 β€” 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) 🫢


and that's the whole page, bestie πŸ˜­πŸ’– you made it to the end!! literally so proud of you. this one's from gcc-13, dated 2026-09-10, and it lives at GDC(1) β€” go compile something beautiful with it βœ¨πŸ§šπŸ’œ

πŸ“¦ where this page comes from