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
You can use the test command:
test -d $(OBJDIR) || mkdir $(OBJDIR)
On Windows
if not exist "$(OBJDIR)" mkdir $(OBJDIR)
On Unix | Linux
if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi
$(OBJDIR):
mkdir $@
Which also works for multiple directories, e.g..
OBJDIRS := $(sort $(dir $(OBJECTS)))
$(OBJDIRS):
mkdir $@
Adding $(OBJDIR)
as the first target works well.
On Windows
if not exist "$(OBJDIR)" mkdir $(OBJDIR)
On Unix | Linux
if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi
ifeq "$(wildcard $(MY_DIRNAME) )" ""
-mkdir $(MY_DIRNAME)
endif
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.
$(OBJDIR):
mkdir $@
Which also works for multiple directories, e.g..
OBJDIRS := $(sort $(dir $(OBJECTS)))
$(OBJDIRS):
mkdir $@
Adding $(OBJDIR)
as the first target works well.
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.
It works under mingw32/msys/cygwin/linux
ifeq "$(wildcard .dep)" ""
-include $(shell mkdir .dep) $(wildcard .dep/*)
endif
$(OBJDIR):
mkdir $@
Which also works for multiple directories, e.g..
OBJDIRS := $(sort $(dir $(OBJECTS)))
$(OBJDIRS):
mkdir $@
Adding $(OBJDIR)
as the first target works well.
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
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.
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.
ifeq "$(wildcard $(MY_DIRNAME) )" ""
-mkdir $(MY_DIRNAME)
endif
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
You can use the test command:
test -d $(OBJDIR) || mkdir $(OBJDIR)
ifeq "$(wildcard $(MY_DIRNAME) )" ""
-mkdir $(MY_DIRNAME)
endif
Inside your makefile:
target:
if test -d dir; then echo "hello world!"; else mkdir dir; fi
You can use the test command:
test -d $(OBJDIR) || mkdir $(OBJDIR)
It works under mingw32/msys/cygwin/linux
ifeq "$(wildcard .dep)" ""
-include $(shell mkdir .dep) $(wildcard .dep/*)
endif
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
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.
ifeq "$(wildcard $(MY_DIRNAME) )" ""
-mkdir $(MY_DIRNAME)
endif
Inside your makefile:
target:
if test -d dir; then echo "hello world!"; else mkdir dir; fi
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.
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.
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.
Inside your makefile:
target:
if test -d dir; then echo "hello world!"; else mkdir dir; fi
Source: Stackoverflow.com