I need to track compiler flags used as part of a rule, e.g when supplied as arguments to a function. Does Shake have a way to track such flags as inputs in the same vein as need
? As a trivial example, I would like for Shake to rebuild all .o
files when the rule changes to pass -O2
to the C compiler instead of -O0
.

- 9,090
- 1
- 27
- 85
1 Answers
There are two approaches to tracking things like whether to use optimisation or not.
1) Use Oracles
Oracles very closely match what you are asking for. To track something like
-O0
vs -O2
you'd need an oracle that tracks optimisation level:
newtype OptLevel = OptLevel ()
deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
type instance RuleResult OptLevel = String
rules = do
addOracle $ \(OptLevel _) -> return $
if <whatever you use to decide> then "-O0" else "-O2"
"foo.o" %> \_ -> do
level <- askOracle $ OptLevel ()
cmd "gcc" level ...
Now the optimisation level is a tracked dependency which will update if anything changes. This example is based on the docs for addOracle
.
2) Use different output files
For compiler flags another approach is to use different build directories, i.e. so build/opt
(and build/opt/obj
etc) has binaries and .o
files built with -O
, build/debug
without, build/profile
with profiling flags, and build/test
with test flags. Some others, like build/doc
and build/hsc
, have generated files that aren't dependent on compiler flags.
The advantage of this approach is that you can keep all the files cached at once, and refreshing the debug or test build doesn't destroy the opt one. The disadvantage is that it's just for a set of hardcoded flags. But it's also not hard to add a new mode, you just need a new (directory, flags) pair for it.

- 9,090
- 1
- 27
- 85
-
This question is based on information from https://groups.google.com/d/msg/shake-build-system/50Xmy4AXPuc/iLANIOqXBgAJ – Neil Mitchell Apr 26 '19 at 12:46