GDC(1)

๐ŸŽ€ GDC(1) ๐ŸŽ€

okay bestie, this one's from the GNU manual ๐Ÿ’– so grab your snacks, we're about to go through gdc together ๐Ÿซถ


โœจ NAME โœจ

gdc is 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...

only the most useful options are listed up there ๐Ÿ‘€ the rest are down below, so don't panic ๐Ÿซถ


๐Ÿ’– DESCRIPTION ๐Ÿ’–

the gdc command is the GNU compiler for the D language ๐Ÿ”ฅ it supports a bunch of the same options as gcc, so if you already know gcc you're literally halfway there โœจ this manual only covers the options that are specific to gdc ๐Ÿฆ‹

๐Ÿ‘‘ OPTIONS ๐Ÿ‘‘

๐Ÿ“ Input and Output files

the file name suffix on each input file decides what kind of compilation happens ๐ŸŒˆ these are the kinds of input file names that work:

  • file.d โ€” D source files ๐Ÿ’œ
  • file.dd โ€” Ddoc source files ๐ŸŒธ
  • file.di โ€” D interface files ๐Ÿงš

you can give gdc more than one input file on the command line ๐Ÿ’… each one gets compiled separately. but if you use -o file, then all the input files get compiled together into one single output file called file. and this works even with -S or -c, so no judgment ๐Ÿ™ˆ

a D interface file only holds what an import of the module actually needs, not the whole implementation of that module โœจ gdc can make these from a D source file if you use the -H option ๐Ÿซถ when the compiler resolves an import declaration, it looks for matching .di files first, and only then goes looking for .d files ๐Ÿ‘€

a Ddoc source file has code written in the D macro processor language ๐Ÿ’– it's mainly made for turning embedded comments into user documentation, leaning a little toward HTML generation ๐ŸŒท and if a .d source file starts with the string "Ddoc", it gets treated as general purpose documentation instead of as D source code ๐Ÿ“„

๐Ÿƒ Runtime Options

these options change how programs compiled with gdc behave at runtime ๐Ÿ”ฅ

  • -fall-instantiations โ€” generates code for all template instantiations ๐Ÿ’… the default emission strategy is to skip code for declarations that were instantiated speculatively (like from __traits(compiles, ...)), or that come from an imported module that isn't being compiled ๐Ÿ™…โ€โ™€๏ธ
  • -fno-assert โ€” turns off code generation for assert contracts ๐Ÿซ 
  • -fno-bounds-check โ€” turns off array bounds checking for all functions ๐ŸŽ๏ธ this can speed things up for code that uses arrays a lot, BUT:
โš ๏ธ bestie, listen: if the code actually does break array bounds, this can cause unpredictable behavior ๐Ÿ’€ it's only safe to use if you're totally sure your code never throws a RangeError.
  • -fbounds-check=value โ€” a more flexible version of -fbounds-check, so you get more control over where bounds checking is on or off ๐ŸŽฏ the supported values are:
    • 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 โ€” doesn't recognize built-in functions unless they begin with the prefix __builtin_ ๐Ÿ™…โ€โ™€๏ธ by default, the compiler does recognize when a function in the core.stdc package is a built-in function โœจ
  • -fcheckaction=value โ€” controls what code gets generated when an assertion, bounds check, or final switch fails ๐Ÿ’ฅ the supported values are:
    • context โ€” throws an AssertError with extra context information ๐Ÿ”
    • halt โ€” halts the program execution ๐Ÿ›‘
    • throw โ€” throws an AssertError (this is the default) ๐ŸŽ€
  • -fdebug, -fdebug=value โ€” turns on compilation of conditional debug code into the program ๐Ÿ› the -fdebug option by itself sets the debug level to 1, while -fdebug= enables debug code identified by any of these values:
    • level โ€” sets the debug level to level, so any debug code <= level gets compiled in ๐Ÿ“Š
    • ident โ€” turns on compilation of any debug code identified by ident ๐Ÿท๏ธ
  • -fno-druntime โ€” implements <https://dlang.org/spec/betterc.html> ๐Ÿงผ hmm, the link is https://dlang.org/spec/betterc.html, and it assumes you're targeting an environment without a D runtime library ๐ŸŒ™ this is the same as compiling with these options:
gdc -nophoboslib -fno-exceptions -fno-moduleinfo -fno-rtti
  • -fextern-std=standard โ€” sets the C++ name mangling compatibility to the version you pick with standard ๐Ÿงš the supported values are:
    • c++98, c++03 โ€” set __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 one's the default, so it's the main character ๐Ÿ‘‘
    • c++20 โ€” sets __traits(getTargetInfo, "cppStd") to 202002 ๐Ÿš€
  • -fno-invariants โ€” turns off code generation for invariant class contracts ๐Ÿซ 
  • -fmain โ€” generates a default main() function when compiling ๐ŸŽ€ this is super handy when you're unittesting a library, since you can run the unittests without manually writing an entry-point function ๐Ÿ™Œ it does nothing if main is already defined in your code ๐Ÿซถ
  • -fno-moduleinfo โ€” turns off generation of ModuleInfo and the related functions that would become unreferenced without it ๐Ÿงน this might let you link to programs that aren't written in D ๐Ÿฆ‹ the functions that don't get 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 supported values are:
    • all โ€” turns on all upcoming D language features ๐Ÿคฏ
    • dip1000 โ€” implements https://wiki.dlang.org/DIP1000 (Scoped pointers) ๐Ÿ“Œ
    • dip1008 โ€” implements https://wiki.dlang.org/DIP1008 (Allow exceptions in @nogc code) ๐Ÿง
    • dip1021 โ€” implements https://wiki.dlang.org/DIP1021 (Mutable function arguments) ๐Ÿ”
    • dip25 โ€” implements https://wiki.dlang.org/DIP25 (Sealed references) ๐Ÿ”’
    • dtorfields โ€” turns on generation for destructing fields of partially constructed objects ๐Ÿงฉ
    • fieldwise โ€” turns on generation of struct equality so it uses field-wise comparisons ๐Ÿชž
    • fixaliasthis โ€” implements new lookup rules that check the current scope for alias this before searching upper scopes ๐Ÿ”
    • in โ€” implements in parameters to mean scope const [ref], and accepts rvalues ๐Ÿซง
    • inclusiveincontracts โ€” implements in contracts of overridden methods so they're a superset of the parent contract ๐Ÿ“š
    • intpromote โ€” implements C-style integral promotion for unary +, - and ~ expressions ๐Ÿ”ข
    • nosharedaccess โ€” turns off and disallows all access to shared memory objects ๐Ÿšซ
    • rvaluerefparam โ€” implements rvalue arguments to ref parameters ๐Ÿ’ซ
    • shortenedmethods โ€” implements use of => for methods and top-level functions, in addition to lambdas โžก๏ธ
  • -frelease โ€” turns on compiling in release mode ๐Ÿš€ that means no runtime checks for contracts and asserts get emitted ๐Ÿƒโ€โ™€๏ธ array bounds checking is skipped for @system and @trusted functions, and assertion failures are undefined behavior ๐Ÿ’€
โš ๏ธ undefined behavior alert: in release mode, assertion failures are undefined behavior, so be careful, bestie ๐Ÿซฃ

this is the same as compiling with these 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 supported values are:
    • all โ€” turns off all revertable D language features ๐Ÿงน
    • dip25 โ€” reverts https://wiki.dlang.org/DIP25 (Sealed references) ๐Ÿ”“
    • dtorfields โ€” turns off generation for destructing fields of partially constructed objects ๐Ÿงฉ
    • markdown โ€” turns off Markdown replacements in Ddoc comments ๐Ÿ“
  • -fno-rtti โ€” turns off generation of run-time type information for all user defined types ๐Ÿซฅ any code that uses language features needing this info will throw an error, so heads up ๐Ÿ’€
  • -fno-switch-errors โ€” controls what code gets generated when no case is matched in a final switch statement ๐Ÿ”€ by default, the run time behavior is to throw a SwitchError ๐Ÿ’ฅ turning off -fswitch-errors means the program immediately halts instead ๐Ÿ›‘
  • -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 these values:
    • level โ€” sets the version level to level, so any version code >= level gets compiled in ๐ŸŽš๏ธ
    • 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 ๐Ÿซง by default, all public symbols get emitted as weak, unless the target doesn't support weak symbols ๐ŸŒ™ if you disable this, common symbols get put in COMDAT or become private instead ๐Ÿ”

these options tell the compiler where to look for files, libraries, and other parts of the compiler itself ๐Ÿงญ

  • -Idir โ€” specifies a directory to search for imported modules at compile time ๐Ÿ“‚ you can use multiple -I options, and the paths get searched in the same order ๐Ÿ”
  • -Jdir โ€” specifies a directory to search for files in string imports at compile time ๐Ÿ“œ this switch is required if you want to use import(file) expressions ๐Ÿ’– you can use multiple -J options, and they're searched in the same order too ๐Ÿ”
  • -Ldir โ€” when linking, specifies a library search directory, just like with gcc ๐Ÿ”—
  • -Bdir โ€” specifies where to find the executables, libraries, source files, and data files of the compiler itself, just like with gcc ๐Ÿงš
  • -fmodule-file=module=spec โ€” okay so this one is a whole vibe ๐Ÿ’… It rewrites the file paths of imported modules. If an imported module matches all of module or its leftmost part, the path in spec becomes the place where D sources get searched for. This comes in clutch when your file paths and names don't line up with your package and module hierarchy ๐Ÿ—‚๏ธ Check out these examples:
gdc test.d -fmodule-file=A.B=foo.d -fmodule-file=C=bar

This tells the compiler to search every import path for the source file foo.d when importing A.B, and to look in the directory bar/ when importing C. Here's how that plays out in D code:

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 โ€” pick dir as a subdirectory of the gcc directory that holds target-specific D sources and interfaces ๐ŸŒธ
  • -iprefix prefix โ€” set prefix as the prefix for that same gcc directory with the target-specific D sources and interfaces ๐Ÿงš If the prefix is a directory, remember to add the final '/' ๐Ÿซถ
  • -nostdinc โ€” skip the standard system directories when hunting for D source and interface files ๐Ÿ™…โ€โ™€๏ธ Only the directories you passed with -I options get searched (plus the directory of the current file, if that applies).

โœจ Code Generation โœจ

Okay so gdc has a bunch of code generation options all its own, on top of the many gcc ones that control code generation ๐Ÿ’–

  • -H โ€” generates D interface files for every module being compiled ๐Ÿฆ‹ The compiler names the output file after the input file, strips any directory components and the suffix, then slaps on the .di suffix.
  • -Hd dir โ€” same as -H, but the interface files land in the directory dir ๐Ÿ“ You can pair this with -Hf file to set the output file and the directory path separately.
  • -Hf file โ€” same as -H, but the interface files get written to file ๐ŸŽ€ You can pair this with -Hd dir 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 read them ๐Ÿ“ The compiler spits out one make rule with the object file name for that source file, a colon, and the names of all the imported files.
  • -MM โ€” basically -M, but it doesn't mention imported modules from the D standard library package directories ๐Ÿ™ˆ
  • -MF file โ€” when used with -M or -MM, it picks the file the dependencies get written to ๐Ÿ“ When used with the driver options -MD or -MMD, -MF overrides the default dependency output file.
  • -MG โ€” exists purely for compatibility with gcc, and the compiler just ignores it ๐Ÿคทโ€โ™€๏ธ
  • -MP โ€” outputs a phony target for each dependency other than the modules being compiled, so each one depends on nothing ๐Ÿ‘ป
  • -MT target โ€” changes the target of the rule made by dependency generation to be exactly the string you give it ๐ŸŽฏ Want multiple targets? Either put them all in one argument to -MT, or use multiple -MT options.
  • -MQ target โ€” same as -MT, except it quotes any characters that are special to make ๐Ÿ’…
  • -MD โ€” this one is equivalent to -M -MF file โœจ The driver figures 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 source files being compiled, in JSON format, to a file ๐Ÿงพ The driver picks file by stripping any directory components and the suffix from the input file, then adding a .json suffix.
  • -Xf file โ€” same as -X, but all the JSON contents get written to the file you specify ๐Ÿ’œ
  • -fdoc โ€” generates "Ddoc" documentation and writes it to a file ๐Ÿ“š The compiler picks file by stripping any directory components and the suffix from the input file, then adding a .html suffix.
  • -fdoc-dir=dir โ€” same as -fdoc, but the docs go into the directory dir ๐ŸŒˆ You can pair this with -fdoc-file=file to set the output file and directory path separately.
  • -fdoc-file=file โ€” same as -fdoc, but the docs get written to file ๐ŸŒท You can pair this with -fdoc-dir=dir to set the output file and directory path independently.
  • -fdoc-inc=file โ€” tells it to read file as a Ddoc macro file ๐Ÿงฉ You can use multiple -fdoc-inc options, and the files get read and processed in the order you gave them.
  • -fdump-c++-spec=file โ€” for D source files, generates matching C++ declarations in file ๐ŸŒŸ
  • -fdump-c++-spec-verbose โ€” works together with -fdump-c++-spec= from above ๐Ÿ’ญ It adds comments for the ignored declarations in the generated C++ header.
  • -fsave-mixins=file โ€” generates the code expanded from D mixin statements and writes the processed sources to file ๐Ÿ” This is super useful for debugging compilation errors, and it gives debuggers the source they need to show when you ask for it.

โœจ Warnings โœจ

Warnings are diagnostic messages that flag constructions that aren't technically wrong, but are risky or hint that there's probably a bug in your program ๐Ÿ‘€ Unless -Werror is specified, they won't stop your program from compiling, so no panic ๐Ÿซถ

  • -Wall โ€” turns on all warning messages ๐Ÿšจ Warnings aren't a defined part of the D language, and every construct that might trigger a warning is still valid code.
  • -Walloca โ€” warns on all uses of alloca in the source ๐Ÿง
  • -Walloca-larger-than=n โ€” warns on unbounded uses of alloca, plus bounded uses whose bound could be bigger than n bytes ๐Ÿ“ -Wno-alloca-larger-than turns off the -Walloca-larger-than warning, and it's equivalent to -Walloca-larger-than=SIZE_MAX or larger.
  • -Wcast-result โ€” warns about casts that will end up producing a null or zero result ๐Ÿ™ƒ Right now this only happens when casting between an imaginary and a non-imaginary data type, or when casting between a D class and a C++ class.
  • -Wno-deprecated โ€” stops the warnings about deprecated features and symbols that have "deprecated" attributes ๐Ÿ™…โ€โ™€๏ธ
  • -Werror โ€” turns every warning into an error ๐Ÿšซ Major main character energy, no cap.
  • -Wspeculative โ€” lists all error messages from speculative compiles, like the ones from __traits(compiles, ...) ๐Ÿ”ฎ This option doesn't report messages as warnings, so they never become errors even when -Werror is also used.
  • -Wtemplates โ€” warns whenever a template instantiation is encountered ๐Ÿงฑ Some coding rules ban templates, and this helps you enforce that rule.
  • -Wunknown-pragmas โ€” warns when a pragma() shows up that gdc doesn't understand ๐Ÿค” This is different from -fignore-unknown-pragmas: a pragma that's part of the D language but isn't implemented by the compiler won't get reported with this one.
  • -Wno-varargs โ€” doesn't warn about questionable usage of the macros used to handle variable arguments, like va_start ๐Ÿซ 
  • -fignore-unknown-pragmas โ€” turns off errors for unsupported pragmas ๐Ÿ™ˆ
  • -fmax-errors=n โ€” caps the number of error messages at n, and then gdc bails out instead of trying to keep going with 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 without actually compiling it ๐Ÿ”Ž You can combine it with -fdoc or -H to generate files for each module on the command line, but it won't produce any other output file.
  • -ftransition=id โ€” reports extra info about the D language changes identified by id ๐Ÿ“ฃ These values are supported:
    • all โ€” lists info on all D language transitions ๐ŸŒ
    • complex โ€” lists all usages of complex or imaginary types ๐ŸŒ€
    • field โ€” lists all non-mutable fields that take up space in an object instance ๐ŸงŠ
    • in โ€” lists all usages of in on a parameter ๐Ÿซณ
    • nogc โ€” lists all hidden GC allocations ๐Ÿ—‘๏ธ
    • templates โ€” lists statistics on template instantiations ๐Ÿ“Š
    • tls โ€” lists all variables going into thread local storage ๐Ÿงต
    • vmarkdown โ€” lists instances of Markdown replacements in Ddoc ๐Ÿ“

โœจ 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, so don't stress about them then ๐Ÿ’€

  • -defaultlib=libname โ€” picks the library to use instead of libphobos when linking ๐Ÿ’œ Options that set the linkage of libphobos, like -static-libphobos or -shared-libphobos, get ignored.
  • -debuglib=libname โ€” picks the debug library to use instead of libphobos when linking ๐Ÿž This does nothing unless the -g option was also given on the command line. Options that set the linkage of libphobos, like -static-libphobos or -shared-libphobos, get ignored here too.
  • -nophoboslib โ€” doesn't use the Phobos or D runtime library when linking ๐Ÿ™…โ€โ™€๏ธ Options that set the linkage of libphobos, like -static-libphobos or -shared-libphobos, get ignored. The standard system libraries are still 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 forces the shared version ๐Ÿซง If no shared version was built when the compiler was configured, this option does nothing.
  • -static-libphobos โ€” on systems that provide 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 does nothing.

โœจ Developer Options โœจ

This section covers command-line options that are mainly for developers or language tooling ๐Ÿ› ๏ธ

  • -fdump-d-original โ€” outputs the internal front-end AST after the "semantic3" stage ๐ŸŒณ This is only useful for debugging the GNU D compiler itself, so it's a dev-only flex ๐Ÿค“
  • -v โ€” dumps info about the compiler's language processing stages while your source program is being compiled ๐Ÿ“œ This includes listing all modules that go through the "parse", "semantic", "semantic2", and "semantic3" stages, all "import" modules and their file paths, and all "function" bodies being compiled.

โœจ SEE ALSO โœจ

gpl(7), gfdl(7), fsf-funding(7), gcc(1) and the Info entries for gdc and gcc ๐ŸŒธ

okay bestie, the legal bit at the end ๐Ÿซถ Copyright (c) 2006-2022 Free Software Foundation, Inc. ๐Ÿ’… That's the FSF claiming it, full stop.

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 ๐Ÿ“œ (so you're allowed to share and remix it, as long as you follow that license ๐Ÿฆ‹). There are 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) โœจ, so go check it out if you want the nitty-gritty ๐Ÿงš.


gcc-12 ยท 2022-02-22 ยท GDC(1) ๐Ÿ“ that's the source version, the date, and the page name all tucked into the footer, and honestly that's giving very organized energy ๐Ÿ’œ Stay iconic and keep reading the manuals, periodt! ๐Ÿ’–๐ŸŒˆ

๐Ÿ“ฆ where this page comes from