Shake with stack

101 views
Skip to first unread message

ryan....@gmail.com

unread,
Jan 22, 2016, 11:04:52 PM1/22/16
to Shake build system
I'm wondering how I can compile and run Shake build files using stack? I recently discovered it
and it gives me hope that I can start using Shake without having to fix my broken ghc/cabal
installation.

Thanks for any help,
Ryan

Neil Mitchell

unread,
Jan 23, 2016, 5:46:00 AM1/23/16
to ryan....@gmail.com, Shake build system
Hi Ryan,

Standard Stack approach should work. Create a .cabal file for your build system. Then create a stack file with stack init. Then stack build and stack exec result. Sack is currently a bit verbose for one of scripts, but there are a few stack tickets to improve that. 

Thanks, Neil 

Neil Mitchell

unread,
Jan 23, 2016, 5:49:11 AM1/23/16
to ryan....@gmail.com, Shake build system
Here's the stack issue I was thinking of: 
https://github.com/commercialhaskell/stack/issues/1124

Thanks, Neil 

mark...@gmail.com

unread,
Mar 30, 2016, 12:55:41 AM3/30/16
to Shake build system, ryan....@gmail.com
Playing around with shake with stack and tried the demo:

https://github.com/ndmitchell/shake/blob/master/src/Development/Shake/Demo.hs#L43

$ repos/play/shake-demo stack install shake
Run from outside a project, using implicit global config
Using resolver: lts-5.4 from global config file: /Users/mark/.stack/global/stack.yaml
NOTE: the install command is functionally equivalent to 'build --copy-bins'
Copying from /Users/mark/.stack/snapshots/x86_64-osx/lts-5.4/7.10.3/bin/shake to /Users/mark/.local/bin/shake

Copied executables to /Users/mark/.local/bin/:
- shake
$ repos/play/shake-demo rehash
$ repos/play/shake-demo shake --demo
% Welcome to the Shake v0.15.5 demo mode!
% Detecting machine configuration... done

% You don't have the 'shake' library installed with GHC, which is required to run the demo.
$ repos/play/shake-demo

Installed via cabal (which I've generally stopped doing), and demo worked. Looking forward to playing with it!

Mark

Neil Mitchell

unread,
Apr 1, 2016, 7:47:23 AM4/1/16
to mark...@gmail.com, Shake build system, Ryan Eckbo
Hi Mark,

If you do:

stack exec -- shake --demo

Does that work?

Thanks, Neil

Mark Fine

unread,
Apr 1, 2016, 1:17:30 PM4/1/16
to Neil Mitchell, Shake build system, Ryan Eckbo
Thanks, that worked! Would be great to add to the documentation:

stack install shake
stack exec -- shake --demo

Unrelated (apologies for hijacking). I'm super new to shake and have been really enjoying working with it; one pattern I've been running into is a phonyish target that has a dependency on files but generates no output - it's transforming the files (e.g., lint, formatting, etc.). So I'm using a "dummy" file under the build directory to track whether the phony target needs to be run or not - it looks something like this:
fake :: FilePath -> Action a -> Rules ()
fake target act = do
  buildDir </> target %> \out ->
    act >> writeFile' out mempty

  phony target $
    need [ buildDir </> target ]

fakeWithHs :: FilePath -> ([FilePath] -> Action a) -> Rules ()
fakeWithHs target act =
  fake target $ do
    files <- getDirectoryFiles "." [ "*/src//*.hs", "*/main//*.hs", "*/test//*.hs" ]
    need files
    act files

main :: IO ()
main = shakeArgs shakeOptions { shakeFiles = buildDir } $ do
  fakeWithHs "stylish" $ \files ->
    unit $ cmd ("stylish" :: String) $ [ "-c", ".stylish-haskell.yaml", "-i" ] ++ files

Is there a more direct way to achieve this in shake? Thanks again for the great software!

Mark

Neil Mitchell

unread,
Apr 1, 2016, 3:03:13 PM4/1/16
to Mark Fine, Shake build system, Ryan Eckbo
> Thanks, that worked! Would be great to add to the documentation:
>
> stack install shake
> stack exec -- shake --demo

Yep, now I know it works I'll add it - I've raised a ticket.
https://github.com/ndmitchell/shake/issues/435

> Unrelated (apologies for hijacking). I'm super new to shake and have been
> really enjoying working with it; one pattern I've been running into is a
> phonyish target that has a dependency on files but generates no output -
> it's transforming the files (e.g., lint, formatting, etc.). So I'm using a
> "dummy" file under the build directory to track whether the phony target
> needs to be run or not - it looks something like this:

So the formatting/lint seem to fall into two different models:

1) For things where it takes in a file and modifies it, you probably
want to have the input and output be different files, and then Shake
handles it nicely. If you don't have the input and output be different
files, you definitely need to record that it ran, and a fake file is
probably the easiest way to do that. One option would be to make the
rule produce a backup file of the original contents, just in case you
decide stylish or whatever went off the rails and broke your file.
Generating custom rules which don't produce the file is a bit complex
right now, but I'm working on making it easier, so I might have a
better answer shortly.

2) For things like linting which produce a report, I recommend putting
the report in a file, and treating the report as output. That way you
can go back and look at the lint output for the current state, which
is often quite useful.

> fake :: FilePath -> Action a -> Rules ()
> fake target act = do
> buildDir </> target %> \out ->
> act >> writeFile' out mempty
>
> phony target $
> need [ buildDir </> target ]

This looks quite a reasonable approach. Only downside is that you run
stylish on all files if any of them change, but to do better you'd
need a fake file per Haskell file, which might be less desirable, and
running styling on everything might not take that long anyway.

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