2

makeとを使用するプロジェクトではbison、コンパイルさgrammar.tab.cれた文法が文法入力grammar.yに依存すること、各オブジェクト ファイルが対応するソース ファイル (を含むgrammar.tab.o) に依存すること、および実行可能ファイルがすべてのオブジェクト ファイルに依存することを指定するのが困難です。

問題は、makegrammar.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

次に、コンパイルされた文法がまだ存在しない場合は構築します。しかし、それが既に存在する場合、実行可能ファイルをビルドするときに、yyparse2 回提供されるというエラーが発生します (おそらく、 2 回$OBJ含まれているためgrammar.tab.o)。

私が目指しているのは、次のような Makefile です。

  1. コマンドで実行可能ファイルを正しくビルドし、make必要に応じて中間ファイルを再ビルドします。
  2. ディレクトリ内のすべての*.cファイルを取得します (つまり、新しいソース ファイルが追加されたときに変更する必要はありません)。
  3. 読みやすく、理解しやすい。make一度に1 つか 2 つだけである限り、新しい機能を学ぶことは気にしません。

他の人の文法構築 Makefile はどのように機能しますか?

編集OK、それらは素晴らしい答えです。最小の変更だったので、フィルターを外したものを使用しました。私が話していることをみんなが正確に理解しているように見えて本当にうれしいです -- automake のような複雑なものを使うように言われるのが心配でした ;-)。

みんな、ありがとう。

4

4 に答える 4

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)))

主に重複を自動的に削除するために「ソート」が必要です

于 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 ファイルの 1 つがどのように見えるかです

/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 に答える