GHC(1)
💅 NAME
ghc — the Glasgow Haskell Compiler, bestie. That's the whole vibe. And also ghci, its interactive little sibling, who's in this page too. 🫶
✨ SYNOPSIS
ghc [option|filename]
ghci [option|filename]
🦋 DESCRIPTION
Okay so this manual page documents briefly the ghc and ghci commands — like, the cliffnotes version, not the whole saga. Heads up though: ghci is not yet available on all architectures, so if it's missing on yours, that's why, don't @ me. 😭
If you want the extensive documentation (and honestly you probably do), it exists in various other formats, including PDF at https://downloads.haskell.org/ghc/latest/docs/users_guide.pdf and HTML at https://downloads.haskell.org/ghc/latest/docs/html/. Go feast, icon behavior. 💅
✨ static vs dynamic flags (the lore)
Every single one of GHC's command line options is classified as either static or dynamic. Lowkey important, so listen:
- a static flag may only be specified on the command line
- a dynamic flag may also be given in an
OPTIONSpragma in a source file, or set from the GHCi command-line with:set
As a rule of thumb, all the language options are dynamic, and so are the warning options and the debugging options. 🎀
Everything else is static — with the notable exceptions of -v, -cpp, -fasm, -fvia-C, -fllvm, and -#include. The OPTIONS section lists the status of each flag, so you can always check. iykyk. 🔥
🌸 common file suffixes for Haskell
.hs— Haskell source code; preprocess, compile.lhs— literate Haskell source; unlit, preprocess, compile.hi— Interface file; contains information about exported symbols.hc— intermediate C files.⟨way⟩_o— object files for "way" ⟨way⟩; common ways are:dyn— dynamically-linkedp— built with profiling
.⟨way⟩_hi— interface files for "way" ⟨way⟩; common ways are:
and yes, the original list for .⟨way⟩_hi literally just stops there. iconic of it. 💀
🎀 OPTIONS 🎀
Strap in, bestie, this is the long part. Every flag is here, in the original order, no cap. 💖
🧚 Code generation
-dynamic-too,-fasm,-fllvm,-fbyte-code,-fbyte-code-and-object-code,-fexpose-internal-symbols,-fexternal-dynamic-refs— the codegen crew. (and yes,-fllvmand-fasmshow up twice in this list, we're just built different ✨)-fllvm,-fasm— the encore. told you. 💀-fno-code,-fobject-code,-fPIC,-fPIE,-fprefer-byte-code— object code decisions: yes, no, position-independent, whatever.-fwrite-if-simplified-core,-fwrite-interface— write-y things for interfaces. 📝
🔮 Debugging the compiler
Okay this is the big dump section, literally. Every flag, in order:
-dasm-lint,-dcmm-lint,-dcore-lint,-ddisable-js-c-sources,-ddisable-js-minifier— linting and JS-disabling business.-ddump-asm,-ddump-asm-conflicts,-ddump-asm-liveness,-ddump-asm-native,-ddump-asm-regalloc,-ddump-asm-regalloc-stages,-ddump-asm-stats— the asm dump family, all seven of them, living their best lives.-ddump-bcos,-ddump-c-backend,-ddump-call-arity,-ddump-cfg-weights— bytecode objects, C backend, call arity, cfg weights.-ddump-cmm,-ddump-cmm-caf,-ddump-cmm-cbe,-ddump-cmm-cfg,-ddump-cmm-cps,-ddump-cmm-from-stg,-ddump-cmm-info,-ddump-cmm-opt,-ddump-cmm-proc,-ddump-cmm-procmap,-ddump-cmm-raw,-ddump-cmm-sink,-ddump-cmm-sp,-ddump-cmm-split,-ddump-cmm-switch,-ddump-cmm-thread-sanitizer,-ddump-cmm-verbose,-ddump-cmm-verbose-by-proc— the Cmm extended universe. enormous. obsessed. 👑-ddump-core-stats,-ddump-cpr-signatures,-ddump-cpranal,-ddump-cs-trace,-ddump-cse— core stats, CPR signatures, CPR analysis, CSE stuff.-ddump-debug,-ddump-deriv,-ddump-dmd-signatures,-ddump-dmdanal,-ddump-ds,-ddump-ds-preopt— debugging and desugaring dumps.-ddump-ec-trace,-ddump-exitify,-ddump-faststrings,-ddump-file-prefix=⟨str⟩,-ddump-float-in,-ddump-foreign,-ddump-full-laziness,-ddump-float-out— note the<str>placeholder on-ddump-file-prefix, keep it literal. ✨-ddump-hie,-ddump-hpc,-ddump-if-trace,-ddump-inlinings,-ddump-js,-ddump-json,-ddump-late-cc,-ddump-liberate-case,-ddump-llvm— hie/hpc/interface-trace/inlinings/js/json/late-cc/liberate-case/llvm dumps.-ddump-mod-map,-ddump-occur-anal,-ddump-opt-cmm,-ddump-parsed,-ddump-parsed-ast,-ddump-prep— module map, occurrence analysis, optimised Cmm, parsed output and parsed AST, prep.-ddump-rn,-ddump-rn-ast,-ddump-rn-stats,-ddump-rn-trace,-ddump-rtti— renamer everything, plus RTTI.-ddump-rule-firings,-ddump-rule-rewrites,-ddump-rules,-ddump-simpl,-ddump-simpl-iterations,-ddump-simpl-stats,-ddump-simpl-trace— the rule/simplifier saga, all seven. 🔥-ddump-spec,-ddump-spec-constr,-ddump-splices,-ddump-static-argument-transformation— specialisation and splices and SAT.-ddump-stg,-ddump-stg-cg,-ddump-stg-final,-ddump-stg-from-core,-ddump-stg-from-js-sinker,-ddump-stg-tags,-ddump-stg-unarised— the STG dump cinematic universe.-ddump-str-signatures,-ddump-stranal,-ddump-tc,-ddump-tc-ast,-ddump-tc-trace,-ddump-ticked,-ddump-timings,-ddump-to-file,-ddump-types— strictness signatures, typechecker dumps, ticked, timings,-ddump-to-file, types.-ddump-verbose-inlinings,-ddump-view-pattern-commoning,-ddump-worker-wrapper— verbose inlinings, view pattern commoning, worker wrapper.-dfaststring-stats,-dhex-word-literals,-dinitial-unique=⟨s⟩,-dinline-check=⟨str⟩,-dipe-stats,-dkeep-comments,-dlinear-core-lint,-dlint— stats, hex word literals,⟨s⟩,⟨str⟩, IPE stats, comments, linear core lint, and plain-dlint.-dno-debug-output,-ddebug-output— off then on, that's the order in the original, we don't question it. 🙈-dno-typeable-binds,-dppr-case-as-let,-dppr-cols=⟨n⟩,-dppr-debug,-dppr-user-length,-drule-check=⟨str⟩,-dshow-passes,-dstg-lint— typeable binds off, pretty-printer knobs (⟨n⟩,⟨str⟩), show passes, STG lint.-dsuppress-all,-dsuppress-coercion-types,-dsuppress-coercions,-dsuppress-core-sizes,-dsuppress-idinfo,-dsuppress-module-prefixes,-dsuppress-stg-free-vars,-dsuppress-stg-reps,-dsuppress-ticks,-dsuppress-timestamps,-dsuppress-type-applications,-dsuppress-type-signatures,-dsuppress-unfoldings,-dsuppress-uniques,-dsuppress-var-kinds— the entire-dsuppress-*family, all fifteen, all iconic. 💅-dtag-inference-checks,-dth-dec-file,-dunique-increment=⟨i⟩,-dverbose-core2core,-dverbose-stg2stg— tag inference checks, TH declaration file,⟨i⟩unique increment, verbose core2core and stg2stg.-fadd-bco-name,-fno-add-bco-name,-falignment-sanitisation,-fcatch-nonexhaustive-cases,-fcheck-prim-bounds,-fcmm-thread-sanitizer,-fdistinct-constructor-tables,-fdump-with-ways— BCO names on/off, alignment sanitisation, nonexhaustive case catching, prim bounds checking, Cmm thread sanitizer, distinct constructor tables, dump with ways.-finfo-table-map,-finfo-table-map-with-fallback,-fno-info-table-map-with-fallback,-fllvm-fill-undef-with-garbage,-fno-info-table-map-with-fallback,-finfo-table-map-with-fallback,-fno-info-table-map-with-stack,-finfo-table-map-with-stack— info table map things. and yeah,-fno-info-table-map-with-fallbackand-finfo-table-map-with-fallbackeach appear twice in the source list. we love a repeat. 💀-forig-thunk-info,-fproc-alignment,-funoptimized-core-for-interpreter,-fno-unoptimized-core-for-interpreter— orig thunk info, proc alignment, and the unoptimized-core-for-interpreter pair.-g,-g⟨n⟩— debug info, optionally at level⟨n⟩. 🐛
🍓 C pre-processor
-cpp— run the C pre-processor-D⟨symbol⟩[=⟨value⟩]— define a symbol, optionally with a value-U⟨symbol⟩— undefine a symbol-I⟨dir⟩— add a directory to the search path-U⟨symbol⟩— yep, listed a second time in the original. keeping it fr fr. 🌸
🌈 Finding imports
-i— the bare one-i⟨dir⟩[:⟨dir⟩]*— a colon-separated list of directories, one or more of them, with the*meaning repeat as much as you want
🦋 Interactive mode
-fbreak-on-error,-fno-break-on-error— break on error, on and off-fbreak-on-exception,-fno-break-on-exception— break on exception, on and off-fbreak-points,-fno-break-points— break points, on and off-fghci-hist-size=⟨n⟩— GHCi history size,⟨n⟩and all-fghci-leak-check,-fno-ghci-leak-check— GHCi leak checking, on and off-fimplicit-import-qualified,-fno-implicit-import-qualified— implicit qualified imports, on and off-fload-initial-targets,-fno-load-initial-targets— load initial targets, on and off-flocal-ghci-history,-fno-local-ghci-history— local GHCi history, on and off-fno-it,-fno-no-it— theittoggle and its chaotic double-negative sibling, both literally spelled like this 🫶-fprint-bind-result,-fno-print-bind-result— print bind results, on and off-fprint-evld-with-show— print evaluated values withshow-fshow-loaded-modules— show loaded modules-ghci-script— GHCi script-ignore-dot-ghci,-no-ignore-dot-ghci— ignore the dot-ghci file, or don't-interactive-print ⟨name⟩— set the interactive printer to⟨name⟩
🧚 Interface files
--show-iface ⟨file⟩— show the interface for⟨file⟩, two dashes and everything-ddump-hi— dump the.hi-ddump-hi-diffs— dump.hidiffs-ddump-minimal-imports— dump minimal imports
💜 Keeping intermediate files
-keep-hc-file,-keep-hc-files— keep the.hcfile(s)-keep-hi-files,-no-keep-hi-files— keep.hifiles, or nope-keep-hscpp-file,-keep-hscpp-files— keep the.hscppfile(s)-keep-llvm-file,-keep-llvm-files— keep the LLVM file(s)-keep-o-files,-no-keep-o-files— keep object files, or nope-keep-s-file,-keep-s-files— keep the.sfile(s)-keep-tmp-files— keep the temp files too, why not
👑 Language options
The whole -X extended family, in original order, every single one of them, no skips:
-XAllowAmbiguousTypes,-XApplicativeDo,-XArrows,-XBangPatterns,-XBinaryLiterals,-XBlockArguments,-XCApiFFI,-XConstrainedClassMethods,-XConstraintKinds,-XCPP,-XCUSKs— the A/C crowd.-XDataKinds,-XDatatypeContexts,-XDeepSubsumption,-XDefaultSignatures,-XDeriveAnyClass,-XDeriveDataTypeable,-XDeriveFoldable,-XDeriveFunctor,-XDeriveGeneric,-XDeriveLift,-XDeriveTraversable,-XDerivingStrategies,-XDerivingVia,-XDisambiguateRecordFields,-XDoAndIfThenElse,-XDuplicateRecordFields— the entire derive/dump-adjacent D block.-XEmptyCase,-XEmptyDataDecls,-XEmptyDataDeriving,-XExistentialQuantification,-XExplicitForAll,-XExplicitLevelImports,-XExplicitNamespaces,-XExtendedDefaultRules,-XExtendedLiterals— empty things, existential things, explicit things.-XFieldSelectors,-XFlexibleContexts,-XFlexibleInstances,-XForeignFunctionInterface,-XFunctionalDependencies— F block, flexible and functional.-XGADTs,-XGADTSyntax,-XGeneralisedNewtypeDeriving,-XGeneralizedNewtypeDeriving,-XGHC2021,-XGHC2024,-XGHCForeignImportPrim,-XHaskell2010,-XHaskell98,-XHexFloatLiterals— GADTs twice-spelled right there, both the BritishGeneralisedand the AmericanGeneralized, plus the language editions.-XImplicitParams,-XImplicitPrelude,-XImplicitStagePersistence,-XImportQualifiedPost,-XImpredicativeTypes,-XIncoherentInstances,-XInstanceSigs,-XInterruptibleFFI— I block.-XKindSignatures,-XLambdaCase,-XLexicalNegation,-XLiberalTypeSynonyms,-XLinearTypes,-XListTuplePuns— K and L block.-XMagicHash,-XMonadComprehensions,-XMonoLocalBinds,-XMonomorphismRestriction,-XMultilineStrings,-XMultiParamTypeClasses,-XMultiWayIf— M block, magic hash included, obviously.-XNamedDefaults,-XNamedFieldPuns,-XNamedWildCards,-XNegativeLiterals,-XNondecreasingIndentation,-XNPlusKPatterns,-XNullaryTypeClasses,-XNumDecimals,-XNumericUnderscores— N block.-XOrPatterns,-XOverlappingInstances,-XOverloadedLabels,-XOverloadedLists,-XOverloadedRecordDot,-XOverloadedRecordUpdate,-XOverloadedStrings— O block, overloaded everything.-XPackageImports,-XParallelListComp,-XPartialTypeSignatures,-XPatternGuards,-XPatternSynonyms,-XPolyKinds,-XPostfixOperators— P block, part one.-XQualifiedDo,-XQuantifiedConstraints,-XQuasiQuotes— Q block, small but mighty.-XRank2Types,-XRankNTypes,-XRebindableSyntax,-XRecordWildCards,-XRecursiveDo,-XRequiredTypeArguments,-XRoleAnnotations— R block.-XSafe,-XScopedTypeVariables,-XStandaloneDeriving,-XStandaloneKindSignatures,-XStarIsType,-XStaticPointers,-XStrict,-XStrictData— S block, part one. ⭐-XTemplateHaskell,-XTemplateHaskellQuotes,-XTraditionalRecordSyntax,-XTransformListComp,-XTrustworthy,-XTupleSections,-XTypeAbstractions,-XTypeApplications,-XTypeData,-XTypeFamilies,-XTypeFamilyDependencies,-XTypeInType,-XTypeOperators,-XTypeSynonymInstances— T block, the biggest one, template haskell to type synonyms.-XUnboxedSums,-XUnboxedTuples,-XUndecidableInstances,-XUndecidableSuperClasses,-XUnicodeSyntax,-XUnliftedDatatypes,-XUnliftedFFITypes,-XUnliftedNewtypes,-XUnsafe``**, **-XViewPatterns` — U and V block, closing it out. 🌈
⭐ Linking options
-c— the lone lowercase-c-debug,-dylib-install-name ⟨path⟩,-dynamic,-dynload,-eventlog— debug, dylib install name at⟨path⟩, dynamic, dynload, eventlog-fcompact-unwind,-fkeep-cafs,-flink-rts,-fno-embed-manifest,-fno-gen-manifest,-fno-shared-implib— the-flinking knobs-framework ⟨name⟩,-framework-path ⟨dir⟩— framework by⟨name⟩, framework path by⟨dir⟩-fsplit-sections,-split-sections,-fno-split-sections— split sections, on/off/plain-fuse-rpaths,-fwhole-archive-hs-libs— rpaths and whole-archive Haskell libs-L ⟨dir⟩,-l ⟨lib⟩— library search⟨dir⟩and link⟨lib⟩-main-is ⟨thing⟩,-no-hs-main— main is⟨thing⟩, or there's no Haskell main-no-pie,-pie— no PIE, then PIE-no-rtsopts-suggestions— no RTS opts suggestions-package ⟨name⟩— package by⟨name⟩-pie,-no-pie— and here they are again, in the opposite order. the original said it, not me. 💀-rdynamic— rdynamic-rtsopts[=⟨none|some|all|ignore|ignoreAll⟩]— the RTS opts switch, with its five possible valuesnone,some,all,ignore,ignoreAll-shared,-single-threaded,-threaded,-static,-staticlib— shared, single-threaded, threaded, static, staticlib-threaded,-single-threaded— yep, threaded and single-threaded again, because this section is a little chaotic and we respect that 🫶-with-rtsopts=⟨opts⟩— with RTS opts⟨opts⟩
more parts incoming, bestie — this was just the appetizer 💖
🧺 Miscellaneous options 🧺
Okay so this first pile is literally the junk drawer of GHC — everything that didn't fit anywhere else got yeeted in here. It's giving "miscellaneous" in the most iconic way possible. No cap, there's stuff about module cycles, deferring errors, GHCi browsers, and some package-name business all chilling in the same list. Bestie, just scan until you find your fave:
-ddump-mod-cycles, -fdefer-out-of-scope-variables, -fno-defer-out-of-scope-variables, -fdefer-type-errors, -fno-defer-type-errors, -fdefer-typed-holes, -fno-defer-typed-holes, -fexternal-interpreter, -ffamily-application-cache, -fno-family-application-cache
Then the GHCi browser era begins 🌐 (yes, there are this many browser flags, and every single one is on the list):
-fghci-browser, -fghci-browser-host, -fghci-browser-playwright-browser-type, -fghci-browser-playwright-launch-opts, -fghci-browser-port, -fghci-browser-puppeteer-launch-opts, -fghci-browser-redirect-wasi-console
And the rest of the drawer 🫶:
-fglasgow-exts, -fno-glasgow-exts, -fno-safe-haskell, -fwrite-if-self-recomp, -fwrite-if-self-recomp-flags, -ghcversion-file ⟨path to ghcversion.h⟩, -H ⟨size⟩, -hidden-module ⟨module name⟩, -j[⟨n⟩], -jsem, -reexported-module ⟨reexport-spec⟩, -this-package-name ⟨unit-id⟩, -unit @⟨filename⟩, -working-dir ⟨dir⟩
Heads up: -j[⟨n⟩] really does have the square brackets around the count in the manpage — that's not me being cute, that's literally how it's written. Keep it exactly like that 💅
🎮 Modes of operation 🎮
This is the "wait, what am I even asking GHC to do" section. Instead of optimising or linking, these switches set the whole vibe of the run. Pick your main character moment ✨
--frontend ⟨module⟩, --help, -?, --info, --interactive, --make
Then the entire --print-* parade, which is honestly so satisfying to read out loud 👑:
--numeric-version, --print-booter-version, --print-build-platform, --print-c-compiler-flags, --print-c-compiler-link-flags, --print-debug-on, --print-global-package-db, --print-have-interpreter, --print-have-native-code-generator, --print-host-platform, --print-ld-flags, --print-leading-underscore, --print-libdir, --print-object-splitting-supported, --print-project-git-commit-id, --print-project-version, --print-rts-ways, --print-stage, --print-support-smp, --print-tables-next-to-code, --print-target-platform, --print-unregisterised
And the final batch 🎀:
--run ⟨file⟩, --show-iface ⟨file⟩, --show-options, --supported-extensions, --supported-languages, --version, -V, -e ⟨expr⟩, -M, -shared
Fr fr,-?is on the list as its own thing, right next to--help. Both of them. We don't skip options here, even the tiny chaotic ones 💀
🔥 Individual optimizations 🔥
Bestie. Sit down. This is the longest list on the entire page and it is unhinged in the best way — it's the full menu of individual optimisations, and almost every one has an on/off twin. Grab a snack 🍓, we're going in order.
Round one:
-fasm-shortcutting, -fno-asm-shortcutting, -fbinary-blob-threshold=⟨n⟩, -fblock-layout-cfg, -fno-block-layout-cfg, -fblock-layout-weightless, -fno-block-layout-weightless, -fblock-layout-weights, -fcall-arity, -fno-call-arity, -fcase-folding, -fno-case-folding, -fcase-merge, -fno-case-merge, -fcmm-control-flow, -fno-cmm-control-flow, -fcmm-elim-common-blocks, -fno-cmm-elim-common-blocks, -fcmm-sink, -fno-cmm-sink, -fcmm-static-pred, -fno-cmm-static-pred, -fcore-constant-folding, -fno-core-constant-folding, -fcpr-anal, -fno-cpr-anal, -fcross-module-specialise, -fno-cross-module-specialise, -fcse, -fno-cse
Round two — the dictionary drama continues:
-fdicts-cheap, -fno-dicts-cheap, -fdicts-strict, -fno-dicts-strict, -fdmd-tx-dict-sel, -fno-dmd-tx-dict-sel, -fdmd-unbox-width=⟨n⟩, -fdo-clever-arg-eta-expansion, -fno-do-clever-arg-eta-expansion, -fdo-eta-reduction, -fno-do-eta-reduction, -fdo-lambda-eta-expansion, -fno-do-lambda-eta-expansion, -feager-blackholing, -fenable-rewrite-rules, -fno-enable-rewrite-rules, -fexcess-precision, -fno-excess-precision, -fexitification, -fno-exitification, -fexpose-all-unfoldings, -fno-expose-all-unfoldings, -fexpose-overloaded-unfoldings, -fno-expose-overloaded-unfoldings
Round three — flavor: "everything is floatable":
-ffloat-in, -fno-float-in, -ffull-laziness, -fno-full-laziness, -ffun-to-thunk, -fno-fun-to-thunk, -fignore-asserts, -fno-ignore-asserts, -fignore-interface-pragmas, -fno-ignore-interface-pragmas, -finline-generics, -fno-inline-generics, -finline-generics-aggressively, -fno-inline-generics-aggressively, -finter-module-far-jumps, -fno-inter-module-far-jumps, -fkeep-auto-rules, -fno-keep-auto-rules, -flate-dmd-anal, -fno-late-dmd-anal, -flate-specialise, -fno-late-specialise, -fliberate-case, -fno-liberate-case, -fliberate-case-threshold=⟨n⟩, -fno-liberate-case-threshold, -fllvm-pass-vectors-in-regs, -flocal-float-out, -fno-local-float-out, -flocal-float-out-top-level, -fno-local-float-out-top-level, -floopification, -fno-loopification, -fmax-forced-spec-args=⟨n⟩, -fmax-inline-alloc-size=⟨n⟩, -fmax-inline-memcpy-insns=⟨n⟩, -fmax-inline-memset-insns=⟨n⟩, -fmax-simplifier-iterations=⟨n⟩, -fmax-uncovered-patterns=⟨n⟩, -fmax-worker-args=⟨n⟩
Round four — the "no-" era begins early, don't panic:
-fno-opt-coercion, -fno-pre-inlining, -fno-state-hack, -fnum-constant-folding, -fno-num-constant-folding, -fobject-determinism, -fno-object-determinism, -fomit-interface-pragmas, -fno-omit-interface-pragmas, -fomit-yields, -fno-omit-yields, -foptimal-applicative-do, -fno-optimal-applicative-do, -fpedantic-bottoms, -fno-pedantic-bottoms, -fpolymorphic-specialisation, -fno-polymorphic-specialisation, -fregs-graph, -fno-regs-graph, -fregs-iterative, -fno-regs-iterative, -fsimpl-tick-factor=⟨n⟩, -fsimplifier-phases=⟨n⟩
Ngl,-fno-opt-coercion,-fno-pre-inliningand-fno-state-hackare the only three in this stretch with no matching plain form listed, and-fllvm-pass-vectors-in-regsis out here with no-fno-twin at all. Main character energy, honestly 💅
Round five — specialisation station:
-fsolve-constant-dicts, -fno-solve-constant-dicts, -fspec-constr, -fno-spec-constr, -fspec-constr-count=⟨n⟩, -fno-spec-constr-count, -fspec-constr-keen, -fno-spec-constr-keen, -fspec-constr-threshold=⟨n⟩, -fno-spec-constr-threshold, -fspec-eval, -fno-spec-eval, -fspec-eval-dictfun, -fno-spec-eval-dictfun, -fspecialise, -fno-specialise, -fspecialise-aggressively, -fno-specialise-aggressively, -fspecialise-incoherents, -fno-specialise-incoherents, -fstatic-argument-transformation, -fno-static-argument-transformation, -fstg-cse, -fno-stg-cse
Round six — the home stretch, we made it 😭:
-fstg-lift-lams, -fno-stg-lift-lams, -fstg-lift-lams-known, -fno-stg-lift-lams-known, -fstg-lift-lams-non-rec-args, -fstg-lift-lams-non-rec-args-any, -fstg-lift-lams-rec-args, -fstg-lift-lams-rec-args-any, -fstrictness, -fno-strictness, -fstrictness-before=⟨n⟩, -funbox-small-strict-fields, -fno-unbox-small-strict-fields, -funbox-strict-fields, -fno-unbox-strict-fields, -funfolding-case-scaling=⟨n⟩, -funfolding-case-threshold=⟨n⟩, -funfolding-creation-threshold=⟨n⟩, -funfolding-dict-discount=⟨n⟩, -funfolding-fun-discount=⟨n⟩, -funfolding-keeness-factor=⟨n⟩, -funfolding-use-threshold=⟨n⟩, -fworker-wrapper, -fworker-wrapper-cbv, -fwrite-if-compression=⟨n⟩
Yes, -funfolding-keeness-factor=⟨n⟩ is spelled "keeness" in the actual flag. Do not "fix" it, bestie, or you'll be staring at an unrecognised-flag error wondering what went wrong 🙈
📈 Optimization levels 📈
The big-picture dials, in the exact order the manpage gives them. Copy them character for character, okay? 🎀
-O, -O1, -O0, -O0, -O2, -O0, -O⟨n⟩, -O0
Not me glitching — -O0 genuinely appears four times in that list. That's the original, that's the truth, that's the tea ☕ Keep all of them. Periodt. 💀
📦 Package options 📦
This is package-management central: trust, distrust, databases, environments, and unit ids for days. It's giving ✨supply chain but make it fashion✨:
-base-unit-id ⟨unit-id⟩, -clear-package-db, -distrust ⟨pkg⟩, -distrust-all-packages, -fpackage-trust, -global-package-db, -hide-all-packages, -hide-package ⟨pkg⟩, -ignore-package ⟨pkg⟩, -no-auto-link-packages, -no-global-package-db, -no-user-package-db, -package ⟨pkg⟩, -package-db ⟨file⟩, -package-env ⟨file⟩|⟨name⟩, -package-id ⟨unit-id⟩, -this-unit-id ⟨unit-id⟩, -trust ⟨pkg⟩, -user-package-db
Little detail that matters:-package-envtakes either⟨file⟩or⟨name⟩, and the manpage writes it with that literal pipe between them. Keep the pipe, keep the angle brackets 🫶
🛠 Phases of compilation 🛠
Where in the whole compile pipeline do you wanna stop? These are the brakes and the "actually, do the whole thing" options 🚦
--merge-objs, -C, -c, -E, -F, -S, -x ⟨suffix⟩
Fun fact from the list itself: they're basically one letter each and they could not be more different. Iykyk 👑
🔁 Overriding external programs 🔁
The -pgm* family — your "hey GHC, use this program instead" squad. Every single variant is here, and yes, the capitalisation is doing A Lot 💅
-pgma ⟨cmd⟩, -pgmc ⟨cmd⟩, -pgmCmmP ⟨cmd⟩, -pgmcxx ⟨cmd⟩, -pgmF ⟨cmd⟩, -pgmi ⟨cmd⟩, -pgminstall_name_tool ⟨cmd⟩, -pgmJSP ⟨cmd⟩, -pgmL ⟨cmd⟩, -pgml ⟨cmd⟩, -pgmlas ⟨cmd⟩, -pgmlc ⟨cmd⟩, -pgmlm ⟨cmd⟩, -pgmlo ⟨cmd⟩, -pgmotool ⟨cmd⟩, -pgmP ⟨cmd⟩, -pgms ⟨cmd⟩, -pgmwindres ⟨cmd⟩
-pgmLand-pgmlare two different flags. Same with the lowercase/uppercase crowd across this list. Case sensitivity is not a joke here, bestie 😭
🎛 Phase-specific options 🎛
Sibling section to the one above: instead of swapping the program, you're handing an extra ⟨option⟩ straight to a phase. The -opt* girlies 🎀
-opta ⟨option⟩, -optc ⟨option⟩, -optCmmP ⟨option⟩, -optcxx ⟨option⟩, -optF ⟨option⟩, -opti ⟨option⟩, -optJSP ⟨option⟩, -optL ⟨option⟩, -optl ⟨option⟩, -optlas ⟨option⟩, -optlc ⟨option⟩, -optlm ⟨option⟩, -optlo ⟨option⟩, -optP ⟨option⟩, -optwindres ⟨option⟩
Plus these two, which are not -opt-anything but live here anyway because they're phase-family vibes:
-pgmc-supports-no-pie, -pgml-supports-no-pie
🖥 Platform-specific options 🖥
SIMD/instruction-set switches, alphabetically assembled like a little bouquet of CPU features 🌸 Every one, in order:
-mavx, -mavx2, -mavx512cd, -mavx512er, -mavx512f, -mavx512pf, -mbmi, -mbmi2, -mfma, -msse, -msse2, -msse3, -msse4, -msse4.2, -mssse3
Note the literal-msse4.2with the dot in it, and-mssse3with its three s's. Type those exactly or the vibe check fails 🫠
🔌 Compiler plugins 🔌
Plugin girlies rise up 🙌 This is where you bolt extra behaviour onto the compiler, plus a couple of options for toggling and trusting plugins:
-fclear-plugins, -fplugin-library=⟨file-path⟩;⟨unit-id⟩;⟨module⟩;⟨args⟩, -fplugin-opt=⟨module⟩:⟨args⟩, -fplugin-trustworthy, -fplugin=⟨module⟩, -hide-all-plugin-packages, -plugin-package ⟨pkg⟩, -plugin-package-id ⟨pkg-id⟩
-fplugin-libraryis genuinely semicolon-separated in that order —⟨file-path⟩;⟨unit-id⟩;⟨module⟩;⟨args⟩— and-fplugin-optuses a colon. Do not swap them, do not get creative, that's the whole assignment 💜
📊 Profiling 📊
Cost-centre town 🎢 Big list, and the -fprof-* crowd have their -fno- counterparts sitting right next to them like little duos. Here's the whole set:
-auto, -auto-all, -caf-all, -fno-prof-count-entries, -fprof-count-entries, -fprof-auto, -fno-prof-auto, -fprof-auto-calls, -fno-prof-auto, -fprof-auto-exported, -fno-prof-auto, -fprof-auto-top, -fno-prof-auto, -fprof-cafs, -fno-prof-cafs, -fprof-callers=⟨name⟩, -fprof-late, -fno-prof-late, -fprof-late-inline, -fno-prof-late-inline, -fprof-late-overloaded, -fno-prof-late-overloaded, -fprof-late-overloaded-calls, -fno-prof-late-overloaded-calls, -fprof-manual, -fno-prof-manual, -no-auto, -no-auto-all, -no-caf-all, -prof, -ticky, -ticky-allocd, -ticky-ap-thunk, -ticky-dyn-thunk, -ticky-LNE, -ticky-tag-checks
Okay so yes — -fno-prof-auto really does show up four separate times in that list, once after each of the auto variants. That's exactly how the manpage has it. Don't dedupe, don't tidy, just copy 👑💀
🎯 Program coverage 🎯
Only two options, and honestly they're kind of iconic for it ✨
-fhpc, -hpcdir⟨dir⟩
Tiny little detail, but-hpcdir⟨dir⟩is written with no space before⟨dir⟩in the manpage. Keep it glued together exactly like that 🫶
🔄 Recompilation checking 🔄
"I already compiled this, why are you doing it again" — the section 😤 Mostly -f / -fno- pairs plus a couple of dependency-inclusion switches:
-exclude-module=⟨file⟩, -fforce-recomp, -fno-force-recomp, -fignore-hpc-changes, -fno-ignore-hpc-changes, -fignore-optim-changes, -fno-ignore-optim-changes, -include-cpp-deps, -include-pkg-deps
📤 Redirecting output 📤
Bestie, this is the "I don't like where you're putting that file" section 💅 Dirs, suffixes, and explicit file names for everything GHC might write out. Full list, no skips:
-dep-makefile ⟨file⟩, -dep-suffix ⟨suffix⟩, -dumpdir ⟨dir⟩, -dynhisuf ⟨suffix⟩, -dyno ⟨file⟩, -dynohi ⟨file⟩, -dynosuf ⟨suffix⟩, -hcsuf ⟨suffix⟩, -hidir ⟨dir⟩, -hiedir ⟨dir⟩, -hiesuf ⟨suffix⟩, -hisuf ⟨suffix⟩, -o ⟨file⟩, -odir ⟨dir⟩, -ohi ⟨file⟩, -osuf ⟨suffix⟩, -outputdir ⟨dir⟩, -stubdir ⟨dir⟩
So many suffixes 😭-hisuf,-hiesuf,-hcsuf,-dynhisuf,-dynosuf,-osuf, and-dep-suffixare all separate flags with their own⟨suffix⟩. Read them one at a time, bestie, they are not interchangeable 🌈
🗂 Temporary files 🗂
One single lone option, and it's the moment of peace at the end of the list 🌸
-tmpdir ⟨dir⟩
That's the whole section, no cap. Just the one. She's got main character energy purely by being alone 💜
💬 VERBOSITY OPTIONS 💬
okay so this is the "how much does GHC talk to me" section, and it's a lot of flags. Like, a genuinely iconic amount. The original page just lists them with zero descriptions, so I'm not gonna sit here and invent lore — I'm just gonna hand you the whole roster, in order, so nothing goes missing. 💅
First up, the hole-fit and diagnostics crew:
-fabstract-refinement-hole-fits-fno-abstract-refinement-hole-fits-fdefer-diagnostics-fdiagnostics-as-json-fdiagnostics-color=⟨always|auto|never⟩-fdiagnostics-show-caret-fno-diagnostics-show-caret-ferror-spans-fhide-source-paths-fkeep-going-fmax-refinement-hole-fits=⟨n⟩-fno-max-refinement-hole-fits-fmax-relevant-binds=⟨n⟩-fno-max-relevant-binds-fmax-valid-hole-fits=⟨n⟩-fno-max-valid-hole-fits-fno-show-valid-hole-fits-fno-sort-valid-hole-fits-fsort-valid-hole-fits
see how -fno-show-valid-hole-fits and -fno-sort-valid-hole-fits show up before their positive versions? yeah. that's just the order. we respect it. 🫶
Then the print-* family, which is lowkey the longest glow-up in the whole page:
-fprint-axiom-incomps-fno-print-axiom-incomps-fprint-equality-relations-fno-print-equality-relations-fprint-error-index-links=⟨always|auto|never⟩-fprint-expanded-synonyms-fno-print-expanded-synonyms-fprint-explicit-coercions-fno-print-explicit-coercions-fprint-explicit-foralls-fno-print-explicit-foralls-fprint-explicit-kinds-fno-print-explicit-kinds-fprint-explicit-runtime-reps-fno-print-explicit-runtime-reps-fprint-potential-instances-fno-print-potential-instances-fprint-redundant-promotion-ticks-fno-print-redundant-promotion-ticks-fprint-typechecker-elaboration-fno-print-typechecker-elaboration-fprint-unicode-syntax-fno-print-unicode-syntax
and then the remaining hole-fit + error-display besties:
-frefinement-level-hole-fits=⟨n⟩-fno-refinement-level-hole-fits-freverse-errors-fno-reverse-errors-fshow-docs-of-hole-fits-fno-show-docs-of-hole-fits-fshow-error-context-fno-show-error-context-fshow-hole-constraints-fshow-hole-matches-of-hole-fits-fno-show-hole-matches-of-hole-fits-fshow-provenance-of-hole-fits-fno-show-provenance-of-hole-fits-fshow-type-app-of-hole-fits-fno-show-type-app-of-hole-fits-fshow-type-app-vars-of-hole-fits-fno-show-type-app-vars-of-hole-fits-fshow-type-of-hole-fits-fno-show-type-of-hole-fits-fsort-by-size-hole-fits-fno-sort-by-size-hole-fits-fsort-by-subsumption-hole-fits-fno-sort-by-subsumption-hole-fits-funclutter-valid-hole-fits
and the last three, which are the ones people actually type at 3am:
-Rghc-timing-v-v⟨n⟩
notice -fshow-hole-constraints is out here living its life with no -fno- twin. main character energy. we do not question it. ✨
⚠️ WARNINGS ⚠️
the big one. the boss level. genuinely there are so many -W flags here that my thumb got tired. same deal as above: the page lists them, no per-flag blurbs, so here's every single one, in the exact order the page gives them. do not ask me to trim this. 🫶
the opening act (mixed -f and -W flags, because the page says so):
-fenable-th-splice-warnings-fno-enable-th-splice-warnings-fhelpful-errors-fno-helpful-errors-fmax-pmcheck-models=⟨n⟩-fshow-warning-groups-fno-show-warning-groups-fvia-C-W-Wno-extra-w-Wall-Wno-all-Wall-missed-specialisations-Wno-all-missed-specialisations-Wall-missed-specializations-Wno-all-missed-specializations
-Wall and -w sitting that close together is honestly the whole duality of woman. 😭
then the alphabetical-ish run, A through E:
-Wambiguous-fields-Wauto-orphans-Wbadly-levelled-types-Wno-badly-levelled-types-Wbadly-staged-types-Wno-badly-staged-types-Wcompat-Wno-compat-Wcompat-unqualified-imports-Wno-compat-unqualified-imports-Wcpp-undef-Wdata-kinds-tc-Wdefault-Wno-default-Wdefaulted-exception-context-Wnop-defaulted-exception-context-Wdeferred-out-of-scope-variables-Wno-deferred-out-of-scope-variables-Wdeferred-type-errors-Wno-deferred-type-errors-Wdeprecated-flags-Wno-deprecated-flags-Wdeprecated-pragmas-Wno-deprecated-pragmas-Wdeprecations-Wno-deprecations-Wderiving-defaults-Wno-deriving-defaults-Wderiving-typeable-Wno-deriving-typeable-Wdodgy-exports-Wno-dodgy-exports-Wdodgy-foreign-imports-Wno-dodgy-foreign-imports-Wdodgy-imports-Wno-dodgy-imports-Wduplicate-constraints-Wno-duplicate-constraints-Wduplicate-exports-Wno-duplicate-exports-Wempty-enumerations-Wno-empty-enumerations
(yes, -Wnop-defaulted-exception-context — it's nop-, not no-. that's not a typo, that's just the page. 💀)
then the error/extra cluster — heads up, -Werror, -Wwarn and -w are each listed more than once in this section. I'm not deleting them. we're being faithful. don't come for me:
-Werror-Wwarn-Weverything-w-Wextended-warnings-Wno-extended-warnings-Wextra-Wno-extra
F through I:
-Wforall-identifier-Wgadt-mono-local-binds-Wno-gadt-mono-local-binds-Whi-shadowing-Wno-hi-shadowing-Widentities-Wno-identities-Wimplicit-kind-vars-Wno-implicit-kind-vars-Wimplicit-lift-Wno-implicit-lift-Wimplicit-prelude-Wno-implicit-prelude-Wimplicit-rhs-quantification-Wno-implicit-rhs-quantification-Winaccessible-code-Wno-inaccessible-code-Wincomplete-export-warnings-Wno-incomplete-export-warnings-Wincomplete-patterns-Wno-incomplete-patterns-Wincomplete-record-selectors-Wno-incomplete-record-selectors-Wincomplete-record-updates-Wno-incomplete-record-updates-Wincomplete-uni-patterns-Wno-incomplete-uni-patterns-Winconsistent-flags-Wno-inconsistent-flags-Winferred-safe-imports-Wno-inferred-safe-imports-Winline-rule-shadowing-Wno-inline-rule-shadowing-Winvalid-haddock-Wno-invalid-haddock
L through N:
-Wloopy-superclass-solve-Wno-loopy-superclass-solve-Wmisplaced-pragmas-Wno-misplaced-pragmas-Wmissed-extra-shared-lib-Wno-missed-extra-shared-lib-Wmissed-specialisations-Wno-missed-specialisations-Wmissed-specializations-Wno-missed-specializations-Wmissing-deriving-strategies-Wno-missing-deriving-strategies-Wmissing-export-lists-Wno-missing-export-lists-Wmissing-exported-pattern-synonym-signatures-Wno-missing-exported-pattern-synonym-signatures-Wmissing-exported-signatures-Wno-missing-exported-signatures-Wmissing-exported-sigs-Wno-missing-exported-sigs-Wmissing-fields-Wno-missing-fields-Wmissing-home-modules-Wno-missing-home-modules-Wmissing-import-lists-Wno-missing-import-lists-Wmissing-kind-signatures-Wno-missing-kind-signatures-Wmissing-local-signatures-Wno-missing-local-signatures-Wmissing-local-sigs-Wno-missing-local-sigs-Wmissing-methods-Wno-missing-methods-Wmissing-monadfail-instances-Wno-missing-monadfail-instances-Wmissing-pattern-synonym-signatures-Wno-missing-pattern-synonym-signatures-Wmissing-poly-kind-signatures-Wno-missing-poly-kind-signatures-Wmissing-role-annotations-Wno-role-annotations-signatures-Wmissing-safe-haskell-mode-Wno-missing-safe-haskell-mode-Wmissing-signatures-Wno-missing-signatures-Wmissing-space-after-bang-Wmonomorphism-restriction-Wno-monomorphism-restriction-Wname-shadowing-Wno-name-shadowing-Wnoncanonical-monad-instances-Wno-noncanonical-monad-instances-Wnoncanonical-monadfail-instances-Wno-noncanonical-monadfail-instances-Wnoncanonical-monoid-instances-Wno-noncanonical-monoid-instances-Wnot
quick vibe check: -Wmissing-space-after-bang has no -Wno- twin, and -Wnot is out here all alone at the end of the list looking like a typo but it's literally just -Wnot. iconic. 🎀
also -Wmissing-role-annotations is paired with -Wno-role-annotations-signatures — asymmetric, unbothered. we copy exactly.
O through R:
-Woperator-whitespace-Wno-operator-whitespace-Woperator-whitespace-ext-conflict-Wno-operator-whitespace-ext-conflict-Worphans-Wno-orphans-Woverflowed-literals-Wno-overflowed-literals-Woverlapping-patterns-Wno-overlapping-patterns-Wpartial-fields-Wno-partial-fields-Wpartial-type-signatures-Wno-partial-type-signatures-Wpattern-namespace-specifier-Wno-pattern-namespace-specifier-Wprepositive-qualified-module-Wno-prepositive-qualified-module-Wredundant-bang-patterns-Wno-redundant-bang-patterns-Wredundant-constraints-Wno-redundant-constraints-Wredundant-record-wildcards-Wno-redundant-record-wildcards-Wredundant-strictness-flags-Wno-redundant-strictness-flags-Wrule-lhs-equalities-Wno-rule-lhs-equalities
S through T:
-Wsafe-Wno-safe-Wsemigroup-Wno-semigroup-Wsimplifiable-class-constraints-Wno-simplifiable-class-constraints-Wstar-binder-Wno-star-binder-Wstar-is-type-Wno-star-is-type-Wtabs-Wno-tabs-Wterm-variable-capture-Wtrustworthy-safe-Wno-safe-Wtype-defaults-Wno-type-defaults-Wtype-equality-out-of-scope-Wno-type-equality-out-of-scope-Wtype-equality-requires-operators-Wno-type-equality-requires-operators-Wtyped-holes-Wno-typed-holes
-Wno-safe showed up again under -Wtrustworthy-safe. second appearance. still keeping it. 💅 and -Wterm-variable-capture has no -Wno- partner — she's solo.
U through W:
-Wunbanged-strict-patterns-Wno-unbanged-strict-patterns-Wunicode-bidirectional-format-characters-Wunrecognised-pragmas-Wno-unrecognised-pragmas-Wunrecognised-warning-flags-Wno-unrecognised-warning-flags-Wunsafe-Wno-unsafe-Wunsupported-calling-conventions-Wno-unsupported-calling-conventions-Wunsupported-llvm-version-Wno-unsupported-llvm-version-Wunticked-promoted-constructors-Wno-unticked-promoted-constructors-Wunusable-unpack-pragmas-Wno-unusable-unpack-pragmas-Wunused-binds-Wno-unused-binds-Wunused-do-bind-Wno-unused-do-bind-Wunused-foralls-Wno-unused-foralls-Wunused-imports-Wno-unused-imports-Wunused-local-binds-Wno-unused-local-binds-Wunused-matches-Wno-unused-matches-Wunused-packages-Wno-unused-packages-Wunused-pattern-binds-Wno-unused-pattern-binds-Wunused-record-wildcards-Wno-unused-record-wildcards-Wunused-top-binds-Wno-unused-top-binds-Wunused-type-patterns-Wno-unused-type-patterns-Wuseless-specialisations-Wno-useless-specialisations-Wuseless-specializations-Wno-useless-specializations-Wview-pattern-signatures-Wno-view-pattern-signatures-Wwarn-Werror-Wwarnings-deprecations-Wno-warnings-deprecations-Wwrong-do-bind-Wno-wrong-do-bind-Wx-⟨category⟩-Wno-x-⟨category⟩
and that's the end — -Wwarn then -Werror again, right at the bottom, mirrored from the top. full circle. poetry, honestly. 🌈
note the spelling shenanigans running through this whole thing: specialisations and specializations, recognised not recognized, unrecognised — that's not me being chaotic, that's literally what's on the page. copy it exactly and you'll be fine. ✨
🔥 CODE GENERATION 🔥
oooh now we get actual descriptions, we love a section that tells us things. this is the "what kind of output do you even want" part.
-dynamic-too— build dynamic object files as well as static object files while compiling. both. at once. overachiever behaviour. 💅-fasm— use the native code generator 🛠️-fbyte-code— generate byte-code-fbyte-code-and-object-code— generate object code and byte-code. yes, both, again.-fexpose-internal-symbols— produce symbols for all functions, including internal functions.-fexternal-dynamic-refs— generate code for linking against dynamic libraries-fllvm— compile using the LLVM code generator-fno-code— omit code generation. literally no code. ghost mode. 👻-fobject-code— generate object code-fPIC— generate position-independent code (where available)-fPIE— generate code for a position-independent executable (where available)
bestie note:-fPICand-fPIEboth say "where available" — that's GHC being honest that it might not be doable on every platform. don't @ me, that's just what it says. 🫶
-fprefer-byte-code— use byte-code if it's available, for evaluating TH splices-fwrite-if-simplified-core— write an interface file containing the simplified core of the module.-fwrite-interface— always write interface files
🐛 DEBUGGING THE COMPILER 🐛
this is the "I'm not debugging my program anymore, I'm debugging GHC itself" section. gangster move honestly. ngl these ones exist for people who are built different. 💀
-dasm-lint— ASM pass sanity checking-dcmm-lint—C--pass sanity checking-dcore-lint— turn on internal sanity checking 🧠-ddisable-js-c-sources— disable the link with C sources compiled to JavaScript-ddisable-js-minifier— generate pretty-printed JavaScript code instead of minified (compacted) code.-ddump-asm— dump final assembly-ddump-asm-conflicts— dumps the register conflicts that came out of the register allocator 🎀-ddump-asm-liveness— dumps the assembly, but with register liveness added on top-ddump-asm-native— dumps the initial assembly-ddump-asm-regalloc— dumps whatever the register allocation ended up producing-ddump-asm-regalloc-stages— dumps the build and spill stages of the-fregs-graphregister allocator ✨-ddump-asm-stats— dumps the register allocator's statistics-ddump-bcos— dumps interpreter byte code-ddump-c-backend— dumps the C code that the C (unregisterised) backend generates-ddump-call-arity— dumps the output of the call arity analysis pass-ddump-cfg-weights— dumps the assumed weights of the CFG 💅-ddump-cmm— dumps the finalC--output-ddump-cmm-caf— dumps the results of theC--CAF analysis pass-ddump-cmm-cbe— dumps the results of common block elimination-ddump-cmm-cfg— dumps the results of theC--control flow optimisation pass-ddump-cmm-cps— dumps the results of the CPS pass 🦋-ddump-cmm-from-stg— dumps the STG-to-C--output-ddump-cmm-info— dumps the results of theC--info table augmentation pass-ddump-cmm-opt— dumps the results of theC--toC--optimising passes-ddump-cmm-proc— dumps the results of proc-point analysis-ddump-cmm-procmap— dumps the results of theC--proc-point map pass-ddump-cmm-raw— dumps rawC---ddump-cmm-sink— dumps the results of theC--sinking pass 🌸-ddump-cmm-sp— dumps the results of theC--stack layout pass-ddump-cmm-split— dumps the results of theC--proc-point splitting pass-ddump-cmm-switch— dumps the results of switch lowering passes-ddump-cmm-thread-sanitizer— dumps the results of theC--ThreadSanitizer elaboration pass-ddump-cmm-verbose— writes the output from the mainC--pipeline passes to files-ddump-cmm-verbose-by-proc— shows the output from the mainC--pipeline passes, grouped by proc-ddump-core-stats— prints a one-line summary of how big the Core program is at the end of the optimisation pipeline 📏-ddump-cpr-signatures— dumps CPR signatures-ddump-cpranal— dumps CPR analysis output-ddump-cs-trace— traces the constraint solver-ddump-cse— dumps CSE output-ddump-debug— dumps the generated DWARF debug information-ddump-deriv— dumps deriving output-ddump-dmd-signatures— dumps top-level demand signatures-ddump-dmdanal— dumps demand analysis output 💜-ddump-ds— dumps desugarer output-ddump-ec-trace— traces the exhaustiveness checker-ddump-exitify— dumps the output of the exitification pass-ddump-faststrings— dumps the whole FastString table when it's finished-ddump-file-prefix=⟨str⟩— sets the prefix used for the filenames of debugging output-ddump-float-in— dumps float in output-ddump-foreign— dumps foreign export stubs-ddump-full-laziness— dumps the full laziness pass output-ddump-hie— dumps the hie file syntax tree 🌈-ddump-hpc— an alias for-ddump-ticked-ddump-if-trace— traces interface files-ddump-inlinings— dumps the inlinings the simplifier performed-ddump-js— dumps the final JavaScript code-ddump-json— deprecated, use-fdiagnostics-as-jsoninstead-ddump-late-cc— dumps Core with the late cost centres added-ddump-liberate-case— dumps liberate case output-ddump-llvm— dumps LLVM intermediate code-ddump-mod-map— dumps the state of the module mapping database-ddump-occur-anal— dumps occurrence analysis output-ddump-opt-cmm— dumps the results of theC--toC--optimising passes-ddump-parsed— dumps the parse tree 🍓-ddump-parsed-ast— dumps the parser output as a syntax tree-ddump-prep— dumps prepared Core-ddump-rn— dumps renamer output-ddump-rn-ast— dumps the renamer output as a syntax tree-ddump-rn-stats— renamer stats-ddump-rn-trace— traces the renamer-ddump-rtti— traces runtime type inference-ddump-rule-firings— dumps rule firing info-ddump-rule-rewrites— dumps the detailed rule firing info-ddump-rules— dumps rewrite rules-ddump-simpl— dumps the final simplifier output 🔥-ddump-simpl-iterations— dumps the output from every single simplifier iteration-ddump-simpl-stats— dumps simplifier stats-ddump-simpl-trace— dumps the trace messages in the simplifier-ddump-spec— dumps specialiser output-ddump-spec-constr— dumps the specialiser output that came from SpecConstr-ddump-splices— dumps TH spliced expressions and what they evaluate to 👀-ddump-static-argument-transformation— dumps static argument transformation output-ddump-stg— deprecated, an alias for-ddump-stg-from-core-ddump-stg-cg— shows the output after Stg2Stg-ddump-stg-final— shows the output of the last STG pass-ddump-stg-from-core— shows CoreToStg output-ddump-stg-from-js-sinker— shows JavaScript sinker output-ddump-stg-tags— shows the output of the tag inference pass-ddump-stg-unarised— shows unarised STG-ddump-str-signatures— deprecated, an alias for-ddump-dmd-signatures-ddump-stranal— deprecated, an alias for-ddump-dmdanal-ddump-tc— dumps typechecker output-ddump-tc-ast— dumps the typechecker output as a syntax tree-ddump-tc-trace— traces the typechecker 🧚-ddump-ticked— dumps the code instrumented by HPC (Observing Code Coverage)-ddump-timings— dumps per-pass timing and allocation statistics ⏱️-ddump-to-file— dumps to files instead of stdout-ddump-types— dumps type signatures-ddump-verbose-inlinings— dumps all the inlinings considered, not just the chosen ones-ddump-view-pattern-commoning— dumps commoned view patterns-ddump-worker-wrapper— dumps worker-wrapper output-dfaststring-stats— shows statistics for fast string usage when finished-dhex-word-literals— prints values of typeWord#in hexadecimal-dinitial-unique=⟨s⟩— starts UniqSupply allocation from⟨s⟩-dinline-check=⟨str⟩— dumps information about inlining decisions-dipe-stats— shows statistics about IPE information-dkeep-comments— includes comments in the parser, which is useful in combination with-ddump-parsed-ast💅-dlinear-core-lint— turns on internal sanity checking-dlint— enables several common internal sanity checkers-dno-debug-output— suppresses unsolicited debugging output-dno-typeable-binds— doesn't generate bindings forTypeablemethods-dppr-case-as-let— prints single-alternative case expressions as strict lets-dppr-cols=⟨n⟩— sets the width of debugging output, like-dppr-cols200for example-dppr-debug— turns on debug printing (more verbose)-dppr-user-length— sets the depth for printing expressions in error messages-drule-check=⟨str⟩— dumps information about potential rule application-dshow-passes— prints out each pass name as it happens 👑-dstg-lint— STG pass sanity checking-dsuppress-all— in dumps, suppresses everything that's suppressible (except for uniques)-dsuppress-coercion-types— suppresses printing coercion types in Core dumps so they're shorter-dsuppress-coercions— suppresses printing coercions in Core dumps so they're shorter-dsuppress-core-sizes— suppresses printing core size stats per binding (since 9.4)-dsuppress-idinfo— suppresses the extended info about identifiers where they're bound-dsuppress-module-prefixes— suppresses printing module qualification prefixes-dsuppress-stg-free-vars— suppresses printing closure free variable lists in STG output-dsuppress-stg-reps— suppresses rep annotations on STG args-dsuppress-ticks— suppresses "ticks" in the pretty-printer output-dsuppress-timestamps— suppresses timestamps in dumps-dsuppress-type-applications— suppresses type applications-dsuppress-type-signatures— suppresses type signatures-dsuppress-unfoldings— suppresses printing the stable unfolding of a variable at its binding site-dsuppress-uniques— suppresses printing uniques in debug output, which makesdiffeasier to use 🫶-dsuppress-var-kinds— suppresses printing variable kinds-dtag-inference-checks— affirms that tag inference results are correct at runtime-dth-dec-file— dumps evaluated TH declarations into*.th.hsfiles-dunique-increment=⟨i⟩— sets the increment for generatedUniques to⟨i⟩-dverbose-core2core— shows output from each core-to-core pass-dverbose-stg2stg— shows output from each STG-to-STG pass 🌟-fadd-bco-name— addsBCO_NAMEinstructions in generated bytecode-falignment-sanitisation— compiles with alignment checks for all info table dereferences-fcatch-nonexhaustive-cases— adds a default error alternative to case expressions that don't have a default alternative-fcheck-prim-bounds— instruments array primops with bounds checks-fcmm-thread-sanitizer— enables ThreadSanitizer instrumentation of memory accesses-fdistinct-constructor-tables— generates a fresh info table for each usage of a data constructor-fdump-with-ways— includes the tag of the enabled ways in the extension of dump files-finfo-table-map— embeds a lookup table in the generated binary that maps the address of an info table to the source position the closure originated from 🗺️-finfo-table-map-with-fallback— includes info tables with no source location information in the info table map-fllvm-fill-undef-with-garbage— instructs LLVM to fill dead STG registers with garbage 💀-fno-info-table-map-with-fallback— keeps info tables that have no source location info out of the info table map 🫶-fno-info-table-map-with-stack— keeps info tables forSTACKclosures out of the info table map, same deal ✨-forig-thunk-info— generatesstg_orig_thunk_infostack frames whenever a thunk gets entered 👀-fproc-alignment— aligns functions at the boundary you give it 📐-funoptimized-core-for-interpreter— turns optimizations off when you're using the interpreter 🙈-g— produces DWARF debug information in your compiled object files. The ⟨n⟩ can be0,1, or2, and higher numbers = richer output 💅 if you just leave ⟨n⟩ off, level2is what you get, no cap.
🧪 C pre-processor
-cpp— runs the C pre-processor over your Haskell source files 💖-D⟨symbol⟩[=⟨value⟩]— defines a symbol in the C pre-processor, literally that 🌸-I⟨dir⟩— adds ⟨dir⟩ to the directory search list for#includefiles 🎀-U⟨symbol⟩— undefines a symbol in the C pre-processor, the inverse vibe 💫
🔎 Finding imports
-i— empties the import directory list, poof, gone 🫧-i⟨dir⟩[:⟨dir⟩]*— adds ⟨dir⟩, ⟨dir2⟩, and so on to the import path 💜
🎮 Interactive mode
-fbreak-on-error— breaks on uncaught exceptions and errors 😭-fbreak-on-exception— breaks on any exception that gets thrown 🔥-fbreak-points— inserts breakpoints into the GHCi debugger 🎯-fghci-hist-size=⟨n⟩— sets how many entries GHCi keeps for:history. Check The GHCi Debugger for the deets 📚-fghci-leak-check— (debugging only!) checks for space leaks when loading new modules in GHCi 🕵️♀️-fimplicit-import-qualified— puts qualified identifiers for every loaded module into scope 👑-fload-initial-targets— loads targets when GHCi starts up 🚀-flocal-ghci-history— uses the current directory for the GHCi command history file.ghci-history📂-fno-it— stops setting that special variableit, sorry bestie 💔-fprint-bind-result— turns on printing of binding results in GHCi 🖨️-fprint-evld-with-show— tells:printto useShowinstances wherever it can ✨-fshow-loaded-modules— shows you the names of the modules GHCi loaded after a:loadcommand 👀-ghci-script— reads extra.ghcifiles 📜-ignore-dot-ghci— disables reading of.ghcifiles, full ignore mode 🙅♀️-interactive-print ⟨name⟩— picks the function used for printing evaluated expressions in GHCi 💅
🗂️ Interface files
--show-iface ⟨file⟩— see Modes of operation 🧚-ddump-hi— dumps the new interface to stdout 🌊-ddump-hi-diffs— shows the differences vs. the old interface, the glow-up receipt 🔍-ddump-minimal-imports— dumps a minimal set of imports 🎀
🧳 Keeping intermediate files
-keep-hc-file— retains intermediate.hcfiles 💖-keep-hi-files— retains intermediate.hifiles (this one's the default, btw) ✨-keep-hscpp-file— retains intermediate.hscppfiles 🌸-keep-llvm-file— retains intermediate LLVM.llfiles. Implies-fllvm🦋-keep-o-files— retains intermediate.ofiles (also the default!) 🫶-keep-s-file— retains intermediate.sfiles 💜-keep-tmp-files— retains all the intermediate temporary files, everything stays 😤
🗣️ Language options
-XAllowAmbiguousTypes— lets you write ambiguous types, and lets the type inference engine infer them too 👑-XApplicativeDo— letsdo-notation statements get desugared viaApplicative✨-XArrows— allows arrow notation (yknow,procand friends) 🏹-XBangPatterns— allows bang pattern syntax 💥-XBinaryLiterals— allows binary literal syntax,0bgirlies rise 🌈-XBlockArguments— allowsdoblocks and other constructs as function arguments 🧩-XCApiFFI— allows foreign imports declared with thecapicalling convention 📞-XConstrainedClassMethods— allows class methods to have non-empty contexts 💅-XConstraintKinds— allows constraints to be used as types of kindConstraint🎀-XCPP— resolves C preprocessor directives 🧪-XCUSKs— detects complete user-supplied kind signatures 🔍-XDataKinds— allows use of data constructors in types 🌟-XDatatypeContexts— allows contexts on data types 🫶-XDeepSubsumption— uses GHC's deep subsumption checking 🕳️-XDefaultSignatures— allows default signatures for typeclass methods ✍️-XDeriveAnyClass— allows deriving syntax to be used for any class 💫-XDeriveDataTypeable— allows deriving for theDataclass 🗃️-XDeriveFoldable— allows deriving for theFoldableclass 🧺-XDeriveFunctor— allows deriving for theFunctorclass 🎠-XDeriveGeneric— allows deriving ofGenericinstances 🧬-XDeriveLift— allows deriving for theLiftclass 🎈-XDeriveTraversable— allows deriving for theTraversableclass 🚶♀️-XDerivingStrategies— allows use of instance deriving strategies 🧠-XDerivingVia— allows deriving instances via types of the same runtime representation 🎭-XDisambiguateRecordFields— automatically disambiguates some record field references ✨-XDoAndIfThenElse— allows semicolons inifexpressions 😮-XDuplicateRecordFields— allows definition of record types with identically-named fields 👯♀️-XEmptyCase— allows case expressions with no alternatives 🫥-XEmptyDataDecls— allows definition of empty data types 🕳️-XEmptyDataDeriving— allows deriving instances of standard type classes for empty data types 🎁-XExistentialQuantification— allows existentially quantified type variables in types 🌌-XExplicitForAll— allows explicit universal quantification 📢-XExplicitLevelImports— allows explicit level imports in Template Haskell 🪜-XExplicitNamespaces— allows use of thetypeanddatakeywords to specify the namespace of entries in import/export lists and in other contexts 🏷️-XExtendedDefaultRules— uses GHCi's extended default rules in a normal module 🎮-XExtendedLiterals— allows numeric literal postfix syntax for unboxed integers 🔢-XFieldSelectors— makes record field selector functions visible in expressions 👁️-XFlexibleContexts— removes some restrictions on class contexts 🔓-XFlexibleInstances— allows instance heads to mention arbitrary nested types 🪆-XForeignFunctionInterface— allows foreign function interface syntax 🌍-XFunctionalDependencies— allows functional dependencies to be given on typeclass declarations 🔗-XGADTs— allows definition of generalised algebraic data types 🧠-XGADTSyntax— allows generalised algebraic data type syntax (syntax only, bestie) ✍️-XGeneralisedNewtypeDeriving— allows instances to be derived via newtype deriving 🎀-XGeneralizedNewtypeDeriving— allows instances to be derived via newtype deriving (yes, the z spelling, same energy) 🎀-XGHC2021— uses GHC's set of default language extensions from 2021 🗓️-XGHC2024— uses GHC's set of default language extensions from 2024 🗓️-XGHCForeignImportPrim— allows theprimcalling convention. Intended for internal use only, so like, don't 💀-XHaskell2010— uses the Haskell 2010 language edition 📘-XHaskell98— uses the Haskell 98 language edition 📗-XHexFloatLiterals— allows hexadecimal floating-point literal syntax 🔯-XImplicitParams— allows implicit parameter constraints 🫥-XImplicitPrelude— implicitly importsPrelude🎁-XImplicitStagePersistence— allows identifiers to be used at different levels from where they're defined 🪜-XImportQualifiedPost— allows the syntaximport M qualified💅-XImpredicativeTypes— allows impredicative types 🌀-XIncoherentInstances— allows definitions of instances that may result in incoherence 😵💫-XInstanceSigs— allows type signatures to be written for instance methods ✍️-XInterruptibleFFI— allows interruptible FFI imports 🛑-XKindSignatures— allows kind signatures to be given for types 🏷️-XLambdaCase— allows\caseexpressions 🌙-XLexicalNegation— uses whitespace to decide whether the minus sign means negation or subtraction ➖-XLiberalTypeSynonyms— relaxes a whole bunch of Haskell 98's rules on type synonym definitions 🕊️-XLinearTypes— allows writing of linear arrow types. ImpliesMonoLocalBinds➡️-XListTuplePuns— enables punning for list, tuple and sum types 🍓-XMagicHash— allows#as a postfix modifier on identifiers 🪄-XMonadComprehensions— allows list comprehension syntax to be used at monads other thanList🧚-XMonoLocalBinds— does not generalise types of local bindings 🚫-XMonomorphismRestriction— applies the Haskell 2010 monomorphism restriction 📏-XMultilineStrings— enables multiline string literals 📝-XMultiParamTypeClasses— enables multi-parameter type classes 🎛️-XMultiWayIf— allows multi-wayif-expressions 🔀-XNamedDefaults— enables default declarations with explicitly named class, extendingTypeclass defaulting 🏷️-XNamedFieldPuns— allows record field punning syntax 🐷-XNamedWildCards— allows named wildcards in types 🃏-XNegativeLiterals— allows negative numeric literal syntax ➖-XNondecreasingIndentation— allows nested contexts to be at the same indentation level as its enclosing context 📐-XNPlusKPatterns— allows use of n+k patterns ➕-XNullaryTypeClasses— deprecated, does nothing. Nullary type classes are now enabled usingMultiParamTypeClasses💀-XNumDecimals— allows use of scientific notation syntax for integer literals 🔬-XNumericUnderscores— allows underscores in numeric literals1_000_000🎀-XOrPatterns— enables or-patterns 🔀-XOverlappingInstances— allows definition of overlapping instances 🥞-XOverloadedLabels— allows overloaded label syntax 🏷️-XOverloadedLists— desugars list syntax via theIsListclass 📋-XOverloadedRecordDot— allows.to be used for record field access 🎯-XOverloadedRecordUpdate— allows.syntax in record updates ✏️-XOverloadedStrings— desugars string literals via theIsStringclass 🧵-XPackageImports— allows package-qualified import syntax 📦-XParallelListComp— allows parallel list comprehension syntax 🏃♀️🏃♀️-XPartialTypeSignatures— allows type signatures to contain wildcards 🃏-XPatternGuards— allows pattern guards syntax 🛡️-XPatternSynonyms— lets you define pattern synonyms 🎀-XPolyKinds— kind polymorphism, go off ✨-XPostfixOperators— yes bestie you can use postfix operators 💅-XQualifiedDo— qualified do-notation desugaring is unlocked 🔓-XQuantifiedConstraints—forallquantifiers inside constraints, iconic behavior 👑-XQuasiQuotes— quasiquotation syntax, live laugh love 🧚-XRank2Types— rank-2 types, on 💖-XRankNTypes— types of rank greater than one, we love a high-rank moment 🌈-XRebindableSyntax— rebinding builtin syntax is allowed 🦋-XRecordWildCards— record wildcard syntax, so convenient fr fr ✨-XRecursiveDo— recursive do notation likemdo, main character energy 🔥-XRequiredTypeArguments— required type argument syntax in terms is a go ✨-XRoleAnnotations— role annotation syntax, slay 💅-XSafe— turns on the Safe Haskell Safe mode 🛡️-XScopedTypeVariables— explicitly-introduced type variables get lexically scoped 💜-XStandaloneDeriving— standalone instance deriving declarations, obsessed 😍-XStandaloneKindSignatures— standalone kind signature declarations ✨-XStarIsType— treats*asData.Kind.Type⭐-XStaticPointers— static syntax is allowed 🎀-XStrict— makes bindings in the current module strict by default (yes, by default, no cap) 💀-XStrictData— datatype fields are strict by default 🌸-XTemplateHaskell— Template Haskell's splice and quotation syntax 🔮-XTemplateHaskellQuotes— just the quotation syntax part of Template Haskell ✨-XTraditionalRecordSyntax— traditional record syntax likeC {f = x}🎀-XTransformListComp— generalised list comprehension syntax, ate 💅-XTrustworthy— turns on the Safe Haskell Trustworthy mode 🫶-XTupleSections— tuple section syntax is allowed ✨-XTypeAbstractions— type abstraction syntax in patterns and type variable binders 💜-XTypeApplications— type application syntax in terms and types, iconic 👑-XTypeData— type data declarations 🔥-XTypeFamilies— define type families 🌈-XTypeFamilyDependencies— injectivity annotations on type families ✨-XTypeInType— deprecated 😭 enables kind polymorphism and datatype promotion-XTypeOperators— type constructors can be given operator names 💅-XTypeSynonymInstances— type synonyms can be mentioned in instance heads 🎀-XUnboxedSums— unboxed sum syntax, we go 🦋-XUnboxedTuples— unboxed tuple syntax, yes ma'am ✨-XUndecidableInstances— lets you define instances that may make solving undecidable, careful bestie 💀-XUndecidableSuperClasses— allows all superclass constraints, including ones that may make the typechecker not terminate 😭 literally what it says-XUnicodeSyntax— unicode syntax on 💖-XUnliftedDatatypes— definitions of unlifted data types 🌸-XUnliftedFFITypes— foreign imports can have certain unlifted types ✨-XUnliftedNewtypes— unlifted newtype definitions 🔥-XUnsafe— turns on the Safe Haskell Unsafe mode 🙈-XViewPatterns— view pattern syntax, go off 👑
🌟 Linking options 🌟
-c— stop after generating the object (.o) file, that's it, we're done here ✋-debug— use the debugging runtime 🐛-dylib-install-name⟨path⟩ — sets the install name (it gets passed to Apple's linker as-install_name) and specifies the full install path of the library file. Any libraries or executables that link with it later will pick up that path as their runtime search location for it. (Darwin/OS X only) 🍎-dynamic— build dynamically-linked object files and executables ✨-dynload— picks one of a number of modes for finding shared libraries at runtime 🔍-eventlog— enable runtime event tracing 📝-fcompact-unwind— tells the linker to produce a__compact_unwindsection 🌀-fkeep-cafs— do not garbage-collect CAFs (top-level expressions) at runtime 🗑️-flink-rts— link the runtime when generating a shared or static library 🔗-fno-embed-manifest— do not embed the manifest in the executable (Windows only) 🪟-fno-gen-manifest— do not generate a manifest file (Windows only) 🪟-fno-shared-implib— don't generate an import library for a DLL (Windows only) 🪟-framework⟨name⟩ — on Darwin/OS X/iOS only, link in the framework ⟨name⟩. This option corresponds to the-frameworkoption for Apple's Linker 🍎-framework-path⟨dir⟩ — on Darwin/OS X/iOS only, add ⟨dir⟩ to the list of directories searched for frameworks. This option corresponds to the-Foption for Apple's Linker 🍎-fsplit-sections— split sections for link-time dead-code stripping ✂️-fuse-rpaths— set the rpath based on-Lflags 🛤️-fwhole-archive-hs-libs— when linking a binary executable, this inserts the flag-Wl,--whole-archivebefore any-lflags for Haskell libraries, and-Wl,--no-whole-archiveafterwards 📦-L⟨dir⟩ — add ⟨dir⟩ to the list of directories searched for libraries 📚-l⟨lib⟩ — link in library ⟨lib⟩ 🔗-main-is⟨thing⟩ — set the main module and function 🎯-no-hs-main— don't assume this program containsmain🙅-no-pie— don't instruct the linker to produce a position-independent executable 🚫-no-rtsopts-suggestions— don't print RTS suggestions about linking with-rtsopts[=⟨none|some|all|ignore|ignoreAll⟩]🤫-package⟨name⟩ — expose package ⟨pkg⟩ 📦-pie— instruct the linker to produce a position-independent executable ✅-rdynamic— tells the linker to add all symbols, not only the used ones, to the dynamic symbol table. Currently Linux and Windows/MinGW32 only. This is equivalent to using-optl -rdynamicon Linux, and-optl -export-all-symbolson Windows 💅-rtsopts[=⟨none|some|all|ignore|ignoreAll⟩]— controls whether the RTS behaviour can be tweaked via command-line flags and theGHCRTSenvironment variable. Here's the tea 🍵:nonemeans no RTS flags can be givensomemeans only a minimum of safe options can be given (this is the default, if-rtsoptsis not passed)allmeans all RTS flags are permitted (the default, if-rtsoptsis passed with no argument)ignoremeans RTS flags can be given, but they're treated as regular arguments and passed to the Haskell program as argumentsignoreAllis the same asignore, butGHCRTSis also ignored- ⚠️
-rtsoptsdoes not affect-with-rtsoptsbehavior; flags passed via-with-rtsoptsare used regardless of-rtsopts
-shared— generate a shared library (as opposed to an executable) 📚-single-threaded— use the single-threaded runtime 🧵-static— use static Haskell libraries 🗿-staticlib— generate a standalone static library (as opposed to an executable). Super useful when cross compiling 💪 The library together with all its dependencies ends up in a single static library that can be linked against.-threaded— use the threaded runtime 🧵✨-with-rtsopts=⟨opts⟩ — set the default RTS options to ⟨opts⟩ 🎛️
🧩 Miscellaneous options 🧩
-ddump-mod-cycles— dump module cycles 🔄-fdefer-out-of-scope-variables— converts out-of-scope variable errors into warnings. Implied by-fdefer-type-errors. See also-Wdeferred-out-of-scope-variables🩹-fdefer-type-errors— turns type errors into warnings, deferring the error until runtime 😳 implies-fdefer-typed-holesand-fdefer-out-of-scope-variables. See also-Wdeferred-type-errors.-fdefer-typed-holes— converts typed hole errors into warnings, deferring the error until runtime 🕳️ implied by-fdefer-type-errors. See also-Wtyped-holes.-fexternal-interpreter— run interpreted code in a separate process 🧚-ffamily-application-cache— use a cache when reducing type family applications 🗄️-fghci-browser— enable wasm ghci browser mode 🌐-fghci-browser-host— wasm ghci browser mode host address 🖥️-fghci-browser-playwright-browser-type— Playwright browser type 🎭-fghci-browser-playwright-launch-opts— Playwrightbrowser.launch()options 🎭-fghci-browser-port— wasm ghci browser mode host port 🔌-fghci-browser-puppeteer-launch-opts—puppeteer.launch()options 🎪-fghci-browser-redirect-wasi-console— redirect wasi console stdout/stderr back to host ghci 📺-fglasgow-exts— deprecated 😭 enables most language extensions; see Controlling editions and extensions for exactly which ones-fno-safe-haskell— disable Safe Haskell 🚫🛡️-fwrite-if-self-recomp— write information for self-recompilation checking in an interface file 📝-fwrite-if-self-recomp-flags— include detailed flag information for self-recompilation checking 🏴-ghcversion-file⟨path to ghcversion.h⟩ — (GHC as a C compiler only) use thisghcversion.hfile 📄-H⟨size⟩ — set the minimum size of the heap to ⟨size⟩ 🧠-hidden-module⟨module name⟩ — a module which should not be visible outside its unit 🙈-j[⟨n⟩]— when compiling with--make, compile ⟨n⟩ modules in parallel ⚡-jsem— when compiling with--make, coordinate with other processes through the semaphore ⟨sem⟩ to compile modules in parallel 🤝-reexported-module⟨reexport-spec⟩ — a module which should be reexported from this unit 📤-this-package-name⟨unit-id⟩ — the name of the package which this module would be part of when installed 🏷️-unit @⟨filename⟩ — specify the options to build a specific unit 🧱-working-dir⟨dir⟩ — specify the directory a unit is expected to be compiled in 📁
🚀 Modes of operation 🚀
--frontend⟨module⟩ — run GHC with the given frontend plugin; see Frontend plugins for the deets 🔌--help— display help 🆘--info— display information about the compiler ℹ️--interactive— interactive mode, normally used by just runningghci; see Using GHCi for details 💬
okay bestie we are STILL deep in flag city 💖 hydrate, stretch, and let's finish this list together, you're doing amazing.
--make— builds a whole multi-module Haskell program and figures out the dependencies for you, automatically. Lowkey it's way easier and faster than wrestling withmake; peep the "Usingghc --make" section for the full story. 🫶
🌸 the little --print-* info-dump era 🌸
okay so GHC will happily just tell you things about itself if you ask nicely. it's giving "ask and you shall receive" energy 👑
--numeric-version— prints the GHC version, digits only, no vibes, no words. just numbers ✨--print-booter-version— tells you the version of the bootstrap compiler.--print-build-platform— shows the platform GHC was built on.--print-c-compiler-flags— the C compiler flags that were used to build GHC, exposed for your viewing pleasure.--print-c-compiler-link-flags— same deal but the C linker flags used to build GHC 🔗--print-debug-on— prints whether GHC was built with-DDEBUG.--print-global-package-db— displays the directory of GHC's global package database. yes, the whole shelf 📚--print-have-interpreter— tells you whether GHC was built with interactive support.--print-have-native-code-generator— whether the target platform has NCG support, yes or no 💅--print-host-platform— shows the host platform of GHC (different from build/target, iykyk).--print-ld-flags— displays the linker flags used to compile GHC.--print-leading-underscore— tells you about the use of leading underscores on symbol names.--print-libdir— displays the GHC library directory. your home away from home 🏠--print-object-splitting-supported— whether GHC supports object splitting, sliced and diced ✂️--print-project-git-commit-id— the Git commit id that GHC was built from. receipts, literally 🧾--print-project-version— displays the GHC version.--print-rts-ways— shows which way the RTS was built.--print-stage— displays the stage number of GHC.--print-support-smp— whether GHC was compiled with SMP support 🧵--print-tables-next-to-code— whether GHC was compiled with--enable-tables-next-to-code.--print-target-platform— displays the target platform of GHC 🎯--print-unregisterised— whether this GHC was built in unregisterised mode.--run ⟨file⟩— runs a Haskell program. that's it, that's the whole flag 🏃♀️--show-iface ⟨file⟩— displays the contents of an interface file. peek behind the curtain 🎭--show-options— displays the supported command line options. a menu of menus, iconic.--supported-extensions— displays the supported language extensions.--version— displays GHC version. the classic.-e ⟨expr⟩— evaluates expr; check the "Expression evaluation mode" section for the deets 🧮-M— generates dependency information suitable for use in aMakefile; the "Dependency generation" section has the full tea ☕-shared— creates a shared object.
🎀 Individual optimizations 🎀
this is the "let me cook" corner of the manpage. every one of these is a knob you can turn, and most of them are already on if you just use -O or -O2, so don't stress 💅
-fasm-shortcutting— enables shortcutting on assembly. implied by-O2.-fbinary-blob-threshold=⟨n⟩— default:500K. tweaks the assembly generator for binary blobs.-fblock-layout-cfg— uses the new cfg-based block layout algorithm. implied by-O.-fblock-layout-weightless— ignores cfg weights for code layout.-fblock-layout-weights— sets the edge weights used by the new code layout algorithm.-fcall-arity— enables call-arity optimisation. implied by-O.-fcase-folding— enables constant folding in case expressions. implied by-O.-fcase-merge— enables case-merging. implied by-O.-fcmm-control-flow— enables control flow optimisation in the Cmm backend. implied by-O.-fcmm-elim-common-blocks— enables Cmm common block elimination. implied by-O.-fcmm-sink— enables Cmm sinking. implied by-O.-fcmm-static-pred— enables static control flow prediction. implied by-O.-fcore-constant-folding— enables constant folding in Core. implied by-O.-fcpr-anal— turns on Constructed Product Result analysis. implied by-O.-fcross-module-specialise— turns on specialisation of overloaded functions imported from other modules. implied by-O.-fcse— enables common sub-expression elimination. implied by-O.-fdicts-cheap— makes dictionary-valued expressions seem cheap to the optimiser (we're manifesting it for them).-fdicts-strict— makes dictionaries strict. implied by-O2.-fdmd-tx-dict-sel— (deprecated) uses a special demand transformer for dictionary selectors.-fdmd-unbox-width=⟨n⟩— default:3. boxity analysis pretends that returned records with this many fields can be unboxed.-fdo-clever-arg-eta-expansion— enables sophisticated argument eta-expansion. implied by-O2.-fdo-eta-reduction— enables eta-reduction. always enabled by default.-fdo-lambda-eta-expansion— enables lambda eta-expansion. always enabled by default.-feager-blackholing— turns on eager blackholing 🕳️-fenable-rewrite-rules— switches on all rewrite rules (including the ones generated by automatic specialisation of overloaded functions). implied by-O.-fexcess-precision— enables excess intermediate precision.-fexitification— enables the exitification optimisation. implied by-O.-fexpose-all-unfoldings— exposes all unfoldings, even for very large or recursive functions. no secrets, no gatekeeping.-fexpose-overloaded-unfoldings— exposes function unfoldings whose type contains constraints, even for very large or recursive functions.-ffloat-in— turns on the float-in transformation. implied by-O.-ffull-laziness— turns on full laziness (floating bindings outwards). implied by-O.-ffun-to-thunk— (deprecated) superseded by-ffull-laziness.-fignore-asserts— ignores assertions in the source. implied by-O.-fignore-interface-pragmas— ignores pragmas in interface files. implied by-O0only.-finline-generics— annotates methods of derivedGenericandGeneric1instances withINLINE[1]pragmas based on heuristics. implied by-O.-finline-generics-aggressively— annotates methods of all derivedGenericandGeneric1instances withINLINE[1]pragmas. no crumbs left, she went aggressive 💀-finter-module-far-jumps— assumes code sections can be very large.-fkeep-auto-rules— keeps all "auto" rules, generated by specialisation.-flate-dmd-anal— runs demand analysis again, at the end of the simplification pipeline.-flate-specialise— runs a late specialisation pass. fashionably late ✨-fliberate-case— turns on the liberate-case transformation. implied by-O2.-fliberate-case-threshold=⟨n⟩— default:2000. sets the size threshold for the liberate-case transformation to ⟨n⟩.-fllvm-pass-vectors-in-regs— (deprecated) does nothing. literally nothing. a ghost 👻-flocal-float-out— enables local floating definitions out of let-binds.-flocal-float-out-top-level— enables local floating to float top-level bindings.-floopification— turns saturated self-recursive tail-calls into local jumps in the generated assembly. implied by-O.-fmax-forced-spec-args=⟨n⟩— default:333. maximum number of value arguments for forced SpecConstr specializations.-fmax-inline-alloc-size=⟨n⟩— default:128. sets the maximum size of inline array allocations to ⟨n⟩ bytes (default:128).-fmax-inline-memcpy-insns=⟨n⟩— default:32. inlinesmemcpycalls if they would generate no more than ⟨n⟩ pseudo instructions.-fmax-inline-memset-insns=⟨n⟩— default:32. inlinesmemsetcalls if they would generate no more than ⟨n⟩ pseudo instructions.-fmax-simplifier-iterations=⟨n⟩— default:4. sets the max iterations for the simplifier.-fmax-uncovered-patterns=⟨n⟩— default:4. sets the maximum number of patterns to display in warnings about non-exhaustive ones.-fmax-worker-args=⟨n⟩— default:10. maximum number of value arguments for a worker.-fno-opt-coercion— turns off the coercion optimiser.-fno-pre-inlining— turns off pre-inlining.-fno-state-hack— turns off the state hack whereby any lambda with a real-world state token as argument is considered to be single-entry. hence it's OK to inline things inside it.-fnum-constant-folding— enables constant folding on nested numerical expressions. implied by-O.-fobject-determinism— produces fully deterministic object code. consistent queen 👑-fomit-interface-pragmas— doesn't generate interface pragmas. implied by-O0only.-fomit-yields— omits heap checks when no allocation is being performed.-foptimal-applicative-do— uses a slower but better algorithm forApplicativeDo. slower but better, the story of my life 😭-fpedantic-bottoms— makes GHC be more precise about its treatment of bottom (but see also-fno-state-hack). in particular, GHC will not eta-expand through a case expression.-fpolymorphic-specialisation— allows specialisation to abstract over free type variables.-fregs-graph— uses the graph colouring register allocator for register allocation in the native code generator 🎨-fregs-iterative— uses the iterative coalescing graph colouring register allocator in the native code generator.-fsimpl-tick-factor=⟨n⟩— default:100. sets the percentage factor for simplifier ticks.-fsimplifier-phases=⟨n⟩— default:2. sets the number of phases for the simplifier. ignored with-O0.-fsolve-constant-dicts— when solving constraints, tries to eagerly solve super classes using available dictionaries. implied by-O.-fspec-constr— turns on the SpecConstr transformation. implied by-O2.-fspec-constr-count=⟨n⟩— default:3.*. sets to ⟨n⟩ the maximum number of specialisations that will be created for any one function by the SpecConstr transformation.-fspec-constr-keen— specializes a call with an explicit constructor argument, even if the argument is not scrutinised in the body of the function.-fspec-constr-threshold=⟨n⟩— default:2000. sets the size threshold for the SpecConstr transformation to ⟨n⟩.-fspec-eval— enables speculative evaluation 🔮-fspec-eval-dictfun— enables speculative evaluation of dictionary functions.-fspecialise— turns on specialisation of overloaded functions. implied by-O.-fspecialise-aggressively— turns on specialisation of overloaded functions regardless of size, if an unfolding is available.-fspecialise-incoherents— enables specialisation on incoherent instances.-fstatic-argument-transformation— turns on the static argument transformation.-fstg-cse— enables common sub-expression elimination on the STG intermediate language. implied by-O.
still going bestie, don't close the tab 💖
-fstg-lift-lams— turns on late lambda lifting on the STG intermediate language. Implied by-O2. slay 💅-fstg-lift-lams-known— lets you turn known calls into unknown calls while you're doing that late lambda lifting. feral behavior but ok ✨-fstg-lift-lams-non-rec-args— creates top-level non-recursive functions with at most<n>parameters while doing late lambda lifting 🎀-fstg-lift-lams-rec-args— same vibe but recursive top-level functions, at most<n>parameters, during late lambda lifting 💖-fstrictness— turn on demand analysis. Implied by-O. Implies-fworker-wrapper. it's giving package deal 🫶-fstrictness-before=⟨n⟩ — runs an additional demand analysis before simplifier phase ⟨n⟩ 👑-funbox-small-strict-fields— flattens strict constructor fields that have a pointer-sized representation. Implied by-O. 💐-funbox-strict-fields— flattens strict constructor fields, periodt-funfolding-case-scaling=⟨n⟩ — default:30. Applies a penalty of(inlining_cost * 1/n)for each level of case nesting 😭-funfolding-case-threshold=⟨n⟩ — default:2. Reduces inlining for cases nested deeper thann.-funfolding-creation-threshold=⟨n⟩ — default:750. tweaks the unfolding settings ✨-funfolding-dict-discount=⟨n⟩ — default:30. also tweaks unfolding settings 🎀-funfolding-fun-discount=⟨n⟩ — default:60. yes bestie, unfolding settings again 💅-funfolding-keeness-factor=⟨n⟩ — okay so this one has been deprecated in GHC 9.0.1. (that spelling is the flag's spelling, don't come for me 🫶)-funfolding-use-threshold=⟨n⟩ — default:90. tweak those unfolding settings one more time for the road 💀-fworker-wrapper— enables the worker/wrapper transformation. Implied by-Oand by-fstrictness🔥-fworker-wrapper-cbv— enables w/w splits for wrappers whose sole purpose is evaluating arguments 👑-fwrite-if-compression=⟨n⟩ — default:2. tweaks the level of interface file compression 🦋
🚀 Optimization levels 🚀
-O— enable level 1 optimisations ✨-O0— disable optimisations (this is the default btw)-O2— enable level 2 optimisations 🔥-O⟨n⟩ — literally any-Onwheren > 2is the same as-O2. no cap 💅
📦 Package options 📦
-base-unit-id⟨unit-id⟩ — the unit-id of the"base"package, which gets automatically linked 🫶-clear-package-db— clears the package db stack 🧹-distrust⟨pkg⟩ — exposes package ⟨pkg⟩ and sets it to be distrusted. see Safe Haskell 💀-distrust-all-packages— distrusts all packages by default. see Safe Haskell 🙈-fpackage-trust— enables the Safe Haskell trusted package requirement for trustworthy modules 👑-global-package-db— adds the global package db to the stack ⭐-hide-all-packages— hides all packages by default 🌸-hide-package⟨pkg⟩ — hides package ⟨pkg⟩-ignore-package⟨pkg⟩ — ignores package ⟨pkg⟩ 💅-no-auto-link-packages— don't automatically link in thebaseandrtspackages 🎀-no-global-package-db— removes the global package db from the stack-no-user-package-db— removes the user's package db from the stack 🌈-package⟨pkg⟩ — exposes package ⟨pkg⟩ ✨-package-db⟨file⟩ — adds ⟨file⟩ to the package db stack 🦋-package-env⟨file⟩|⟨name⟩ — uses the specified package environment 💖-package-id⟨unit-id⟩ — exposes a package by id ⟨unit-id⟩ 👑-this-unit-id⟨unit-id⟩ — compile to be part of unit (i.e. package) ⟨unit-id⟩ 🫶-trust⟨pkg⟩ — exposes package ⟨pkg⟩ and sets it to be trusted. see Safe Haskell ⭐-user-package-db— adds the user's package db to the stack 🌸
🛠️ Phases of compilation 🛠️
--merge-objs— merges a set of objects into a GHCi library 🧚-C— stop after generating C (.hcfile) 🎀-c— stop after generating object (.o) file 💅-E— stop after preprocessing (.hsppfile) ✨-F— enable the use of a pre-processor (set with-pgmF⟨cmd⟩) 🦋-S— stop after generating assembly (.sfile) ⭐-x⟨suffix⟩ — overrides the default behaviour for source files 👑
🧰 Overriding external programs 🧰
okay so this whole section is "bestie, use this command instead of the default one" — extremely customizable, we love to see it 💅
-pgma⟨cmd⟩ — use ⟨cmd⟩ as the assembler 🎀-pgmc⟨cmd⟩ — use ⟨cmd⟩ as the C compiler-pgmCmmP⟨cmd⟩ — use ⟨cmd⟩ as the C-- C pre-processor ✨-pgmcxx⟨cmd⟩ — use ⟨cmd⟩ as the C++ compiler-pgmF⟨cmd⟩ — use ⟨cmd⟩ as the pre-processor (with-Fonly) 🦋-pgmi⟨cmd⟩ — use ⟨cmd⟩ as the external interpreter command 🌸-pgminstall_name_tool⟨cmd⟩ — use ⟨cmd⟩ as the program to inject runpath into mach-o dylibs on macOS 🍓-pgmJSP⟨cmd⟩ — use ⟨cmd⟩ as the JavaScript C pre-processor (only forjavascript-backend) 💜-pgmL⟨cmd⟩ — use ⟨cmd⟩ as the literate pre-processor 📚-pgml⟨cmd⟩ — use ⟨cmd⟩ as the linker 🔗-pgmlas⟨cmd⟩ — use ⟨cmd⟩ as the LLVM assembler-pgmlc⟨cmd⟩ — use ⟨cmd⟩ as the LLVM compiler-pgmlm⟨cmd⟩ — use ⟨cmd⟩ as the linker when merging object files-pgmlo⟨cmd⟩ — use ⟨cmd⟩ as the LLVM optimiser ✨-pgmotool⟨cmd⟩ — use ⟨cmd⟩ as the program to inspect mach-o dylibs on macOS 🍓-pgmP⟨cmd⟩ — use ⟨cmd⟩ as the Haskell C pre-processor (with-cpponly) 🎀-pgms⟨cmd⟩ — use ⟨cmd⟩ as the splitter ✂️-pgmwindres⟨cmd⟩ — use ⟨cmd⟩ as the program for embedding manifests on Windows 🪟
🎯 Phase-specific options 🎯
these are the "pass this straight through to that tool" girlies 🫶
-opta⟨option⟩ — pass ⟨option⟩ to the assembler 🎀-optc⟨option⟩ — pass ⟨option⟩ to the C compiler-optCmmP⟨option⟩ — pass ⟨option⟩ to the C-- C pre-processor ✨-optcxx⟨option⟩ — pass ⟨option⟩ to the C++ compiler-optF⟨option⟩ — pass ⟨option⟩ to the custom pre-processor 🦋-opti⟨option⟩ — pass ⟨option⟩ to the interpreter sub-process 💜-optJSP⟨option⟩ — pass ⟨option⟩ to the JavaScript C pre-processor (only forjavascript-backend) 🍓-optL⟨option⟩ — pass ⟨option⟩ to the literate pre-processor 📚-optl⟨option⟩ — pass ⟨option⟩ to the linker 🔗-optlas⟨option⟩ — pass ⟨option⟩ to the LLVM assembler-optlc⟨option⟩ — pass ⟨option⟩ to the LLVM compiler-optlm⟨option⟩ — pass ⟨option⟩ to the linker when merging object files ✨-optlo⟨option⟩ — pass ⟨option⟩ to the LLVM optimiser-optP⟨option⟩ — pass ⟨option⟩ tocpp(with-cpponly) 🎀-optwindres⟨option⟩ — pass ⟨option⟩ towindres🪟-pgmc-supports-no-pie— (deprecated) indicates that the linker supports-no-pie💀-pgml-supports-no-pie— indicates that the linker supports-no-pie👑
💻 Platform-specific options 💻
x86 girlies, this one's for you 🫶
-mavx— (x86 only) enable support for AVX SIMD extensions ✨-mavx2— (x86 only) enable support for AVX2 SIMD extensions 🔥-mavx512cd— (x86 only) enable support for AVX512-CD SIMD extensions-mavx512er— (x86 only) enable support for AVX512-ER SIMD extensions-mavx512f— (x86 only) enable support for AVX512-F SIMD extensions-mavx512pf— (x86 only) enable support for AVX512-PF SIMD extensions-mbmi— (x86 only) use BMI1 for bit manipulation operations 🎀-mbmi2— (x86 only) use BMI2 for bit manipulation operations 💅-mfma— use native FMA instructions for fused multiply-add floating-point operations ✨-msse— (x86 only) use SSE for floating-point operations 🌸-msse2— (x86 only) use SSE2 for floating-point operations-msse3— (x86 only) use SSE3 for floating-point operations-msse4— (x86 only) use SSE4 for floating-point operations-msse4.2— (x86 only) use SSE4.2 for floating-point operations ⭐-mssse3— (x86 only) use SSSE3 for vector operations 🦋
🔌 Compiler plugins 🔌
-fclear-plugins— clears the list of active plugins 🧹-fplugin-library=⟨file-path⟩;⟨unit-id⟩;⟨module⟩;⟨args⟩* — loads a pre-compiled static plugin from an external library 📦-fplugin-opt=⟨module⟩:⟨args⟩* — gives arguments to a plugin module; the module has to be specified with-fplugin=⟨module⟩ 🎀-fplugin-trustworthy— trusts the used plugins and stops marking the compiled module as unsafe 👑-fplugin=⟨module⟩* — loads a plugin exported by a given module ✨-hide-all-plugin-packages— hides all packages for plugins by default 🙈-plugin-package⟨pkg⟩ — exposes ⟨pkg⟩ for plugins 💜-plugin-package-id⟨pkg-id⟩ — exposes ⟨pkg-id⟩ for plugins 🦋
📊 Profiling 📊
-auto— (deprecated) alias for-fprof-auto-exported💀-auto-all— (deprecated) alias for-fprof-auto💀-caf-all— (deprecated) alias for-fprof-cafs💀-fno-prof-count-entries— does not collect entry counts 🙈-fprof-auto— auto-addsSCCs to all bindings not markedINLINE✨-fprof-auto-calls— auto-addsSCCs to all call sites 🎀-fprof-auto-exported— auto-addsSCCs to all exported bindings not markedINLINE👑-fprof-auto-top— auto-addsSCCs to all top-level bindings not markedINLINE⭐-fprof-cafs— auto-addsSCCs to all CAFs 🌸-fprof-callers=⟨name⟩* — auto-addsSCCs to all call-sites of the named function 🔍-fprof-late— auto-addsSCCs to all top level bindings after the core pipeline has run 🦋-fprof-late-inline— auto-addsSCCs to all top level bindings after the optimizer has run, and keeps them when inlining 💅-fprof-late-overloaded— auto-addsSCCs to all top level overloaded bindings after the core pipeline has run 🎀-fprof-late-overloaded-calls— auto-addsSCCs to all call sites that include dictionary arguments after the core pipeline has run 📚-fprof-manual— processes manualSCCannotations ✍️-no-auto— (deprecated) alias for-fno-prof-auto💀-no-auto-all— (deprecated) alias for-fno-prof-auto💀-no-caf-all— (deprecated) alias for-fno-prof-cafs💀-prof— turn on profiling 📈-ticky— turn on ticky-ticky profiling 🎰-ticky-allocd— tracks the number of times each closure type is allocated 🎀-ticky-ap-thunk— doesn't use standard AP thunks, in order to get more reliable entry counters 👑-ticky-dyn-thunk— tracks allocations of dynamic thunks 💜-ticky-LNE— treats join point binders similar to thunks/functions 🦋-ticky-tag-checks— bestie, this one emits dummy ticky counters to record how many tag-inference checks tag inference avoided. yes, that sentence is a whole mood, but those are the exact facts 💅
🌸 Program coverage 🌸
okay so this is the coverage-instrumentation corner of the flag list, and it’s giving “did we actually run that?” energy.
-fhpc— turn on Haskell program coverage instrumentation. slay, instrumentation is on ✨-hpcdir⟨dir⟩— set the directory where GHC places.mixfiles. very “put your mix files here” energy 🎀
🧚 Recompilation checking 🧚
this is the “do I really have to rebuild that?” zone, and GHC has opinions.
-exclude-module=⟨file⟩— regard ⟨file⟩ as “stable”; i.e., exclude it from having dependencies on it. lowkey the “don’t bug me about this one” flag 💅-fforce-recomp— turn off recompilation checking. this is implied by any-ddump-Xoption when compiling a single file (i.e. when using-c). no cap, it’s the “rebuild it anyway” button 🔥-fignore-hpc-changes— do not recompile modules just to match changes to HPC flags. this is especially useful for avoiding recompilation when using GHCi, and it’s enabled by default for GHCi. GHCi said “not today” 🫶-fignore-optim-changes— do not recompile modules just to match changes to optimisation flags. this is especially useful for avoiding recompilation when using GHCi, and it’s enabled by default for GHCi. same vibe, different flag ✨-include-cpp-deps— include preprocessor dependencies. okay, dependency lore 🎀-include-pkg-deps— regard modules imported from packages as unstable. so package imports get the “unstable” label 👀
🎀 Redirecting output 🎀
the “where do my files go?” department, and honestly? iconic.
-dep-makefile ⟨file⟩— use ⟨file⟩ as the makefile. very “make it make” of you 💅-dep-suffix ⟨suffix⟩— make dependencies that declare that files with suffix.⟨suf⟩⟨osuf⟩depend on interface files with suffix.⟨suf⟩hi. this one is all about suffixes, iykyk 🦋-dumpdir ⟨dir⟩— redirect dump files. dump files have a new home now 🎀-dynhisuf ⟨suffix⟩— set the suffix to use for dynamic interface files.-dyno ⟨file⟩— set dynamic output filename.-dynohi ⟨file⟩— set the filename in which to put the dynamic interface.-dynosuf ⟨suffix⟩— set the dynamic output file suffix.-hcsuf ⟨suffix⟩— set the suffix to use for intermediate C files.-hidir ⟨dir⟩— set directory for interface files.-hiedir ⟨dir⟩— set directory for extended interface files.-hiesuf ⟨suffix⟩— set the suffix to use for extended interface files.-hisuf ⟨suffix⟩— set the suffix to use for interface files.-o ⟨file⟩— set output filename.-odir ⟨dir⟩— set directory for object files.-ohi ⟨file⟩— set the filename in which to put the interface.-osuf ⟨suffix⟩— set the output file suffix.-outputdir ⟨dir⟩— set output directory.-stubdir ⟨dir⟩— redirect FFI stub files.
🦋 Temporary files 🦋
temporary files, permanent attitude 💅
-tmpdir ⟨dir⟩— set the directory for temporary files. tiny files, big directory energy 🎀
💜 Verbosity options 💜
aka how much GHC wants to yap at you, and honestly the way that this list goes on is so real.
-fabstract-refinement-hole-fits— default: off. toggles whether refinements where one or more of the holes are abstract are reported. abstract holes, concrete drama 🫶-fdefer-diagnostics— defer and group diagnostic messages by severity. organize the chaos ✨-fdiagnostics-as-json— output diagnostics inJsonformat specified by JSON schema. json girlies rise 🌈-fdiagnostics-color=⟨always|auto|never⟩— use colors in error messages. pick your color vibe: always, auto, or never 🎀-fdiagnostics-show-caret— whether to show snippets of original source code. caret? more like care 😭-ferror-spans— output full span in error messages. full span, full drama 🔥-fhide-source-paths— hide module source and object paths. incognito mode for paths 🙈-fkeep-going— continue compilation as far as possible on errors. never give up, never surrender 🔥-fmax-refinement-hole-fits=⟨n⟩— default: 6. set the maximum number of refinement hole fits for typed holes to display in type error messages. six is the default, bestie 🍓-fmax-relevant-binds=⟨n⟩— default: 6. set the maximum number of bindings to display in type error messages.-fmax-valid-hole-fits=⟨n⟩— default: 6. set the maximum number of valid hole fits for typed holes to display in type error messages.-fno-show-valid-hole-fits— disables showing a list of valid hole fits for typed holes in type error messages.-fno-sort-valid-hole-fits— disables the sorting of the list of valid hole fits for typed holes in type error messages.-fprint-axiom-incomps— display equation incompatibilities in closed type families.-fprint-equality-relations— distinguish between equality relations when printing.-fprint-error-index-links=⟨always|auto|never⟩— whether to emit diagnostic codes as ANSI hyperlinks to the Haskell Error Index.-fprint-expanded-synonyms— in type errors, also print type-synonym-expanded types.-fprint-explicit-coercions— print coercions in types.-fprint-explicit-foralls— print explicit forall quantification in types. see alsoExplicitForAll.-fprint-explicit-kinds— print explicit kind foralls and kind arguments in types. see alsoKindSignatures.-fprint-explicit-runtime-reps— printRuntimeRepandLevityvariables in types which are runtime-representation polymorphic.-fprint-potential-instances— display all available instances in type error messages.-fprint-redundant-promotion-ticks— print redundantDataKindspromotion ticks.-fprint-typechecker-elaboration— print extra information from typechecker.-fprint-unicode-syntax— use unicode syntax when printing expressions, types and kinds. see alsoUnicodeSyntax.-frefinement-level-hole-fits=⟨n⟩— default: off. sets the level of refinement of the refinement hole fits, where level n means that hole fits of up to n holes will be considered.-freverse-errors— output errors in reverse order. plot twist energy 😭-fshow-docs-of-hole-fits— toggles whether to show the documentation of the valid hole fits in the output.-fshow-error-context— whether to show textual information about error context.-fshow-hole-constraints— show constraints when reporting typed holes.-fshow-hole-matches-of-hole-fits— toggles whether to show the type of the additional holes in refinement hole fits.-fshow-provenance-of-hole-fits— toggles whether to show the provenance of the valid hole fits in the output.-fshow-type-app-of-hole-fits— toggles whether to show the type application of the valid hole fits in the output.-fshow-type-app-vars-of-hole-fits— toggles whether to show what type each quantified variable takes in a valid hole fit.-fshow-type-of-hole-fits— toggles whether to show the type of the valid hole fits in the output.-fsort-by-size-hole-fits— sort valid hole fits by size.-fsort-by-subsumption-hole-fits— sort valid hole fits by subsumption.-funclutter-valid-hole-fits— unclutter the list of valid hole fits by not showing provenance nor type applications of suggestions.-Rghc-timing— summarise timing stats for GHC (same as+RTS -tstderr).-v— verbose mode (equivalent to-v3).-v⟨n⟩— set verbosity level.
🔥 Warnings 🔥
the “hey bestie, heads up” section. warning flags go brrr.
-fenable-th-splice-warnings— generate warnings for Template Haskell splices.-fhelpful-errors— make suggestions for mis-spelled names. it’s giving helpful 💅-fmax-pmcheck-models=⟨n⟩— soft limit on the number of parallel models the pattern match checker should check a pattern match clause against.-fshow-warning-groups— show which group an emitted warning belongs to.-fvia-C— use the C code generator.-W— enable normal warnings.-w— disable all warnings. silence, but make it fashion 🎀-Wall— enable almost all warnings (details in Warnings and sanity-checking).-Wall-missed-specialisations— warn when specialisation of any overloaded function fails.-Wall-missed-specializations— alias for-Wall-missed-specialisations.-Wambiguous-fields— warn about ambiguous field selectors or updates.-Wauto-orphans— (deprecated) Does nothing.-Wbadly-levelled-types— warn when type binding is used at the wrong Template Haskell level.-Wbadly-staged-types— A deprecated alias for-Wbadly-levelled-types.-Wcompat— enable future compatibility warnings (details in Warnings and sanity-checking).-Wcompat-unqualified-imports— (deprecated) Report unqualified imports of core libraries which are expected to cause compatibility problems in future releases.-Wcpp-undef— warn on uses of the#ifdirective on undefined identifiers.-Wdata-kinds-tc— (deprecated) Does nothing.-Wdefault— enable default flags.-Wdefaulted-exception-context— warn when anControl.Exception.Context.ExceptionContextimplicit parameter is defaulted toControl.Exception.Context.emptyExceptionContext.-Wdeferred-out-of-scope-variables— report warnings when variable out-of-scope errors are deferred until runtime. see-fdefer-out-of-scope-variables.-Wdeferred-type-errors— report warnings when deferred type errors are enabled. This option is enabled by default. see-fdefer-type-errors.-Wdeprecated-flags— warn about uses of commandline flags that are deprecated.-Wdeprecated-pragmas— warn about deprecated pragmas.-Wdeprecations— warn about uses of functions & types that haveDEPRECATEDpragmas, orWARNINGpragmas with the deprecated category.-Wderiving-defaults— warn about default deriving when using bothDeriveAnyClassandGeneralizedNewtypeDeriving.-Wderiving-typeable— warn whenTypeableis derived.-Wdodgy-exports— warn about dodgy exports.-Wdodgy-foreign-imports— warn about dodgy foreign imports.-Wdodgy-imports— warn about dodgy imports.-Wduplicate-constraints— warn when a constraint appears duplicated in a type signature.-Wduplicate-exports— warn when an entity is exported multiple times.-Wempty-enumerations— warn about enumerations that are empty.-Werror— make warnings fatal. scary but iconic 💀-Weverything— enable all warnings supported by GHC.-Wextended-warnings— warn about uses of functions & types that haveWARNINGorDEPRECATEDpragmas, across all categories.-Wextra— alias for-W.-Wforall-identifier— (deprecated) Does nothing.-Wgadt-mono-local-binds— warn when pattern matching on a GADT withoutMonoLocalBinds.-Whi-shadowing— (deprecated) warn when a.hifile in the current directory shadows a library.-Widentities— bestie, this one calls out Prelude numeric conversions that are probably just the identity function in disguise, meaning you could've literally omitted them. It's giving "girl why are you doing all that" 💅-Wimplicit-kind-vars— (deprecated) yells at you when kind variables get implicitly quantified over. Old news, but we keep her in the list 🫶-Wimplicit-lift— warns about implicitlifthappening in Template Haskell quotes. Sneaky little lift, no cap ✨-Wimplicit-prelude— warns when thePreludesneaks in via implicit import. Like when someone shows up to the party uninvited 🙈-Wimplicit-rhs-quantification— warns when type variables sitting on the RHS of a type synonym get implicitly quantified. RHS girlies stay on notice 💖-Winaccessible-code— warns about code that's inaccessible. Literally unreachable, like my will to live during finals 😭-Wincomplete-export-warnings— warns when only some but not all of the exports for a name got warned about. Partial tea, we want the full cup ☕-Wincomplete-patterns— warns when a pattern match could fail. Yourcaseis missing a branch and it's giving "I forgot something" energy 💀-Wincomplete-record-selectors— warns when a record selector application could fail. Yes, that selector. She might not exist in the record you grabbed 🎀-Wincomplete-record-updates— warns when a record update could fail. Updating a field that might not be there? Risky behavior, love that for you but no 🔥-Wincomplete-uni-patterns— warns when a pattern match could fail inside a lambda expression, a pattern binding, or a lazy pattern. Three whole places to get caught lacking 🦋-Winconsistent-flags— warns when your command line options are inconsistent in some way. The flags are fighting, and honestly? Valid of them to say so 🌸-Winferred-safe-imports— warns when an explicitly Safe Haskell module imports aSafe-Inferredone. Mixed signals at the module level, iykyk 👑-Winline-rule-shadowing— Warn if a rewriteRULEmight fail to fire because the function might be inlined before the rule has a chance to fire. See How rules interact with INLINE/NOINLINE pragmas. The rule got sniped pre-payoff, tragic 💔-Winvalid-haddock— warns when a Haddock comment shows up in an invalid position. Girl, that comment does NOT go there 😭-Wloopy-superclass-solve— (deprecated) warns when creating potentially-loopy superclass constraint evidence. Loopy! The evidence is going in circles 🌀-Wmisplaced-pragmas— warns about file header pragmas being used in the module body. Wrong place, bestie, those belong at the top ⭐-Wmissed-extra-shared-lib— Warn when GHCi can't load a shared lib. GHCi said "not found" and honestly same 😔-Wmissed-specialisations— warns when specialisation of an imported, overloaded function fails. The specialisation missed. Off the guest list 🎀-Wmissed-specializations— alias for-Wmissed-specialisations. Same girl, American spelling 💅-Wmissing-deriving-strategies— warns when you derive without mentioning a deriving strategy. Just say which one, it's not that deep 🫶-Wmissing-export-lists— warns when a module declaration doesn't explicitly list all its exports. No export list = mystery box, and not the cute kind 📦-Wmissing-exported-pattern-synonym-signatures— warns about pattern synonyms without signatures, but only if they're exported. Private ones get a pass ✅-Wmissing-exported-signatures— warns about top-level functions without signatures, again only if they're exported 🌈-Wmissing-exported-sigs— (deprecated) warns about top-level functions without signatures, only if they're exported. Takes precedence over-Wmissing-signatures. She's the bossy older sibling here 👑-Wmissing-fields— warns when fields of a record are uninitialised. Empty fields, empty vibes 🍓-Wmissing-home-modules— warns when you import a home module but it's not listed on the command line. Useful forcabalto make sure GHC won't pick up modules that are listed neither inexposed-modulesnor inother-modules. Cabal is watching, she always is 👀-Wmissing-import-lists— warns when an import declaration doesn't explicitly list all the names it brings into scope. Stop dumping the whole namespace on my floor ✨-Wmissing-kind-signatures— warns when type declarations have neither kind signatures nor CUSKs. Both missing? Bold. 💀-Wmissing-local-signatures— warns about polymorphic local bindings without signatures. Local legend with no documentation 🦋-Wmissing-local-sigs— (deprecated) warns about polymorphic local bindings without signatures. Same energy, shorter name 💜-Wmissing-methods— warns when class methods are undefined. The method said "undefined" and dipped 😭-Wmissing-monadfail-instances— (deprecated) Warn when a failable pattern is used in a do-block that doesn't have aMonadFailinstance. No instance, no deal 🚫-Wmissing-pattern-synonym-signatures— warns when pattern synonyms don't have type signatures. Sign your work, artist 🎨-Wmissing-poly-kind-signatures— warns when an inferred polykinded type or class declaration doesn't have kind signatures nor CUSKs. Polykinded and undocumented, a mystery icon 🌟-Wmissing-role-annotations— warns when type declarations don't have role annotations. Tell us your role, main character 🎭-Wmissing-safe-haskell-mode— warns when the Safe Haskell mode isn't explicitly specified. Don't leave us guessing, babe 🫶-Wmissing-signatures— warns about top-level functions without signatures. Classic. Iconic. Still a problem 💅-Wmissing-space-after-bang— (deprecated) Does nothing. Literally nothing. She's just here for the vibes 🪑💀-Wmonomorphism-restriction— warns when the Monomorphism Restriction is applied. Yes, the MR. She's real and she's coming for your bindings 💀-Wname-shadowing— warns when names are shadowed. Two names walk into a scope, only one leaves 😭-Wnoncanonical-monad-instances— warns whenApplicativeorMonadinstances have noncanonical definitions ofreturn,pure,(>>), or(*>). See the flag description in Warnings and sanity-checking for more details. Noncanonical? In this economy? 🔥-Wnoncanonical-monadfail-instances— (deprecated) warns whenMonadorMonadFailinstances have noncanonical definitions offail. Fail, but make it noncanonical 💀-Wnoncanonical-monoid-instances— warns whenSemigrouporMonoidinstances have noncanonical definitions of(<>)ormappend. See the flag description in Warnings and sanity-checking for more details. The monoid girlies are being shady 🍓-Wnot— (deprecated) Alias for-w. That's it. That's the whole personality 🌸-Woperator-whitespace— warns on prefix, suffix, and tight infix uses of infix operators. Space your operators, bestie, they need room to breathe 🫧-Woperator-whitespace-ext-conflict— warns on uses of infix operators that would be parsed differently if a particular GHC extension were enabled. Same characters, different meaning, depending on the timeline 🌈-Worphans— warns when the module contains orphan instance declarations or rewrite rules. Orphaned! Somebody adopt them 😭-Woverflowed-literals— warns about literals that will overflow their type. Number too big for her container, she's spilling 💀-Woverlapping-patterns— warns about overlapping patterns. Two patterns fighting over the same match, toxic 💅-Wpartial-fields— warns when you define a partial record field. Partial field, partial commitment, we've all been there 🙈-Wpartial-type-signatures— warns about holes in partial type signatures whenPartialTypeSignaturesis enabled. Not applicable whenPartialTypeSignaturesisn't enabled, because then those holes are straight-up errors instead 🕳️-Wpattern-namespace-specifier— warns on uses of the pattern namespace specifier. Yes, that specifier. She's on watch 🎀-Wprepositive-qualified-module— Reports imports with a leading/prepositivequalified. Put it where it belongs, please ✨-Wredundant-bang-patterns— Warns about redundant bang patterns. Extra!energy with nowhere to go 😤-Wredundant-constraints— has the compiler warn about redundant constraints in type signatures. Two constraints doing the job of one, we love efficiency (we do not have it here) 🌸-Wredundant-record-wildcards— Warns about record wildcard matches when the wildcard binds no patterns. Wildcard that caught nothing. A tragedy 🎣-Wredundant-strictness-flags— Warns about redundant strictness flags. Strictness on strictness, girl pick one 🔥-Wrule-lhs-equalities— warns about rules whose LHS contains equality constraints. Equality on the left, chaos on the right 💜-Wsafe— warn if the module being compiled is regarded to be safe. Look at her, being all safe and correct 🛡️-Wsemigroup— (deprecated) Warn when aMonoidis not aSemigroup, and on non-Semigroupdefinitions of(<>).Old-school structural drama 💅-Wsimplifiable-class-constraints— Warns about class constraints in a type signature that can be simplified using a top-level instance declaration. Girl, that constraint is doing extra credit for no reason 📚-Wstar-binder— warns about binding the(*)type operator despiteStarIsType. You can't just bind her, she's a star ⭐-Wstar-is-type— warns when*is used to meanData.Kind.Type. Star girl, we know who you really are ✨-Wtabs— warn if there are tabs in the source file. TABS. In MY source file. The audacity 😤-Wterm-variable-capture— warns when an implicitly quantified type variable captures a term's name. That variable stole somebody's name and honestly? Rude 💀-Wtrustworthy-safe— warn if the module being compiled is marked asTrustworthybut it could instead be marked asSafe, which is the more informative bound. Level up, bestie, you earned it 👑-Wtype-defaults— warns when defaulting happens. Defaulting said "I'll pick for you" and picked wrong, probably 💅-Wtype-equality-out-of-scope— warns when type equalitya ~ bis used despite being out of scope. Out of scope but still trying it 😭-Wtype-equality-requires-operators— warns when type equalitya ~ bis used despite being out of scope. Same wording, different flag, both on the list, we don't question the manpage 🎀-Wtyped-holes— Reports warnings when typed hole errors are deferred until runtime. See-fdefer-typed-holes. The hole has been postponed, how ominous 🕳️✨-Wunbanged-strict-patterns— warns on a pattern bind of an unlifted variable that is neither bare nor banged. Neither! Barely! Banged never! 💀-Wunicode-bidirectional-format-characters— warns about the usage of unicode bidirectional layout override characters. Those characters are hiding your code's real intentions, and honestly? Suspicious 🌈👀-Wunrecognised-pragmas— warns about uses of pragmas that GHC doesn't recognise. GHC said "who are you" 💅-Wunrecognised-warning-flags— throw a warning when an unrecognised-W...flag is encountered on the command line. You typed a flag that doesn't exist, and she WILL tell on you 📢-Wunsafe— warn if the module being compiled is regarded to be unsafe. See Safe Haskell. Living dangerously, no seatbelt 🏎️-Wunsupported-calling-conventions— warns about use of an unsupported calling convention. She's calling, you're not answering ☎️-Wunsupported-llvm-version— Warn when using-fllvmwith an unsupported version of LLVM. Wrong LLVM, wrong era, wrong vibe 💀-Wunticked-promoted-constructors— warn if promoted constructors are not ticked. No tick, no vote, bestie ✔️-Wunusable-unpack-pragmas— warns when an{-# UNPACK #-}pragma is unusable. You asked for unpack and got... nothing. Tale as old as time 📦-Wunused-binds— warns about bindings that are unused. Alias for-Wunused-top-binds,-Wunused-local-binds, and-Wunused-pattern-binds. Three-for-one deal 🎀-Wunused-do-bind— warns about do bindings that appear to throw away values of types other than(). You bound it and then ignored it? Jail. (For values that aren't()anyway —()gets a pass.) 😭-Wunused-foralls— warns about type variables in user-writtenforalls that are unused. You saidforalland then didn't use them, so dramatic for nothing 💅-Wunused-imports— warns about unnecessary imports. You imported it for what? Exactly. Unnecessary 🗑️-Wunused-local-binds— warns about local bindings that are unused. Local girl, no use, sad 🥀-Wunused-matches— warns about variables in patterns that aren't used. Named her and never spoke to her again 💀-Wunused-packages— warns when a package is requested on the command line, but isn't needed. You brought the whole package for nothing, put it back 🎒-Wunused-pattern-binds— warns about pattern match bindings that are unused. The pattern held on, the usage did not 😔-Wunused-record-wildcards— Warns about record wildcard matches when none of the bound variables are used. Wildcard bound everything, you used nothing, iconic behavior 🙈-Wunused-top-binds— warns about top-level bindings that are unused. Top-level and still unappreciated, story of my life 🌟-Wunused-type-patterns— warns about unused type variables which arise from patterns in type family and data family instances. Family drama, unused variables, we've all been there 👨👩👧-Wuseless-specialisations— warns on uselessSPECIALISEpragmas. Useless! Somebody had to say it 💀-Wuseless-specializations— alias for-Wuseless-specialisations. Same uselessness, different spelling 💜-Wview-pattern-signatures— warns when a view pattern is used with a type signature without explicit parens. Parenthesize, bestie, the parser is asking nicely 🫶-Wwarn— make warnings non-fatal. Warnings stay warnings, nobody gets yeeted 🎀-Wwarnings-deprecations— warns about uses of functions & types that haveDEPRECATEDpragmas, orWARNINGpragmas with the deprecated category. Alias for-Wdeprecations. She's deprecated and she wants you to know it 📢-Wwrong-do-bind— warns about do bindings that appear to throw away monadic values that you should have bound instead. You dropped a monadic value in the group chat and didn't bind it, bestie 😭-Wx-⟨category⟩— warns about uses of functions & types that haveWARNINGpragmas with the given category. Custom category, custom warning, custom era ✨🌈
✨ COPYRIGHT ✨
Okay bestie, legal moment, don't scroll past this one 💅
Copyright 2015. The University Court of the University of Glasgow. All rights reserved.
That's the whole thing, no cap. All the rights, reserved, by the University Court of the University of Glasgow, and the year is 2015. Iconic of them honestly 🎀
🦋 SEE ALSO 🦋
Like, if you wanna keep hanging out after this (and why wouldn't you), the GHC homepage is literally right there:
https://www.haskell.org/ghc— the GHC homepage ✨
That's it, that's the link. Go say hi, tell them I sent you 🫶
👑 AUTHOR 👑
The GHC Team
Yep. Not one person, a whole team. Collective main character energy fr fr 💜
📜 COPYRIGHT 📜
Second round of legal, bestie, and this one's got a different year so pay attention 🙈
2025, GHC Team
(Yes there are two COPYRIGHT sections. Yes I also thought that was a typo the first time. It's not. We respect the structure here 🔥)
That's the whole page, bestie! You made it to the end, I'm so proud of you 😭💖 Go forth and compile something iconic. Slay.
And a little sign-off for the footer, since every good manpage needs one: this was GHC(1), version 9.14.1, dated Dec 28, 2025 — bookmark it, screenshot it, tattoo it on your forearm, iykyk 🌸✨
📦 where this page comes from
- epel 10: ghc9.14-compiler 9.14.1-1.el10_2 · BSD-3-Clause
- 💖 girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms