如何兼容bison2.3和bison3.0.4版本

写这篇文章的目的,一方面是解决在句法分析器中的的版本不同,另外一方面可以扩展到其它软件的兼容性是否也可以采用类似方法解决。此文中最好需要有automake的基础来阅读这篇文章。

我们假设有一个工程,采用autoconf来进行编译。对于不同版本的bison,弄清楚其差异化点,对于bison2.3bison3.0.4来说,主要在于code段引用的方式不一样,bison2.3版本的句法文件MySampleParser.yy如下:

%{

#include <stdio.h>

#include <string>

#include <limits.h>

#include <ot/common.h>

BEGIN_OT_NAMESPACE(dsp);

class MySampleScanner;

END_OT_NAMESPACE(dsp);
...

%}

Makefile.am里面,需要添加:

AM_YFLAGS = -d

AM_LFLAGS = -olex.yy.c

noinst_LTLIBRARIES = libmysample_scanner.la

libmysample_scanner_la_SOURCES = MySampleParser.yy MySampleScanner.ll

CLEANFILES = MySampleParser.hh \

MySampleParser.cc \

stack.hh \

position.hh \

location.hh

值得注意的是,在MySampleParser.yy文件中,BEGIN_OT_NAMESPACE不会被C++编译器编译执行,所以使用automake解析的时候会出现找不到 namespace ot 的情况,这个时候需要在MySampleScanner.ll文件的code段中添加namespace,如:

%{

namespace ot

{

}

#include <string>

...

%}

当然MySampleScanner.h头文件一般不是自动生成,需要构造类MySampleScanner,且继承yyFlexLexer,但由于符号冲突的问题,需要在定义类MySampleScanner之前,对yyFlexLexer重新定义,像这样:

#ifndef __FLEX_LEXER_H

#define yyFlexLexer QueryFlexLexer

#include <FlexLexer.h>

#undef yyFlexLexer

#endif

但对于bison3.0.4版本来说,code段的表达方式发生了变化,需要采用如下描述:

% code requires{

#include <stdio.h>

#include <string>

#include <limits.h>

#include <ot/common.h>

BEGIN_OT_NAMESPACE(dsp);

class MySampleScanner;

END_OT_NAMESPACE(dsp);
...

}

了解到区别之后,如果需要兼容,应该怎么办呢?首先要获取到bison版本才能做下一步策略:

configure.ac里面(如果有m4的宏文件,也可以放置在m4文件中)添加:

dnl -------------------------------------------------------------------------

dnl Checks for bison version

dnl -------------------------------------------------------------------------

BISON_VERSION=$(bison --version | head -1 | awk '{print $ 4}')

AC_SUBST(BISON_VERSION)

AC_SUBST(BISON_VERSION_3_FLAG)

AC_SUBST(BISON_VERSION_2_FLAG)

AC_MSG_CHECKING([bison version])

AS_IF([test "$(echo "$BISON_VERSION 3.0.4" | tr " " "\n" | sort -rn | head -n 1)" == "$BISON_VERSION"], [

BISON_VERSION_3_FLAG="define HAVE_BISON_VERSION_3"

BISON_VERSION_2_FLAG="undef HAVE_BISON_VERSION_2"

], [

BISON_VERSION_3_FLAG="undef HAVE_BISON_VERSION_3"

BISON_VERSION_2_FLAG="define HAVE_BISON_VERSION_2"

])

AM_CONDITIONAL(ENABLE_BISON_VERSION_3, test "$(echo "$BISON_VERSION 3.0.4" | tr " " "\n" | sort -rn | head -n 1)" == "$BISON_VERSION" )

AC_MSG_RESULT([$BISON_VERSION])

这里面定义了四个重要的变量:

  • BISON_VERSION是用来记录bison的版本号;
  • BISON_VERSION_3_FLAGBISON_VERSION_2_FLAG是方便在C/C++的一些头文件中定义是版本3还是版本2,好做对应的处理;
  • ENABLE_BISON_VERSION_3是用来在Makefile.am里面用于条件判定

那么Makefile.am里面的条件判断可以写成如下所示:

AUTOMAKE_OPTIONS = foreign

dist_headers = $(wildcard *.h *.hh)

AM_CPPFLAGS = -I$(top_srcdir)/src \

$(NULL)

AM_LDFLAGS = $(NULL)

AM_YFLAGS = -d

AM_LFLAGS = -olex.yy.c

if ENABLE_BISON_VERSION_3

noinst_LTLIBRARIES = libmysample_scanner.la libmysample.la

libmysample_scanner_la_SOURCES = MySampleParser.yy MySampleScanner.ll

libmysample_scanner_la_DEPENDENCIES = MySampleParser.yy

MySampleParser.yy :

sed 's#%{#%code requires {#' MySampleParser.yy.in > MySampleParser.yy

else

noinst_LTLIBRARIES = libmysample.la

cc_files = MySampleParser.cc MySampleScanner.cc

endif

libmysample_la_SOURCES = XX.cpp $(cc_files) $(dist_headers)

if ENABLE_BISON_VERSION_3

libmysample_la_LIBADD = libmysample_scanner.la

else

libmysample_la_DEPENDENCIES = MySampleParser.hh

MySampleParser.hh : MySampleParser.yy libmysample_scanner.la

bison -o MySampleParser.cc MySampleParser.yy

endif

CLEANFILES = MySampleParser.hh \

MySampleParser.cc \

stack.hh \

position.hh \

location.hh

其中MySampleParser.yy.in写成和bison2.3版本的MySampleParser.yy一样即可。

通过此次调整,完美的解决了bison2.3bison3.0.4autoconf编译的冲突问题,类似的冲突也可以采用此方式解决。

Monthly Archives

Pages

Powered by Movable Type 7.7.2

About this Entry

This page contains a single entry by Cnangel published on October 17, 2016 5:31 PM.

VirtualBox5.1安装问题 was the previous entry in this blog.

Linux应用心得(四) is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.