タイヤネコをMAKE

2005-06-06

タイヤネコの構築事情

Chararina キャラクターの開発サンプルとして提供されている TEST-APX-02 タイヤネコ は、幾つかのバッチファイルによって構築するようになっています。 こんな具合です:

要するに、ソースを書き換えたら、自分でそのソースをコンパイルするバッチを考えて実行してね、という事です1。 まぁ、タイヤネコではほとんどが「メインモジュール」に含まれるので、会話データの追加程度では m.bat を使えばOK、と言う事でしょう。 この程度の規模ならば、手作業でも許容できるかも知れません。

けど、自動化しておいた方が良いのは言うまでもありません。
普通は MAKEユーティリティ を使うのですが、今はフリーの MAKEユーティリティは入手が難しいのです。 で、代替手段として、バッチファイルで MAKE する方法を考えました。 SillyTalk 2005-05-30 の記事 がそれです。

m.batの内容

まずは、提供されている環境がどうなっているのか見てみましょう。

上記のとおり構築用に m.bat, t.bat, v.bat の3つがありますが、これらはパラメータを変えて core.bat を呼び出すだけです。 実際の構築処理は core.bat が行っています。 その内容は、次の通り。 必要最低限の単純な内容ですから、難解なところはありません。

core.bat に渡されるパラメータは、ソースファイルのベース名です(Main.aya であれば "main"2)。

タイヤネコ構築バッチ

では、make.bat を使って m.bat, t.bat, v.bat を自動化してみます。

第1引数 target

make.bat の第1引数は、target です。
ここでは .exa ファイルを作る事が目的になります。 .exa ファイルは datUpdate に同じ物が配置されますが、どちらを target に指定しても結果は同じです。 ここでは実行用(dat)を target としておきましょうか。

第2引数 source

make.bat の第2引数は、source です。
target になる .exa を生成するのに必要な .aya ファイル群です。 上で m.bat を見たとおり、core.bat に渡されるパラメータは main, test, visitor です。 そして綾織コンパイラに main.aya, test.aya, visitor.aya が渡されます。 つまり、Main.aya と、Main.aya から Import しているファイル群から Main.exa が生成されています。 と言う事で、これら一式が source となります。

デリミタは空白ですので、そのままバッチパラメータとして渡すと、第2、第3、第4… という具合になってしまいます。 引数としてまとめるために、二重引用符(")で括ります。 ファイルが1つの場合は引用符は不要ですが、ファイルが1つの時に引用符を使っても問題ありません。 なお、引用符の中に引用符は入れられませんので、空白を含むファイル名やパス名は使用不可です。

第3引数 command

make.bat の第3引数は、command です。
Main.aya をコンパイルするコマンドを記述します。 m.bat の内容が正にそれなんですが、せっかく新しい環境を作るのですから m.bat の事は忘れましょう。 つまり、core.bat の中でやっている

ayac %1.aya

これが command という訳です。
コマンドとパラメータの間に空白を含むので、やはり二重引用符で括っておく必要があります。

エラーチェックや .exa を移動する処理は、呼出し側で行い command には含めません。 こうすれば、タイヤネコ構築バッチと make.bat の他にバッチファイルを用意しなくて済みますから。 1度作ってしまえば make.bat はメンテナンス不要なので、実質的にメンテナンスが必要なバッチファイルをひとつにでき、楽です。

その他

make.bat を呼ぶ所は、たとえば m.bat 相当の所で次のようになります。 これで1行。 動作はしますが、長すぎて管理が困難です。

..\dat\main.exa "main.aya Initialize.aya Graphics.aya Greeting.aya DayEvent.aya Event.aya TimeSignal.aya Menu.aya Infodeli.aya Charadeli.aya StrFunc.aya IdleTalk.aya Setting.aya" "ayac main.aya"

そこで、各々 tgt, src, ope という環境変数に設定してパラメータとして渡します。 特に src は、足し算の要領で1ファイル名ごとに継ぎ足して行きます。 これによって、1行=1ファイル名となり、Importファイルの増減に対応するのが楽になります。 具体的には、go.bat を参照してください。

プログラム・ソース

go.bat

以上を踏まえ、タイヤネコを構築するバッチファイルです。
短くて打ちやすいって事で go.bat としてみました。 tireneko.bat とか、名前は何でも構わないんですが。

go.bat
@echo off

:opening
    echo -----------------------------------
    echo  TEST-APX-02 タイヤネコ 構築中
    echo -----------------------------------

:setenv
    set UpdateDir=.\update
    set DatDir=..\dat
    set AyacDir=.
    set PassPhrase=
    set PWSBATCH_MODE=s
    set verbose=no
    set ErrHistory=

rem -----------------------------------
rem メインモジュール
rem -----------------------------------
:main
    set name=main
    set tgt=%DatDir%\%name%.exa
    set src=%name%.aya
    set src=%src% Initialize.aya
    set src=%src% Graphics.aya
    set src=%src% Greeting.aya
    set src=%src% DayEvent.aya
    set src=%src% Event.aya
    set src=%src% TimeSignal.aya
    set src=%src% Menu.aya
    set src=%src% Infodeli.aya
    set src=%src% Charadeli.aya
    set src=%src% StrFunc.aya
    set src=%src% IdleTalk.aya
    set src=%src% Setting.aya
    set ope=%AyacDir%\ayac %PassPhrase% %name%.aya
    
    call :commproc

rem -----------------------------------
rem テストモジュール
rem -----------------------------------
:test
    set name=test
    set tgt=%DatDir%\%name%.exa
    set src=%name%.aya
    set src=%src% plugin\lf-lnch.aya
    set src=%src% plugin\lf-sntpclient.aya
    set src=%src% plugin\lf-mailchecker.aya
    set src=%src% plugin\lf-httpserver.aya
    set ope=%AyacDir%\ayac %PassPhrase% %name%.aya
    
    call :commproc

rem -----------------------------------
rem ビジターモジュール
rem -----------------------------------
:visitor
    set name=visitor
    set tgt=%DatDir%\%name%.exa
    set src=%name%.aya
    set src=%src% Charadeli.aya
    set src=%src% Graphics.aya
    set src=%src% Initialize.aya
    set src=%src% StrFunc.aya
    set ope=%AyacDir%\ayac %PassPhrase% %name%.aya
    
    call :commproc

rem -----------------------------------
rem ビルド結果
rem -----------------------------------
:buildresult
    if  "%ErrHistory%"=="" goto complete

:failed
    echo ビルドに失敗しました.
    goto end

:complete
    echo 正常にビルドが終了しました.
    goto end

rem -----------------------------------
rem 共通処理
rem -----------------------------------
:commproc
    echo ▲ %name%
    call make.bat %tgt% "%src%" "%ope%"
    
    rem skipした場合は以下の処理を全てスキップしてreturn
    if errorlevel 255 goto :EOF
    
    rem エラーの場合はエラーメッセージを表示してreturn
    if errorlevel 1 goto error
    
:objectmove
    rem 成功の場合は .exa を所定のフォルダへ登録
    
    copy %name%.exa %DatDir% >nul
    if not errorlevel 1 goto copy1end
        echo %name%: %name%.exa の %DatDir% へのコピーに失敗しました.
        goto :EOF
    :copy1end
        if "%verbose%"=="yes" echo %name%: %name%.exa を %DatDir% へコピーしました.
    
    move %name%.exa %UpdateDir%>nul
    if not errorlevel 1 goto copy2end
        echo %name%: %name%.exa の %UpdateDir% への移動に失敗しました.
        goto :EOF
    :copy2end
        if "%verbose%"=="yes" echo %name%: %name%.exa を %UpdateDir% へ移動しました.
    
:success
    echo %name%: コンパイルは正常に終了しました.
    if not "%PWSBATCH_MODE%"=="s" pause
    goto :EOF

:error
    set ErrHistory=%ErrHistory%x
    echo エラーが発生しました.ソースを編集の上再コンパイルしてください.
    if not "%PWSBATCH_MODE%"=="s" pause
    goto :EOF

rem -----------------------------------
rem バッチ終了
rem -----------------------------------
:end
    set PWSBATCH_MODE=
    set verbose=
    set ErrHistory=

環境変数で幾つかの動作を切り替えることができます。

make.bat

make.bat も若干変更しています。
処理スキップ時に、明示的に ERRORLEVEL=255 を返すようにしました。

make.bat
@echo off
rem -----------------------------------
rem パラメータチェックとヘルプ
rem -----------------------------------
:help
    if not "%~3"=="" goto start
    rem  ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8
    echo/
    echo %0 -- usage
    echo/
    echo [書式]
    echo     %0 target source command
    echo/
    echo     target  = targetのファイル名
    echo     source  = sourceのファイル名
    echo               複数の場合は二重引用符で囲み空白で区切る.
    echo     command = sourceからtargetを生成するコマンド
    echo               command引数は二重引用符で囲み空白で区切る.
    echo [説明]
    echo     target と1つ以上の source のタイムスタンプを比較し、source の方が
    echo     新しい物が1つでもあれば command を実行する.
    echo     「1つ以上のファイル名」の区切に空白を使用するため、パス名/ファイル名は
    echo     空白を含んではならない.
    echo/
    echo     command 実行時、環境変数 resultcode に返り値を返す.
    echo     環境変数 verbose が yes の時、target/source の日付を表示する.
    goto :EOF
    
rem -----------------------------------
rem make処理
rem -----------------------------------
:start
    call :updatechk %1 %2
    if not "%update%"=="yes" goto skip
    %~3
    set resultcode=%ERRORLEVEL%
    goto end

:skip
    if "%verbose%"=="yes" echo make  : skipped.
    goto end0

rem -----------------------------------
rem target:source 日付チェック
rem -----------------------------------
:updatechk
    if "%verbose%"=="yes" echo/
    if "%verbose%"=="yes" echo target: %~t1  %~1
    
    set update=no
    for %%s in ( %~2 ) do call :chkdate %1 %%s
    goto :EOF

:chkdate
    if "%verbose%"=="yes" echo source: %~t2  %~2
    
    if not exist %2 echo make: source file [%2] not found.
    if "%~t2" GEQ "%~t1" set update=yes
    goto :EOF

rem -----------------------------------
rem 終了
rem -----------------------------------
:end0
    set update=
    exit /B 255

:end
    set update=
    if "%verbose%"=="yes" echo make: return (%ERRORLEVEL%)
  1. 考えて実行してね
    Chararina の前身である PersonaWare では "絢夏"というキャラクターが開発サンプルでした。 今でも時折「コンパイルし忘れてました」なんて記事や BBSの記事を見かけますから、その当時も似たような事情だったと考えられます。 HALCA の開発では"絢夏"を全く無視して独自の環境を構築したので、この辺りの事情は把握していないんです…。

  2. Main であれば"main"
    本来は "Main" をパラメータとして与えるべきでしょう。 コマンドプロンプト(言うか MS-DOS)は、ファイル名の大文字/小文字を区別しませんので、こう言う指定でも問題としては現れません。 けど、素人向けの開発サンプルとしてはどうよ? って気がします。 余計な所で悩んだりしないんでしょうか。

Copyright© 1998-2006 Hira