error in makefile

时光怂恿深爱的人放手 提交于 2019-12-23 16:45:46

问题


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 $(objdir)             \
fi

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


回答1:


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.




回答2:


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 


来源:https://stackoverflow.com/questions/4403861/error-in-makefile

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!