使用make生成bison语法

时间:2009-11-07 02:03:18

标签: makefile bison compilation

在使用makebison的项目中,我很难指定编译的语法grammar.tab.c依赖于语法输入grammar.y,即每个目标文件取决于相应的源文件(包括grammar.tab.o),并且可执行文件依赖于所有目标文件。

问题是当grammar.tab.c尚不存在时运行make意味着没有尝试构建它,并且当构建可执行文件时,yyparse函数丢失。< / p>

我的Makefile是:

CFLAGS = -g -Wall
YACC = bison -d -r all
OBJ=$(patsubst %.c, %.o, $(wildcard *.c))
HEADERS=grammar.tab.h hex.h compiler.h types.h

all: grammar.tab.h c

clean:
    rm -f $(OBJ) *.tab.c *.tab.h c c.exe *.output

c: $(OBJ)
    $(CC) -o $@ $(OBJ) $(CFLAGS)

grammar.tab.c: grammar.y
    $(YACC) grammar.y

grammar.tab.h: grammar.y
    $(YACC) grammar.y

%.o: %.c $(HEADERS)
    $(CC) -c $< $(CFLAGS)

如果我改为:

OBJ=$(patsubst %.c, %.o, $(wildcard *.c)) grammar.tab.o

然后它将构建已编译的语法(如果它尚不存在)。但如果确实存在,那么 在构建可执行文件时,会出现两次yyparse提供错误的错误(大概是因为$OBJ包含grammar.tab.o两次)。

我的目标是Makefile:

  1. 将在make命令上正确构建可执行文件,并根据需要重建中间文件。
  2. 将获取目录中的所有*.c个文件(即添加新的源文件时不需要更改)。
  3. 易于阅读和理解。我不介意学习新的make功能,只要它一次只有一两个。
  4. 其他人的语法构建Makefile如何运作?

    编辑好的,这些都是很棒的答案。我选择了滤出器,因为它是最小的变化。我很高兴每个人似乎都知道我正在谈论的内容 - 我很担心被告知使用类似于automake的东西; - )。

    谢谢大家。

4 个答案:

答案 0 :(得分:5)

对于一般的'run yacc'规则,您需要类似

的内容
%.tab.c: %.y
        $(YACC) $<

%.tab.h: %.tab.c
        @touch $@

获取您想要的所有来源

OBJ=$(sort $(patsubst %.c, %.o, $(wildcard *.c)) $(patsubst %.y, %.tab.o, $(wildcard *.y)))

您需要'排序'主要是为了自动删除重复项

答案 1 :(得分:2)

# you can consolidate both rules into one:
grammar.tab.c grammar.tab.h: grammar.y
        $(YACC) grammar.y

# but I find ``make'' more workable without many-to-one target-to-prerequisites
grammar.tab.c: grammar.tab.h
        touch $@
grammar.tab.h: grammar.y
        $(YACC) $<


# your problem, though, does seem to be with linking ``grammar.tab.o''

# you can exclude grammar.tab.o
OBJ =: $(filter-out grammar.tab.o,$(patsubst %.c,%.o,$(wildcard *.c))) grammar.tab.o

# you can remove duplicates from $(OBJ)
OBJ =: $(sort $(patsubst %.c,%.o,$(wildcard *.c)) grammar.tab.o)

# you can remove duplicates when linking
c: $(OBJ)
        $(CC) $(LDFLAGS) -o $@ $(sort $^) $(LDLIBS)

# but personally, I prefer not to use $(wildcard) at all,
# explicitly updating the makefile as needed

答案 2 :(得分:0)

如果您正在使用GNU make,则可以使用过滤出谓词手动从目标的依赖项中排除特定文件。像这样:OBJ=$(filter-out $(grammar.tab.o), $(patsubst %.c, %.o, ...)) grammar.tab.o

首先从现有的目标文件中排除grammar.tab.o(可能不存在),然后在所有情况下将其添加回来。不可否认有点迂回,但它的确有效。这就是我们在工作中使用的东西。

答案 3 :(得分:0)

Something like this... you'll have to play around with it. This is kind-sort-a how
I did this in the 90's... it's unconventional but served its purpose

SRCS          = foo.c bar.c lex.c yacc.c
OBJS          = $(SRCS:%.c=$(OBJ_DEST_DIR)/%.o)
OBJS.d        = $(SRCS:%.c=$(OBJ_DEST_DIR)/%.d)
CC_RULE       = $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
YACC_RULE     = cd $(@D); $(YACC) $(YFLAGS) -o $(@F) $<
LEX_RULE      = cd $(@D); $(LEX) $(LEXFLAGS) -o$(@F) $<
CC_DEP_RULE   = @echo -n "$(@D)/" > $@;
CC_DEP_RULE   += gcc -M $(DEFINES) $(INCLUDES) $< |
CC_DEP_RULE   += sed -e 's@:@: $(MAKEFILE_DEPS) @' >> $@;

$(OBJ_DEST_DIR)/%.o: $(OBJ_DEST_DIR)/%.c
    $(CC_RULE)

$(OBJ_DEST_DIR)/%.c: $(SRC_DIR)/%.l
     $(LEX_RULE)

$(OBJ_DEST_DIR)/%.c: $(SRC_DIR)/%.y
    $(YACC_RULE)

$(OBJ_DEST_DIR)/%.o: $(SRC_DIR)/%.c
    $(CC_RULE)

$(OBJ_DEST_DIR)/%.d: $(OBJ_DEST_DIR)/%.c
    $(CC_DEP_RULE)

$(OBJ_DEST_DIR)/%.d: $(SRC_DIR)/%.c
    $(CC_DEP_RULE)

-include $(OBJS.d)

这是其中一个.d文件的样子

/tmp/builds/objs/opt/libiberty/static/alloca.o:   /tmp/src/binutils-2.20/libiberty/alloca.c \
  /tmp/src/binutils-2.20/libiberty/config.h \
  /tmp/src/binutils-2.20/include/libiberty.h \
  /tmp/src/binutils-2.20/include/ansidecl.h \
  /usr/lib/gcc/i686-apple-darwin10/4.2.1/include/stddef.h \
  /usr/lib/gcc/i686-apple-darwin10/4.2.1/include/stdarg.h \
  /usr/include/stdio.h /usr/include/_types.h /usr/include/sys/_types.h \
  /usr/include/sys/cdefs.h /usr/include/machine/_types.h \
  /usr/include/i386/_types.h /usr/include/secure/_stdio.h \
  /usr/include/secure/_common.h /usr/include/string.h \
  /usr/include/secure/_string.h /usr/include/stdlib.h \
  /usr/include/Availability.h /usr/include/AvailabilityInternal.h \
  /usr/include/sys/wait.h /usr/include/sys/signal.h \
  /usr/include/sys/appleapiopts.h /usr/include/machine/signal.h \
  /usr/include/i386/signal.h /usr/include/i386/_structs.h \
  /usr/include/sys/_structs.h /usr/include/machine/_structs.h \
  /usr/include/mach/i386/_structs.h /usr/include/sys/resource.h \
  /usr/include/machine/endian.h /usr/include/i386/endian.h \
  /usr/include/sys/_endian.h /usr/include/libkern/_OSByteOrder.h \
  /usr/include/libkern/i386/_OSByteOrder.h /usr/include/alloca.h \
  /usr/include/machine/types.h /usr/include/i386/types.h \

您可以使用MAKEFILE_DEPS变量来插入其他依赖项