Search code examples
shake-build-system

What will (getDirectoryFiles "" (dir </> "//*.c")) actually match?


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?


Solution

  • 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.