Making directories in GNU Make


make.  If you don\'t you could run into the situation where the directories have not been built.

Solution 3: use a directory \'marker\' file

If you look back at the original broken solution there\'s one rather nice feature: it builds the directory needed for a specific target and only that directory.   In a more complex example (where there were many such directories to be built) it would be nice to be able to use something like that solution while avoiding the problem of constant rebuilds as the timestamp on the directory changes.

To do that you can store a special empty file, that I call a \'marker\' file in the directory and use that as the prerequisite.  Since it\'s a normal file, normal GNU Make rebuilding rules apply and its timestamp is not affected by changes in its directory.

If you add a rule to build the marker file (and to ensure that its directory exists), it\'s possible to specify a directory as a prerequisite, by specifying the marker file as a proxy for the directory and get the desired effect.

In this example the marker file is called .f

OUT = /out

.PHONY: all
all: $(OUT)/foo.o

$(OUT)/foo.o: foo.c $(OUT)/.f
    @$(COMPILE.C) -o $@ $<

    mkdir -p $(dir $@)
    touch $@

Notice how the rule to build $(OUT)/.f both creates the directory, if necessary, and touches the .f file.  Since the target is a file (the .f) it can safely be used as a prerequisite in the $(OUT)/foo.o rule.

The $(OUT)/.f rule uses the GNU Make function $(dir FILE) to extract the directory portion of the target (which is the path to the .f file) and passes that directory to mkdir.

The only disadvantage here is that it\'s necessary to specify the .f files for every rule that builds a target in a directory that might need creating.

Solution 4: use an \'order-only\' prerequisite to build the directory

If you are using GNU Make 3.80 or above another solution is to use an \'order-only\' prerequisite.  An order-only prerequiste is a prerequisite of a target that will be built before the target, but whether it is rebuilt or not does not affect the rebuilding of the target.  So GNU Make will cause an order-only prerequisite to be rebuilt but it will only affect the order in which targets are handled, and not the relationship between targets that causes rebuilding.

This is exactly what we\'d like in the original broken example: make sure that the directory has been rebuilt, but if its timestamp changes don\'t rebuild the .o file. 

Order-only prerequisites are specified by prefixing them with the bar symbol | before the prerequisites (and after any normal prerequisites have been specified). 

In fact a single character change to the broken example makes it work correctly under GNU Make 3.80 and above:

OUT = /out

.PHONY: all
all: $(OUT)/foo.o

$(OUT)/foo.o: foo.c | $(OUT)/
    @$(COMPILE.C) -o $@ $<

    mkdir -p $@

Solution 5: use pattern rules, second expansion and a marker file

In a typical Makefile (i.e. not the sort of simple example people come up with in articles like this) targets are usually built using pattern rules.  For example, the simple example would more likely be written using a pattern rule like this:

OUT = /out

.PHONY: all
all: $(OUT)/foo.o

$(OUT)/%.o: %.c
    @$(COMPILE.C) -o $@ $<

It would be nice to be able to change the pattern rule so that it builds the directory automatically using marker files.

In GNU Make 3.81 there\'s an exciting new feature called \'second expansion\' (which is enabled by specifying the .SECONDEXPANSION target in the Makefile). 

About the author

AgileConnection is a TechWell community.

Through conferences, training, consulting, and online resources, TechWell helps you develop and deliver great software every day.