1

I was experiencing unnecessary rebuilds while using this matching pattern:

getDirectoryFiles "" $ "foo" </> "//*.c"

I'm on Linux so from my understanding the second argument will evaluate to

"foo///*.c"

and I presume that it would be incorrect to replace this with

"foo" </> "/*.c"

as that would not work on windows? On Linux however this works as I expect it to.

From testing I concluded that the pattern matched files outside of "foo" which makes no sense in my world. As an example the pattern above would match both testA.c and testB.c in a directory structure like the one below.

foo/testA.c
bar/testB.c

I see now that there is a <//> operator, so maybe I should be using "foo" <//> "*.c" instead but still. This was quite nasty to find and what does "foo///*.c" actually do?

nesqi
  • 97
  • 7

1 Answers1

1

The problem is that the </> operator is defined so that:

"foo" </> "//*.c" == "//*.c"

That means that using </> to create a // value is almost never the right thing to do. <//> solves that, but as you note, it's not predictable and quite nasty.

The solution is using foo/**/*.c as an alternative pattern to foo//*.c. The advantage of the first form is that it is perfectly predictable and works well with </>, eliminating the need for <//>. Since Shake 0.15.6 that has been a permissible alternative, and in Shake 0.16 it will probably be recommended over //.

As to your other questions: 1) for Windows you can use either / or \ interchangeably in pattern values, so writing foo//*.c literally is just fine. 2) foo///*.c is equivalent to foo//*.c, and there are extensive test suites for such forms in Shake.

Neil Mitchell
  • 9,090
  • 1
  • 27
  • 85
  • Thanks, good explanation! Unfortunate combination of `>` and `"//"`. It makes me happy that it will be replaced in 0.16. In 0.15.11 the documentation says "Currently considered experimental" which resulted in me not even testing it. – nesqi Feb 22 '17 at 06:16