How do I tell stack to build my executable and all its dependencies with -prof? 
Simply adding it to ghc-options in the .cabal file is not enough, because it only tries to build the executable with profiling enabled, which fails.
To build with profiling enabled:
stack build --profile   You may need to run stack clean first, but this should be fixed in Stack 1.5.0.
To profile:
stack exec --profile -- <your program> +RTS <profiling options>   where for <profiling options> you might want -p for time profiling or -h for memory profiling. For time profiling, the profile appears in ./<your program>.prof, and for memory profiling, the profile appears in ./<your program>.hp.
See GHC profiling documentation for more profiling options.
Due to a long standing Stack issue, switching between profiling and non-profiling builds can cause a lot of unnecessary rebuilding of local packages and extra-deps. To work around this, you can use separate build caches for your profiling and non-profiling builds. For example, where you use stack <cmd> for non profiling you can use
stack --work-dir .stack-work-profile --profile <cmd>   for a profiling version of <cmd>. This uses a separate  cache in .stack-work-profile for profiling artifacts, whereas non profiling artifacts will be preserved in the default .stack-work cache.
To build with profiling enabled:
stack build --executable-profiling --library-profiling --ghc-options="-fprof-auto -rtsopts"   To profile:
stack exec -- <your program> +RTS <profiling options>   Suppose you have a package called test with a single executable test defined by main here:
module Main where  main :: IO () main = do   print $ foo 0  foo :: Int -> Int foo x = fooSub (x+1)   where     fooSub x = bar (x+1)  bar :: Int -> Int bar x = barSub (x+1)   where     barSub x = barSubSub (x+1)       where         barSubSub x = x+1   then doing stack build --profile && stack exec -- test +RTS -p will produce a file ./test.prof which includes
                                                                                                individual      inherited COST CENTRE                 MODULE                SRC                        no.     entries  %time %alloc   %time %alloc    [... many lines omitted ...]   main                      Main                  src/Main.hs:(4,1)-(5,15)    97          0    0.0    0.0     0.0    0.0    foo                      Main                  src/Main.hs:(8,1)-(10,24)   98          1    0.0    0.0     0.0    0.0     foo.fooSub              Main                  src/Main.hs:10:5-24         99          1    0.0    0.0     0.0    0.0      bar                    Main                  src/Main.hs:(13,1)-(17,46) 100          1    0.0    0.0     0.0    0.0       bar.barSub            Main                  src/Main.hs:(15,5)-(17,46) 101          1    0.0    0.0     0.0    0.0        bar.barSub.barSubSub Main                  src/Main.hs:17:9-46        102          1    0.0    0.0     0.0    0.0  main                       Main                  src/Main.hs:(4,1)-(5,15)    95          0    0.0   20.5     0.0   20.5   I.e., there is profiling information for all definitions, including local definitions in where clauses.
If you only want to profile top-level definitions, you can build with the GHC option -fprof-auto-top instead: doing stack build --profile --ghc-options=-fprof-auto-top && stack exec -- test +RTS -p produces a ./test.prof which includes
                                                                                individual      inherited COST CENTRE MODULE                SRC                        no.     entries  %time %alloc   %time %alloc   [... many lines omitted ...]   main      Main                  src/Main.hs:(4,1)-(5,15)    97          0    0.0    0.0     0.0    0.0    foo      Main                  src/Main.hs:(8,1)-(10,24)   98          1    0.0    0.0     0.0    0.0     bar     Main                  src/Main.hs:(13,1)-(17,46)  99          1    0.0    0.0     0.0    0.0  main       Main                  src/Main.hs:(4,1)-(5,15)    95          0    0.0   20.5     0.0   20.5   instead.
Finally, note that stack build --profile also turns on stack traces. If you change the program so that barSubSub x = error $ show x, then running stack build --profile && stack exec test produces
test: 4 CallStack (from HasCallStack):   error, called at src/Main.hs:17:23 in main:Main CallStack (from -prof):   Main.bar.barSub.barSubSub (src/Main.hs:17:9-36)   Main.bar.barSub (src/Main.hs:(15,5)-(17,36))   Main.bar (src/Main.hs:(13,1)-(17,36))   Main.foo.fooSub (src/Main.hs:10:5-24)   Main.foo (src/Main.hs:(8,1)-(10,24))   Main.main (src/Main.hs:(4,1)-(5,15))   Main.CAF:lvl8_r4Fc (<no location info>)   Pretty cool!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With