KPexEA
KPexEA

Reputation: 16778

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

I need to generate a directory in my makefile and I would like to not get the "directory already exists error" over and over even though I can easily ignore it.

I mainly use mingw/msys but would like something that works across other shells/systems too.

I tried this but it didn't work, any ideas?

ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif

Upvotes: 123

Views: 134702

Answers (12)

Mischa
Mischa

Reputation: 2298

A little simpler than Lars' answer:

something_needs_directory_xxx : xxx/..

and generic rule:

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

No touch-files to clean up or make .PRECIOUS :-)

If you want to see another little generic gmake trick, or if you're interested in non-recursive make with minimal scaffolding, you might care to check out Two more cheap gmake tricks and the other make-related posts in that blog.

Upvotes: 0

wmad
wmad

Reputation: 101

On Windows

if not exist "$(OBJDIR)" mkdir $(OBJDIR)

On Unix | Linux

if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi

Upvotes: 10

tchen
tchen

Reputation: 2242

On UNIX Just use this:

mkdir -p $(OBJDIR)

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

Upvotes: 128

ofavre
ofavre

Reputation: 4786

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.

Upvotes: 129

Andrew
Andrew

Reputation: 3061

If you explicitly ignore the return code and dump the error stream then your make will ignore the error if it occurs:

mkdir 2>/dev/null || true

This should not cause a race hazard in a parallel make - but I haven't tested it to be sure.

Upvotes: 0

Northern Stream
Northern Stream

Reputation: 381

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.

Upvotes: 19

skymt
skymt

Reputation: 3259

You can use the test command:

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

Upvotes: 72

lygstate
lygstate

Reputation: 561

It works under mingw32/msys/cygwin/linux

ifeq "$(wildcard .dep)" ""
-include $(shell mkdir .dep) $(wildcard .dep/*)
endif

Upvotes: 3

Martin Fido
Martin Fido

Reputation: 1090

$(OBJDIR):
    mkdir $@

Which also works for multiple directories, e.g..

OBJDIRS := $(sort $(dir $(OBJECTS)))

$(OBJDIRS):
    mkdir $@

Adding $(OBJDIR) as the first target works well.

Upvotes: 6

andrewdotnich
andrewdotnich

Reputation: 16804

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

Upvotes: 13

Michael McCarty
Michael McCarty

Reputation: 709

ifeq "$(wildcard $(MY_DIRNAME) )" ""
  -mkdir $(MY_DIRNAME)
endif

Upvotes: 7

Lee H
Lee H

Reputation: 5177

Inside your makefile:

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

Upvotes: 11

Related Questions