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個でした。

0 件のコメント:

コメントを投稿