Can a makefile have a directory as a target?

43.2k Views Asked by At

I am trying to say "the download of the git repository will only work if the directory yank/ exists. If the directory yank/ does not exist then make it"

yank/gist.el/gist.el : yank
    cd yank ; git clone http://github.com/defunkt/gist.el.git 

yank:
    mkdir yank

I am using makepp - http://makepp.sf.net and am getting the error:

[metaperl@andLinux ~/edan/pkg/gist.el] makepp
makepp: Loading makefile `/home/metaperl/edan/pkg/gist.el/Makeppfile'
makepp: Entering directory `/home/metaperl/edan/pkg/gist.el'
mkdir yank
mkdir: cannot create directory `yank': File exists
makepp: error: Failed to build target `/home/metaperl/edan/pkg/gist.el/yank' [1]
makepp: 0 files updated, 0 phony targets built and 1 target failed
[metaperl@andLinux ~/edan/pkg/gist.el] 

But why would it try to make the yank directory if it exists? The "source" has already ben created...

4

There are 4 best solutions below

2
On BEST ANSWER

Yes, a Makefile can have a directory as target.

Your problem could be that the cd doesn't do what you want: it does cd and the git clone is carried out in the original directory (the one you cded from, not the one you cded to). This is because for every command in the Makefile an extra shell is created. A workaround is to run cd and clone as one command with the shell's &&.

This should work:

bla/f: dir
    cd dir && touch f

dir:
    mkdir dir
0
On

Yes, a Makefile can have a directory as target.

However, you shouldn't. When a file is added or removed from a directory, its mtime is updated. This can cause weird behaviour by causing multiple targets depending on a single directory to become implicitly rebuilt by one another. So as a rule of thumb, you should avoid using directories as targets and/or dependencies..

all: d/a d/b

d/a d/b: d
  rm -f $@
  touch $@

d:
  mkdir $@

The output from running this multiple times looks like...

$ make
mkdir d
rm -f d/a
touch d/a
rm -f d/b
touch d/b

$ make
rm -f d/a
touch d/a

$ make
rm -f d/b
touch d/b

$ make
rm -f d/a
touch d/a
0
On

Your makefile should do what you expect. Since yank has no dependency, it won't be remade if it exists. So this looks like a bug in makepp. You could confirm this by trying your makefile with a traditional implementation of make.

1
On

In a makefile, is a directory name a phony target or "real" target?

What you need is an order-only prerequisite.

yank/gist.el/gist.el : | yank
    cd yank ; git clone http://github.com/defunkt/gist.el.git

yank:
    mkdir -p yank