使用make生成bison语法
在使用 make
和 bison
的项目中,我很难指定编译的语法 grammar.tab.c
取决于语法输入grammar.y
,每个目标文件都依赖于相应的源文件(包括grammar.tab.o
),并且可执行文件依赖于所有目标文件。
问题是,在 Grammar.tab.c 尚不存在时运行 make
意味着不会尝试构建它,而当构建可执行文件时,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:
- 将在
make
命令上正确构建可执行文件,并根据需要重建中间文件。 - 将拾取目录中的所有
*.c
文件(即添加新源文件时不需要更改)。 - 易于阅读和理解。我不介意学习新的
make
功能,只要一次只学习一两个即可。
其他人的语法构建 Makefile 是如何工作的?
编辑好的,这些都是很好的答案。我选择了过滤器,因为这是最小的改变。我真的很高兴每个人似乎都确切地知道我在说什么——我很担心被告知使用像 automake 这样的拜占庭式的东西;-)。
谢谢大家。
In a project that uses make
and bison
, I'm having difficulty specifying that the compiled grammar grammar.tab.c
depends on the grammar input grammar.y
, that each object file depends on a corresponding source file (including grammar.tab.o
), and that the executable depends on all object files.
The problem is that running make
when grammar.tab.c does not yet exist means that there is no attempt to build it, and when the executable is built the yyparse
function is missing.
My Makefile
is:
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 lt; $(CFLAGS)
If I change it with:
OBJ=$(patsubst %.c, %.o, $(wildcard *.c)) grammar.tab.o
Then it will build the compiled grammar if it doesn't already exist. But if it does already exist, then
when building the executable, there will be an error about yyparse
being provided twice (presumably because $OBJ
contains grammar.tab.o
twice).
What I'm aiming for is a Makefile that:
- Will correctly build the executable on a
make
command, rebuilding intermediate files as necessary. - Will pick up all
*.c
files in the directory (i.e. doesn't need to be changed when new source files are added). - Is easy to read and understand. I don't mind learning new
make
features as long as it's only one or two at a time.
How do others' grammar-building Makefiles work?
Edit Ok, those are great answers. I went with the filter-out one, since it was the smallest change. I'm really glad that everyone seemed to know exactly what I'm talking about -- I was apprehensive about being told to use something byzantine like automake ;-).
Thanks everyone.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对于一般的“运行 yacc”规则,您需要类似的内容
要获取所需的所有源,
您需要“排序”主要是为了自动删除重复项
For the general 'run yacc' rule you want something like
To get all the sources you want
You need the 'sort' mostly for its automatic removal of duplicates
如果您使用的是 GNU make,则可以使用过滤谓词手动从目标的依赖项中排除特定文件。像这样:
OBJ=$(filter-out $(grammar.tab.o), $(patsubst %.c, %.o, ...)) Grammar.tab.o
。首先从现有对象文件中排除 Grammar.tab.o(它可能不存在),然后在所有情况下将其添加回来。诚然有点迂回,但它确实有效。这就是我们在工作中使用的。
If you're using GNU make, you can use the filter-out predicate to manually exclude a particular file from the dependencies of a target. Like so:
OBJ=$(filter-out $(grammar.tab.o), $(patsubst %.c, %.o, ...)) grammar.tab.o
.You first exclude grammar.tab.o from the existing object files (it might not be there), then add it back in all cases. Admittedly a bit roundabout, but it works. That's what we use at work.
这就是其中一个 .d 文件的样子。
您也可以使用 MAKEFILE_DEPS 变量来插入其他依赖项
This is what one of the .d files will look like
You can play around with the MAKEFILE_DEPS variable to insert other dependencies too