【问题标题】:error in makefile生成文件中的错误
【发布时间】:2010-12-09 22:40:59
【问题描述】:

我正在使用 gnu Make 3.82 并且有一个烦人的问题。

我有一个规则设置目录之间的依赖关系。

OBJDIR=../obj

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

为此,obj 目录必须存在。 我想 mkdir 目录作为先决条件

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

$(objdir):
    mkdir $(objdir)

这不起作用,因为当目录存在然后make停止时它会失败 我试过壳

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

但显然我有问题。这样做的最佳方法是什么?

【问题讨论】:

标签: makefile directory


【解决方案1】:

一种简单的方法是使用:

mkdir -p ../obj

目录存在时不会失败。

我通常为此创建一个宏 MKPATH:

MKPATH = mkdir -p

然后在规则中引用宏:

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

这样,如果有必要,我可以在不更改 makefile 的情况下更改行为。


你的外壳片段:

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

因为 make 单独执行每一行,所以不能像写的那样工作。

你可以写(注意添加的分号):

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

或者:

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

或者:

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

注意命令行必须整体成功,请勿尝试:

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

如果目录存在,第一个替代方案失败,但 shell 以非零状态退出,因此失败......并导致构建失败。

【讨论】:

  • @Dov:你的规则说目标文件依赖于目标目录——这意味着如果目标文件自上次构建以来目标目录发生了变化(例如,因为你编译了另一个文件) ,那么您的文件需要重建。您的整体构建目标取决于现有的对象目录;单独的目标文件不需要仅仅因为目录改变而重建。
【解决方案2】:

mkdir

"mkdir -p"

变化:

$(objdir): mkdir $(objdir) 

到 =>

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

如果那个特定的 mkdir 没有 -p 那么:

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

生成文件

target: 和命令(mkdir 等)分开放置。

另外,在 make 中,要忽略失败的命令,在命令前加上 minus:

$(objdir):
    -mkdir $(objdir)

多行命令(if-then-else; for 循环等)需要添加 `\;'表示 shell 的换行符:

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

if-then-else 的这种特殊用法也可以写成:

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

下面的 Makefile 演示了上面的每个点

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

运行 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 

【讨论】:

  • 谢谢,目标和命令在不同的行,我尝试使用反斜杠来转义 \n 但它没有用。我很困惑你在分号前有一个反斜杠,这看起来像是一个错字?但是你至少有两个新的解决方案可以尝试,一个 -p 和一个测试 ||我会看看这些是否有效。
  • 我在 mkdir 上有一个前导 - 但这只是阻止错误显示,规则仍然失败
  • @Dov:没错,反斜杠在最后(更正)。但是,-mkdir(带有破折号)应该允许 make 继续:添加了经过测试的演示 Makefile。 GNU make 3.81, 3.82
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-02
  • 2011-10-14
  • 2023-03-26
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多