开发者

error in makefile

I am using gnu Make 3.82 and have an annoying problem.

I have a rule setting dependencies between directories.

OBJDIR=../obj

$(objdir)/%.o: %.C
    $(COMPILE) -MM -MT$(objdir)/$(notdir $@) $< -o $(DEPDIR)/$(notdir $(basename $<).d )
$(COMPILE) -o $(objdir)/$(notdir $@ ) -c $<

In order to do this, the obj directory must exist. I want to mkdir the directory as a prerequisite

$(objdir)/%.o: %.C $(objdir)
    $(COMPILE) -MM -MT$(objdir)/$(notdir $@) $< -o $(DEPDIR)/$(notdir $(basename $<).d )
$(COMPILE) -o $(objdir)/$(notdir $@ ) -c $<

$(objdir):
    mkdir $(objdir)

This doesn't work, because it fails when the directory is there and then the make stops I tried shell

if [ ! -d $(objdir) ] ; then  \
  mkdir $(objdi开发者_Go百科r)             \
fi

but obviously I've got something wrong. What's the best way of doing this?


One simple way is to use:

mkdir -p ../obj

It doesn't fail when the directory exists.

I usually create a macro, MKPATH, for this:

MKPATH = mkdir -p

and then reference the macro in the rule:

$(objdir):
    $(MKPATH) $(objdir)

That way, I can change the behaviour without changing the makefile if it becomes necessary.


Your shell fragment:

if [ ! -d $(objdir) ] ; then
  mkdir $(objdir)
fi

does not work as written because make executes each line separately.

You could write (note the added semi-colon):

if [ ! -d $(objdir) ] ; then \
  $(MKPATH) $(objdir) ; \
fi

Or:

if [ ! -d $(objdir) ] ; then $(MKPATH) $(objdir); fi

Or:

[ -d $(objdir) ] || $(MKPATH) $(objdir)

Note that the command line must be successful overall, so do not try:

[ ! -d $(objdir) ] && $(MKPATH) $(objdir)

If the directory exists, the first alternative fails, but the shell exits with a non-zero status, thus failing...and causing the build to fail.


mkdir

"mkdir -p"

Change:

$(objdir): mkdir $(objdir) 

to =>

$(objdir): 
   mkdir -p $(objdir)

If that particular mkdir does not have -p then:

$(objdir): 
   test -d $(objdir) || mkdir $(objdir)

Makefiles

Keep the target: and the comands (mkdir, etc) on seperate lines.

Also, in make, to ignore failed commands, prefix command with minus:

$(objdir):
    -mkdir $(objdir)

Commands (if-then-else; for loops, etc) with multiple lines require adding `\;' to represent newlines to the shell:

$(objdir):
    if [ ! -d $(objdir) ] ; then \
      mkdir $(objdir) ; \
    fi

This particular usage of if-then-else can also written as:

$(objdir):
    if [ ! -d $(objdir) ] ; then mkdir $(objdir) ; fi

The following Makefile that demonstrates each point above

all: setup dirs report

# Create an intefering dir1
# Remove dir2.  It is work to be done later.
setup: 
    @mkdir -p dir1
    @if test -d dir2 ; then rmdir dir2 ; fi

# Continue (with dir2), even though dir1 re-creation fails
dirs:
    -mkdir dir1
    mkdir -v dir2

# Show we're still running
report:
    @echo DIRS:
    @for d in dir?;  do \
        test -d $$d || break ; \
        echo -n "$$d " ; \
    done
    @echo

Output from running running make:

mkdir dir1
mkdir: cannot create directory `dir1': File exists
make: [dirs] Error 1 (ignored)
mkdir -v dir2
mkdir: created directory `dir2'
DIRS:
dir1 dir2 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜