2011/12/14
cvs や svn のリビジョン番号
	プログラムを作成する際、
	特にまだ未完成で頻繁に修正とコンパイルを繰り返している間は、
	どのリビジョンのプログラムを実行しているのか知りたい事はよく有る。
	そんな時に、例えば実行時オプションとして -v を指定すると
	cvs や svn のリビジョン番号とコミットした日時が表示されると便利だ。
	しかし、多くの場合において -v オプションを解析し実行するだろう
	main 関数が含まれるファイルが最終修正されているとは限らない。
	従って main 関数の含まれるファイル中に
	
static char *id = "$Id$";などと定義しておいて commit 時に $Id$ を展開したとしても、 必ずしも最新のリビジョンにはならない場合が多い。
そこで -v オプションのハンドラ部分では
static char *id = "revision: " REVISION ", " COMMITED ;と記述としておいて make 時に自動で REVISION と COMMITED を全てのソース/ヘッダファイル中の cvs や svn の $Id$ キーワードから取得して設定する方法を検討してみる。
build 時に必ず実行する必要がある処理なので Makefile に記述して、 make 中で自動的に実行してしまうのが楽。
    :
# 変数定義
PROGRAM  = myprog
OBJECTS  = sub.o pthread.o common.o util.o
HEADER   = myprog.h const.h config.h
 
# 全ソース/ヘッダ中の `$Id' 行から最大のリビジョンを取得する
REVISION = $(shell awk '/\$$Id/{ if($$4 ~ /[[:digit:]]/) \
            if(max < $$4) max = $$4 } END{ print max }' \
            $(OBJECT:.o=.c) $(HEADER) $(PROGRAM).c)
# 全ソース/ヘッダ中の `$Id' 行から最大のリビジョンのコミット日時を取得する
COMMITED = $(shell awk '/\$$Id.*'$(REVISION)'/{ \
            print $$5 " " $$6; exit }' \
            $(OBJECT:.o=.c) $(HEADER) $(PROGRAM).c)
# コンパイルオプション(REVISIONとCOMMITEDを定義)
CFLAGS   = -g -Wall -Wextra -Werror -Wno-unused-parameter -I.-O2 \
            -DREVISION=\""$(REVISION)"\" -DCOMMITED=\""$(COMMITED)"\"
    :
    :
# ターゲット(デフォルトターゲットは touch と $(PROGRAM)に依存
all: touch $(PROGRAM)
# $(PROGRAM).o ファイルの削除($(PROGRAM).o ファイルは必ずコンパイルする)
touch:
    rm $(@).o
$(PROGRAM): $(OBJECTS)
    $(CC) $(CFLAGS) -o $(@) $^ 
$(OBJECTS): $(HEADER)
    :
	
	これでどのファイルを commit した場合でも
	必ず最新のリビジョンとコミット日付が -v で表示される。
	
	当初ターゲット touch は touch $(PROGRAM).c としていたが、
	とある方よりの指摘で rm $(PROGRAM).o に変更した。
	ご指摘感謝です > N.S. さま
	

