Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to prevent "directory already exists error" in a makefile when using mkdir

People also ask

What happens if you mkdir a directory that already exists?

mkdir WILL give you an error if the directory already exists. mkdir -p WILL NOT give you an error if the directory already exists. Also, the directory will remain untouched i.e. the contents are preserved as they were.

Why does mkdir not create directory?

mkdir: cannot create directory – Permission denied The reason for this error is that the user you're running the mkdir as, doesn't have permissions to create new directory in the location you specified. You should use ls command on the higher level directory to confirm permissions.


Looking at the official make documentation, here is a good way to do it:

OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)

$(OBJDIR)/%.o : %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

all: $(OBJS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
    mkdir -p $(OBJDIR)

You should see here the usage of the | pipe operator, defining an order only prerequisite. Meaning that the $(OBJDIR) target should be existent (instead of more recent) in order to build the current target.

Note that I used mkdir -p. The -p flag was added compared to the example of the docs. See other answers for another alternative.


On UNIX Just use this:

mkdir -p $(OBJDIR)

The -p option to mkdir prevents the error message if the directory exists.


You can use the test command:

test -d $(OBJDIR) || mkdir $(OBJDIR)

Here is a trick I use with GNU make for creating compiler-output directories. First define this rule:

  %/.d:
          mkdir -p $(@D)
          touch $@

Then make all files that go into the directory dependent on the .d file in that directory:

 obj/%.o: %.c obj/.d
    $(CC) $(CFLAGS) -c -o $@ $<

Note use of $< instead of $^.

Finally prevent the .d files from being removed automatically:

 .PRECIOUS: %/.d

Skipping the .d file, and depending directly on the directory, will not work, as the directory modification time is updated every time a file is written in that directory, which would force rebuild at every invocation of make.


If having the directory already exist is not a problem for you, you could just redirect stderr for that command, getting rid of the error message:

-mkdir $(OBJDIR) 2>/dev/null

Inside your makefile:

target:
    if test -d dir; then echo "hello world!"; else mkdir dir; fi