我有一个make文件来构建一个使用bison和flex的简单pascal编译器,但是当我从终端运行make时,它显示正在调用yacc而不是bison。
我的Makefile:
all: minipascal
minipascal.tab.h minipascal.tab.c: minipascal.y
bison -r all -d minipascal.y
minipascal.flex.c: minipascal.l minipascal.tab.h
flex -o minipascal.flex.c minipascal.l
calc: minipascal.c minipascal.tab.c minipascal.lex.c
gcc minipascal.flex.c minipascal.tab.c minipascal.c -lf -o minipascal >& buildlog.txt
clean:
rm minipascal.tab.h minipascal.tab.c minipascal.lex.c buildlog.txt minipascal minipascal.output
我的路径中有野牛,当我逐行输入命令时,构建按预期工作。文件minipascal.h和minipascal.c存在于我运行make的当前目录中。
make命令的输出:
yacc minipascal.y
yacc: e - line 73 of "minipascal.y", syntax error
%empty {$$ = NULL;}
^
<builtin>: recipe for target 'minipascal.c' failed
make: *** [minipascal.c] Error 1
答案 0 :(得分:1)
如果您还有名为foo.c
或foo.y
的源文件,那么拥有一个名为foo.l
的源文件真的不是一个好主意。 make会高兴地覆盖foo.c
,让你争先恐后地备份。 (你有备份,对吧?)。如果您想使用其他源文件并且不想考虑其他名称,请使用其他后缀,例如foo.base.c
。 (或者您可以使用明确的空规则,如下所述。但是恕我直言,避免这个问题是安全的。)
make中可以将任何在makefile中命名的文件(无论是作为目标还是先决条件)视为可构建的文件。由于minipascal.c
被列为先决条件,这意味着minipascal.c
位于make准备构建的文件列表中。
您确实没有minipascal.c
的任何构建规则。但是make知道如何从%.c
或%.y
构建%.l
(%是一个通配符;它将被替换为目标中的相同字符串,先决条件。)
当make看到它需要minipascal.c
时,它首先检查是否有该文件的明确配方(没有),然后查看其默认的配方数据库。在这里,它找到了%.y → %.c
食谱和%.l → %.c
食谱。幸运的是,.y
食谱在其数据库中排在第一位,所以它尝试了。更幸运的是,配方在没有修改“目标”minipascal.c
的情况下失败了,因为配方是:
%.c: %.y
# recipe to execute (built-in):
$(YACC.y) $<
mv -f y.tab.c $@
并且来自yacc
的非零退出代码导致配方终止而不执行mv
命令。 .l食谱是:
%.c: %.l
# recipe to execute (built-in):
@$(RM) $@
$(LEX.l) $< > $@
如果符号不明显,则可以解决:
@rm minipascal.c
lex minipascal.l > minipascal.c
其中@
表示rm
命令不会回显到屏幕上。并不是说它有很大的不同,因为lex
命令中的重定向也会删除minipascal.c,即使lex
失败。
当然,make不会无条件地尝试重建minipascal.c
。它首先检查时间戳以确保重建是必要的。决定使用%.y
规则构建minipascal.c
后,它会比较minipascal.c
和minipascal.y
的时间戳。它决定重建minipascal.c
,因为野牛来源更新,所以它假设minipascal.c
文件已过时。
碰巧,您的all
规则取决于minipascal
,但没有规则可以构建minipascal
。有一条规则可以构建calc
,但make无法知道您的意思是minipascal
。
但这并不会停止make,因为它知道如何从minipascal
构建minipascal.c
(使用另一个默认规则)。决定这样做之后,它会继续验证minipascal.c
是否是最新的,如上所述。如果它确定minipascal.c
是最新的,那么它将使用其默认构建规则构建minipascal
,这也会因链接器错误而失败,因为它既不是解析器也不是词法分析器(也不是你的-lf
库)属于默认构建规则。
您的makefile也不一致地使用minipascal.flex.c
和minipascal.lex.c
。那也会让你感到悲伤。
如果您真的想要一个名为minipascal.c
的源文件,那么您需要通过提供一个空的构建规则来保护它免受自动构建:
minipascal.c: ;
但是,正如我所说,这可能不是最佳解决方案。