【问题标题】:How to compile yacc/bison with multiple files?如何用多个文件编译 yacc/bison?
【发布时间】:2014-06-02 11:25:47
【问题描述】:

我想调整 kconfig-libs (/<path-to-kconfig>/libs/parser) 的 yacc-parser。但是我在解析各种符号、变量、函数、令牌等方面遇到了问题。我想问题是,编译时并未包含 kconfig-parser 的所有文件。这是我的工作:

lex lconf.l
bison -d -y ./yconf.y 
gcc -o yconf y.tab.c

我收到如下错误消息:

./yconf.y 499:44: Error: >>ROOTMENU<< not declared (first use in this function)
rootmenu.prompt = menu_add_prompt(P_MENU, ROOTMENU, NULL);
                                          ^

./yconf.y:576:2: Error: »zconfnerrs« not declared (first use in this function)
zconfnerrs++;
^

./yconf.y:546:3: Error: »zconfnerrs« not declared (first use in this function)
zconfnerrs++;
^

解析器的目录中有更多文件(.c 和 .h),(我猜)需要包含在编译器进程中:hconf.c, lconf.c util.c symbol.c menu.c expr.c confdata.c, lkc.h lkc_proto.h(但在源代码中已经有特定的 @ 987654326@ 命令)

我直接使用此代码。当我在该目录中使用 makefile 时,它​​可以毫无问题地编译,但是像上面显示的那样手动执行它似乎不起作用。不幸的是,makefile 对我来说看起来相当神秘 - 因为我不是 makefile 专业人士 - 所以查找他们做了什么并不容易。

感谢有关“传递”这些文件的位置的建议,以便正确完成编译。

亲切的问候

[编辑:] kconfiglib 的源代码可以在http://ymorin.is-a-geek.org/projects/kconfig-frontends 找到。解析器的源码位于:/&lt;path-to-kconfig&gt;/libs/parser

【问题讨论】:

  • 请问您是从哪里下载这些文件的吗?并非我们所有人都对宇宙中的全部源存储库有百科全书式的了解,了解更多细节会有所帮助。
  • 对不起,我忘了这个。我在顶部帖子的末尾添加了来源

标签: parsing compiler-errors bison yacc flex-lexer


【解决方案1】:

这些构建问题实际上与 bison 或 flex 几乎没有关系。每当您尝试在不使用项目的构建系统的情况下构建复杂的软件项目时,都会出现类似的问题。

所以简单的答案是kconfig-frontends项目是使用自动工具构建的,这意味着你应该执行

./configure [options]

在顶级目录中以创建构建项目所需的Makefiles。

像往常一样,git 存储库实际上并不包含configure 脚本。相反,有必要使用自动工具创建该脚本(和其他必要的配置文件)。

如果您使用的是发行版 tarball,则无需弄清楚如何生成配置脚本,因为它包含在 tarball 中。因此,您可能会遇到更少的构建问题。

顺便说一句,源代码管理不是一个简单的问题,关于如何做到这一点有很多不同的意见。问题之一是在构建过程中对源文件进行修改是很常见的,例如为了配置特定于平台的默认值。例如,采取以下行:

rootmenu.prompt = menu_add_prompt(P_MENU, ROOTMENU, NULL);

yconf.y 底部的conf_parse 函数中找到。这里,ROOTMENU 应该(我相信)是一个包含根菜单文件路径的字符串;该文件路径将是特定于安装的,因此它没有在源代码中的任何地方定义。相反,它被注入到Makefile 中,其中将包含如下一行:

CPPFLAGS = -DROOTMENU="\"$(root_menu)\"" -DCONFIG_=\"$(config_prefix)\" ...

(比这更复杂;我大大简化了过程。但是在libs/parser/Makefile.am 中有类似的一行,在顶层运行./configure 后,您会在libs/parser/Makefile 中找到相关内容.)

make 在需要构建目标文件时将 CPPFLAGS(即 C 预处理器标志)传递给 C 编译器。 (有很多这样的预定义变量;您可以在make 的文档中找到一个列表。)而gcc(和大多数其他C 编译器)将-DMACRO=value 解释为表示“将MACRO 预定义为value before预处理这些源文件”。

结果是您的宏的定义在源文件的任何地方都不可见,除非您认为automake 的输入文件是源文件的一部分。除非您了解这些宏,否则您无法在不使用捆绑的构建系统的情况下编译文件。

以上是 C/C++ 源代码发行版的标准问题。您遇到的另一个问题很容易避免(我认为),但也很常见。

flexbison 都带有一个选项,可以将生成的代码中的前缀 yy 更改为其他内容。如果您的项目中有多个解析器或扫描器,则需要这样做;否则会出现像yylex 或(在这种情况下)yynerrs 这样的全局符号的冲突。 kconfig 项目使用前缀zconf,因此符号zconfnerrs 是解析器每次报告语法错误时递增的全局变量。但要使其正常工作,您需要在使用bison 生成解析器和使用flex 生成扫描器时设置前缀。

前缀可以在命令行选项中设置,也可以在bisonflex 源文件中设置。与上面描述的魔术宏一样,使用命令行选项会使设置不那么明显。此外,如果前缀未设置为预期值,生成的代码可能无法编译并且肯定不会链接。因此,我更喜欢在源文件中设置前缀,但并不是每个人都同意这个观点,显然,包括你正在尝试构建的包的作者。

我在顶级configure文件中找到了设置:

AM_LFLAGS="-L -P zconf"
AM_YFLAGS="-t -l -p zconf"

这些设置用于为 Makefile 创建LFLAGS(flex 标志)和YFLAGS(bison “yacc”标志)变量。 (如果您知道自己在寻找什么,它们很容易找到,但这不是借口。)

为了它的价值,我会把这个设置放到源文件中:

  /* Flex (.l) file: */
%option prefix="zconf"

  /* Bison (.y) file: */
%define api.prefix "zconf"

其他命令行选项不太重要,但如果需要,它们也可以在源文件中设置。

我不知道为什么使用-l/-L 标志:它们导致bison/flex 省略#line 指令,这些指令将生成的文件链接到.y/.l 文件中的源行号;如果没有这些指令,调试会更加痛苦。 bison -t 标志使 bison 包含用于“跟踪”解析的代码,尽管您仍然必须将全局变量 yydebug(或在这种情况下为 zconfdebug)设置为非零值才能进行跟踪要实际生产。强烈推荐使用-t,因为它成本低并且可以简化调试,但是没有它,项目应该可以正常构建。

【讨论】:

  • 哇!结果很好。我没想到会有这么精确的答案,这非常有帮助,我非常感谢。只是为了您的兴趣:我必须在 makefile 的 bison 行上使用 -t 选项,否则他无法解析“zconfdebug”。此外,您的帖子信息让我对 bison/flex/yacc/lex 的世界更加清晰。感谢您的支持
  • @user3085931:如果没有-t 标志到bison 项目将无法构建,那么您最好将指令%debug 包含在yconf.y 文件中。这做同样的事情,并且不需要构建系统的任何支持。 (但是,它不适用于除bison 之外的yacc 实现,这实际上与我建议的%define api.prefix 行相同。我应该编辑答案以提及这一点。明天。)
  • 感谢您的建议。两种方法有区别吗?是不是一样,只是在不同的时间调用?
  • @user3085931:唯一的区别是它使源文件更加独立。没有“电话”;该选项仅用于生成 C 文件。 (设置yydebug 实际上是导致跟踪发生的原因;%debug 选项将yydebug 的测试插入到 C 文件中。)在我看来,需要特定的源文件特定的选项设置应该包括该选项,而不是对正确的构建命令具有未记录的依赖关系。然而,显然不是每个人都同意这种观点。
  • 同意该意见
猜你喜欢
  • 2011-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-01
  • 2017-04-14
  • 1970-01-01
相关资源
最近更新 更多