3

Sometimes it is the case that to create a directory mkdir is not the right tool. It may be git clone or rsync or mount. So when we have a rule like this:

needDir dirs = filterM ((fmap not) . doesDirectoryExist) dirs >>= need

rules = do {
  "project" </> "tool" %> \out -> do {
    needDir [takeDirectory out];
    cmd "make -C" [takeDirectory out];
    }

  "project" %> \out -> cmd "git clone a.url.to/repo.git" [out]
  }

As one might expect the "project" </> "tool" creates the directory project before anything else and git clone isn't even run. Is there a way to go around this?

I suspect a new Rule is due here but I the docs were minimal and the code too confusing for me to come up with a working solution.

fakedrake
  • 6,528
  • 8
  • 41
  • 64
  • This issue is also being discussed at https://github.com/ndmitchell/shake/issues/430 (and the conclusions will be copied as an answer). – Neil Mitchell Mar 12 '16 at 14:14

1 Answers1

1

Think of directories as containers for files. They exist or don't pretty randomly, but if they have files, they must exist. In particular, you can't depend on a directory with need or write a rule to create a directory. Directories are created as needed - the rule for project/tool.txt will create the project directory if necessary.

If you want to depend on a git clone having being performed, depend on a particular checked-out file instead (e.g. README.md), with the rule to create it being git clone. If you want to ensure a make was run, depend on a file that make produces.

It is possible to define directory-aware rules, see this discussion, but there are lots of caveats so it's not the recommended approach or supported by default.

Neil Mitchell
  • 9,090
  • 1
  • 27
  • 85