GDC(1)

πŸ“¦
version 14.2.0 Β· 2 versions
, in ubuntu noble

🌸 NAME 🌸

gdc β€” a GCC-based compiler for the D language. that's the whole name bestie, short and slay πŸ’…


✨ SYNOPSIS ✨

okay so here's the vibe of how you actually call it:

gdc [-c|-S] [-g] [-pg]
    [-Olevel] [-Wwarn...]
    [-Idir...] [-Ldir...]
    [-foption...] [-mmachine-option...]
    [-o outfile] [@file] infile...
real talk: only the most useful options are listed up there, so keep reading below for the rest of them. don't come for me, the list is long 😭

πŸ’– DESCRIPTION πŸ’–

so the gdc command is the GNU compiler for the D language, and it supports a ton of the same options as gcc β€” like, they're cousins, they share a wardrobe 🫢

this manual only documents the options that are specific to gdc though, so don't expect the whole gcc saga in here. iykyk.


πŸ‘‘ OPTIONS πŸ‘‘

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

for any input file you hand over, the file name suffix decides what kind of compilation happens. it's giving "your extension is your destiny". the following kinds of input file names are supported:

  • file.d β€” D source files. the main character πŸ’…
  • file.dd β€” Ddoc source files.
  • file.di β€” D interface files.

you can specify more than one input file on the gdc command line, and each one gets compiled separately in the compilation process. but!! if you specify a -o file option, then all the input files are compiled together, producing a single output file, named file. and yes, this is allowed even when you're using -S or -c. no cap. πŸ”₯

a D interface file contains only what an import of the module needs, rather than the whole implementation of that module. you can make 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, and only then for .d. so .di is literally first in line, as it should be πŸ’…

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


πŸ¦‹ Runtime Options πŸ¦‹

these options affect the runtime behavior of programs compiled with gdc. so like, they change what your program does when it's actually out there living its life.

  • -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, like from __traits(compiles, ...), or that come from an imported module that isn't being compiled. so this flag is basically "no, do everything, i said what i said" πŸ’…
  • -fno-assert β€” turn off code generation for assert contracts. gone. bye.
  • -fno-bounds-check β€” turns off array bounds checking for all functions, which can improve performance for code that uses arrays extensively. but 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. and only then. fr fr.
  • -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. so this is you telling the compiler "i know her, but no". πŸ™ˆ
  • -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. the gossip included πŸ“
    • halt β€” halt the program execution. abrupt. iconic.
    • 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. she's the moment πŸ‘‘
    • 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, because it lets you run 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 β€” like, if you already brought your own, she's not gonna fight you on it.
  • -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. so everyone gets read, but only one gets the spotlight ✨
  • -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. the everything bagel πŸ₯―
    • 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. nobody touches the shared memory, periodt.
    • 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. so, like, she will simply refuse 😭
  • -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. lights off, party over.
  • -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. it's basically telling gdc where to go look for things 🧚

  • -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. first come, first searched πŸ’…
  • -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. so if you're wondering why your string imports are throwing a fit β€” it's because you forgot this one. every single time πŸ™ˆ

<div style="display:none">okay that's the first chunk, and there's way more coming β€” don't go anywhere bestie πŸ’–</div>

…and that's where part 1 wraps, but hold on, we are not done β€” more of this page is coming, so keep scrolling 🫢✨

  • -Ldir β€” when you're linking, this tells the compiler where to go looking for libraries, exactly like it does with gcc. Your girl does not make up new rules for the classics. πŸŽ€
  • -Bdir β€” this one points the compiler at where it can find its own executables, libraries, source files and data files. Again, same energy as gcc. ✨
  • -fmodule-file=module=spec β€” okay this one is giving ✨file path manipulation✨ and it's lowkey iconic. If an imported module matches all of, or the leftmost part of, module, then the file path in spec is used as the place to search for D sources. Bestie, you want this when your source file paths and names do NOT line up with the package and module hierarchy. Look at these examples:
gdc test.d -fmodule-file=A.B=foo.d -fmodule-file=C=bar

So this tells the compiler: search in all import paths for the source file foo.d when importing A.B, and search in the directory bar/ when importing C β€” just like it says in this little annotated D snippet:

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 that holds target-specific D sources and interfaces. 🫢
  • -iprefix prefix β€” set prefix as the prefix for the gcc directory containing target-specific D sources and interfaces. Heads up: if that prefix represents a directory, you gotta include the final /. Don't forget it, babe. πŸ’…
  • -nostdinc β€” do NOT search the standard system directories for D source and interface files. The only places searched are the directories you specified with -I options (plus the directory of the current file, if appropriate). We're keeping it tight. πŸ”₯

✨ Code Generation ✨

On top of the many gcc options that control code generation, gdc has a few of its own. Not me being obsessed with a compiler having personal touches, but here we are. πŸ’–

  • -H β€” generates D interface files for every module being compiled. The compiler figures out the output file from the input file's name: it strips any directory components and the suffix, then slaps on the .di suffix. πŸ‘‘
  • -Hd dir β€” same as -H, but writes those interface files to directory dir. You can use this with -Hf file to set the output file and the directory path independently. Mix and match, bestie. ✨
  • -Hf file β€” same as -H but it writes interface files to file. Works with -Hd dir so you can set the output file and directory path independently. πŸŽ€
  • -M β€” outputs the module dependencies of all source files being compiled, in a format that make can vibe with. The compiler outputs one make rule containing the object file name for that source file, a colon, and the names of all the imported files. Chef's kiss. πŸ’…
  • -MM β€” like -M, but it does NOT mention imported modules from the D standard library package directories. Filtered, filtered. 🧚
  • -MF file β€” when used with -M or -MM, this specifies a file to write the dependencies to. And when it's used with the driver options -MD or -MMD, -MF overrides the default dependency output file. Slay. 🌸
  • -MG β€” this one exists for compatibility with gcc, and the compiler straight up ignores it. It's just there to keep the peace. πŸ™ˆ
  • -MP β€” outputs a phony target for each dependency other than the modules being compiled, which makes each of them depend on nothing. Iconic phony behavior. ✨
  • -MT target β€” changes the target of the rule emitted by dependency generation to be exactly the string you specify. Want multiple targets? You can pass them as a single argument to -MT, or just use multiple -MT options. Your call, main character. πŸ‘‘
  • -MQ target β€” same as -MT, except it quotes any characters that are special to make. Safety first. 🫢
  • -MD β€” this is equivalent to -M -MF file. The driver determines file by removing any directory components and suffix from the input file, then adding a .deps suffix. πŸ’–
  • -MMD β€” like -MD but it 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 determines file by removing any directory components and suffix from the input file, then adding a .json suffix. JSON girlies rise up. πŸ”₯
  • -Xf file β€” same as -X, but it 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 an .html suffix. Documentation? We love her. πŸ’…
  • -fdoc-dir=dir β€” same as -fdoc, but it writes the documentation to directory dir. Use it with -fdoc-file=file to independently set the output file and directory path. πŸŽ€
  • -fdoc-file=file β€” same as -fdoc, but it writes the documentation to file. Pairs with -fdoc-dir=dir for independent output file + directory path energy. ✨
  • -fdoc-inc=file β€” specifies 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. 🌸
  • -fdump-c++-spec=file β€” for D source files, this generates corresponding C++ declarations into file. Interop moment. πŸ”₯
  • -fdump-c++-spec-verbose β€” used together with -fdump-c++-spec= above, it adds comments for ignored declarations in the generated C++ header. Verbose but make it cute. πŸ’–
  • -fsave-mixins=file β€” generates 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 source to show when they get asked. 🫢

πŸ’€ Warnings πŸ’€

Warnings are diagnostic messages that report constructions that are not inherently erroneous, but that are risky, or that suggest there's probably a bug in the program. Unless -Werror is specified, they do NOT stop the program from compiling. So like… a heads-up, not a block. 😭

  • -Wall β€” turns on all warning messages. And no, warnings are not a defined part of the D language, so every construct that this might warn about is still valid code. Periodt. πŸ’…
  • -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. Also: -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. Mismatch? Not on our watch. πŸ™ˆ
  • -Wcast-result β€” warns about casts that will produce a null or zero result. Currently 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 that have "deprecated" attributes. Living in the past is a choice, bestie. πŸ’œ
  • -Werror β€” turns all warnings into errors. All of them. Every last one. Good luck. 😭
  • -Wextra β€” enables some extra warning flags that aren't enabled by -Wall. The lineup is:
    • -Waddress
    • -Wcast-result
    • -Wmismatched-special-enum
    • -Wunknown-pragmas
  • -Wmismatched-special-enum β€” warns when an enum that the compiler recognizes as special is declared with a different size than the built-in type it's representing. Sizing matters. πŸ’…
  • -Wspeculative β€” lists all error messages from speculative compiles, like "__traits(compiles, ...)". Important: this option does NOT report messages as warnings, so these messages never become errors even when -Werror is also used. Sneaky but fair. ✨
  • -Wunknown-pragmas β€” warns when a pragma() is encountered that gdc doesn't understand. Heads up, this differs from -fignore-unknown-pragmas, where a pragma that is part of the D language but isn't implemented by the compiler won't get reported. Different vibes, different reporting. πŸ¦‹
  • -Wno-varargs β€” do not warn upon 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 will result in an error.
⚠️ Okay so real talk: this option is now deprecated and will be removed in a future release. Don't build your whole personality around it. πŸ’€
  • -fmax-errors=n β€” limits the maximum number of error messages to n, at which 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 on the number of error messages produced. 🌸
  • -fsyntax-only β€” checks the code for syntax errors, but does not actually compile it. You can use this alongside -fdoc or -H to generate files for each module present on the command-line β€” but no other output file. Just vibes, no binary. πŸ”₯
  • -ftransition=id β€” reports additional 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 options show up when the compiler links object files into an executable output file. If the compiler isn't doing a link step, they're literally meaningless. Zero effect. Nada. πŸ’…

  • -defaultlib=libname β€” specifies the library to use instead of libphobos when linking. And options that specify the linkage of libphobos, like -static-libphobos or -shared-libphobos, get ignored. Sorry bestie, they're out. 🫢
  • -debuglib=libname β€” specifies the debug library to use instead of libphobos when linking. This one 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 β€” 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 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 use of the shared version. If no shared version was built when the compiler was configured, this option has no effect. 🌈
  • -static-libphobos β€” on systems that provide libgphobos and libgdruntime as both a shared and a static library, this option forces the use of the static version. If no static version was built when the compiler was configured, this option has no effect. πŸ’œ

🧚 Developer Options 🧚

This section describes command-line options that are primarily of interest to developers or to language tooling. Iykyk. πŸ‘‘

  • -fdump-d-original β€” drops the internal front-end AST after the semantic3 stage, right into your lap. This one is only useful for debugging the GNU D compiler itself β€” like, it's for the compiler devs peeking under the hood, not for us mere mortals writing actual code πŸ’…
  • -v β€” the yapper option πŸ—£οΈ It dumps everything about the compiler language processing stages while your source program is getting compiled. What's in the dump, bestie? Literally:
    • every module processed through the parse, semantic, semantic2, and semantic3 stages
    • every import module plus its file path
    • every function body currently being compiled

So yeah, it's giving "tell me everything," and the compiler WILL tell you everything. Obsessed.


🌈 SEE ALSO 🌈

Go read these too, bestie, they're the whole friend group:

…and the Info entries for gdc and gcc, obviously. iykyk ✨


Copyright (c) 2006-2024 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). 🫢


okay that's the whole page, you made it to the end πŸŽ€ This icon was brought to you by gcc-14, dated 2024-09-08, and it's officially known as GDC(1). go compile something iconic, bestie πŸ’–βœ¨πŸ¦‹

πŸ“¦ where this page comes from