views:

75

answers:

5

I have an rule that creates a directory

bin:
    -mkdir $@

However after the first time the directory has been generated, I receive this output:

mkdir bin
mkdir: cannot create directory `bin': File exists
make: [bin] Error 1 (ignored)

Is there some way I can only run the rule if the directory doesn't exist, or suppress the output when the directory already exists?

A: 

The error is ignored already by the leading '-' on the command line. If you really want to lose the error messages from mkdir, use I/O redirection:

bin:
    -mkdir bin 2>&1

You will still get the 'ignored' warning from make, though, so it might be better to use the option to mkdir that doesn't cause it to fail when the target already exists, which is the -p option:

MKDIR_P = mkdir -p

bin:
    ${MKDIR_P} $@

The -p option actually creates all the directories that are missing on the given paths, so it can generate a a number of directories in one invocation, but a side-effect is that it does not generate an error for already existing directories. This does assume a POSIX-ish implementation of mkdir; older machines may not support it (though it has been standard for a long time now).

Jonathan Leffler
+1  A: 

You rule should not be executed unless its target does not exists or is out of date because of its dependencies. In other words, you should never encounter this error.

[Example Added]

[max@truth tmp]$ ls -la
total 20
drwxr-xr-x.  2 max users 4096 Aug 14 21:11 .
drwx------. 80 max max   4096 Aug 14 18:25 ..
-rw-rw-r--   1 max max     38 Aug 14 21:11 Makefile
[max@truth tmp]$ cat Makefile 
.PHONY: all
all: bin

bin:
    mkdir $@

[max@truth tmp]$ make
mkdir bin
[max@truth tmp]$ ls -la
total 24
drwxr-xr-x.  3 max users 4096 Aug 14 21:11 .
drwx------. 80 max max   4096 Aug 14 18:25 ..
drwxrwxr-x   2 max max   4096 Aug 14 21:11 bin
-rw-rw-r--   1 max max     38 Aug 14 21:11 Makefile
[max@truth tmp]$ make
make: Nothing to be done for `all'.
[max@truth tmp]$ make
make: Nothing to be done for `all'.

Does your folder depend on anything? Is your folder a phony target?

Maxim Yegorushkin
Nope. It's always out of date, what you see in the OP is what I have.
Matt Joiner
A: 

Well I ended up with this construct, maybe someone will find it useful or can comment on it:

BINDIR = .
TMPDIR = tmp
OUTDIRS = $(BINDIR) $(TMPDIR)
$(OUTDIRS):
    @test -d $@ || mkdir $@
Matt Joiner
Make does `test` for you anyway, so it ends up stat'ing the directory twice. This just hides the problem that the default target is .(dot).
Maxim Yegorushkin
+1  A: 

Make assumes the first target is the default target. If that is your complete makefile, then it must be always trying to remake the default target, which is bin. Insert the following lines to the top of your makefile:

all: bin
.PHONY: all
Maxim Yegorushkin
+1  A: 

The traditional way to handle directory creation is to use a stamp file that is depended on and creates the dir as a side effect. Remove the stamp file when making distclean or whatever your "really clean" target is:

bin/.dirstamp:
    mkdir -p $(DIRS)
    touch $@

bin/foo: bin/.dirstamp
    $(MKFOO) -o $@

distclean:
    rm -rf bin

The reason for this is as follows: whenever a file in bin is created/removed, the mtime of the containing directory is updated. If a target depends on bin, then the next time make runs, it will then recreate files that it doesn't need to.

Jack Kelly
Does the dir dep go on all the files generated into that location?
Matt Joiner
Every file created in that directory would need to depend, either directly or indirectly, on the stampfile to ensure that it was created before use.
Jack Kelly