Reputation: 1261
I have some issues with the behavior of the wildcard function of GNU Make with respect to terminating slashes in the pattern and the output.
Consider the following simple directory structure:
dir
|
+-- file
|
+-- subdir
On Linux,
$(wildcard dir/*/) # (1)
evaluates with GNU Make 4.1 to
dir/subdir/ dir/file
but with GNU Make 4.3 to
dir/subdir/
One could argue whether including the regular file file
in the former case is a bug or a feature (names of directories but not those of regular files are terminated with a slash). However, both versions of GNU Make evaluate
$(wildcard $(addsuffix /,$(wildcard dir/*))) # (2)
to
dir/file dir/subdir/
(subject to sorting). In particular, $(wildcard dir/file/)
evaluates to dir/file
. This is more in the spirit of the above GNU Make 4.1 feature but seems to be somewhat inconsistent with respect to GNU Make 4.3.
What can I assume from the wildcard function regarding a terminating slash in the pattern?
I would like to determine the content of a directory such that the names of subdirectories are terminated by a slash while the names of regular files are not. In GNU Make 4.1 I used approach 1 which broke my build with GNU Make 4.3. In both cases I could use approach 2. But is this feasible or do I rely on undefined behavior here? If so, what would be the correct (and efficient) way to do what I want?
Upvotes: 0
Views: 635
Reputation: 2898
The function wildcard-rec
in the GNUmake table toolkit does exactly what you want. It distinguishes between files and directories via a obvious feature: if the given glob ends in /
then you want directories, if the /
is absent you want files.
include gmtt.mk
$(info $(call wildcard-rec,**.c)) # all C source files in the tree
$(info $(call wildcard-rec,**.c **.h)) # a C source and header files
$(info $(call wildcard-rec,drivers/**.c)) # only sources for the `drivers` tree
$(info $(call wildcard-rec,drivers/**/test/)) # all test subdirectories in the `drivers` tree
$(info $(call wildcard-rec,drivers/**/test/*.cfg)) # config files in all test subdirectories in the `drivers` tree
Upvotes: 0
Reputation: 100866
The problem is not simple. The short answer is that the behavior of GNU make 4.3 is correct for the expansion of dir/*/
and the behavior of earlier versions of make that don't agree with that, are wrong.
As for the behavior of dir/file/
that seems to me to be wrong in all versions of GNU make; that is, it should return the empty string.
However, GNU make doesn't actually implement its own file globbing, at least not on systems that provide the GNU libc C runtime library, which is most Linux systems. It simply calls the system-provided glob(3) function. I wrote a small test program that simply calls GNU libc's glob(3) function directly and it gives the same behavior as GNU make 4.3:
dir/*/
-> dir/subdir/
dir/file/
-> dir/file/
In my opinion this is a bug in GNU libc's glob(3) but perhaps I'm missing some subtlety here.
In any event, if what you really want is just directories then the best/safest/works everywhere solution is to use this:
$(wildcard dir/*/.)
then you don't have to worry about magical behaviors related to trailing slashes.
Upvotes: 1