Generating Rules from Actions

43 views
Skip to first unread message

Theodore Witkamp

unread,
Aug 7, 2014, 3:53:04 PM8/7/14
to shake-bui...@googlegroups.com
Hi,

I would like find all of the 'Makefiles' in my project and then generate Rules based them.
However, it looks like (purposely) nothing can escape an Action.
So, Instead I lifted my 'Makefile' scanner to the IO operation before the shake function.

main = do
    makefiles <- findMakefiles
    shake skakeOptions $ generate_rules makefiles


Is there  a better way?

Thanks.

Neil Mitchell

unread,
Aug 7, 2014, 4:41:00 PM8/7/14
to Theodore Witkamp, shake-bui...@googlegroups.com
Hi Theodore,

My alternative question would be "what's wrong with that way?". I use
that strategy in the Ninja and Makefile interpreters built into Shake,
see http://neilmitchell.blogspot.co.uk/2014/01/running-makefiles-with-shake.html
or http://neilmitchell.blogspot.co.uk/2014/05/shake-as-dependency-library.html
. As long as processing the Makefile is sufficiently quick not to
matter (which it usually is) then you are basically writing an
interpreter for your custom build syntax using Shake, which works
nicely.

If you really want to avoid that approach, or if for some reason you
can't use that approach (e.g. the Makefile itself is a dependency)
then you can probably use newCache in some way to store the output of
the Makefile, see
https://github.com/ndmitchell/ghc-make/blob/master/Build.hs, in
particular the "makefile" rule and call to newCache, combined with
addOracle. However, that approach is trickier to get right, almost
forces a level of indirection, and you have to pin down some details
about how generate_rules works in advance. In some ways
usingConfigFile from
http://hackage.haskell.org/package/shake/docs/Development-Shake-Config.html#v:usingConfigFile
is a good example of the Oracle/Cache pattern.

Thanks, Neil

Neil Mitchell

unread,
Aug 8, 2014, 9:51:35 AM8/8/14
to Theodore Witkamp, shake-bui...@googlegroups.com
Hi Theodore,

In fact, there is somewhere slightly different you can put your findMakefiles step. You can do:

main = shakeArgsWith shakeOptions [] $ \_ -> xs -> do
    makefiles <- findMakefiles
    let rules = generate_rules makefiles
    if null xs then rules else withoutActions rules >> want xs

This has the advantage that you can easily add command line flags to figure out where to find the Makefile. Both the Ninja and Makefile systems in Shake support that, using --makefile=FILE to override the default. Even if you don't want to do that, you might want to replace shake with shakeArgs in your original example, which will provide you with command line handling.

Thanks, Neil
Reply all
Reply to author
Forward
0 new messages