Звони бизону-у тебя без просьбы - PullRequest
1 голос
/ 22 марта 2011

Я пишу грамматику, которая называется 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, который делает это. Нет ошибок в процессе.

Итак, теперь я решил выучить 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 после бизона, никак.

Пока у меня заканчиваются идеи.

Есть ли способ предотвратить вызов второго бизона make? Или вызвать команду mv? Или обмануть, чтобы не перезаписывать мой файл portugol.c?

Спасибо! Бек

PS- Отредактировано. Использование:

 Ubuntu 10.04.2 LTS
 GNU Make 3.81

PPS. Ред. Незначительные опечатки.

PPPS. Ред. Отвечая на Ise wisteria:

Спасибо за ваш ответ. Я сохранил твой make-файл как makefile2 и попробовал. Ответ, который я получил от марки:

$ 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. Может быть, мы говорим о некоторой переменной среды здесь? Это также меняется с моим make-файлом:

$ 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. Отвечая на бета-версию. Ваш совет работает. Я позвонил make y.tab.c и получил простое:

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

Вот мой полный make-файл:

# 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 ]

6 голосов
/ 22 марта 2011

Проблема в том, что в make есть встроенные правила для создания файлов .c из файлов .y и .l, и именно эти встроенные правила запускаются и вызывают у вас горе.

С GNU makeВы можете отключить эти встроенные правила, переопределив их пустыми правилами.Поместите

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

в ваш make-файл и ваши проблемы должны исчезнуть.

Вы можете увидеть все встроенные правила GNU make, запустив make -p -f /dev/null

1 голос
/ 22 марта 2011

В принципе, не пытайтесь бороться с системой. Вы должны иметь возможность создавать portugol.o - и иметь три возможных исходных файла: portugol.l, portugol.y, portugol.c. Это как минимум в два раза больше.

Убедитесь, что базовые имена исходных файлов (за исключением расширения) являются уникальными. Например, используйте portugoll.l, portugoly.y и portugol.c с объектными файлами portugoll.o, portugoly.o и portugol.o. Или используйте более длинные суффиксы - portugol-lex.l, portugol-yacc.y. Или portlex.l, portyacc.y или ...

0 голосов
/ 22 марта 2011

Странно, насколько я тестировал с небольшими импровизированными файлами, проблема у вас упомянутое не произошло. Моя 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 $<

Надеюсь, это поможет

0 голосов
/ 22 марта 2011

Спасибо, Джонатан,

Итак, вы видите единственное решение, которое я тоже воспринял: изменить имя файла. Но, в этом-то и заключается вопрос. У меня нет проблем с использованием сценария. Если я вызываю bison -dy portugol.y из сценария оболочки flexyagcc.sh, это дает мне y.tab.c и y.tab.h. Почему не из makefile, это центральная точка!

Мне нравятся имена моих файлов, все они становятся такими связными: portugol.c: подпрограммы ручной работы, portugol.h: файл заголовка, portugol.l: сканер lex и portugol.y: анализатор. Кроме того, это не тот проект, который я сделал сегодня, так было уже много лет, много версий (сейчас 3.0). Таким образом, это не вариант для изменения имен файлов. Кроме того, я все равно получу portugol.c! Но это будет файл, автоматически сгенерированный из бизона, он же y.tab.c. Таким образом, очень странно перестать использовать portugol.c для ручных процедур и начать использовать одно и то же имя для парсера.

Я просто хочу знать, что происходит с make-файлом, и как я могу использовать его, чтобы заменить скрипт таким, какой он есть. Пока я не могу, к сожалению, я буду использовать сценарий. Сценарий очень прост:

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

Видите, я даже не удосужился иметь цели portugol.o, y.tab.o и lex.yy.o. Я пропускаю их создание, просто запустив gcc на источниках напрямую. Я также могу сделать это в make-файле, если после первой попытки уничтожить мой portugol.c, я переименую вручную созданный файл в y.tab.c.

Таким образом, проблема в том, что make-файл отличается от приведенного выше сценария попыткой создать следующее:

  • lex одинаково: portugol.l для обоих случаев (script и makefile)
  • бизон: автоматически изменяется с y.tab.c на portugol.c (здесь проблема!)
  • c код: мне нужно изменить portugol.c на что-то другое, например portugol-funcs.c

Спасибо за ваше внимание! Бек

...