Wildcard to obtain list of all directories - makefile

In my Makefile I need to get a list of all directories present in some other directory.
To get a list of all directories in the same folder as my Makefile I use:
DIRECTORIES = $(wildcard */)
all:
echo $(DIRECTORIES)
which works fine, and gives me the desired list. However if I want to have a list of all directories in another directory using
DIRECTORIES = $(wildcard ../Test/*/)
all:
echo $(DIRECTORIES)
I get a list of ALL files (with paths) in that directory, including .h and .cpp files.
Any suggestions why this happens and how to fix it? Other solutions to obtain the list are also welcome.

Use sort and dir functions together with wildcard:
DIRECTORY = $(sort $(dir $(wildcard ../Test/*/)))
From GNU make manual:
$(dir names...)
Extracts the directory-part of each file name in names. The directory-part of the file name is everything up through (and including) the last slash in it. If the file name contains no slash, the directory part is the string ‘./’.
$(sort list)
Sorts the words of list in lexical order, removing duplicate words. The output is a list of words separated by single spaces.
Also look at the second and the third method in this article: Automatically Creating a List of Directories

Try:
$(shell find <directory> -maxdepth 1 -type d)
which will give you the list of directories inside a given directory without going into subdirectories. You may need to clean that list up since it will include . and ./ before every directory listed.

Use:
$(wildcard ../Test/*/.)
This works fine.

Related

How to print the list of files in a folder from build logs in make file?

We are using make utility in windows to build our project. The version of make is "GNU Make 3.81". I need to understand how our project is built and so have added additional log lines like below which is working as expected --
$(warning Entering componentsWin32.mak )
Additionally I need to find the current directory and the list of files in that directory, for the first one, this is working--
$(warning Entering componentsWin32.make $(CURDIR))
To print the list of files in a directory I tried this but it did-not work --
$(warning Entering componentsWin32.make $(DIR))
Is it possible using $(SHELL...some command) or any other way? Any pointers to this would be helpful.
The function $(wildcard [path string]) will evaluate to a list of files which are desginated by path string: the path string may be written as a glob, so e.g.
$(wildcard $(CURDIR)/src/*.c)
will evaluate to a list of all C files, given that there is a subdirectory src under your current directory with *.c files in it.
You can even pass an arbitrary number of such path expressions:
$(wildcard $(CURDIR)/src/*.c $(MY_INCLUDE_DIR)/*.h)
Obviously, spaces in path names are not allowed.

How to write a Make rule for files of certain type in a directory tree?

Imagine a directory tree (which might be more than one level deep) containing several Markdown files. A PDF version of each file exist in the same directory and must be updated each time the corresponding Markdown file is updated. What rule must be written in a single Makefile in the root directory of this tree to achieve this?
I am looking a for a solution where files can be added or removed from the directory tree without a need for updating the Makefile.
Assumptions:
all markdown files follow a certain pattern in their name; for example they end with a .md postfix.
GNU Make is being used.
You can use $(shell find) to find files recursively. For example:
markdown := $(shell find . -name '*.md')
all: $(patsubst %.md, %.pdf, $(markdown))
%.pdf: %.md
pandoc -o $# $<

How to use make to convert files in subdirectories?

I have a directory with a bunch of subdirectories. Each subdirectory contains a traj.dat file. I want to use a Makefile to make sure that the file traj.dat gets converted to a different format, and the output file is printed in the same subdirectory as the original file.
Therefore, if I wanted to specify the names of the subdirectories, I could just use:
subdir1/traj.dat.xyz: subdir1/traj.dat
my_convert subdir1/traj.dat subdir1/traj.dat.xyz
subdir2/traj.dat.xyz: subdir2/traj.dat
my_convert subdir2/traj.dat subdir2/traj.dat.xyz
and so on.
How can I get the above result FOR ALL the subdirectories containing a traj.dat file, regardless of their name, without having to list them explicitly?
Cheers!
Assuming you're using GNU make, try:
DATFILES := $(shell find . -name traj.dat)
OUTFILES := $(addsuffix .xyz,$(DATFILES))
all: $(OUTFILES)
%.dat.xyz : %.dat
my_convert $< $#
You weren't really clear what you mean by "subdirectories"; if you just mean immediate subdirectories you can use this instead of the shell function, which is more efficient (and works on Windows):
DATFILES := $(wildcard */traj.dat)

How to apply wildcard on a list of directories

I've this directory structure:
root/
build/ #I'm inside this directory
dir1/
build
obj #.o files inside this
dir2/
build
obj #.o files inside this
dir3/
build
obj #.o files inside this
As you see my makefile is in root/build — the makefile defines a variable as:
DIRS = dir1 dir2 dir3 #there could be many
and then I try to create a variable as:
OBJDIRS = $(DIRS:%=../%/build/obj)
$(info $(OBJDIRS)) #lets print the list
Here info prints this list:
../dir1/build/obj ../dir2/build/obj ../dir3/build/obj
Now I want to get a list of all the object files inside obj directories of all the dir* directories. How to get that? I tried this:
OBJECTS = $(wildcard $(OBJDIRS)/*.o)
$(info $(OBJECTS))
which prints this only:
../dir1/build/obj
The wildcard doesn't seem to work on a list of directories. Is there any way to achieve that?
I see two things wrong with your current attempt.
$(wildcard) doesn't use % as its wildcard character. It uses *. So you need $(wildcard $(OBJDIRS)/*.o) to fix that.
$(OBJDIRS)/*.o is going to expand into ../dir1/build/obj ../dir2/build/obj ../dir3/build/obj/*.o. Which, you'll notice, isn't what you want. So you need to use $(addsuffix /*.o,$(OBJDIRS)) or another substitution to generate the list of wildcard patterns you want.

Makefile rule that depends on all files under a directory (including within subdirectories)

One rule in my Makefile zips an entire directory (res/) into a ZIP file. Obviously, this rule needs to execute when any file under the res/ directory changes. Thus, I want the rule to have as a prerequisite all files underneath that directory. How can I implement this rule?
In Bash with the globstar option enabled, you can obtain a list of all the files in that directory using the wildcard pattern res/**/*. However, it doesn't seem to work if you specify it as a prerequisite in the Makefile:
filename.jar: res/**/*
Even after touching a file in res/, Make still reports
make: `filename.jar' is up to date.
so clearly it is not recognizing the pattern.
If I declare the directory itself as a prerequisite:
filename.jar: res
then Make will not re-execute when a file is modified (I think make only looks at the modified date of the directory itself, which only changes when immediate children are added, removed, or renamed).
This:
filename.jar: $(wildcard res/**/*)
seems to work, at least on some platforms.
EDIT:
Or better, just cut the knot:
filename.jar: $(shell find res -type f)

Resources