kiyo_hikoのブログ

メモ+日記?

きよツール:Javaアプリをビルド→リリースする方法の研究

ちまちま開発中のJavaでクイズ暗記ソフト「きよツール」配布方法について、ビルド方法、PC初心者でも簡単に使える方法とかいろいろ研究中。

リリース前にやるべきタスクとか

  • 起動方法をほとんど誰でもすぐ理解できるようにする
  • 最低限のカスタマイズ性を確保する
    • クイズデータは当然利用者側で差し替えできるようにする。クイズデータは今「アニゲ四択.txt」とかの固定名になっているが、ファイル名の自由度を上げたい
    • 正解/不正解時その他の効果音も利用者側で差し替えできるようにする
  • ビルドの自動化=Ant復習
  • 取説を書く

起動方法をほとんど誰でも理解できるようにする

配布形式はzipにして、解凍するとフォルダー直下に「起動.bat」があってこれをダブルクリックするとjarを実行して起動するようにするつもり。jar直接ダブルクリックだと関連付けの問題?で起動しない環境があるし、だったら単にバッチファイルのダブルクリックですぐ立ち上がるようにしといたほうが、リリース後にいちいち質問されるより精神衛生上よい。

で、バッチファイル書いたらコマンド・プロンプトのウィンドウが超じゃまだった。


バッチファイルから自分のコマンド・プロンプトを最小化する方法を調べたのだけど、環境変数を使って自分自身を呼ぶようにすれば解決するらしい。

Windows、バッチファイル(.bat)を最小化した状態で起動する|マコトのおもちゃ箱 ~ぼへぼへ自営業者の技術メモ~

すごいなこの技。


あとコマンド・プロンプトのウィンドウタイトル変更だが、これはtitleコマンドでできることがわかった。
てことで起動.bat書いてみた。

@echo off
rem きよツール起動用バッチファイルです。
rem updated: 2014/ 5/--
rem author: きよひこう

:init
	setlocal
	if not "%running%"=="yes" (
		set running=yes
		start /min cmd /c,"%~0" %*
		exit /b
	)

:main
	title きよツール
	java -jar .\bin\kiyotool.jar

:final
	endlocal
	exit /b

最低限のカスタマイズ性を確保する

クイズデータのファイル名が固定でこれは良くないので、以下の様な動作をするようにJavaソースコードを変更する:

  • quizdataフォルダー直下にあるもので、*.txtファイルならとにかく総当りでStream開いてみる
  • 1行目にクイズデータであることを示すマーカーがあればクイズローダーで読み込む
    • マーカーはどうするか決めてないが、たぶん「@@kiyotool-quiz-format」とかにすると思う
  • マーカーがなければそれはクイズデータとはみなさず、Streamをそっ閉じ


効果音については一応デフォルト効果音をフリー素材サイトからお借りして付けるつもり。

Ant復習

仕事がPerlなせいで、どうもJava関連ツールの使用頻度が低すぎてすぐ忘れてしまい、良くない。
以下に要点を書き出しておく。


まず、やりたいことは

既存のコンパイル済みデータのクリア
→ デプロイするフォルダーの用意
→ ツールに付帯するファイルの配備 (起動.batや取説やクイズら外部データなど)
→ javac
→ obfuscation (jarとどっちが先かよくわからない)
→ jar

である。


Antの動作は、ルートタグprojectからdefault属性によって実行するビルド・ターゲットを指定する。

  • Antではビルドを構成するひとつひとつのユーザー定義の仕事単位を「ターゲット」といい、
  • 予めカプセル化された命令群を「タスク」というらしい
  • また、定数として「プロパティ」が使える


で、build.xmlの記述はproject以下にまずプロパティを書く(あまりにも多い場合外出しも可能)、そしてターゲットをバンバン書いていくらしい。
で、ターゲットの実行順序制御はtargetタグに属性「depends」を書いて行う。dependsはカンマ区切りで複数ターゲットを書ける。


例えば、骨格として、

<project default="main" name="サンプル">
 <property name="greentea" value="おい、お茶" />
 <target name="main" depends="init, do, final">
  <echo>${greentea}</echo>
 </target>
 <target name="init">
 </target>
 <target name="do">
 </target>
 <target name="final">
 </target>
</project>

みたいな雰囲気で書く。

あとはtargetタグの中にtaskタグでタスクをつらつら書いていくが、例えば標準のタスクとして、以下の様なお仕事ができる。他にも膨大なタスクがある。

delete ファイル消す
mkdir フォルダー作る
copy コピる
javac コンパイル
touch ファイルの更新日時を更新
jar jar作る


ファイル操作系のタスクはfilesetという機能に対応していて、これは特定のパスにある特定パターンのファイルをグループ化して扱うことができる。だから、/manualフォルダーに*.txtだけをコピーしたりとかが可能。

とりあえず現状のbuild.xmlを。部分部分手抜きっぽい

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="main" name="きよツール">
	<property name="productpath" location="/kiyotool" />
	<property name="productname" value="kiyotool.jar"/>
	<property name="time" value="05/01/2014 9:00 am"/>
	<property name="charset" value="utf-8" />
	<property name="entrypoint" value="kiyohikou.quiz.Main" />
	<property name="srcpath" location="src" />
	<property name="binpath" location="classes" />
	<target name="main" depends="init, javac, jar, finalize" />
	<target name="init" depends="root, config, media, quiz" />
	<target name="root">
		<delete dir="${productpath}" />
		<mkdir dir="${productpath}" />
		<copy file="起動.bat" todir="${productpath}" />
		<copy file="取説.txt" todir="${productpath}" />
	</target>
	<target name="config">
		<mkdir dir="${productpath}/config" />
	</target>
	<target name="media">
		<mkdir dir="${productpath}/media" />
		<copy todir="${productpath}/media">
			<fileset dir="media">
				<include name="**/*.wav" />
			</fileset>
		</copy>
	</target>
	<target name="quiz">
		<mkdir dir="${productpath}/quizdata" />
		<fileset dir="quizdata">
			<include name="**/*.txt" />
		</fileset>
	</target>
	<target name="javac">
		<delete includeemptydirs="true">
			<fileset dir="${binpath}">
				<include name="**/*" />
			</fileset>
		</delete>
		<javac srcdir="${srcpath}" destdir="${binpath}"
			classpath="." encoding="${charset}"
			includeantruntime="false" />
		<touch datetime="${time}">
			<fileset dir="${binpath}" />
		</touch>
	</target>
	<target name="proguard">
		<taskdef resource="proguard/ant/task.properties" classpath="proguard.jar" />
		<proguard configuration="proguard.cfg" />
	</target>
	<target name="jar">
		<jar destfile="${productpath}/bin/${productname}"
			filesetmanifest="mergewithoutmain"
			encoding="${charset}">
			<manifest>
				<attribute name="Main-Class" value="${entrypoint}" />
				<attribute name="Class-Path" value="." />
			</manifest>
			<fileset dir="${binpath}" />
		</jar>
	</target>
	<target name="finalize">
		<touch datetime="${time}">
			<fileset dir="${productpath}" />
		</touch>
	</target>
</project>

取説を書く

長すぎるのでここには載せないが、それっぽいものが書けた。


あとブログエントリーでもきよツール公開に前後して説明エントリーをいくつか上げる予定。