はたはたのメモ

主に勉強したことについてのメモ用ブログです。PHPerを目指しています。Pythonはまりかけ。GitHub: https://github.com/a-japonicus

cocos2d-xのantのbuild.xml設定 ②assetsのコピー

cocos2d-xのantのbuild.xml設定 ①ndk-build - はたはたのメモでbuild-native.shで行っていたビルドをantコマンドでできるようになった。

今回はassetsをコピーをするタスクを追加する。
assetsはアプリ内で読み込む画像やフォントなどのデータを置いておくディレクトリで、Resourceディレクトリから持ってくる必要がある。

プロジェクトディレクトリにあるResourcesからデータをコピーするassets-copyタスクは以下のようになる。

    <!-- assets-copy -->
    <target name="assets-copy" depends="assets-clean" description="Copy files from a resource to assets.">
        <mkdir dir="assets" />
        <copy todir="assets">
            <fileset dir="../Resources" />
        </copy>
    </target>

    <!-- assets-clean -->
    <target name="assets-clean" description="Removes assets files.">
        <delete dir="assets" />
    </target>


    <target name="-pre-build" depends="update-version,assets-copy,ndk-build" />
    <target name="cleanall" depends="assets-clean,ndk-clean,clean" description="Removes all output files created by other targets." />

これでビルドするたびにResourcesからassetsにデータがコピーされ、build-native.shを使わずにビルドできるようになった。

cocos2d-xのantのbuild.xml設定 ①ndk-build

antの設定ファイルであるbuild.xmlを見てみると、

    <!-- version-tag: 1 -->
    <import file="${sdk.dir}/tools/ant/build.xml" />

と書かれており、antはAndroid SDKにあるbuild.xmlを使ってビルドする。

SDKbuild.xmlはそのままだとJavaしかビルドしてくれない。
そこでプロジェクトのbuild.xmlを修正し、C++コードをビルドできるようにする。

プロジェクトのbuild.xmlには

    <import file="custom_rules.xml" optional="true" />

とカスタム設定用のXMLをインポートするようになっているため、今後カスタムルールはcustom_rules.xmlに記述していく。


build-native.shを見てみると、C++をビルドするためにndk-buildを呼び出していることがわかる。
なのでcustom_rules.xmlにndk-buildでビルドするように設定を追加する。

<!-- customrules.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules">
    <!-- ndk.dir -->
    <fail message="ndk.dir is missing." unless="ndk.dir" />

    <!-- ndk-build設定 -->
    <condition property="ndk-build" value="${ndk.dir}/ndk-build.cmd" else="${ndk.dir}/ndk-build">
        <os family="windows" />
    </condition>

    <!-- NDKビルド -->
    <target name="ndk-build" description="Builds the ndk.">
        <exec executable="${ndk-build}" failonerror="true">
            <arg value="-j4"/>
        </exec>
    </target>

    <!-- NDKクリーン -->
    <target name="ndk-clean" description="Removes ndk build files.">
        <exec executable="${ndk-build}" failonerror="true">
            <arg value="clean"/>
        </exec>
    </target>

    <target name="-pre-build" depends="ndk-build" />
    <target name="cleanall" depends="ndk-clean,clean" description="Removes all output files created by other targets." />
</project>

各設定の説明

ndk.dirの確認

    <!-- ndk.dir -->
    <fail message="ndk.dir is missing." unless="ndk.dir" />

NDKのディレクトリをndk.dirに書かれているかどうかを判定する。
ndk.dirが設定されていなければ失敗する。
ndk.dirは local.properties に書くか、ant実行時に引数として -Dndk.dir=NDKのパス を与える。

ndk-build

    <!-- ndk-build設定 -->
    <condition property="ndk-build" value="${ndk.dir}/ndk-build.cmd" else="${ndk.dir}/ndk-build">
        <os family="windows" />
    </condition>

ndk-buildの実行ファイル名を設定する。
windowsだとndk-build.cmd、それ以外だとndk-buildが実行ファイルになる。

ビルド

    <!-- NDKビルド -->
    <target name="ndk-build" description="Builds the ndk.">
        <exec executable="${ndk-build}" failonerror="true">
            <arg value="-j4"/>
        </exec>
    </target>

C++ビルドターゲット。
`ant ndk-build` でビルドされる
-j* オプションはビルドに使用するコア数

クリーン

    <!-- NDKクリーン -->
    <target name="ndk-clean" description="Removes ndk build files.">
        <exec executable="${ndk-build}" failonerror="true">
            <arg value="clean"/>
        </exec>
    </target>

ndk-buildでビルドされたファイルをクリーンする。
`ant ndk-clean` で実行される

実行ターゲット設定

    <target name="-pre-build" depends="ndk-build" />
    <target name="cleanall" depends="ndk-clean,clean" description="Removes all output files created by other targets." />

ビルドおよびクリーンの設定をする。
-pre-buildはビルド前に実行されるターゲットで、dependsにndk-buildを指定することでapkビルド前にndk-buildを実行する。
cleanallはndk-cleanとcleanを実行する


以上の設定を記述したcustom-rules.xmlbuild.xmlと同じディレクトリに置き、`ant debug`および`ant release`を実行するとC++のビルドも実行される。
また、`ant cleanall`でC++のオブジェクトファイルも含めた全ファイルがクリーンされる。

cocos2d-xによるantのreleaseビルド設定

cocos2d-xでreleaseビルドするためのメモ。

前回でdebugビルドを作れるようになったが、releaseビルドをインストールしようとしてもエラーが出て失敗する。
ログを見てみると

C:\adt-bundle-windows\sdk\tools\ant\build.xml:1410: File C:\adt-bundle-windows\cocos2dx-test
\projects\TestProject\proj.android\bin\TestProject-release.apk does not exist.

TestProject-release.apk がありませんよ、と怒られている。
binディレクトリを見てみると TestProject-release-unsigned.apk はあるが TestProject-release.apk は無い。
unsigned というのは未署名という意味で、android端末にアプリをインストールするためにはapkに署名をする必要がある。

さらにログを見てみると

-release-nosign:
     [echo] No key.store and key.alias properties found in build.properties.
     [echo] Please sign E:\project\Bitbucket\cocos2dx-test\projects\TestProject\proj.android\bin\TestProject-release-unsigned.apk manually

keystoreの設定がないので手動で署名してください、と書かれている。
apkに手動で署名するにはJDKのjarsignerを使えばいいが、antに任せたいのでkeystoreの設定を追加する。

keystoreはJDK付属の keytool で作成することができるが、今回はdebug用のkeystoreを使用する*1
debugビルドを行うと自動で C:\Users\ユーザ名\.android に debug.keystore が作成されているはずなので、local.propertiesに以下の設定を記述する

key.store=C:\\Users\\ユーザ名\\.android\\debug.keystore
key.store.password=android
key.alias=androiddebugkey
key.alias.password=android

*.properiesは設定を書くファイルで、local.propertiesはコミットせずにローカル専用の設定を書くファイルになる。
debug.keystoreはPCごとに変わるため今回はここに書くが、例えばkeystoreもコミットしている場合はant専用プロジェクト設定の ant.properties に書いてもいい。

keystoreを記述した状態で ant clean release install を実行するとインストールに成功する。

インストールしたreleaseビルドを実行すると強制終了される。
ddms を実行し、LogCatで実行ログを確認してみると

01-26 13:59:06.151: E/AndroidRuntime(2329): FATAL EXCEPTION: main
01-26 13:59:06.151: E/AndroidRuntime(2329): java.lang.UnsatisfiedLinkError: b
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at a.a.a.x.b(Native Method)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at a.a.a.x.a(Unknown Source)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at a.a.a.b.onCreate(Unknown Source)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at jp.co.testproject.TestProject.onCreate(Unknown Source)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at android.app.ActivityThread.access$1500(ActivityThread.java:117)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at android.os.Handler.dispatchMessage(Handler.java:99)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at android.os.Looper.loop(Looper.java:123)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at android.app.ActivityThread.main(ActivityThread.java:3683)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at java.lang.reflect.Method.invokeNative(Native Method)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at java.lang.reflect.Method.invoke(Method.java:507)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
01-26 13:59:06.151: E/AndroidRuntime(2329): 	at dalvik.system.NativeStart.main(Native Method)
01-26 13:59:06.171: W/ActivityManager(246):   Force finishing activity jp.co.testproject/.TestProject

とエラーで強制終了されている。

release指定でビルドすると難読化ツールのproguardが実行されるため、メソッド名を変更されたり、未使用と判断したクラスを削除され、ビルドに失敗したり上記のように実行時にエラーが発生したりする。
そのため、難読化しないクラス設定などをproguard-project.txtに書く必要がある。
ひとまずcocos2d-xのライブラリを難読化対象外とするために

-keepclasseswithmembers class org.cocos2dx.lib.* { *; }

を追加しておく。
ほかにライブラリ等を追加した場合には随時記述していく必要がある。

これでreleaseビルドを作成できるようになったはず。

*1:実際にはリリース用のkeystoreを作成し使用する必要がある

cocos2d-xのコマンドラインビルド

cocos2d-xのC++プロジェクトでコマンドラインビルドをやることがあったのでメモ。

コマンドラインからapkファイルをビルドをするためにはantを使う。
Gradleでもできるらしいがこっちは未調査。


まずは以下のソフトをインストールしてパスを通す。

これで android, adb, ndk-build, ant が使えるようになる。

次にandroidプロジェクトをupdateする。

android project update -p "プロジェクトのパス"

cocos2d-xは最初からant用のprojectが作成されているためupdateだけでいい。
updateする対象は最低限 project/プロジェクト名/proj.android と cocos2dx\platform\android\java の二つ。
ほかにプロジェクトを追加したらそれもupdateする必要がある。

とりあえずこれでプロジェクトのディレクトリで

ant debug

を実行すると bin ディレクトリ内にapkが作成されるはず。
Eclipseと並列でビルドしていた場合にはエラーが起こることがあるので、その場合は

ant clean build install

とすればcleanした後にビルドしてくれる。また、installとつけることにより、端末にインストールまでしてくれる。
初期設定のままだとJava部分だけビルドするようなので、C++ はcleanされない。
cocos2d-xはJava部分が少ないため、毎回リビルドしてもたいして時間はかからない。そのため、毎回cleanをつけたほうが良さげ。

また、antはJavaしかビルドしてくれないため、build_native.sh を事前に実行し、assetsファイルのコピーおよびC++のビルドを行う必要がある。
よってapkを作成するには

bash build-native.sh
ant clean debug install

と実行すれば端末にデバッグビルドがインストールされる。

releaseビルドを作成するには単に

bash build-native.sh
ant clean release install

とすればいいが、apkのインストールに失敗する。
releaseビルドの設定についてはまた次回。

ZendFrameworkでXML-RPC

ZendFrameworkのXML-RPCの使い方をメモ


XML-RPC用置き場としてxmlrpcモジュールを追加する( http://hatahata-memo.hatenablog.jp/entry/2013/11/20/154753 参照)

xmlrpc処理用クラスを置くservicesディレクトリを作成する(application/mocules/xmlrpc/services)
これでservicesディレクトリ下の Xmlrpc_Service_***** というクラスをオートローダが読み込んでくれる(ディレクトリ名がservices(複数形)、クラス名がService(単数形)なのに注意!)

XML-RPCのテストとして、四則演算メソッドを持つXmlrpc_Service_Calculatorクラスを作成する(http://framework.zend.com/manual/1.12/ja/zend.json.server.html のCalculatorクラスまんま)

<?php
/* application/modules/xmlrpc/services/Calculator.php */
class Xmlrpc_Service_Calculator
{
    /**
     * 2つの変数の合計を返します
     *
     * @param  int $x
     * @param  int $y
     * @return int
     */
    public function add($x, $y)
    {
        return $x + $y;
    }
    /* 以下略 */
}

XML-RPCはコメントを見て型判別を行っているためメソッドのコメントは省略しないこと

indexコントローラにXML-RPCサーバの記述を行う

<?php
/* application/modules/xmlrpc/controllers/IndexController.php */
class Xmlrpc_IndexController extends Zend_Controller_Action
{
    protected $_server = null;

    public function init()
    {
        // viewは非表示
        $this->_helper->viewRenderer->setNoRender(true);
        
        $this->_server = new Zend_XmlRpc_Server();
        // クラス追加
        // Xmlrpc_Service_CalculatorをCalculatorという名前でアクセスする
        $this->_server->setClass('Xmlrpc_Service_Calculator', 'Calculator');
    }

    public function indexAction()
    {
        // POSTのみ許可
        if ('POST' != $_SERVER['REQUEST_METHOD']) {
            echo $this->_server->fault();
            return;
        }
        // 結果表示
        echo $this->_server->handle();
    }
}

XML-RPCのテストを行う
http://zfのアドレス/xmlrpc に次のXMLをPOSTで送る
FireFoxだとHTTP Resource Testが便利

<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
  <methodName>Calculator.add</methodName>
  <params>
    <param>
      <value><int>42</int></value>
    </param>
    <param>
      <value><int>18</int></value>
    </param>
  </params>
</methodCall>

Xmlrpc_Service_Calculatorクラスのaddメソッドが呼ばれ、42+18の結果が返ってくるはず。

ZendFrameworkでmoduleを追加する

zfでは機能ごとにmoduleという単位でコードを分けておくことができる。
moduleを作成するためのzfコマンドが用意されているが、コマンドを叩くだけではうまくいかなかったのでメモ。


testモジュールを追加

  zf create module test

これでmoduleディレクトリ application/modules/test 以下が追加されるが、これだけだと動かないので以下の作業が必要

application.iniにmoduleの設定を追記する

resources.modules[] =

module用のBootstrapを置く

<?php
/* application/modules/test/Bootstrap.php */
class Test_Bootstrap extends Zend_Application_Module_Bootstrap
{
}

testモジュールにindexコントローラを作成する

 zf create controller index 1 test

これでmoduleが使えるようになったので http://zfのアドレス/test にアクセスできればおk。

踏み台サーバを経由してssh/scpを実行する方法

踏み台サーバを経由してsshおよびscpを実行する方法のメモ

 

sshコマンドにはポートフォワード機能があり、これを使用すればローカルサーバから踏み台経由でssh、scpが使える。

gateway-host.com:1022経由でtarget-host.com:22に接続するためのコマンドは以下の通り

 ssh -i /home/user/.ssh/id_rsa -fCL 65536:target-host.com:22 -p 1022 user@gateway-host.com sleep 1 > /dev/null

このコマンド実行後1秒以内にlocalhost:65536に対してssh/scpコマンドを実行するとtarget-host.comに対して接続できる

 ssh -i /home/user/.ssh/id_rsa -p 65536 user@localhost 'ls'

踏み台サーバと接続サーバで異なるユーザおよびrsaキーを使用することも可能

1秒以内に接続がなかった場合、もしくは接続終了すると自動的に終了するので安心