ttt

getttyent

最近Solarisでpkgsrcを使うとエラー /bin/sh: syntax error at line 1: `;' unexpected

2007-08-23 23:03:38 | デジタル・インターネット

FreeBSDでportsによるソフトウェア・パッケージ管理の快感を覚えてしまったので、FreeBSD以外のSolarisやLinux系などのOSでも(なぜかNetBSDは無いのですが・・・笑)、portsによく似た、pkgsrcを使っています。

さてさて、このごろ、Solaris9、Solaris10なホストで、pkgsrcを使って、bmakeコマンドでソフトウェアをビルドしようとすると、

/bin/sh: syntax error at line 1: `;' unexpected

というエラーがでるようになりました。

たとえば、こんな感じです。

# bmake
=> Required installed package digest>=20010302: digest-20070803 found
===> Skipping vulnerability checks.
=> Checksum SHA1 OK for php-5.2.3/php-5.2.3.tar.bz2
=> Checksum RMD160 OK for php-5.2.3/php-5.2.3.tar.bz2
===> Installing dependencies for php-5.2.3nb3
==========================================================================
The supported build options for php are:

        cgi fastcgi inet6 ssl

The currently selected options are:

        cgi inet6 ssl

You can select which build options to use by setting PKG_DEFAULT_OPTIONS
or the following variable.  Its current value is shown:

        PKG_OPTIONS.php (not defined)
/bin/sh: syntax error at line 1: `;' unexpected
*** Error code 2

Stop.
bmake: stopped in /usr/pkgsrc/lang/php5


bmake -n
してコマンドを抽出して、実行しなおしてみると、この部分がエラーになっていることがわかりました。

set -- dummy  "Deprecated variable "USE_INET6" set to "YES", use PKG_DEFAULT_OPTIONS+="inet6" instead.";  if test $# -gt 1; then /usr/ucb/echo; fi;  for l; do  if test "$l" = "dummy"; then continue; fi;  /usr/ucb/echo "$l";  done

ためしに、セミコロンで継続している部分を、改行して別々の行に分離してみると、エラーがでません。

少しずつ、セミコロンを置き換えてみて、問題となる箇所をしぼりこんでいくと・・・こんな内容のファイルhogehogeを、

set -- dummy  "Deprecated variable "USE_INET6" set to "YES", use PKG_DEFAULT_OPTIONS+="inet6" instead."
if test $# -gt 1
then /usr/ucb/echo
fi
for l ;  do  if test "$l" = "dummy"; then continue; fi
  /usr/ucb/echo "$l";  done

/bin/sh hogehogeして、実行してみると

hogehoge: syntax error at line 5: `;' unexpected

となるので、どうやらSolarisの/bin/shは、

for l ;  do  if test "$l" = "dummy"; then continue; fi

という書き方が、気に入らないようです(!?)。

ちなみに、上記のコマンドは、pkgsrc/mk/bsd.options.mkの以下の部分から作られているようです。

@${ECHO} "or "${PKG_OPTIONS_VAR:Q}"."
@set -- dummy ${PKG_OPTIONS_DEPRECATED_WARNINGS}; \
if ${TEST} $$# -gt 1; then ${ECHO}; fi; \
for l; \
do \
        if ${TEST} "$$l" = "dummy"; then continue; fi; \
        ${ECHO} "$$l"; \
done

しかし、/bin/shでエラーになる書き方でも、bashならOKなので、/etc/mk.confに、こんなのを書いてみました。

.SHELL: name=bash path=/bin/bash hasErrCtl=true \
       check="set -e" ignore="set +e" \
       echo="set -v" quiet="set +v" filter="set +v" \
       echoFlag=v errFlag=e

こうすると、Makefile中のコマンドが、/bin/shではなく、/bin/bashで実行されるようになるそうです。

こんなテクニックを、昔から知ってたわけじゃなくて、FreeBSDのmakeコマンド(GNU makeではなく、BSD系のmake)のマニュアルをざ~っと眺めて、あたりをつけたのち、pkgsrc/mk/platform/OSF1.mk のなかに、そっくりな記述を見つけたのでした。

# current bmake is broken, see pkg/25559

#.SHELL: name=ksh path=/bin/ksh hasErrCtl=true \
#       check="set -e" ignore="set +e" \
#       echo="set -v" quiet="set +v" filter="set +v" \
#       echoFlag=v errFlag=e

これを参考にしただけです。