在没有被要求的情况下打电话给野牛

时间:2011-03-22 04:03:37

标签: makefile yacc bison lex

我正在编写一种语法,称为portugol。文件名是基本的,但我选择调用我的c程序portugol.c

所以,基本上,我必须这样做:

flex portugol.l      ==> lex.yy.c
bison -dy portugol.y ==> y.tab.c and y.tab.h
gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly  ==> portugol.bin

(我也有portugol.h,但这与问题无关)

很长一段时间以来,我正在使用一个名为flexyagcc.sh的shell脚本来执行此操作。这个过程没有错误。

所以现在我决定学习makefile

我面临的问题是,由于一些奇怪的原因,我调用的是“bison -dy”,后面是我没写过的命令:mv -f y.tab.c portugol.c

嗯,这会破坏我手工制作的源文件!

我尽我所能,但无法摆脱这种“mv”。

我甚至做过sleep并尝试过:

y.tab.c y.tab.h : portugol.y
    @echo --- bison -----------------------------------------------
    mv -f portugol.c ptg.c
    $(BISON) $(BFLAGS) portugol.y
    @echo --- bison sleeping --------------------------------------
    sleep 5
    -mv -f portugol.c y.tab.c
    -mv -f ptg.c portugol.c

但令我惊讶的是,我收到了以下事件(按此顺序):

$ make all o=pequeno
--- bison -----------------------------------------------
mv -f portugol.c ptg.c
bison -dy portugol.y
--- bison sleeping --------------------------------------
sleep 5
mv -f portugol.c y.tab.c
mv: cannot stat `portugol.c': No such file or directory
make: [y.tab.c] Error 1 (ignored)
mv -f ptg.c portugol.c
bison -dy portugol.y 
mv -f y.tab.c portugol.c

惊喜! mv命令是最后一个命令!不管我做什么。我创建了其他规则,只是为了让它最后发生(或者首先欺骗递归过程)。没门!我也使用了指令:.NOTPARALLEL.没办法。

我也尝试了同一行,确保它们以给定的顺序执行:

mv -f portugol.c ptg.c && $(BISON) $(BFLAGS) portugol.y && sleep 5 && mv -f portugol.c y.tab.c && mv -f ptg.c portugol.c

没有成功。

好吧,在我放弃之前,我决定使用标准的野牛输出。所以,我会:

flex portugol.l         ==> lex.yy.c
bison -d portugol.y     ==> portugol.tab.c and y.tab.h
gcc portugol.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly  ==> portugol.bin

但我仍然明白这一点:

--- bison -----------------------------------------------
bison -d portugol.y
bison -y portugol.y 
mv -f y.tab.c portugol.c

我之前尝试过chmod -w并且在野牛之后+w尝试过,{没法。

目前,我已经没想完了。

有没有办法阻止制作召唤第二个野牛?或者调用mv命令?或者欺骗它不要覆盖我的文件portugol.c

谢谢! 贝乔

PS-编辑。使用:

 Ubuntu 10.04.2 LTS
 GNU Make 3.81

PPS。编辑。小错字。

PPPS。编辑。回答伊势紫藤:

感谢您的回答。我已将您的makefile保存为makefile2并尝试过。我从make中得到的答案是:

$ make -f makefile2
bison -dy portugol.y
yacc  portugol.y 
mv -f y.tab.c portugol.c
gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly
gcc: y.tab.c: No such file or directory
make: *** [portugol.bin] Error 1

我还注意到“今天”第二次野牛呼叫不是野牛呼叫,而是yacc呼叫。也许我们在这里谈论一些环境变量?它也随我的makefile改变:

$ make all o=pequeno
--- bison -----------------------------------------------
bison --defines=y.tab.h --output=y.tab.c portugol.y
--- flex ------------------------------------------------
flex  portugol.l
yacc  portugol.y 
mv -f y.tab.c portugol.c

PPPPS。回答Beta。你的建议有效。我打电话给y.tab.c并得到一个简单的:

$ make y.tab.c
--- bison -----------------------------------------------
bison --defines=y.tab.h --output=y.tab.c portugol.y
$

这是我的完整makefile:

# Compila o compilador Portugol usando lex e yacc,
# e opcionalmente gera o .asm.c e o .bin
# a partir do fonte .ptg usando o novo compilador gerado.
#
#/*
#    arquivo: makefile
#    Autor: Ruben Carlo Benante
#    Email: ***@beco.cc
#    Data: 23/04/2009
#    Modificado: 22/03/2011
#    Versao: Portugol v3q
#*/
#
# Exemplo:
# ./flexyagcc portugol teste
#
# inicia os seguintes processos:
#      flex portugol.l                                          (gera lex.yy.c)
#      bison -dy portugol.y                                     (gera yy.tab.c e yy.tab.h)
#      gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly  (gera portugol.bin)
#
# inicia opcionalmente (ultimas linhas descomentadas):
#      portugol.bin teste.ptg teste.asm.c                (gera teste.asm.c)
#      gcc -x c teste.asm.c -o teste.bin -lm             (gera teste.bin)
#
#
# entrada:
#          portugol.l (arquivo em linguagem lex, analisador lexico)
#          portugol.y (arquivo em linguagem yacc, analisador sintatico)
#          portugol.c (arquivo em linguagem c, gerador de codigo)
# entrada opcional:
#          teste.ptg  (arquivo em linguagem portugol)
#
# saida:
#        lex.yy.c (saida do lex, em linguagem c)
#        y.tab.c  (saida do yacc, em linguagem c)
#        y.tab.h  (saida do yacc, definicoes da linguagem portugol)
#        portugol.bin (saida do gcc, arquivo executavel, finalmente o compilador portugol)
# saida opcional:
#        teste.asm.c   (saida do compilador portugol, arquivo em codigo de quadruplas)
#        teste.bin     (saida do gcc, arquivo executavel, o fonte .ptg em binario)
#
###################################### 
LEX     = flex
BISON = bison
BFLAGS  = --defines=y.tab.h --output=y.tab.c
CC = gcc
#CFLAGS = -g0 -O3 -Wall
CFLAGS = -g0
OBJS = y.tab.o lex.yy.o portugol.o
#OBJS = portugol.tab.o lex.yy.o portugol.o
DEPS =  portugol.h y.tab.h
SOURCES = y.tab.c lex.yy.c portugol.c
#SOURCES = portugol.tab.c lex.yy.c portugol.c

.PHONY : clean cleanall cleanptg run all makebug teste

.NOTPARALLEL :

#portugol.bin : lex.yy.c y.tab.c y.tab.h portugol.c portugol.h
portugol.bin : $(SOURCES) $(DEPS) $(OBJS)
    @echo --- gcc portugol ----------------------------------------
    $(CC) $(CFLAGS) $(OBJS) -o portugol.bin -lm -ly
#   gcc lex.yy.c y.tab.c portugol.c -o portugol.bin -lm -ly
#   $(CC) $(CFLAGS) $(SOURCES) -o portugol.bin -lm -ly

%.o : %.c
    @echo --- gcc objects -----------------------------------------
    $(CC) $(CFLAGS) -c $< -o $@

#portugol.tab.c y.tab.h : portugol.y
y.tab.c y.tab.h : portugol.y
    @echo --- bison -----------------------------------------------
    $(BISON) $(BFLAGS) portugol.y
#   @echo --- bison y.tab.c ---------------------------------------
#   mv -f portugol.c ptg.c
#   sleep 3
#   -mv -f portugol.c y.tab.c
#   -mv -f ptg.c portugol.c

lex.yy.c : portugol.l
    @echo --- flex ------------------------------------------------
    $(LEX) $(LFLAGS) portugol.l

teste :
    @echo --- testing ---------------------------------------------
    @echo $(o)

#Portugol -----------

%.asm.c : %.ptg portugol.bin
    @echo --- portugol --------------------------------------------
    ./portugol.bin $< $@

%.bin : %.asm.c
    @echo --- gcc asm ---------------------------------------------
    $(CC) -x c $< -o $@ -lm

run : $(o).bin
    @echo --- running! --------------------------------------------
    ./$(o).bin

all : $(o).bin

clean:
    -rm lex.yy.c y.tab.c y.tab.h *.o portugol.bin portugol.tab.c

cleanall:
    -rm lex.yy.c y.tab.c y.tab.h *.o *.bin

cleanasm:
    -rm *.asm.c

VPS。重要的编辑更新。注意可能表明真正的问题:

我将名称portugol.y更改为portugol.syn,问题已停止!

--- bison -----------------------------------------------
bison --defines=y.tab.h --output=y.tab.c portugol.syn
---------------------------------------------------------
那是怎么回事?在我看来,这表明make对文件“.y”有一些默认评估,现在我们需要回答这个问题,找出它的根源,以及如何禁用它。非常感谢。

4 个答案:

答案 0 :(得分:6)

问题是make有内置的规则来构建来自.y和.l文件的.c文件,正是这些内置规则被触发并引起你的悲痛。

使用GNU make,您可以通过使用空白规则覆盖这些内置规则来禁用它们。放

%.c: %.y
%.c: %.l

在你的makefile中,你的问题应该消失。

您可以通过运行make -p -f /dev/null

来查看所有GNU make的内置规则

答案 1 :(得分:1)

基本上,不要试图打击系统。您需要能够创建portugol.o - 并且有三个可能的源文件:portugol.lportugol.yportugol.c。至少有两个太多了。

确保源文件的基本名称(减去扩展名)是唯一的。例如,使用portugoll.lportugoly.yportugol.c,使用对象文件portugoll.oportugoly.oportugol.o。或者使用更长的后缀 - portugol-lex.lportugol-yacc.y。或portlex.lportyacc.y或......

答案 2 :(得分:0)

谢谢乔纳森,

所以你看到我也认识到的一个解决方案:更改文件的名称。但是,这就是问题的关键所在。我使用脚本没有问题。如果我从shell脚本bison -dy portugol.y中调用flexyagcc.sh,则会向我y.tab.cy.tab.h。为什么不从makefile,这是中心点!

我喜欢我的文件名,它使所有内容如此连贯:portugol.c:手工例程,portugol.h:头文件,portugol.l:lex扫描程序和portugol.y:解析器。此外,这不是我今天制作的一个项目,它已经存在多年了,很多版本(现在3.0)。因此,不能更改文件名。除此之外,我最终会以portugol.c结束!但它将是一个从野牛自动生成的文件,即y.tab.c。因此,停止使用portugol.c来制作手工例程并开始使用相同的名称来获得解析器是非常令人困惑的。

我只想知道makefile发生了什么,我怎样才能用它来替换脚本。虽然我不能,但不幸的是,我将使用该脚本。脚本非常简单:

flex portugol.l
bison -dy portugol.y
gcc y.tab.c lex.yy.c portugol.c -o portugol.bin -lm -ly

请参阅,我甚至不打算实现目标portugol.oy.tab.olex.yy.o。我只是直接在源上运行gcc来跳过创建它们。我也可以在makefile中执行此操作,如果在第一次尝试销毁我的portugol.c之后,我会手动将创建的文件重命名为y.tab.c

所以问题是makefile与上述脚本的不同之处在于尝试创建以下内容:

  • lex相同:portugol.l两种情况(脚本和makefile)
  • bison:自动从y.tab.c更改为portugol.c(此处问题!)
  • c代码:我需要将portugol.c更改为其他内容,例如portugol-funcs.c

感谢您的关注! 贝乔

答案 3 :(得分:0)

奇怪的是,就我用小型即兴文件测试而言,问题就在于此 提到没有发生。 我make的版本是GNU 3.80 有关您的信息,以下是我使用的makefile

portugol.bin: y.tab.c lex.yy.c portugol.c
        gcc $^ -o $@ -lm -ly

y.tab.c: portugol.y
        bison -dy $<

lex.yy.c: portugol.l
        flex $<

希望这有帮助