|
ここにある情報はかなり古くなっており、正しくなくなっている可能性があります。掲載しているサンプルコードiなどは、最新のPHPでは動作しない、もしくは、別途設定・調整が必要になるかも知れません。情報を鵜呑みにせず、あなたの手を動かして、あなたの目で確認してください。
Javaの世界ではApache Antという有名なビルドツールがあります。C言語に対するmakeのような存在で、コンパイルや各種アーカイブ化、APIドキュメントの作成、テストの実行などのタスクを自動化していました。今でもバッチやEclipseなどのIDEから実行したりして使われています。また、Makefileに相当する定義ファイル(どういうタスクを行うか)はXMLで定義します。
一方PHPは?というと、スクリプト言語ですから前もってコンパイルすることはありませんが、他の言語と同様ファイルのコピー・移動、アーカイブ化やテストの実行など必要となるタスクはあるもので、従ってそのタスクを自動化したいという要望(要求)もあるかと思います。
やはりAntが有名なのでそれに似たツールがあれば。。。ということで探してみるとあるもんです(^-^;
Phingは元々PHP用フレームワークbinarycloudの一部として開発されていましたが、現行バージョン(2005/08/09現在ver.2.1.0)は独立してPHP5専用になっています。
機能的にもAntとかなり似ていて、定義ファイルもAntと同じbuild.xmlで定義し、内容もほぼ同様です。また、独自タスクをPHPのクラスで定義することができます。
今回はPHP4を対象としたbinarycloudを使ってみました。
インストール
まずはbinarycloudのReleasesのページからアーカイブをダウンロードします。2005/08/09現在の最新バージョンは3.0.0RC4ですがRC4からPhingが含まれなくなったようなので一つ前のRC3をダウンロードします(恐らく、これがPHP4用Phingの最後のバージョンです)。
ダウンロード後、適当なディレクトリにアーカイブを展開します。
アーカイブを展開後の作業は、基本的にUnixInstallInstructionsのページ(このページはobsoleteになっています)にある通りですが、実際に行った手順を書いておきます。
アーカイブ展開後、環境変数を設定します。PHP_COMMANDに指定するphpコマンドへのパスは適宜変更してください。また、今後Phingを使い続けるのであれば、$HOME/.bash_profileなどに追記しておくと良いと思います。
●環境変数の設定$ export BCHOME=[binarycloudのインストールパス]/binarycloud-3-0-0_rc3/r3
$ export PHING_HOME=$BCHOME/phing
$ export PHP_COMMAND="[phpコマンドへのパス]/php"
$ export PHP_CLASSPATH=.:$PHING_HOME/classes:$BCHOME
$ export PATH=${PATH}:$PHING_HOME/bin
$
環境変数の設定後、Phingの設定を行います。
●Phingの設定$ cd $PHING_HOME/bin
$ chmod u+x phing.sh
$ ln -s phing.sh phing
$
設定が終わったら、正しくPATHが通っているか確認しておきます。
●PATHの確認$ which phing
[binarycloudのインストールパス]/binarycloud-3-0-0_rc3/r3/phing/bin/phing
$
Phingの設定後、インストールのテストを行うのですが、mysqlが必要とのことで今回は割愛しましたm(_"_)m
簡単な利用例
Phingのドキュメントは、展開したアーカイブ下のr3/phing/docs/phing_guide/ディレクトリにあります。index.htmlをブラウザで開くと各種ドキュメントを参照することができます(英語ですが)。
ここでは手始めに、左メニューの[Getting Started]-[Writing A Simple Buildfile]にあるXML形式の設定ファイル(build.xml)を試してみることにします。
まずは、実行環境を整備します。適当なディレクトリ下にディレクトリと仮のソースファイルを作成します。ここではベースとなるディレクトリを「sample」としています。
●実行環境の整備
$ cd sample
$ mkdir src
$ echo "<?php echo 'File.php'; ?>" > src/File.php
$ echo "<?php echo 'File2.php'; ?>" > src/File2.php
$
次に、build.xmlを作成します。基本的な書き方は掲載されているXMLの通り、
- root要素はproject要素
- target要素でタスクをグループ化し、大きなタスクを作る(実行時に渡すtargetパラメータになる)
- ディレクトリの作成やコピー、tarによるアーカイブ化など基本となるタスクは用意されており、それぞれタグ形式で記述する
となります。
で、このbuild.xml、整形式でない上存在しないタスクなどあり、このままでは動作しません。。。(T~_T)
ということで以下のように変更し、sample/build.xmlとして保存します。
●build.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
|| プロジェクト FooBarの定義
||
|| デフォルトのターゲットは "dist"
||
|| @project FooBar
|| @default dist
|| @basedir "."
-->
<project name="FooBar" default="dist" basedir=".">
<!--
|| ディレクトリの定義
-->
<property name="BUILD_DIR" value="./build" />
<property name="DOC_DIR" value="./apidoc" />
<!--
|| buildディレクトリを作成する
||
|| @target prepare
-->
<target name="prepare">
<echo msg="Preparing build..." />
<mkdir dir="${BUILD_DIR}" />
</target>
<!--
|| ビルドする
|| 実際にはsrcのFile2?.phpをbuildディレクトリにコピーするだけ。
|| 実行前にprepareターゲットを実行する。
||
|| @target build
|| @depends prepare
-->
<target name="build" depends="prepare">
<echo msg="Building..." />
<copy file="./src/File.php" tofile="./build/File.php" />
<copy file="./src/File2.php" tofile="./build/File2.php" />
</target>
<!--
|| ビルドしアーカイブ furbee.tar.gz を作成する
|| 実行前にbuildターゲットを実行する。
||
|| @target dist
|| @depends build
-->
<target name="dist" depends="build">
<echo msg="Creating archive..." />
<tar outfile="furbee.tar.gz" usegzip="true">
<fileset dir="./build">
<include name="**/**" />
</fileset>
</tar>
</target>
<!--
|| ビルド環境をクリアする
||
|| @target clean
-->
<target name="clean">
<echo msg="Cleaning up..." />
<delete file="./build" />
</target>
</project>
build.xmlを作成したら、いよいよphingコマンドを実行します。
●phingの実行
$ phing
Buildfile: build.xml
Target: prepare
[echo] Preparing build...
[mkdir] Created dir: /path/to/sample/./build
Target: build
[echo] Building...
[copy] Copying 1 file to /path/to/sample/./build
[copy] Copying 1 file to /path/to/sample/./build
Target: dist
[echo] Creating archive...
BUILD SUCCESSFUL
Total time: 0.2050 seconds
build finished at Sun Aug 21 17:15:17 JST 2005
$
実行後、sampleディレクトリにfurbee.tar.gzが作成されていることを確認してみてください。どうでしょうか?しかし、ホントにAntと同じですね。。。
今回はパラメータなしで実行しましたが、本来は
●phingの実行
$ phing -help
phing [options] [target [target2 [target3] ...]]
Options:
-h -help print this message
-l -list list available targets in this project
-v -version print the version information and exit
-q -quiet be extra quiet
-verbose be extra verbose
-debug print debugging information
-logfile <file> use given file for log
-logger <classname> the class which is to perform logging
-f -buildfile <file> use given buildfile
-D<property>=<value> use value for given property
-find <file> search for buildfile towards the root of the
filesystem and use it
Report bugs to <dev@lists.binarycloud.com>
build finished at Sun Aug 21 17:26:28 JST 2005
$
のようにbuild.xmlで設定したターゲットをパラメータとして指定します。パラメータがない場合、project要素のdefault属性で指定されたターゲットが実行されますので、今回の場合、
●phingの実行
$ phing dist
と等価になります。
使い方はこれだけです。あとは用途に応じてタスクを組み替えてターゲットを作成する事になります。用意されているタスクについては、左メニューの[Appendix B: System Tasks]や[Appendix C: Core Types]を見るとすぐに分かると思います。
また、タスクとは別の重要な要素としてfilesetがあります。使い方はAntと同じですので、慣れるとかなり強力な要素です。上記のサンプルで使用しているその他タスクについては、ドキュメントを参照してください。
ドキュメントにないタスク
ドキュメントのAppendixにタスク一覧がありますが、$PHING_HOME/tasks以下のディレクトリを見てみるとドキュメントに記載されていないタスクも存在します。中でもphpDocumentorを使ってAPIドキュメントを作成するタスクPHPDocuTaskは使えそうです(DocではなくDocuです)。
このタスクを使用するには、
- タスクtaskdefを使用してタスクを登録する
- $PHING_HOME/tasks/defaults.propertiesにタスクを追記する
のいずれかの作業が必要になります。phpDocumentor自身については、binarycloudに同梱されていますので、別途インストールする必要はありません。
前者の場合、build.xmlを以下のように修正します。
●build.xmlの抜粋
<?xml version="1.0" encoding="utf-8"?>
:
<project name="FooBar" default="dist" basedir=".">
:
<!--
|| phpDocumentorを使ってAPIドキュメントを作成する
||
|| @target apidoc
-->
<taskdef name="phpdoc" classname="phing.tasks.ext.PHPDocuTask" />
<target name="apidoc" depends="build">
<echo msg="Building API documents..." />
<mkdir dir="${DOC_DIR}" />
<phpdoc source="${BUILD_DIR}"
target="${DOC_DIR}"
package="FooBar"
title="Phing Test"
output="HTML:Smarty:PHP"
clean="true" />
</target>
</project>
後者の場合、build.xmlを以下のように修正し、
●build.xmlの抜粋
<?xml version="1.0" encoding="utf-8"?>
:
<project name="FooBar" default="dist" basedir=".">
:
<!--
|| phpDocumentorを使ってAPIドキュメントを作成する
||
|| @target apidoc
-->
<target name="apidoc" depends="build">
<echo msg="Building API documents..." />
<mkdir dir="${DOC_DIR}" />
<phpdoc source="${BUILD_DIR}"
target="${DOC_DIR}"
package="FooBar"
title="Phing Test"
output="HTML:Smarty:PHP"
clean="true" />
</target>
</project>
defaults.propertiesに以下の行を追加します。
●$PHING_HOME/tasks/defaults.properties
phpdoc=phing.tasks.ext.PHPDocuTask
いずれの方法を採るかはお好みでどうぞ。なお、実行結果は以下のような感じになります。
●APIドキュメントの作成
$ phing apidoc
Buildfile: build.xml
Target: prepare
[echo] Preparing build...
[mkdir] Created dir: /path/to/sample/./build
Target: build
[echo] Building...
[copy] Copying 1 file to /path/to/sample/./build
[copy] Copying 1 file to /path/to/sample/./build
Target: apidoc
[echo] Building API documents...
[mkdir] Created dir: /path/to/sample/./apidoc
[phpdoc] Cleaning target directory first
[delete] Deleting directory /path/to/sample/./apidoc
Parsing configuration file phpDocumentor.ini...
done
using experimental tokenizer Parser
BUILD SUCCESSFUL
Total time: 0.5307 seconds
build finished at Sun Aug 21 23:07:47 JST 2005
$
独自のタスクを作る
ドキュメントの[Extending Phing]-[Writing Tasks]にもあるように、独自のタスクを作成することもできます。当然、PHPで記述します。サンプルはドキュメントにもありますが、AntのSymlinkタスクを真似てざっと作ってみました。以下のファイルを$PHING_HOME/tasks/example/SymLinkTask.phpとして保存します。なお、「example」ディレクトリは任意で、systemディレクトリやextディレクトリにも配置可能です。
●SymLinkTask.php
<?php
import('phing.Task');
import('phing.system.io.FileSystem');
class SymLinkTask extends Task
{
var $__taskname = "symlink";
var $link_ = null;
var $resource_ = null;
function setLink($link) {
$this->link_ = $link;
return true;
}
function setResource($resource) {
$this->resource_ = $resource;
return true;
}
function init() {
}
function main() {
$fs =& FileSystem::getFileSystem();
$fs->Unlink($this->link_);
$fs->Symlink($this->resource_, $this->link_);
return true;
}
}
?>
PHPソースの方はかなりJavaを意識しているようで、import関数や今回は使用していませんがthrow/catch関数などが用意されています。実装のポイントとしては以下のものがあります。
- 必要なパッケージをimport関数を使用してロードする
- クラス名はタスク名+「Task」
- 最低限Taskクラスを継承する
- XML属性に対するセッタメソッドを用意する
- initメソッドを用意する
- mainメソッドに処理内容を記述する
一方のbuild.xmlですが、先ほどのPHPDocuTaskと同様の書き方になります。以下はtaskdef要素を使用した場合です。
●build.xmlの抜粋
<?xml version="1.0" encoding="utf-8"?>
:
<project name="FooBar" default="dist" basedir=".">
:
<!--
|| シンボリックリンクを作成する
||
|| @target link
-->
<taskdef name="symlink" classname="phing.tasks.example.SymLinkTask" />
<target name="link">
<symlink resource="build" link="build.link" />
</target>
</project>
classname属性の値はタスクのソースファイルを配置したディレクトリと連動しているため、もし「system」ディレクトリに配置した場合は
●classname属性
<taskdef name="symlink" classname="phing.tasks.system.SymLinkTask" />
となります。実行結果は以下のようになります。
●APIドキュメントの作成
$ ls
apidoc/ build/ build.xml* src/ test/
$
$ phing link
Buildfile: build.xml
FileSystem::Symlink() SUCCESS. build to build.link.
BUILD SUCCESSFUL
Total time: 0.1560 seconds
build finished at Mon Aug 22 01:06:08 JST 2005
$
$ ls
apidoc/ build/ build.link@ build.xml* src/ test/
$ ls -l build.link
lrwxrwxrwx 1 shimooka shimooka 5 Aug 22 01:13 build.link -> build/
$
まとめ
実はPhing自体はかなり前から知っていたのですが、「スクリプト言語のPHPになぜAnt?」ということで使っていませんでした。今思うと「ちょっともったいなかったなぁ」という感じです。使ってみた感じはほとんどAntと同じなので違和感はありませんでした。ただ、Antと比べタスクの数があまりないので、scpやrsync、cvsなどのリモートサーバとのやりとりはexecタスクを多用する感じになるでしょうか?
また、PHP5専用のPhingも2005/07にバージョン2.1.0がリリースされましたので、近いうちにやってみようかと思います。
|