[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Has anyone ever tried this technique for creating target parent director
Has anyone ever tried this technique for creating target parent directories?
Sat, 19 Nov 2011 22:43:03 -0800
Mozilla/5.0 (X11; Linux x86_64; rv:8.0) Gecko/20111108 Thunderbird/8.0
I tried many iterations on creating the most "automatic" way that I
could think of for creating target directories in my Makefile, having
read about the pros and cons of various solutions suggested on the web
and also having seen different techniques used in practice in the
makefiles of working projects.
What I wanted was some way to have the parent directory of every target
created if it didn't already exist (using mkdir -p style so that all
intermediate directories are created as well), and I wanted it to not
require special incantations on the part of other makefiles in my system
that relied on my base set of include'd rules.
What I came up with is this (simplified form):
$(if $(wildcard $(dir $(patsubst %/../.dir,%,$@))),,$(shell mkdir
-p $(dir $(patsubst %/../.dir,%,$@))))
For this rule, the directory in question is defined as the parent
directory of a file called '.dir' located in the same directory as a
target. So for example if I have a target foo/bar/obj/foo.o, then I
would invoke this rule by creating a prerequisite of foo.o of
foo/bar/obj/foo.o/../.bar. As you can see if we fold out the .. then we
get a prerequisite file of foo/bar/obj/.bar.
What the commands do is to check to see if the wildcard function finds
that the directory containing this .dir file, which is the parent
directory of the target that we want to create the parent directory,
exists or not, and only if it does not exist, then we call mkdir on the
Then I use this target like this in all of my pattern rules:
%.o: %.o/../.dir %.c
gcc -o $@ -c $(filter .c $^)
The result is that whenever the parent directory of a target object file
does not exist, it is first created.
This works great, and my un-simplified version, which I will not present
here, works on MSDOS style cmd shells as well as on Unix (the
un-simplified version just uses a variable to invoke "mkdir -p" that is
appropriate for MSDOS vs Unix and also does substitution of / with \ in
the directory name passed to mkdir).
A nice aspect to this is that the .dir file never actually has to be
created; once the .o file is created then it doesn't matter whether the
.dir file was ever created, make ceases to care about the .dir file. So
subsequent builds don't do any extra work of checking for directory
existence or trying to re-create the directory. I expect that if a .o
file fails to compile for some reason, then even if the parent directory
of the .o file was successfully created, then my rule will be
re-invoked; but it will do nothing because the wildcard will match the
target directory that was already created.
The .PRECIOUS is necessary, otherwise make will produce lots of
unnecessary error messages about not being able to remove the
never-created .dir files; the make will not fail but the errors are ugly
The reason that I like my solution is that it doesn't require that any
of the other rules that I create add mkdir commands to their list of
commands; they just create a prerequisite of %/../.dir and the mkdir is
automagically taken care of.
One annoyance of this solution is that your list of prerequisites gets a
.dir file in it, which means that you can't use $^ or $< unless you
don't mind passing the .dir file to your command (and there are very few
commands which can tolerate this). So you have to use, e.g.
I have seen alot of suggestions for how to handle directory creation for
targets, but never the one that I have come up with. Has anyone done
Also - I am far from a make expert. Is there anything suboptimal or
ugly about my solution that could be made tidier?
- Has anyone ever tried this technique for creating target parent directories?,
Bryan Ischo <=