automake / autoconf / libtool オプション AC_ARG_ENABLE 条件式

AC_ARG_ENABLEではまった

初歩的な話ですが、automake, autoconf, libtoolを使ってconfigureのオプションを追加したときがあります。
具体的には./configureに対して、./configure –enable-hogeなど、環境によってオプションを追加したりします。
で、簡単な事なんだけど、小一時間はまったのでメモっておきます。

前提知識

autoconfでenableオプションを有効にするには以下の、マクロの知識が必要となります。
あと、libtoolなどの細かい説明はここでは割愛させていただきます。


AC_ARG_ENABLE(feature, help-text, [if-given], [if-not-given])
configureが受け取る追加のパッケージオプション(たとえば–enable-zlibなど)を指定することができる。アクションシェルコードは、シェル変数enablevalに設定されているすのオプションへの任意の引数にアクセスできる。たとえば–enable-buffers=128を使用すると、configureがenablevalを128に設定する。

AM_CONDITIONAL(name, testcode)
第一引数は条件の名前で、もう1つはその条件の真偽を判定するために使われるシェルステートメント。シェルコードtestcodeが成功(0)の状態を返す場合は、条件は真になる。configure.in内の条件は、自動的にそのプロジェクト内のどのMakefile.amでも使用可能になる。


configure.inの設定

この二つのマクロを使って、enableオプションを設定します。
いろいろ方法はあると思いますが、そして、この方法が一般的であるかどうかは一切保障がないのですが、僕は以下の方法で追加しています。

たとえば、fcgiというCGIのプログラムがあるのですが、通常の環境ではこれを使わず普通のCGIを使う、fcgiが入っている環境ではfcgiを有効にしたい。ということがあるとしますね。

そんなときはまず、configure.inに以下のような記述を書きます。

AC_ARG_ENABLE(fcgi, ## 1
AS_HELP_STRING([--enable-fcgi], [build with fcgi]), ## 2
enable_fcgi="$enableval", ## 3
enable_fcgi="no" ## 4
        )
AM_CONDITIONAL(ENABLE_FCGI, test "$enable_fcgi" = "yes") ## 5
  1. ##1のfcgiの部分、このオプションの名前となります。具体的には./configure-xxxのxxx部分の名前となります。
  2. ##2 は./configure –helpをしたときのヘルプメッセージとなります。同じ書式で書けばOKです。
  3. ##3 enableの時の処理です。enableオプションにしたときには$enable_fcgiはyesが代入されているので、enable_fcgiにyesが代入されます。
  4. ##4 はenableにしていないときの処理です、つまり、enable_fcgiがnoになります。
  5. ##5 はtestコマンドを使って、enable_fcgiがyesなら、ENABLE_FCGI、を有効にするという設定です。(テストコマンドについてはここらへんを参照してください)

Makefile.amの設定

Makefile.amには以下のようにして、条件分岐を作ってあげます。
./configure –enable-fcgiであれば、bin_PROGRAMSにhoge.fcgiというfcgiをinlucdeしたプログラムをビルドする、といった仕組みの場合です。

bin_PROGRAMS = main_prog
if ENABLE_INTERFACE
     bin_PROGRAMS += hoge.fcgi
endif

if ENABLE_INTERFACE
    hoge_fcgi_CPPFLAGS = -Wall
    hoge_fcgi_LDFLAGS  =  -lfcgi
    hoge_fcgi_SOURCES  = hoge.cpp
endif

簡単ではありますが、こんな感じでうまくいくと思います。
間違いなどがありましたらぜひご連絡くださいー。

Tags: , , ,

emacsですべての行を字下げ(tab)する

時々プログラムを書いていてif文が一個抜けたりしてすべての行に対して、tabを連打するという愚かな行為をしたりしています。そして何気にtabを連打している音がうるさい。
「すべての行を一気に字下げする方法あったんだけどな~」とか思いつつもtabを連打している。いや、あるんだから、使おうよということでメモしておくことにする。

- すべての行を選択する

C-x h または mark-whole-buffer

- 選択された行(region)を適切に字下げする

C-M-¥ または indent-region

これでtabをもう連打しなくてよい。
隣の人にも迷惑にならない。

Tags:

XZ Utilsを試してみた

XZ Utilsという圧縮ユーティリティの圧縮率がめちゃくちゃ良いとの噂を聞いてさっそく試してみた。
以下を参考にした。
http://oku.edu.mie-u.ac.jp/~okumura/blog/node/2409

 

Downloadは以下のサイトから。
http://tukaani.org/xz/

 

■実験に使ったファイル
- wikipediaのダンプファイル(XML)を解凍したもの
http://download.wikimedia.org/jawiki/latest/jawiki-latest-pages-meta-current.xml.bz2

 

■実行コマンド
- 圧縮
xz -z [入力ファイル] [出力ファイル]
xz -z current.xm current.xml.xz

- 結果
– 実行時間:81min
– 圧縮後サイズ 4.5G => 880MB

 

■比較
- bzip2
- 結果
– 実行時間13min
– 圧縮後サイズ 4.5 => 1015MB

 

■比較結果
- xzのほうが1.15倍圧縮された
- されどxzのほうが6.23倍時間がかかった

 

さあ、どちらを選択するか。

enumハック

実は、今Effective C++を読んでいる。
いわゆる、C++における入門書の次に読む本。

現在進行形でとても参考になっているので、ところどころメモっておこうと思う。

曰く、

単純な定数には、#defineより、constかenumを使うようにしよう。

Effective C++ p.8より

クラス定数なんかを定義するときに、enumで作っちゃうとよいよ、とのこと。
enumハックって名前がかっこいいから、なんとなくサンプル書いてメモっておく。

 
#include <iostream>
 
namespace TestClass {
  class SuperCls{
 
  private:
    /*************************************************************************** 
       enumハックといわれている、かっこいい名前のハック
       クラスに定数を作りたいときとかに便利
    ****************************************************************************/
    enum {
      A = 1,
      B = 2,
      C = 3,
    };
 
    /*************************************************************************** 
      enumハックじゃない場合の、クラス定数は以下のように作る
    ****************************************************************************/
    static const int Numval = 5;
 
  public:
    int get_numval() const {
      return Numval;
    }
 
    int get_B() const {
      int b = B;
      return b;
    }
  };
}
 
 
int main(void){
  std::cout << "konnichiwa sekai" << std::endl;
  TestClass::SuperCls cls;
  int num = cls.get_numval();
  std::cout << num << std::endl;
  int b = cls.get_B();
  std::cout << b << std::endl;
  return 0;   
}

何から手をつけたらいいのかわからない時

新しい企画を作る時や、プログラムの要件定義を作る時、ユースケースなどを考える時に、何から手をつけたらいいのかわからなくなる経験があるかと思います。
このエントリは小ネタだし、誰でも思い浮かぶことではあるのですが、メモ程度で、このような時の僕の取り組み方を記述します。

「問題の具体化・細分化」
なぜ、何から手をつけていいのかわからないかというと、今自分がやろう!としていることがよく見えていないからなんだと思うのです。
たとえば、ソーシャルブックマークのシステムを作ろう!と考えた時に、いざユーズケースを考えようとしても中々はかどらない。。。なんてことがあると思うんです。
そんな時は、対象物(ここでいうソーシャルブックマーク)という機能を実現させるために具体化・再分化してみるといいと思います。
いきなり全部の機能について仕様書やユースケースを書こうとしてしまうから、行き詰ってしうのであって、必要な細かい機能に分解してから書くとかなりすらすら書けたりします。

Aという機能を作りたいのであれば、まずAを実現させるためには、大きく分けてA-1、A-2、A-3という機能を作らなければならない。では、まずここから仕様書を書いてみよう。といった具合に。
たとえば、上記のソーシャルブックマークの場合だと、これを実現させるためには、まずフロントエンドの仕様を決めないとなりません。ユーザが任意のwebページにブックマークができることや、それを共有できることなどなど。これをA-1とすると、バックエンドでは、定期的にユーザのブックマークをカウントして、ランキングを生成したいといった機能をA-2とする。などなど、対象物を再分化することによって考えなければならないことがもりもり!と出てきます。

よく「とりあえず手を動かせ!そうすれば進みだすから!」みたいなことを聞くのですが、それは確かに事実だと思います。でも、「とりあえず!」というのができないときは、今一度今抱えている問題が何なのかを具体化・細分化してみることから初めてみませんか?これはプログラミングのみならず、企画にも応用できると思います。

※注意 プログラムを作る手順は人・流派によって最適な手法はまったく異なります。今回はあくまで、何かをしようとしたときに行き詰ったときの一例としてプログラミングを用いましたが、プログラミングの工程で今回の内容が最適であるとは思っておりません。

perlの使用メモリサイズを取得する

perlのプログラムを走らせていて、長時間走らせれば走らせるほど、そのプログラムのメモリサイズが増大していってしまうことがあります。
そのプログラムが何かしらのでデータをメモリ上にキャッシュしていくモデルならばそれは、当然のことなのですが、プログラムが巨大化すればするほど、いったいどのオブジェクトがメモリを食っているのか発見するのに困難になります。

そんなときは、Devel::Sizeが便利です。このモジュールは任意の配列や、ハッシュ、クラスオブジェクトに対して使用しているメモリサイズを計算することができます。

以下のようにインスタンスオブジェクトに対してtotal_size()を使うとそのオブジェクトのメモリサイズがわかります。異常にメモリを食ってしまうバグなどを生んでしまった時などに便利です!

#!/usr/bin/perl
 
use strict;
use warnings;
use Devel::Size qw/size total_size/;
 
use constant TEST_NUM => 100;
 
package Class1;
 
sub new {
my $class = shift;
my %hash;
my $self = { hash => \%hash };
return bless $self, $class;
}
 
sub add_key {
my $self = shift;
my $key = shift;
$self->{hash}->{$key}++;
}
 
sub get_key_num {
my $self = shift;
my $key_num = keys %{$self->{hash}};
return $key_num;
}
 
package main;
 
my $cl1 = Class1->new();
for(my $i = 0; $i < TEST_NUM; $i++) {
my $rand = rand(10000);
$cl1->add_key($rand);
my $key_num = $cl1->get_key_num();
my $mem_siz = total_size($cl1);
print "key_num:$key_num\tmem_siz:$mem_siz [$i]\n";
}

Tags: ,