2

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

问题是make在 Grammar.tab.c 还不存在时运行意味着没有尝试构建它,并且在构建可执行文件时yyparse缺少该函数。

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只要一次只有一两个,我不介意学习新功能。

其他人的语法构建 Makefile 是如何工作的?

编辑好的,这些都是很好的答案。我选择了过滤器,因为它是最小的变化。我真的很高兴每个人似乎都确切地知道我在说什么——我很担心被告知使用像 automake 这样的拜占庭式的东西 ;-)。

谢谢大家。

4

4 回答 4

5

对于一般的“运行 yacc”规则,您需要类似

%.tab.c: %.y
        $(YACC) $<

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

获取您想要的所有资源

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

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

于 2009-11-07T02:25:14.163 回答
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
于 2009-11-07T02:24:52.280 回答
0

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

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

于 2009-11-07T02:24:14.293 回答
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 变量来插入其他依赖项

于 2011-07-27T01:31:39.463 回答