Win32とUNIXで条件分け

只今、メルマガ向けのSocketプログラミングをしているところですが(UNIX版は終了)、同じソースで条件分けする際にヘッダーファイルで定義しないとダメのかなと思っていたら、コンパイラ自身である程度定義が入っているとネット上の情報で発見。実際はコンパイル時に必ず読み込まれるヘッダー辺りにも書いていると思いますが、その内容の今回使用する部分を抜粋。

GCC(UNIX系)の場合
#define __GNUC__

Windowsの場合
#define _WIN32

つまり、ヘッダーファイルの名前が違うとか、ライブラリ関数の差異を埋めるためには、

#ifdef __GNUC__
// ここにUNIX版の処理を記述
#endif
#ifdef
// ここにWindows版の処理を記述
#endif

このようにすればOK

参考:Hey! Java Programming! –移植性–http://www.mars.dti.ne.jp/~torao/program/general/portability.html

厳格にコンパイル

この前から、基本ライブラリはincludeしなくてもコンパイルが通ってしまう件について、コンパイルオプションで厳格にチェックが可能かググってみた。すぐに見つかりました。UNIXでC言語の授業あったのになにやってたんだろオレ。確か98年頃だったかな…。

まずは、-Wallオプション。これで#include忘れを解消。ワーニングがなくなるまで続ける。
あとは -02とか-04ってあるけど今のところは気にしなくてもいいかな。

参考:gccのデバッグ術
http://www-or.amp.i.kyoto-u.ac.jp/algo-eng/db/debug.html

autoconf automake libtoolをインストール

ずっとconfigureの書き方について検索していたらautoconfとツールに辿り着いた。あれは手書きじゃなかったのか?とりあえず入れておくと後々便利そうなのでインストールすることに、

因みに、私の環境ではgnu m4を別途インストールする必要があった、makeの時と同じで最小構成で入っているm4ではautoconfのインストールが出来なかった。libtoolの必要性は不明だが多くのサイトで3つを一緒に扱っているので念のためインストール

コマンドと順序は次の通り
# tar zxvf m4-1.4.4.tar.gz
# cd m4-1.4.4
# ./configure
# make
# make install

何も設定せずインストールされたのでシステムの/usr/bin/m4は上書きされず/usr/local/bin/m4としてインストールされたので/usr/bin/m4はリネームした。

# tar zxvf libtool-1.5.20.tar.gz
# cd libtool-1.5.20
# ./configure
# make
# make install

# tar zxvf autoconf-2.59.tar.gz
# cd autoconf-2.59
# ./configure
# make
# make install

# tar zxvf automake-1.9.tar.gz
# cd automake-1.9
# ./configure
# make
# make install

インストールできたので早速使ってみる。

ソースファイルがあるディレクトリで
> autoscan
autom4te: configure.ac: no such file or directory
autoscan: /usr/local/bin/autom4te failed with exit status: 1

これでconfigure.scanが作られるのでこれを参考にconfigure.acを作る。
> cat configure.scan

# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ(2.59)
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
AC_CONFIG_SRCDIR([bench.c])
AC_CONFIG_HEADER([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
AC_OUTPUT

作ったconfigure.acは以下の内容
AC_PREREQ(2.59)
AC_INIT(bench, 1.0.0, no-define)
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([bench.c])
AC_PROG_CC
AC_OUTPUT(Makefile)

configure.acの作成が終わったら、Makefile.amの作成に入る。
> vi Makefile.am

bin_PROGRAMS = hello
hello_SOURCES = hello.c

ソース1個ならこれだけでOK
次に必要なファイルを準備するため(?)aclocalを使う。

> aclocal

これで*.m4ファイルなど自動生成。
そしてautomakeする。
> automake -a -c
configure.ac: installing `./install-sh’
configure.ac: installing `./missing’
Makefile.am: installing `./INSTALL’
Makefile.am: required file `./NEWS’ not found
Makefile.am: required file `./README’ not found
Makefile.am: required file `./AUTHORS’ not found
Makefile.am: required file `./ChangeLog’ not found
Makefile.am: installing `./COPYING’
Makefile.am: installing `./depcomp’

これでも4つ準備しなければいけないファイルがあるが唯のテキストなのでダミーで誤魔化す。

> touch NEWS
> touch README
> touch AUTHORS
> touch ChangeLog

> automake -a -c
これでautomakeが成功してMakefile.inが生成されたので最後にautoconfで仕上げる。
> autoconf
configureの出来上がり。

実際に使ってみた。
> ./configure
checking for a BSD-compatible install… /usr/bin/install -c
checking whether build environment is sane… yes
checking for gawk… no
checking for mawk… no
checking for nawk… nawk
checking whether make sets $(MAKE)… yes
checking for gcc… gcc
checking for C compiler default output file name… a.out
checking whether the C compiler works… yes
checking whether we are cross compiling… no
checking for suffix of executables…
checking for suffix of object files… o
checking whether we are using the GNU C compiler… yes
checking whether gcc accepts -g… yes
checking for gcc option to accept ANSI C… none needed
checking for style of include used by make… GNU
checking dependency style of gcc… gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands

> make
if gcc -DPACKAGE_NAME=”bench” -DPACKAGE_TARNAME=”bench” -DPACKAGE_VERSION=”1.0.0″ -DPACKAGE_STRING=”bench 1.0.0″ -DPACKAGE_BUGREPORT=”no-define” -DPACKAGE=”bench” -DVERSION=”1.0.0″ -I. -I. -g -O2 -MT hello.o -MD -MP -MF “.deps/hello.Tpo” -c -o hello.o hello.c; then mv -f “.deps/hello.Tpo” “.deps/hello.Po”; else rm -f “.deps/hello.Tpo”; exit 1; fi
gcc -g -O2 -o hello hello.o

試しに使ってみたし生成されたconfigureやMakefile.inをみてみたが大きすぎてカスタマイズの方法が探れなかった。1ソースなのに生成されるテキストでか過ぎ…。

Makefile書くのは今のところ困ってないので変数変換のカラクリを解析してautoconfのみするかconfigure直書きを目指してみよう。