2011/12/24

Titanium pluginの開発

module ではなくて、 plugin についての話です。
TitaniumSDKのディレクトリをのぞいていると、plugin というようなディレクトリやplugin.py というような Python ファイルが見つかります。 Appcelerator の Web ページを見ても特にこれについて説明がないようです。ほとんど情報がありません。.... ただ CoffeeScript の Titanium 用 plugin というのがあって、実際この仕組みで作られています。現状 Titanium の plugin は CoffeeScript のためだけにあるということができます。


module 作成と同じように、titanium.py で plugin プロジェクトが作成できます。 module を作成したことがあれば、自分の .bash_profile に titanium.py のエイリアスの設定をしていると思います。これがすんでいるものとして話を進めます。
$ titanium help create
Appcelerator Titanium
Copyright (c) 2010-2011 by Appcelerator, Inc.


Usage: titanium.py create [--platform=p] [--type=t] [--dir=d] [--name=n] [--id=i] [--ver=v]
--platform=p1,p2 platform: iphone, ipad, android, blackberry, etc.
--type=t type of project: project, module, plugin
--dir=d directory to create the new project
--name=n project name
--id=i project id (ie com.companyName.project
--ver=i platform version
--android=sdk_folder For android module - the Android SDK folder
help で create コマンドの情報を見ると、確かに type に plugin を指定できることがわかります。
最小限必要なオプションで、作成してみます。
$ titanium create --type=plugin --name=myplugin --id=jp.isisredirect.myplugin
Created plugin project
確かに plugin プロジェクトが jp.isisredirect.myplugin ディレクトリとして作成されました。
$ ls -l jp.isisredirect.myplugin
total 40
-rw-r--r-- 1 <username> staff 77 12 24 11:56 LICENSE
-rw-r--r-- 1 <username> staff 681 12 24 11:56 README
-rwxr-xr-x 1 <username> staff 3034 12 24 11:56 build.py
-rw-r--r-- 1 <username> staff 363 12 24 11:56 manifest
-rwxr-xr-x 1<username> staff 185 12 24 11:56 plugin.py
生成された build.py が plugin を作成するスクリプトになります。 jp.isisredirect.mypluginディレクトリにcdして、build.py を実行してみます。
$ ./build.py
[WARN] please update the manifest key: 'copyright' to a non-default value
[WARN] please update the manifest key: 'license' to a non-default value
[WARN] please update the LICENSE file with your license text before distributingPlugin
packaged at jp.isisredirect.myplugin-0.1.zip

manifst や LICENSE ファイルを修正していないのでしかられますが、ともかく jp.isisredirect.myplugin-0.1.zip として、plugin が作成されました。

README ファイルによれば、この zip ファイルを、module と同様、TitaniumSDK ディレクトリに置くか、plugin.py を Titanium プロジェクトディレクトリの plugins/jp.isisredirect. myplugin/ におけば、ビルドシステムに認識されます。

そして Titanium プロジェクトで実行されるようにするには、module と同じように、tiapp.xml に
<plugins>
   <plugin version="0.1">jp.isisredirect.myplugin</plugin>
</plugins>
というpluginsタグとpluginタグを追加してやります。

これで、Titanium プロジェクトをビルドするたびに、plugin.py が実行されることになります。

さて、実行されるといっても、plugin.py になにも修正を加えていないので、以前と何の変わりもありません。しかし、どういう修正が必要なのか、何が許されるのか、はたまたどのタイミングで実行されるか、どこにも情報がありません。ということで、モバイルアプリ向けの build.py の中を探ることにします( iPhone 用と Android 用の build.py は当然違ったものになっていますが、plugin 周りの実装はほぼ共通です)。Titanium プロジェクトのビルドのはじめの方で、以下のように plugin.py が使われています。
for plugin in ti.properties['plugins']:
local_plugin_file = os.path.join(local_compiler_dir,plugin['name'],'plugin.py')
plugin_file = os.path.join(tp_compiler_dir,plugin['name'],plugin['version'],'plugin.py')
if not os.path.exists(local_plugin_file) and not os.path.exists(plugin_file):
o.write("+ Missing plugin at %s (checked %s also)\n" % (plugin_file,local_plugin_file))
print "[ERROR] Build Failed (Missing plugin for %s). Please see output for more details" % plugin['name']
sys.stdout.flush()
sys.exit(1)
o.write("+ Detected plugin: %s/%s\n" % (plugin['name'],plugin['version']))
print "[INFO] Detected compiler plugin: %s/%s" % (plugin['name'],plugin['version'])
code_path = plugin_file
if os.path.exists(local_plugin_file):
code_path = local_plugin_file
o.write("+ Loading compiler plugin at %s\n" % code_path)
compiler_config['plugin']=plugin
fin = open(code_path, 'rb')
m = hashlib.md5()
m.update(open(code_path,'rb').read())
code_hash = m.hexdigest()
p = imp.load_source(code_hash, code_path, fin)
p.compile(compiler_config)
fin.close()
tiapp.xml にある <plugins> の <plugin> の情報をもとに、起動すべき plugin.py を選び、起動可能でなければ、”Build Failed (Missing plugin” のエラーをはき、起動可能であれば、plugin.py 内の compile 関数を呼びます。
これ以外の箇所で、plugin.py の参照はないので、Titanium の plugin は完全にビルドのプリプロセスとして働くことがわかります。

titanium.py で作成直後の plugin.py は
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Titanium Compiler plugin
# jp.isisredirect.myplugin
#
def compile(config):
 print "[INFO] jp.isisredirect.myplugin plugin loaded"
というように、ほとんど空の compile 関数が生成されています。ここに必要な処理を書いていくことになります。
引数の config には、呼び出し元で
(ios用を引用。android用とは構成も若干異なっています)
compiler_config = {
 'platform':'ios',
'devicefamily':devicefamily,
'simtype':simtype,
'tiapp':ti,
'project_dir':project_dir,
'titanium_dir':titanium_dir,
'appid':appid,
'iphone_version':iphone_version,
'template_dir':template_dir,
'project_name':name,
'command':command,
'deploytype':deploytype,
'build_dir':build_dir,
'app_name':app_name,
'app_dir':app_dir,
'iphone_dir':iphone_dir
}
という具合に設定されています。それぞれの値の意味は、build.py をじっくり読んでいただくことにして、ともかくこの引数の値で、ビルドのいろいろな状況に応じた処理が可能なのがわかります。


Titanium の plugin は、ビルドのプリプロセスとして働くので、ビルド前に独自のファイルの整合性チェックや、コードやリソースの前処理などを行うことができるでしょう。CoffeeScript の plugin が今のところ最大の例ですので、これを読みながら研究するのがよいと思われます。



0 件のコメント:

コメントを投稿