如何用多个文件编译yacc / bison?

时间:2014-06-02 11:25:48

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

我想调整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(但在源代码中已有特定的#include命令)

我直接使用此代码。当我在该目录中使用makefile时,它编译没有问题,但如上所示手动执行似乎不起作用。不幸的是,makefile对我来说看起来很神秘 - 因为我不是makefile-pro - 因此查找他们所做的事情并不容易。

感谢您提供建议,关于在哪里通过&#34;这些文件,以便可以正确地完成编译。

亲切的问候

[修改:] 可以在http://ymorin.is-a-geek.org/projects/kconfig-frontends找到kconfiglib的源代码。解析器的来源位于:/<path-to-kconfig>/libs/parser

1 个答案:

答案 0 :(得分:3)

这些构建问题与bison或flex实际上没什么关系。每次尝试构建复杂的软件项目而不使用项目的构建系统时,都会出现类似的问题。

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

./configure [options]

在顶级目录中,以创建构建项目所需的Makefile

通常,git存储库实际上并不包含configure脚本。相反,有必要使用autotools创建该脚本(和其他必要的配置文件)。

如果您使用的是发布tar包,则不需要弄清楚如何生成配置脚本,因为它包含在 中。因此,构建问题可能会更少。

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

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

conf_parse函数中找到yconf.y的底部。这里,ROOTMENU预计(我相信)是一个包含根菜单文件路径的字符串;该文件路径将是特定于安装的,因此它未在源中的任何位置定义。相反,它被注入Makefile,其中包含类似的行:

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

(它比这复杂得多;我很大程度上简化了这个过程。但libs/parser/Makefile.am中有一条线就像libs/parser/Makefile一样,你会在{{1}找到相关内容在最高级别运行./configure之后。)

make在需要构建目标文件时将CPPFLAGS - 即C预处理器标志 - 传递给C编译器。 (有许多这样的预定义变量;您可以在make的文档中找到一个列表。)gcc(以及大多数其他C编译器)将-DMACRO=value解释为&#34;在预处理这些源文件之前预定义MACROvalue&#34;。

结果是,您的宏的定义在源文件中的任何位置都不可见,除非您认为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&#34; yacc&#34;标志)变量。 (如果你知道自己在寻找什么,那么它们很容易找到,但这不是理由。)

对于它的价值,我会将此设置放入源文件中:

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

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

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

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