カテゴリー別アーカイブ: Autotools

Automake + 条件コンパイル

条件コンパイルを試したメモ。
ある条件のときに、特定のソースコードをコンパイルから除外 or 包含する。
libevent の configure を参考にしました。
通信システム(select, poll, epoll, …etc)の有無をチェックしてコンパイル対象を選択するとこが今回の目的にピッタリ。

書いたコード一覧

hello.c

#include <stdio.h>
#include <hello.h>
#include "config.h"
 
#ifdef HAVE_DOG
extern const struct helloop dogop;
#endif
#ifdef HAVE_CAT
extern const struct helloop catop;
#endif
 
const struct helloop *ops[] = { 
#ifdef HAVE_DOG
    &dogop,
#endif
#ifdef HAVE_CAT
    &catop,
#endif
    NULL
};
 
int main()
{
    int i;
    for( i = 0; ops[i] != NULL; ++i ){
        ops[i]->func( i );
    }   
    return 0;
}

hello.h

#ifndef HELLO_H_
#define HELLO_H_
 
struct helloop
{
    void (*func)(int);
};
 
#endif

dog.c

#include <stdio.h>
#include "hello.h"
 
static void func_dog( int num );
 
const struct helloop dogop = { 
    func_dog
};
 
static void func_dog( int num )
{
    printf( "Hello dog. num:%d\n", num );
}

cat.c

#include <stdio.h>
#include "hello.h"
 
void func_cat( int num );
 
const struct helloop catop = { 
    func_cat
};
 
void func_cat( int num )
{
    printf( "Hello cat. num:%d\n", num );
}

configure.ac

AC_PREREQ(2.59)
AC_INIT(automake-cond, 0.1, none)
AC_CONFIG_SRCDIR([hello.h])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE
AC_PROG_CC
 
# テストコード。
# yes なら dog.c をコンパイル対象に。
have_dog="yes"
if test "$have_dog" = "yes"
then
    AC_SUBST([COMPILE_OBJS], 'dog.$(OBJEXT)')
    AC_DEFINE(HAVE_DOG, 1, [Define dog.])
fi
 
# yes なら cat.c をコンパイル対象に。
have_cat="no"
if test "$have_cat" = "yes"
then
    AC_SUBST([COMPILE_OBJS], 'cat.$(OBJEXT)')
    AC_DEFINE(HAVE_CAT, 1, [Define cat.])
fi
 
AC_C_CONST
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

Makefile.am

bin_PROGRAMS = hello
hello_SOURCES = hello.c hello.h
EXTRA_hello_SOURCES = dog.c cat.c
hello_LDADD = @COMPILE_OBJS@
hello_DEPENDENCIES = @COMPILE_OBJS@

実行

configure.ac の中で have_dog=yes, have_cat=no と設定しているから最終的に dog.c がコンパイル&リンクされ func_dog() が呼ばれる。

$ ./configure
$ make
$ ./hello
Hello dog. num:0

参考

autotools + 使い方
ソースの条件コンパイル

autotools + with-mysql

書くと言いつつだいぶサボっていた autotools のメモ。

今回は、–with-mysql の付け方をメモ。

サンプルとして書いたコードが以下のもの。

#include <stdio.h>
#include <mysql.h>
int main()
{
	MYSQL	  sql;
	MYSQL_RES   *pres;
	MYSQL_ROW   row;
   if( !mysql_init( &sql))
   {
	   puts("init error.");
	   return0;
   }
   if( !mysql_real_connect( &sql,"localhost","root","root","testdb",0,NULL,0))
   {
	   puts("connect error.");
	   return0;
   }
   if( mysql_query( &sql,"SELECT count(*) from tb_test"))
   {
	   puts("query error.");
	   return0;
   }
   if( !( pres = mysql_store_result( &sql)))
   {
	   puts("store error.");
	   return0;
   }
   if( !( row = mysql_fetch_row( pres)))
   {
	   puts("fetch row error.");
	   return0;
   }
   printf("count = %s\n", row[0]);
   return0;
}

単純に testdb にコネクトして tb_test の行をカウントして表示しているだけ。

通常、これを make する場合、-I/usr/local/mysql/include などと INCLUDE 先や LIBS 先を
Makefileにハードコーディングする必要があります。

MySQL のインストール先が変わったりしたら、その度に vi で編集して。。。なんてメンドスギ!

そこで –with-mysql オプション。

./configure –with-mysql=/usr/local/mysql と指定すれば、自動でMakefileが記述されます。
MySQL のインストール先が違っても –with-mysql の指定先を変更して configure し直せばいいだけ!
すばらすぃー。

以下、configure.in に追加したコード。

# Checks for MySQL
AC_MSG_CHECKING([for MySQL])
AC_ARG_WITH([mysql],
		   [AS_HELP_STRING([--with-mysql=@<:@ARG@:>@],[path to'mysql_config' or path to mysql directory])],
		   [with_mysql=$withval],
		   [AC_MSG_RESULT([no])
			 AC_MSG_ERROR([MySQL is required.])])
find_mysql="no"
if test $with_mysql ="no"; then
	AC_MSG_ERROR([MySQL is required.])
fi
if test -d $with_mysql; then
	for mysql_config in"${with_mysql}/mysql_config""${with_mysql}/bin/mysql_config"
	do
		if test -x ${mysql_config}; then
			MYSQL_INCLUDE=`${mysql_config} --include`
			MYSQL_LIBS=`${mysql_config} --libs`
			MYSQL_LIBS_R=`${mysql_config} --libs_r`
			find_mysql="yes"
			break1;
		fi
	done
elif test -x ${with_mysql}; then
	MYSQL_INCLUDE=`$with_mysql --include`
	MYSQL_LIBS=`$with_mysql --libs`
	MYSQL_LIBS_R=`$with_mysql --libs_r`
	find_mysql="yes"
fi
AC_MSG_RESULT([$find_mysql])
if test $find_mysql ="no"; then
	AC_MSG_ERROR(['mysql_config' was not found. :${with_mysql}])
fi
AC_SUBST( MYSQL_INCLUDE)
AC_SUBST( MYSQL_LIBS)
AC_SUBST( MYSQL_LIBS_R)

指定されたディレクトリ配下の mysql_config を探しにいくやら、
もしくは、直接 mysql_config を指定してもらう形式。
mysql_config とは、コンパイルオプションを取得するスクリプト。

ソースからインストールしたら、mysql/bin に入っています。
RPMなどバイナリの場合は、MySQL-devel パッケージ が必要らしい。

AC_MSG_CHECKING は、checking … って表示されるやつ。
AC_ARG_WITH が –with をつけてくれるマクロ。
第2引数は、ヘルプ。第3引数は、指定した場合。第4引数は、指定していない場合に入る。

今回は、–with-mysql 無指定の場合、 AC_MSG_ERROR マクロで configure を中止させています。
また、見つからなかった場合も中止させています。

見つかったら、AC_SUBST で外部でも使えるようにします。

最後に Makefile.am

INCLUDES = @MYSQL_INCLUDE@
LIBS = @MYSQL_LIBS_R@
bin_PROGRAMS = hello
hello_SOURCES = main.cpp

@…@ で囲まれた変数が、シェル変数に置き換わります。

これでバッチリ。

あとは、configure を作り直して、再度configure を行えば終了。

$ autoreconf -i
$ ./configure –with-mysql=/usr/local/mysql
$ make
$ ./hello
count = 3

実行時にエラーが出る場合、おそらくライブラリを認識していない為。

ldconfig などを使って認識させるか、もしくは以下のようにすれば OK かと。
(とはいえ、このコードもスクリプト化して autotools 化しないと –with-mysql の意味がない)

$ LD_LIBRARY_PATH=/usr/local/mysql/lib/mysql ./hello

以上、メモでした。

autotools + config.nice

autotools のメモ2

configure.in に ./configure [引数] コマンドを記録する処理を加えた。

以下のコードを configure.in に追加
configure.in

#----------------------------------------------------------------
# Create config.nice
#----------------------------------------------------------------
conf_file="config.nice"
rm -f $conf_file
cat >$conf_file<<EOF
#! /bin/sh
#
# Created by configure
 
EOF
if test -n "$CC"; then
	echo "CC=\"$CC\"; export CC" >> $conf_file
fi
if test -n "$CFLAGS"; then
	echo "CFLAGS=\"$CFLAGS\"; export CFLAGS" >> $conf_file
fi
if test -n "$CPPFLAGS"; then
	echo "CPPFLAGS=\"$CPPFLAGS\"; export CPPFLAGS" >> $conf_file
fi
if test -n "$LDFLAGS"; then
	echo "LDFLAGS=\"$LDFLAGS\"; export LDFLAGS" >> $conf_file
fi
if test -n "$LTFLAGS"; then
	echo "LTFLAGS=\"$LTFLAGS\"; export LTFLAGS" >> $conf_file
fi
if test -n "$LIBS"; then
	echo "LIBS=\"$LIBS\"; export LIBS" >> $conf_file
fi
if test -n "$INCLUDES"; then
	echo "INCLUDES=\"$INCLUDES\"; export INCLUDES" >> $conf_file
fi
if test -n "$NOTEST_CFLAGS"; then
	echo "NOTEST_CFLAGS=\"$NOTEST_CFLAGS\"; export NOTEST_CFLAGS" >> $conf_file
fi
if test -n "$NOTEST_CPPFLAGS"; then
	echo "NOTEST_CPPFLAGS=\"$NOTEST_CPPFLAGS\"; export NOTEST_CPPFLAGS" >> $conf_file
fi
if test -n "$NOTEST_LDFLAGS"; then
	echo "NOTEST_LDFLAGS=\"$NOTEST_LDFLAGS\"; export NOTEST_LDFLAGS" >> $conf_file
fi
if test -n "$NOTEST_LIBS"; then
	echo "NOTEST_LIBS=\"$NOTEST_LIBS\"; export NOTEST_LIBS" >> $conf_file
fi
 
# Retrieve command-line arguments.
eval "set x $[0] $ac_configure_args"
shift
 
for arg
do
  	var=`eval "echo ${arg}"`
	echo "\"$var\" \\" >> $conf_file  	
done
 
echo '"[$]@"' >> $conf_file
chmod +x $conf_file

参考:APR

CC, CFLAGS 等に文字列が入っていたら、export するよう書き込み
$ac_configure_args に ./configure の引数が入ってるので、for で回して書き込み
var=`eval “echo $var”` で ‘ を取り除いて書き込み
最後に “$@” を書き込んで終了。

なぜ最後に “$@” をつけるのか、はっきりとは分からず。。。
“$@”じゃなく”"だと、build_alias= など余計なものも入るので、意味はある模様。
“” じゃなく空白なら大丈夫だった。
$@は、引数を表すものだから、./config.nice の場合、何も引数がないので、
空白すなわち \0 的な役割になるのかな?

変更したら autoreconf で configure 作り直し

$ autoreconf -i

autoreconf が使えなかったら

    $ aclocal
    $ autoconf

configure する

$ ./configure --prefix=/usr/local/hello

config.nice が出来ているか確認

目視。or
$ ls | grep nice

次からの configure は、これだけでOK。

    $ ./config.nice

実にらくちん、手間いらず!(笑

–with とかいっぱいつけてると次に ./configure するときよくオプション忘れてるんですよね。
なので、結構重要な機能だと個人的には思ってます。

ということで config.nice 導入メモでした。

autotools + 使い方

autotools + 使い方

autotools の基本的な使い方をざっくばらんにメモ。

テスト用のディレクトリを作成する

$ mkdir autotool
$ cd autotool

適当にソースコードを記述する

$ vi main.cpp
#include
int main()
{
	   puts("hello autotool.");
	   return0;
}

autoscan を実行する

$ autoscan

出来た configure.scan をconfigure.ac に名称変更

$ mv configure.scan configure.ac

configure.ac を編集する。

$ vi configure.ac

AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) を編集。
automake を使うので AM_INIT_AUTOMAKE を追加。
AC_CONFIG_FILES([Makefile]) を追加。

# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT( hoge-pkg,0.1, hoge@mail.com)
AC_CONFIG_SRCDIR([main.cpp])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE # automakeを使うので追加
# Checks for programs.
AC_PROG_CXX
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

Makefile.am を作成する

$ vi Makefile.am
bin_PROGRAMS = hello
hello_SOURCES = main.cpp

aclocal を実行する

$ aclocal

autoheader を実行する

$ autoheader

automake を実行する

$ automake -a -c

-a は、足りないファイルを追加してくれるオプション
-c は、上のファイルをコピーしてくれるオプション。

もし足りないファイルがあると言われたら
昔の automake を使うと./ChangeLog’ not found などと言われる事がある。
そんなときは、空で良いので同名のファイルを作ってあげる。

$ touch README AUTHORS ChangeLog NEWS

autoconf を実行する

$ autoconf

configure する

$ ./configure

make する

$ make

出来たバイナリを実行してみる

$ ./hello
hello autotool.

配布したい場合

$ make dist

おしまい

以上、簡単な導入でした。

明日以降、–with オプションの付け方をメモする。