I have an rule that creates a directory
bin:
-mkdir $@
However after the first time the directory has been genera开发者_开发技巧ted, 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?
Another way to suppress the make: error ... (ignored)
output is to append || true
to a command that could fail. Example with grep that checks for errors in a LaTeX log file:
undefined:
@grep -i undefined *.log || true
Without the || true
, make complains when grep fails to find any matches.
This works for all commands, not just mkdir; that's why I added this answer.
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> /dev/null
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).
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.
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 $@
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?
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
精彩评论