36

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...

P Shved
  • 96,026
  • 17
  • 121
  • 165
Terrence Brannon
  • 4,760
  • 7
  • 42
  • 61
  • We already had a discussion on creating directories: http://stackoverflow.com/questions/1950926/create-directories-using-make-file. You might also want to know that [the way you create directories is not thread-safe](http://stackoverflow.com/questions/1894427/makefile-with-directory-tree-creation-suitable-for-parallel-j-build). – P Shved Jul 18 '10 at 12:33
  • @Pavel: the way the directory is created is fine, because it's a dependency of the file. In the example you cite, the problem is precisely that the directory is not a dependency of the targets that use it but of another target, which doesn't do any good. – Gilles 'SO- stop being evil' Jul 18 '10 at 14:02
  • @Gilles, ok, you're right, I mingled the issues. Just wanted to persuade you that directories as targets is not a good option... – P Shved Jul 18 '10 at 14:12

4 Answers4

33

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
Benjamin Bannier
  • 55,163
  • 11
  • 60
  • 80
  • 1
    True, and on general principles makefiles should always `&&` rather than `;`. However this can't be an issue here: `cd` only runs *after* the `yank` target has been remade. – Gilles 'SO- stop being evil' Jul 18 '10 at 13:59
  • 20
    I usually use a target of `dir/.dirstamp` instead of `dir` with a rule of `mkdir -p dir && touch $@`. The timestamps on dirs in unix change when the contents of the directory change preventing dependent rules from running. – docwhat Jan 31 '11 at 17:02
18

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

What you need is an order-only prerequisite.

A quick search didn't turn up any reference for makepp and order-only prerequisites, but it may still work.

Community
  • 1
  • 1
altendky
  • 4,176
  • 4
  • 29
  • 39
2

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
Craig
  • 4,268
  • 4
  • 36
  • 53
1

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.

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254