5.1さらうどん

@giginetの技術ブログ。ゲーム開発、iOS開発、その他いろいろ

JenkinsでLuaのSyntaxチェックを自動化してみた

開発中のゲームがそろそろ追い込みです。5月中には公開できるかなぁ。

さて、今開発しているゲームではLuaによるレベルデザインを行っていて、過去にいろいろな記事を書いてきました

cocos2d-xのバグを直したらmergeされた話 - 5.1さらうどん

cocos2d-xのLuaバインディングについて解説してみる - 5.1さらうどん

Luaの強み

レベルデザインや値調整、文字入力をプログラマ以外が作業しやすい。レベルデザインとコードが分離できてしあわせ。

Luaの弱み

プログラマにゲームの実装をお願いすることで、必ず発生するのが、単純なシンタックスエラー。

今回の開発でも、文章や簡単な数値調整の大部分を非プログラマにお願いしていたのですが

「おい、また,がなくて落ちるぞ。死ね」
「うるせーお前が死ね」

などという煽り合いが日常茶飯事でした。

Luaの場合、シンタックスエラーが起きてもゲーム自体は普通に動いてしまい、そのスクリプトが呼ばれているヶ所に到達して初めてミスに気づけるので、バグの温床となっていました。良くない。

そうだ、Jenkinsだ!

というわけで、最近Jenkinsを導入してTestFlightなどを自動化してみたりしているのですが、LuaのSyntaxチェックもこれでやってしまえ、と思いつきました。


ググってみたところ、lua-checkerと呼ばれるLua向けのsyntaxチェッカーを発見できたので、Jenkinsに組み込んでみます


lua-checker - Check Lua source code for various errors. - Google Project Hosting

導入してみる

lua-checkerのビルド

環境はMac OS X 10.8

svn checkout http://lua-checker.googlecode.com/svn/trunk/ lua-checker-read-only
cd lua-checker-read-only
curl -O http://www.lua.org/ftp/lua-5.2.2.tar.gz
tar xcvf lua-5.2.2.tar.gz
mv lua-5.2.2 lua
cd lua
make maxosx
cd ../
make
Shellスクリプトを書き換える

これで、付属しているCHECK_LUA.shを使うことで単体ファイルのシンタックスチェックは完了です!

今回、対象プロジェクトのリポジトリ下に含まれている全てのLuaスクリプトについてチェックしたいので、findなんかを使ってLuaスクリプト全てに適応します。基本はCHECK_LUA.shのコピー

#!/bin/sh
SRC_DIR=$(cd $(dirname $1) && pwd)
SUCCEED=1

cd $(cd $(dirname $0);pwd)

function check() {
    if [ $? -ne 0 ]; then
        echo $SRC
        SUCCEED=0
        continue
    fi
}

for SRC in `find ${SRC_DIR} -name "*.lua"`; do
    CLEAN_ASM="while(<>){s/^\t(\d+)\t\[\d+\]/\t\1/;s/(main|function) <[^\]]+>/function/;s/0x[0-9a-f]+//;print}"

    # Some shell settings
    set -o pipefail

    # Check that the simplified source is functionally identical to the original.
    rm -f /tmp/original.asm /tmp/simplified.asm /tmp/original.luac /tmp/simplified.luac
    check
    lua/src/luac -s -l -o /tmp/original.luac $SRC | perl -e "$CLEAN_ASM" > /tmp/original.asm
    check
    ./lua_simplifier -luac $SRC | lua/src/luac -s -l -o /tmp/simplified.luac - | perl -e "$CLEAN_ASM" > /tmp/simplified.asm
    check
    diff /tmp/original.asm /tmp/simplified.asm
    check

    # Check that the simplified source simplifies to itself.
    rm -f /tmp/simplified.lua /tmp/simplified2.lua
    check
    ./lua_simplifier $SRC > /tmp/simplified.lua
    check
    ./lua_simplifier /tmp/simplified.lua > /tmp/simplified2.lua
    check
    diff /tmp/simplified.lua /tmp/simplified2.lua
    check

    # Check the simplified source.
    ./lua_simplifier -emit_lines $SRC > /tmp/simplified.lua
    # ./lua_checker -const_functions /tmp/simplified.lua # 削除
    check
done

if [ $SUCCEED -eq 0 ]; then
    echo ">>>>> FAILED <<<<<"
    exit 1
fi
echo "***** SUCCEED *****"
exit 0

元から付いてくるスクリプトにそのまま投げ込むと、何か一つでもエラーが見つかった時点でexit 1を返してしまい、その時点でビルドが失敗となってしまうので、全てをチェックして、どれか一つでもエラーがあったらexit 1を投げています

また、lua_checkerにかけると、未定義の変数が見つかった時点でエラーを出してしまい、C++とbindingしているコードもエラーになってしまうので、ここでは意図的に外しています。(後述)

Jenkinsの設定

Jenkinsの設定としては、shellスクリプトを1行呼び出すだけです。lua-checkerは別の場所においても大丈夫ですが、リポジトリに含んでしまうのが簡単な感じでオススメです。

ビルド手順の追加 > シェルの追加を選びましょう

cd ${WORKSPACE}/path/to/checker
sh syntax_checker.sh ${WORKSPACE}

ここで書いたスクリプトがexit1を返した時点で失敗判定になってビルドが失敗します。

結果的に

f:id:gigi-net:20130503174845j:plain

Luaのsyntaxが間違っていたときにビルド失敗して怒ってくれた!

さらにJenkins github pluginを導入して、githubへのpushにhookさせれば、コミットと同時にLuaのsyntaxチェックをかけてくれる環境が完成!何か文法ミスがあれば、怒ってくれるので幸福感あります。


お好みに応じてJenkins Sounds Pluginなどを導入しておくと、何かミスっていたときに音でお知らせしてくれて良い感じです。(うちの開発環境では呪われたときのSEをならしてお気の毒な感じにしています)

問題点

tolua++などを使って、C++のクラスをBindingしている部分は定義されていない変数と見なされ、シンタックスチェックで弾かれてしまいます。これらを考慮してのチェックが行えれば便利度がさらに増しそうですが、一筋縄ではいかない感じがしたのでやめました。

MoonScript良さそう

最近知ったのですがMoonScript良さそうですね!

MoonScript, a language that compiles to Lua


CoffeeScriptと同様に、そもそもこれでコンパイルが通れば、Luaのsyntaxミスに怯えなくてもいいし、
Windows向けのコンパイラも配布されているので、開発にも使いやすい感じですね!

これを使えば今回の記事は割と無意味かも。


次回の開発では取り入れていきたいなぁって思ってます。