portsのdevel/kdesdk3をportupgradeしたら、エラーになりました。
エラーが出た様子:
Making all in libgettext
gmake[4]: `/ports.work/usr/ports/devel/kdesdk3/work/kdesdk-3.5.9/kbabel/common/libgettext'
flex -+ -opofiles.cc ./pofiles.ll
/bin/sh /usr/local/bin/libtool --silent --tag=CXX --mode=compile c++ -DHAVE_CONFIG_H -I. -I../../.. -D_THREAD_SAFE -pthread -DQT_THREAD_SUPPORT -I/usr/local/include -I/usr/local/include -I/usr/local/include -D_GETOPT_H -D_THREAD_SAFE -Wno-long-long -Wundef -Wall -W -Wpointer-arith -DNDEBUG -DNO_DEBUG -O2 -O2 -fno-strict-aliasing -pipe -Wno-non-virtual-dtor -fno-exceptions -fno-check-new -fno-common -DQT_CLEAN_NAMESPACE -DQT_NO_ASCII_CAST -DQT_NO_STL -DQT_NO_COMPAT -DQT_NO_TRANSLATION -MT pofiles.lo -MD -MP -MF .deps/pofiles.Tpo -c -o pofiles.lo pofiles.cc
pofiles.cc:450:5: warning: "YY_STACK_USED" is not defined
pofiles.cc:1518:5: warning: "YY_MAIN" is not defined
In file included from pofiles.cc:249:
/usr/local/include/FlexLexer.h:130: error: expected unqualified-id before numeric constant
pofiles.cc: In member function 'virtual int GettextBaseFlexLexer::yylex()':
pofiles.cc:575: error: 'yy_current_buffer' was not declared in this scope
pofiles.cc:731: error: 'yy_current_buffer' was not declared in this scope
pofiles.cc:754: error: 'yy_current_buffer' was not declared in this scope
pofiles.cc: In constructor 'GettextBaseFlexLexer::GettextBaseFlexLexer(std::istream*, std::ostream*)':
pofiles.cc:871: error: 'yy_current_buffer' was not declared in this scope
pofiles.cc: In destructor 'virtual GettextBaseFlexLexer::~GettextBaseFlexLexer()':
pofiles.cc:883: error: 'yy_current_buffer' was not declared in this scope
pofiles.cc: In member function 'virtual void GettextBaseFlexLexer::switch_streams(std::istream*, std::ostream*)':
pofiles.cc:890: error: 'yy_current_buffer' was not declared in this scope
(以下略)
後半のエラーは、一番最初のエラー
/usr/local/include/FlexLexer.h:130: error: expected unqualified-id before numeric constant
をきっかけに発生していると思われるので、最初のエラーだけ調べてみます。
/usr/local/include/FlexLexer.h を見ると、130行目あたりはこんな感じ。
virtual int yylex();
virtual void switch_streams( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 );
virtual int yywrap();
「cc」に「-E」オプションをつけると、プリプロセッサを通した後のコードが見られるので、そうやってエラーが出た130行目(に相当する行)を見ると
virtual int yylex();
virtual void switch_streams( std:: istream* new_in, std:: ostream* new_out = 0 );
virtual int 1;
となってまして、「virtual int 1;」という意味不明な行があり、これがエラーになっているんでしょう。なんじゃこりゃ?!
pofiles.ccを見たら
#define yywrap() 1
というのがあるから、このマクロが展開されて「1」が出てきているようです。
実は、FlexLexer.hは、/usr/include/FlexLexer.h にもあって、似たような記述を探すと
virtual int yylex();
virtual void switch_streams( std::istream* new_in, std::ostream* new_out );
こっちには、yywrap()はありません。
これで、ピンときました。
上の「エラーが出た様子」のログで、flexが実行されていますが、
- flexは、/usr/bin/flexがつかわれていた
- includeされたFlexLexer.hは、/usr/local/include/FlexLexer.h だった
というわけで、ツールとヘッダファイルが食い違っているのでエラーが出ているのでした。
とりあえずPATHの順番を変えて
# setenv PATH /usr/local/bin:$PATH
/usr/local/bin/flexをつかわせることで、正常にコンパイルできるようになり、portupgradeが完了しました。
☆
だいたい、flexという名前のコマンドが、/usr/binと/usr/local/binの2箇所にあるのが、そもそも紛らわしいというか、混乱の元ですね。
# /usr/bin/flex --version
/usr/bin/flex version 2.5.4
# /usr/local/bin/flex --version
flex 2.5.35
/usr/local/bin/gflexとか、名前を変えてインストールしてくれればいいのにと思ったのですが、
http://sourceforge.net/projects/flex/
をみると、BSD Licenseになってるので、それじゃあgflexにはなりえませんか。
☆
そうか。
pofiles.ccってflexが生成したファイルです。
flex自身は、自分が、/usr/bin/flexなのか、/usr/local/bin/flexなのか区別はつくはずだし、flex自身をビルドした際に、FlexLexer.hがどこにインストールされるのか、flexに教えておくことはできるはずです。flexがpofiles.ccを生成するときに
#include "/usr/include/FlexLexer.h"
もしくは
#include "/usr/local/include/FlexLexer.h"
のどちらか、適切な方のコードを生成してくれていれば、上のような、違うヘッダファイルをインクルードしてしまう、ってことは無くなるんじゃないですかね?うまくいかないかな?
とはいえ、同名で別バージョンのコマンドをインストールするというのは、紛らわしいことですし、できるだけ避けるべきでしょう。