|
|
By utahta, on 12月 12th, 2009%
条件コンパイルを試したメモ。
ある条件のときに、特定のソースコードをコンパイルから除外 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 + 使い方
ソースの条件コンパイル
By utahta, on 6月 10th, 2008%
書くと言いつつだいぶサボっていた 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
以上、メモでした。
By utahta, on 6月 2nd, 2008%
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 が使えなかったら
configure する
$ ./configure --prefix=/usr/local/hello
config.nice が出来ているか確認
次からの configure は、これだけでOK。
実にらくちん、手間いらず!(笑
–with とかいっぱいつけてると次に ./configure するときよくオプション忘れてるんですよね。
なので、結構重要な機能だと個人的には思ってます。
ということで config.nice 導入メモでした。
By utahta, on 6月 1st, 2008%
autotools + 使い方
autotools の基本的な使い方をざっくばらんにメモ。
テスト用のディレクトリを作成する
$ mkdir autotool
$ cd autotool
適当にソースコードを記述する
#include
int main()
{
puts("hello autotool.");
return0;
}
autoscan を実行する
出来た configure.scan をconfigure.ac に名称変更
$ mv configure.scan configure.ac
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 を作成する
bin_PROGRAMS = hello
hello_SOURCES = main.cpp
aclocal を実行する
autoheader を実行する
automake を実行する
-a は、足りないファイルを追加してくれるオプション
-c は、上のファイルをコピーしてくれるオプション。
もし足りないファイルがあると言われたら
昔の automake を使うと./ChangeLog’ not found などと言われる事がある。
そんなときは、空で良いので同名のファイルを作ってあげる。
$ touch README AUTHORS ChangeLog NEWS
autoconf を実行する
configure する
make する
出来たバイナリを実行してみる
$ ./hello
hello autotool.
配布したい場合
おしまい
以上、簡単な導入でした。
明日以降、–with オプションの付け方をメモする。
|
|