(Gnu) make:具有特殊编译器开关的多个目标
(Gnu) make: multiple targets with special compiler switches
我在使联编文件工作时遇到问题。我有几个编译 XML 模式的解析器如下:
$(srcdir)/schema_1_parser.cpp: \
$(srcdir)/schema_1_parser.l \
$(srcdir)/schema_1_parser.tab.cpp
$(LEX) -Pschema_1 -o$(srcdir)/schema_1_parser.cpp \
$(srcdir)/schema_1_parser.l
$(srcdir)/schema_1_parser.tab.cpp $(srcdir)/schema_1_parser.tab.hpp: \
$(srcdir)/schema_1_parser.y
$(YACC) -ldv -p schema_1 -o $(srcdir)/schema_1_parser.tab.cpp \
$(srcdir)/schema_1_parser.y
有多个这样的规则对,使用 schema_2、schema_3 等。这些名称确实遵循我想尽可能利用的模式。 (目前我只有特殊规则。)
由于 makefile 错误 "Do not know how to make schema_1_parser.tab.hpp",我添加了第二个目标 $(srcdir)/schema_1_parser.tab.hpp
,即使 header 与 .tab.cpp 文件一起自动生成。
现在 bison 解析器被调用了两次。我仔细阅读了这篇文章,并相信这是具有多个目标的特殊规则的预期行为,我应该改用模式规则。但是,我有点不确定 flex 的命令行选项 -Pschema_1
和 bison 的 -p schema_1
是什么。我也可以使用该模式来处理这些问题吗? (我的经历是负面的,但我可能还漏掉了其他东西。)
嗯,我们不能给你一个完整的答案,因为你没有给我们展示任何其他规则,所以我们不知道它们之间有哪些模式是共同的。但是,是的,当然有多种方法可以处理您描述的情况。如果你的解析器都匹配模式 %_parser.y
和 %_parser.l
,你可以这样写规则:
$(srcdir)/%_parser.cpp: \
$(srcdir)/%_parser.l \
$(srcdir)/%_parser.tab.cpp
$(LEX) -P$* -o$@ $<
$(srcdir)/%_parser.tab.cpp $(srcdir)/%_parser.tab.hpp: \
$(srcdir)/%_parser.y
$(YACC) -ldv -p $* -o $(srcdir)/$*_parser.tab.cpp $<
因为 $*
扩展到模式的主干。
如果这不起作用,您可以使用递归变量:
NAME_schema_1_parser = schema_1
$(srcdir)/%.cpp: $(srcdir)/%.l $(srcdir)/%.tab.cpp
$(LEX) -P$(NAME_$*) -o$@ $<
$(srcdir)/%.tab.cpp $(srcdir)/%.tab.hpp: $(srcdir)/%.y
$(YACC) -ldv -p $(NAME_$*) -o $(srcdir)/$*_parser.tab.cpp $<
您还可以使用特定于目标或特定于模式的变量。
我在使联编文件工作时遇到问题。我有几个编译 XML 模式的解析器如下:
$(srcdir)/schema_1_parser.cpp: \
$(srcdir)/schema_1_parser.l \
$(srcdir)/schema_1_parser.tab.cpp
$(LEX) -Pschema_1 -o$(srcdir)/schema_1_parser.cpp \
$(srcdir)/schema_1_parser.l
$(srcdir)/schema_1_parser.tab.cpp $(srcdir)/schema_1_parser.tab.hpp: \
$(srcdir)/schema_1_parser.y
$(YACC) -ldv -p schema_1 -o $(srcdir)/schema_1_parser.tab.cpp \
$(srcdir)/schema_1_parser.y
有多个这样的规则对,使用 schema_2、schema_3 等。这些名称确实遵循我想尽可能利用的模式。 (目前我只有特殊规则。)
由于 makefile 错误 "Do not know how to make schema_1_parser.tab.hpp",我添加了第二个目标 $(srcdir)/schema_1_parser.tab.hpp
,即使 header 与 .tab.cpp 文件一起自动生成。
现在 bison 解析器被调用了两次。我仔细阅读了这篇文章,并相信这是具有多个目标的特殊规则的预期行为,我应该改用模式规则。但是,我有点不确定 flex 的命令行选项 -Pschema_1
和 bison 的 -p schema_1
是什么。我也可以使用该模式来处理这些问题吗? (我的经历是负面的,但我可能还漏掉了其他东西。)
嗯,我们不能给你一个完整的答案,因为你没有给我们展示任何其他规则,所以我们不知道它们之间有哪些模式是共同的。但是,是的,当然有多种方法可以处理您描述的情况。如果你的解析器都匹配模式 %_parser.y
和 %_parser.l
,你可以这样写规则:
$(srcdir)/%_parser.cpp: \
$(srcdir)/%_parser.l \
$(srcdir)/%_parser.tab.cpp
$(LEX) -P$* -o$@ $<
$(srcdir)/%_parser.tab.cpp $(srcdir)/%_parser.tab.hpp: \
$(srcdir)/%_parser.y
$(YACC) -ldv -p $* -o $(srcdir)/$*_parser.tab.cpp $<
因为 $*
扩展到模式的主干。
如果这不起作用,您可以使用递归变量:
NAME_schema_1_parser = schema_1
$(srcdir)/%.cpp: $(srcdir)/%.l $(srcdir)/%.tab.cpp
$(LEX) -P$(NAME_$*) -o$@ $<
$(srcdir)/%.tab.cpp $(srcdir)/%.tab.hpp: $(srcdir)/%.y
$(YACC) -ldv -p $(NAME_$*) -o $(srcdir)/$*_parser.tab.cpp $<
您还可以使用特定于目标或特定于模式的变量。