ラベル GZIP の投稿を表示しています。 すべての投稿を表示
ラベル GZIP の投稿を表示しています。 すべての投稿を表示

2016-03-19

configureが生成するCプログラムの抽出

gzip-1.4をOpenVMS alphaでコンパイルしてみるためにはlib/config.hが必要です。このファイルはconfigureによって作成されますが、OpenVMSではconfigureが動かないので手作業で作らなければなりません。configureは自動化されているとはいえ、内部ではCプログラムを生成し、コンパイルをおこない、実行させた結果をみて設定値を決めています。configureがどのようなCプログラムを生成しようとしているのかが分かれば、OpenVMS alphaの設定値を決める参考になるでしょう。

configureを変更して、生成しようとしているCプログラムと、そのコンパイル方法を表示させるようにしてみました。
--- configure.org       2016-03-16 16:07:02.148767000 +0900
+++ configure   2016-03-16 16:13:11.852319000 +0900
@@ -1992,6 +1992,9 @@
 {
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
   rm -f conftest.$ac_objext
+  echo "#+++#ac_fn_c_try_compile#$as_lineno#$(eval $(echo $ac_compile | sed -e 's/>&5//' -e 's/.*/echo &/'))"
+  cat conftest.c
+  echo "#---#"
   if { { ac_try="$ac_compile"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
@@ -2029,6 +2032,9 @@
 ac_fn_c_try_cpp ()
 {
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  echo "#+++#ac_fn_c_try_cpp#$as_lineno#$(eval $(echo $ac_compile | sed -e 's/>&5//' -e 's/.*/echo &/'))"
+  cat conftest.c
+  echo "#---#"
   if { { ac_try="$ac_cpp conftest.$ac_ext"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;

この変更を加えたconfigureを実行すると、次のように#+++#から#---#の間に生成しようとしているソースが表示されます。
checking for suffix of object files... o
checking whether we are using the GNU C compiler... #+++#ac_fn_c_try_compile#4267#gcc -c conftest.c
/* confdefs.h */
#define PACKAGE_NAME "gzip"
#define PACKAGE_TARNAME "gzip"
#define PACKAGE_VERSION "1.4"
#define PACKAGE_STRING "gzip 1.4"
#define PACKAGE_BUGREPORT "bug-gzip@gnu.org"
#define PACKAGE_URL ""
#define PACKAGE "gzip"
#define VERSION "1.4"
/* end confdefs.h.  */

int
main ()
{
#ifndef __GNUC__
       choke me
#endif

  ;
  return 0;
}
#---#
yes
checking whether gcc accepts -g... #+++#ac_fn_c_try_compile#4305#gcc -c -g conftest.c
ここからCプログラムを抜き出してOpenVMS alpha上でコンパイルしてみれば良いのですが、手作業で切り出すのは大変なので簡単なツールを作りました。今まではsh、sed、awkなどを組み合わせて作っていましたが、今回はpythonを使う事にしました。pythonは気にいっている言語で、今後も多用したいと思っています。提供されているライブラリが便利なことに驚き、とても気持ちよく作成できました。
  1. OptionParseライブラリを使えば、コマンドラインのオプションを解析するだけでなく、ヘルプ・メッセージや、バージョン表示オプションなども出せるようになるので、便利でした。
  2. fileinputライブラリを使うと、処理対象となる入力ファイルがコマンドラインで指定されても、標準入力から与えられても、気にせずに処理できるので、楽でした。
     1  #! /usr/local/bin/python
     2  # -*- coding: utf-8 -*-
     3  # genconftest.py -- configureの実行ログファイルからconftest.cを抽出
     4  def main():
     5      import fileinput
     6      import os.path
     7      import sys
     8      from optparse import OptionParser
     9
    10      parser = OptionParser(
    11          usage="usage: %prog [options] [logfile]",
    12          version="$Id: genconftest.py,v 1.5 2016-03-18 11:54:12 furusawa Exp $")
    13      parser.set_defaults(verbose=0)
    14      parser.add_option('-v', '--verbose',
    15                        action='count', dest='verbose',
    16                        help='make lots of noise')
    17      parser.add_option('-q', '--quiet',
    18                        action='store_const', dest='verbose', const=0,
    19                        help="be vewwy quiet (I'm hunting wabbits)")
    20      parser.add_option('-d', '--directory',
    21                        dest='dirname',
    22                        default="conftest",
    23                        help="Output files into the directory")
    24      (opts, args) = parser.parse_args()
    25
    26      if len(args) >= 2:
    27          sys.exit("Too many logfiles")
    28
    29      if os.path.isdir(opts.dirname) == False:
    30          sys.exit("%s:Directory not found" % opts.dirname)
    31
    32      if opts.verbose >= 2:
    33          sys.stderr.write("opts.verbose:%d\n" % opts.verbose)
    34          sys.stderr.write("opts.dirname:%s\n" % opts.dirname)
    35
    36      writing = False
    37      for line in fileinput.input(args):
    38          if fileinput.isfirstline() and opts.verbose >= 2:
    39              sys.stderr.write("read from:%s\n" % fileinput.filename())
    40
    41          if '#+++#' in line:
    42              writing = True
    43              l = ['/*\n', line, '*/\n']
    44              x = line.split("#")
    45              filename = "%s/conftest_%s_%d.c" % (opts.dirname,
    46                                                  x[3],
    47                                                  fileinput.lineno())
    48              continue
    49          if '#---#' in line:
    50              if opts.verbose >= 1:
    51                  sys.stderr.write("write to:%s\n" % filename)
    52              f = open(filename, 'w')
    53              f.writelines(l)
    54              f.close()
    55              writing = False
    56          if writing:
    57              l += line
    58
    59  if __name__ == '__main__':
    60      main()
    61  # $Id: genconftest.py,v 1.5 2016-03-18 11:54:12 furusawa Exp $

configureの結果を処理してみたところ、108個のCプログラムが生成されました。そのうちac_fn_c_try_compileによるものは105個、ac_fn_c_try_cppによるものは5個でした。

2016-03-12

configureで生成されたconfig.hの修正

gzip 1.4のlib/config.hを確認してみたところ、configureで自動的に調整された項目が300弱ほどありました。もっと少なければOpenVMS用に手作業で闇雲に変更してもなんとかなるかもしれませんが、流石に多すぎます。何か統一的な方法に基づいて変更をおこなわないと、後々大事になりそうな気がします。

このファイルはconfigureが生成したものですから、OpenVMS上でconfigureが動けば言うこともありませんが、それは無いものねだりと言うべきでしょう。Microsoft Windows上でCygwin環境を動かすように、OpenVMS上でposix環境を構築すれば、見かけ上ではconfigureが動作するかもしれませんが、できればネイティブのDCL上で「configure的な動作」をして貰いたいところです。

configureがconfig.hを生成するにあたり、個々の設定値を決定するために内部でおこなっている処理がわかれば、同じようなことを手作業で確認することで、対処できるのではないかと素朴に考えています。configure自体はシェルスクリプトですから、簡単ではないかもしれませんが、可能性はあると考えています。

2016-03-10

gzip 1.4のファイルを展開してコンパイルしようとして躓く

OpenVMS alphaのディスクをFreeBSD/i386からNFSでマウントすることができるようになったので、gzip-1.4.tar.gzをFreeBSD/i386側にあるtar+gzipを使いOpenVMS alpha上のディスクに展開してみました。ただしNFSでエクスポートする設定に「/options=(name_conversion)」を指定しないと、OpenVMSにおけるファイル名規約のため展開できませんでした。展開すると以下に示しようなファイルが現れました。「name_conversion」をつけているのでOpenVMS側から見ると余分な記号などがついています。
 Directory DISK$USER:[FURUSAWA.GZIP-1$5N4]

$AUTHORS.;1         $C$HANGE$L$OG-2007.;1                   $C$HANGE$L$OG.;1
$COPYING.;1         $GNU$MAKEFILE.;1    $INSTALL.;1         $M$AKEFILE.AM;1
(以下略)
まず[.GZIP-1$5N4.VMS]$R$EADME.VMSにある「a) MAKEZIP.COM」の記述に従ってコンパイルしようとしたらエラーになりました。
$ @[.vms]makegzip

#include <config.h>
.^
%CC-F-NOINCLFILE, Cannot find file <config.h> specified in #include directive.
at line number 57 in file DISK$USER:[FURUSAWA.GZIP-1$5N4]GZIP.C;1
 config.hが見つからないというエラーですが、gzipに限らず普通ならconfigureを走らせることで作られるファイルです。

「Gzip 1.5 for VMS (1.5b)」 で提供されるtarballではgzip-1_5b_vms/vms/config.h_vmsが用意されています。その先頭には次のようなコメントが入っています。
 /* config.h_vms 1.5.  Generated manually (from Tru64).  2012-08-28 SMS. */
/* lib/config.h.  Generated from config.hin by configure.  */
/* lib/config.hin.  Generated from configure.ac by autoheader.  */
つまりOpenVMS以外(この場合はTru64)でconfigureを走らせてconfig.hを生成し、その後に手作業で修正したということなのでしょう。

gzip-1.4.tar.gzを展開するとVMSディレクトリの下にファイルが用意されているので、直ちにコンパイルできるものと考えていましたが、そういう訳ではなかったようです。まずはconfig.hを生成してみようと思います。OpenVMSではconfigureが動かないので、今回はFreeBSD/i386を使おうと思います。将来的にはconfigureがOpenVMSでも動くと良いと思いますが、既に実現されているのでしょうか。

2016-03-08

OpenVMS alphaとFreeBSD/i386との間のファイル交換

OpenVMSにgzipを移植するにあたり、gzip-1.4.tar.gzを展開して出てくるファイルを如何にしてOpenVMS上に持ってくれば良いのかが課題になります。一般論としてはOpenVMS上のgzipやtarを使って展開すれば良いわけですが、そのgzipやtarを移植しようとしている訳ですから、過渡期としてのブートストラップ対応が必要になります。いろいろな方法が考えられるかと思いますが、ここではFreeBSD/i386で展開させて、出てきたファイルをOpenVMS alphaにコピーすることにします。

このファイル転送をおこなうために、FTPを使うか、NFSを使うか考える必要があります。さらにOpenVMS alphaとFreeBSD/i386のいずれをサーバとするかを考える必要もあります。これらの組み合わせは4通りになります。
  1. OpenVMS alphaをFTPサーバとし、FreeBSD/i386のFTPクライアントからファイルを送りこむ。
  2. FreeBSD/i386をFTPサーバとし、OpenVMS alphaのFTPクライアントでファイルを受け取る。
  3. OpenVMS alphaをNFSサーバとし、FreeBSD/i386をNFSクライアントとして接続しファイルを送りこむ。
  4. FreeBSD/i386をNFSサーバとし、OpenVMS alphaをNFSクライアントとして接続しファイルを受け取る。
FTPの使用は、設定が簡単ですし、ファイル転送も容易ですが、gzip-1.4のようにディレクトリ構造が複雑に分かれているとディレクトリ構造を保ちつつファイルを転送するのは簡単ではありません。NFSならディレクトリ構造を保ったファイル転送は容易ですが、設定がFTPほど簡単ではありません。

上述した4通りを試してみて違いを比較しようと思います。