5

I'm trying to migrate an existing makefile to Shake and so far I've tried the following (just create a file with the content of a directory)

module Main where
import Development.Shake

main :: IO ()
main = shakeArgs shakeOptions{shakeFiles="_build"} $ do
    let ls = "_build/ls.txt"
    want [ls]
    ls *> \out ->  do
        cmd "ls >  " out

When I run it, I get the following error message :

> runghc test.hs _build/ls.txt
# ls (for _build/ls.txt)
ls: >: No such file or directory
ls: _build/ls.txt: No such file or directory
Error when running Shake build system:
* _build/ls.txt
Development.Shake.cmd, system command failed
Command: ls > _build/ls.txt
Exit code: 1
Stderr:
ls: >: No such file or directory
ls: _build/ls.txt: No such file or directory

What Am I doing wrong? How do you execute a sh command and redirect its output?

Neil Mitchell
  • 9,090
  • 1
  • 27
  • 85
mb14
  • 22,276
  • 7
  • 60
  • 102

1 Answers1

13

To start with the conversion you probably want:

cmd Shell "ls >" out

The argument Shell tells Shake to use the system shell, meaning the redirect works. Later on you may wish to switch to:

Stdout result <- cmd "ls"
writeFile' out result

Now you are not invoking the shell, but capturing the output with Shake. Sometime later, you may wish to switch to:

getDirectoryFiles "." ["*"]

Which is the Shake tracked way of getting a list of files.

Neil Mitchell
  • 9,090
  • 1
  • 27
  • 85
  • 1
    `Shell` works indeed. Why is it needed then ? I thought `cmd` was already running a shell command, isn't it ? – mb14 Jul 22 '14 at 15:53
  • 2
    Nope, `cmd` is running the command directly, through something like `exec` (if this were C). Avoiding `Shell` often gives more predictable behaviour cross-platform, avoids starting the shell, makes escaping much simpler etc. – Neil Mitchell Jul 22 '14 at 16:50