読者です 読者をやめる 読者になる 読者になる

なんとなく

誰得感満載な記事が多いかも。Mono関係とLinuxのサーバ関係、レビューとか。

Protobuildを使ってXamarin.Android用のプロジェクトを生成

Xamarin.Android libopenmetaverse

はじめに

今回は、LibOpenMetaverseというクロスプラットフォームライブラリをXamarin.Androidにも対応させる際に必要となったProtobuildというクロスプラットフォームプロジェクト自動生成ツールの紹介と実際に使ってみての感想を記述していきます。

なお、例示しているライブラリとそれを支えるプラットフォームの関係から、このエントリは、

クロスポストしています。

そのため、

で見てほしいです。

手動で既存のcsprojをXamarin.Android用にする方法

プロジェクト自動生成ツールの話に入る前に、Xamarin.Android用のプロジェクトファイルに触れて見たいと思います。

Xamarin.Android用に作られていないプロジェクトは、当然、Xamarin.StudioやVisualStudioなどのIDEで開いてもXamarin.Android向けには使えないわけで、Xamarin.Android用として使いたいなら、それ用にするという作業が発生します。

LibOpenMetaverseをXamarin.Android*1用に動かし始めた2011年当時は、IDEを2つ立ち上げ、1つでは既存のもの開き、もう一つでは既存のものと同じ名のプロジェクトファイルを作って、Xamarin.Android用で既存のもとと同じ構成になるように手作業でポチポチとインポートなどをしていました。

今回、ちょっと調べてみてると、基本的には既存のプロジェクトファイル(拡張子が.csproj)をほんの少し修正するだけでXamarin.Android用のプロジェクトファイルになるということが今更わかり2011年当時に知りたかったよとなりました*2

実際に既存のプロジェクトファイル(*.csproj)をXamarin.Android用にする方法ですが、

  • 特定のProjectTypeGuidsを追加する
  • Import Projectを変更する

です。

具体的には、プロジェクトファイルを適当なテキストエディタで開いて

ProjectGuidの下辺りに

<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

を追加します。 また、大体の場合以下のようになっているのを

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

次のように

<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />

に変更します。

現状、以下のように変更しても動きますが、近い将来Novell.MonoDroid.CSharp.targetsが無くなる可能性が高いので非推奨です。*3

<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />

これで、基本的にXamarin.Android用のプロジェクトになります。(<TargetFrameworkVersion>なども変更する必要がありますが、後々IDEで修正すれば問題ありません。) 仕組みなどについては、中の人が少し触れている電子書籍がありますので、そちらを参照してください。*4

この方法は、うまくいかない場合もあります。その場合は、後述するProtobuildを使って作成することができます。もちろん、同名のものを新規で作成するのもありです。なんとかしようと思ってプロジェクトファイルを編集しまくるとハマります。

また、おわかりのこととは思いますが、あくまでもプロジェクトファイルがXamarin.Android用になるだけで、Xamarin.Anroidで動くようにするためには適宜ソースコードの修正が必要です。

プロジェクト自動生成ツール

LibOpenMetaverseにおいては、プロジェクト自動生成ツールを使用して管理しているので、それにならい、Xamarin.Androidに対応したものを使用するが必要がありました。 そこで探したところ、LibOpenMetaverseではprebuildという今はディスコンのツール使用していて明らかに対応していませんでしたし、時々見かけるPremake でもXamarin.Androidには対応していませんでした。さらに調べているとMonoGameでいろいろと議論されており*5*6、MonoGameはProtobuildというものを使うようになったということがわかりました。

Protobuildは.NET Foundationにもjoinしている*7ので、Xamarin.Androidを含んだクロスプラットフォームプロジェクト自動生成はProtobuildを使うのがいいと判断し、紹介するに至りました。

使い始めて数週間ですので誤りがあるかもしれません。おかしいところがございましたら、コメントください。 詳しくは公式のドキュメントを参照ください。 http://protobuild.readthedocs.io/en/latest/

Protobuildについて

github.com

  • Protobuildは、C#向けのクロスプラットフォームプロジェクト自動生成ツールです。
  • Protobuildは各プラットフォームごとの異なる参照を生成するので、クロスプラットフォームだけど、それぞれのnativeのAPIガンガン叩くぜって言う場合に使えます。
  • .NETをサポートしている各プラットフォームでC#C++のソリューションとプロジェクトを生成できます。

デスクトップ環境とモバイル環境においてC#ソースコードを共有する場合で、プロジェクトの自動生成をする場合はいまのところProtobuildしか対応していないように思えました。もし、他のツールをご存じの方はコメントください。

Protobuildのサポートしているプラットフォーム

現状、Protobuildのサポートしているプラットフォームについては、GitHub - Protobuild/Protobuild: Cross-platform project generation for C#によると以下です*8

  • Android (via Xamarin)
  • iOS (via Xamarin)
  • tvOS (via Xamarin)
  • Linux
  • MacOS
  • Ouya (via Xamarin)
  • PCL (for Bait-and-Switch PCL only)
  • Windows
  • Windows8
  • WindowsPhone
  • WindowsPhone81
  • WindowsUniversal
  • Web (via JSIL)

Protobuildの使い方

ざっくりとした使い方については、プロジェクトファイルのもとになる定義ファイルをXMLで記述し、それをもとにソリューションファイル(.sln)とプロジェクトファイル(.csproj)を生成します。定義ファイルの中で各プラットフォームに対応させるために<Platform>を使います。

これだけではイメージがつかみにくいので、実際にみていきます。

ダウンロード

まずは、ここからProtobuildをダンロードします。

http://protobuild.org/get

初期処理

Protobuildでプロジェクトを生成するための構成をまずは作成します。 なお、Protobuild.ManagerというGUIも用意されているのですが、今回はCLIでいきます。

ダウンロードしたProtobuild.exeを、任意のフォルダに置き

Windows場合:

Protobuild.exe --start http://protobuild.org/commons/Library hoge

Linux or macOS の場合:

mono Protobuild.exe --start http://protobuild.org/commons/Library hoge

これを実行すると(Windowsの場合)、初期処理をして、そしていきなり生成します。

|--Build
|  |--Modules.xml
|  |--Projects
|  |  |--hoge.definition
|--hoge
|  |  |--MyClass.cs
|  |  |--hoge.Windows.csproj
|--hoge.Windows.sln
|--hoge.Windows.speccache
|--Protobuild.exe

という構成になります。

基本構成は以下となります。

|--Build
|  |--Modules.xml
|  |--Projects
|  |  |--hoge.definition
|--Protobuild.exe

なお、コンソールプロジェクトの場合は

Protobuild.exe --start http://protobuild.org/commons/Console hoge

アプリケーションプロジェクトの場合は

Protobuild.exe --start http://protobuild.org/commons/App hoge

とします。

そして、初期処理によって出力されたて生成するための各ファイルの中身は以下のようになっています。

Modules.xml:

<?xml version="1.0" encoding="utf-8"?>
<Module>
  <Name>hoge</Name>
  <DefaultAction>resync</DefaultAction>
  <GenerateNuGetRepositories>true</GenerateNuGetRepositories>
</Module>

hoge.definition:

<?xml version="1.0" encoding="utf-8"?>
<Project Name="hoge" Path="hoge" Type="Library">
  <References>
    <Reference Include="System" />
    <Reference Include="System.Core" />
  </References>
  <Files>
    <Compile Include="MyClass.cs" />
  </Files>
</Project>

なおPathはProtobuild.exeがあるPathからみてであって、.definitionファイルが有る場所からではないです。

各プラットフォーム用の生成

Xamarin.Android用の生成は以下のようにします。

Protobuild.exe --generate Android

GUIのマネージャーを使うとIDEとシンクロして、プラットフォームの変更もできます。

Protobuild.exe --execute Protobuild.Manager

GUIを使った、ここまでの流れは動画で確認することができるので、参考にしてください。

www.youtube.com

既存のものの移行

ここからは既存のものに合わせていきます。すでにプロジェクトがあるけれどもProtobuildで自動生成できるようにするという場合です。 概略としては、

  • 別フォルダで上述したように初期処理を行う
  • それを対象のフォルダにコピー
  • 既存のプロジェクトファイルをエディタで開いて、もう一方で既存のプロジェクトファイル名.definitionを開き、既存のプロジェクトファイルの<ItemGroup>内にある<Reference >,<Compile>, <Content>, <EmbeddedResource>などをコピペ。

です。 ここでは、LibOpenMetaverseの中で使われているPrimMesherというライブラリを例に見ていきたいと思います。

フォルダ構成は以下のようになっているとします。

|--PrimMesher
|  |--PrimMesher
|  |  |--ObjMesh.cs
|  |  |--PrimMesher.cs
|  |  |--SculptMap.cs
|  |  |--SculptMesh.cs
|  |  |--VertexIndexer.cs
|  |  |--PrimMesher.csproj
|  |--PrimMesher.sln
|--Protobuild.exe
  • 適当なフォルダを作って、移動してそのフォルダにProtobuild.exeをコピー
mkdir demo
cd demo
xcopy ..\Protobuild.exe .\

この時点でフォルダ構成は以下のようになってます。

|--demo
|  |--Protobuild.exe
|--PrimMesher
|  |--PrimMesher
|  |  |--ObjMesh.cs
|  |  |--PrimMesher.cs
|  |  |--SculptMap.cs
|  |  |--SculptMesh.cs
|  |  |--VertexIndexer.cs
|  |  |--PrimMesher.csproj
|  |--PrimMesher.sln
|--Protobuild.exe
  • 初期処理して、定義ファイルなどを作成
Protobuild.exe --start http://protobuild.org/commons/Library PrimMesher
  • 生成されてしまったのを削除
Protobuild.exe --clean

この時点でフォルダ構成は以下のようになっています。

|--demo
|  |--Build
|  |  |  |--Modules.xml
|  |  |  |--Projects
|  |  |  |  |--PrimMesher.definition
|  |--Protobuild.exe
|--PrimMesher
|  |--PrimMesher
|  |  |--ObjMesh.cs
|  |  |--PrimMesher.cs
|  |  |--SculptMap.cs
|  |  |--SculptMesh.cs
|  |  |--VertexIndexer.cs
|  |  |--PrimMesher.csproj
|  |--PrimMesher.sln
|--Protobuild.exe
  • BuildフォルダとProtobuild.exe をソースのあるフォルダにコピー
xcopy build ..\PrimMesher
xcopy Protobuild.exe ..\PrimMesher
  • 既存のPrimMesher.csprojを開いて、<Reference>タグと<Compile>タグのところをコピー

PrimMesher.csproj

略
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="ObjMesh.cs" />
    <Compile Include="PrimMesher.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="SculptMap.cs" />
    <Compile Include="SculptMesh.cs" />
    <Compile Include="VertexIndexer.cs">
      <SubType>Code</SubType>
    </Compile>
  </ItemGroup>
略
  • <Compile>タグをBuild\PrimMesher.definitionにペーストし、以下のように編集します。
<?xml version="1.0" encoding="utf-8"?>
<Project Name="PrimMesher" Path="PrimMesher" Type="Library">
  <References>
    <!-- プラットフォーム別の参照するためのExternal Project -->
    <Reference Include="PrimMesherReference" />
  </References>
  <Files>
    <Compile Include="ObjMesh.cs" />
    <Compile Include="PrimMesher.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="SculptMap.cs" />
    <Compile Include="SculptMesh.cs" />
    <Compile Include="VertexIndexer.cs">
      <SubType>Code</SubType>
    </Compile>
  </Files>
</Project>
  • 新規でBuild\PrimMesherReference.definitionを作成し、<Reference>タグをプラットフォーム別に作成
<?xml version="1.0" encoding="utf-8" ?>
<ExternalProject Name="PrimMesherReference">
    <!-- デフォルト -->
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
    
    <!-- プラットフォーム別での追加 -->
    <Platform Type="Windows">
        <Reference Include="System.Drawing" /> 
    </Platform>
    
    <Platform Type="MacOS">
        <Reference Include="System.Drawing" />
    </Platform>
    
    <Platform Type="Linux">
        <Reference Include="System.Drawing" />
    </Platform>
</ExternalProject>

<References>タグ内では、<Reference>タグしか有効ではないようなので、プラットフォーム別に参照を分けたい場合は、別のdefinitionを用意し、ExternalProjectとし作成し、<Platform>タグで分けます。そして作成したExternalProjectを主のdefinition内で<Reference>でincludeします。

詳しいExternalProjectの書き方については、 Defining External Projects — Protobuild latest documentation を御覧ください。

この時点でフォルダ構成は以下のようになってます。

|--demo
|  |--Build
|  |  |  |--Modules.xml
|  |  |  |--Projects
|  |  |  |  |--PrimMesher.definition
|  |--Protobuild.exe
|--PrimMesher
|  |--Build
|  |  |  |--Modules.xml
|  |  |  |--Projects
|  |  |  |  |--PrimMesher.definition
|  |  |  |  |--PrimMesherReference.definition
|  |--PrimMesher
|  |  |--ObjMesh.cs
|  |  |--PrimMesher.cs
|  |  |--SculptMap.cs
|  |  |--SculptMesh.cs
|  |  |--VertexIndexer.cs
|  |  |--PrimMesher.csproj
|  |--PrimMesher.sln
|  |--Protobuild.exe
|--Protobuild.exe
Protobuild.exe --generate Android

とすると以下のように生成されます。PrimMesher.Android.slnを開くと

f:id:takeshich:20161201212148p:plain

Protobuild.exe --generate Windows

とすると以下のように生成されます。PrimMesher.Windows.slnを開くと

f:id:takeshich:20161202000157p:plain

実際に使ってみて

TargetFramworkVersion

Xamarin.Android用の設定として、気にしたところの一つとしては、ターゲットフレームワークで、その設定は

<Properties>
  <FrameworkVersions>
    <Platform Name="Android">
      <Version>v4.2</Version>
    </Platform>
    <Platform Name="Windows">
      <Version>v4.0</Version>
      <Profile>ClientOnly</Profile>
    </Platform>
    <Platform Name="Linux">
      <Version>v4.5</Version>
    </Platform>
    <!-- etc. -->
  </FrameworkVersions>
</Properties>

Customizing Projects with Properties — Protobuild latest documentation

のようにします。 プロジェクトごとに設定するのが面倒で、すべてのプロジェクトで同様にしたかったので、後述するカスタマイズで対応しました。

細かいところはカスタマイズ

Protobuildはテンプレートを使うことによってカスタマイズすることができます。その方法は2つあります。

Customizing Protobuild — Protobuild latest documentation

プロジェクトのカスタマイズについては

  • Protobuild自身で使用しているプロジェクト生成のテンプレートを抽出し、それを変更する
  • AdditionalProjectTransforms.xsltを追加する

前者は、すべてのプロジェクトで変更したい場合に使うようです。ただ、テンプレートの量が大きく、変更箇所の修正におけるコストが高いです*9。一方後者は名前で絞ることでプロジェクトを指定でき、比較的楽です。編集というよりは追加のようです。

カスタマイズその1

Protobuildは自身で使用しているプロジェクト生成のテンプレートを抽出でき、それを変更することによってカスタマイズすることができます。

Protobuild.exe --extract-xslt

とするとBuild\以下に

  • GenerateProject.CPlusPlus.MonoDevelop.xslt
  • GenerateProject.CPlusPlus.VisualStudio.xslt
  • GenerateProject.CSharp.xslt
  • GenerateSolution.xslt
  • GenerationFunctions.cs
  • SelectSolution.xslt

を吐き出します。

好きなようにカスタマイズできるようです。今回はGenerateProject.CSharp.xsltのみを使用しました。

現在、Protobuildのデフォルト設定で指定されるようになりましたが、私がissue*10を上げるまでXamarin.Android向けプロジェクトで

  • <Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />と生成されていた
  • <AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>と生成されていた

ので、GenerateProject.CSharp.xsltの対象の部分を

  • <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
  • <AndroidSupportedAbis>armeabi,armeabi-v7a,arm64-v8a,x86,x86_64</AndroidSupportedAbis>

にして使っていました。現在は修正されています。

ただ、LibOpenMetaverseのOutputフォルダはプラットフォーム別に分けることなく一つなのですが、Protobuildは、プラットフォーム別に生成するのでGenerateProject.CSharp.xslt<OutputPath>を指定するところをLibOpenMetaverse向けに変更しています。 また、<TargetFrameworkVersion>を指定するところを今のところv5.1にしています。

カスタマイズその2

もう一つのカスタマイズの方法として、Build\AdditionalProjectTransforms.xsltを追加する方法があります。 GenerateProject.CSharp.xsltを変更するとProtobuildで生成するすべてのプロジェクトに適用されてしまいますが、以下のようにしてプロジェクト名を指定することによってそのプロジェクトだけをカスタマイズすることもできます。

AdditionalProjectTransforms.xslt

<xsl:if test="Input/Generation/ProjectName = 'OpenMetaverse'">
  <Target Name="BeforeBuild">
    <Exec>
      <xsl:attribute name="WorkingDirectory">
        <xsl:text>jni</xsl:text>
      </xsl:attribute>
      <xsl:attribute name="Command">
          <xsl:text>$(AndroidNdkDirectory)\ndk-build</xsl:text>
      </xsl:attribute>
    </Exec>
  </Target>
</xsl:if>

OpenMetaverse.Android.csproj内では対象は以下のようになります。

<Target Name="BeforeBuild">
  <Exec WorkingDirectory="jni" Command="$(AndroidNdkDirectory)\ndk-build" />
</Target>

上記は、2013年のAdventCalendar

takeshich.hatenablog.com

で書いたNativeライブラリをビルドする前にビルド(ndk-build)して、まとめてビルドできるようにするものです。

Xamarin.AndroidでNDKを利用する - Qiita

に記述されていた方法を参考にしました。 また、プラットフォームによる判定も必要と思いますが、今回の場合、Xamarin.Android用のみでおこなっておりますので、そのような記述になっています。

しかし、問題がありまして、Protobuildでプロジェクトの自動生成した際には、NDKビルドで生成される.soは実体のない状態でして、その状態でビルドすると以下のようなエラーが出て、ビルドできません。

ターゲット _CreateNativeLibraryArchive:
    C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1149,5): error MSB4018: "CreateNativeLibraryArchive" タスクが予期せずに失敗しました。\r
    C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1149,5): error MSB4018: System.IO.DirectoryNotFoundException: パス 'libs\arm64-v8a\libopenjpeg-dotnet.so' の一部が見つかりませんでした。\r
    C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1149,5): error MSB4018:    場所 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)\r
    C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1149,5): error MSB4018:    場所 System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite, Boolean checkHost)\r
    C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1149,5): error MSB4018:    場所 System.IO.File.Copy(String sourceFileName, String destFileName, Boolean overwrite)\r
    C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1149,5): error MSB4018:    場所 Xamarin.Android.Tools.Files.CopyIfChanged(String source, String destination)\r
    C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1149,5): error MSB4018:    場所 Xamarin.Android.Tasks.CreateNativeLibraryArchive.Execute()\r
    C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1149,5): error MSB4018:    場所 Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()\r
    C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1149,5): error MSB4018:    場所 Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()
プロジェクト "OpenMetaverse.Android.csproj" 内のターゲット "_CreateNativeLibraryArchive" のビルドが終了しました -- 失敗。

プロジェクト "OpenMetaverse.Android.csproj" のビルドが終了しました -- 失敗。

期待していることは、build前にNDKビルドが実行され、実体が存在し、buildされることなのですが。。。 これについては、今のところの回避策として、プロジェクトを生成する前にNDKビルドしています。Target NameをBeforeCompileにしても大丈夫なようです。IDEでプロジェクトを開いたときにコンパイルするみたいで、実体が存在すればエラーは出ません。Beforebuildの前にビルドに使われるNativeLibraryがアーカイブされているのかなど、ちょっとビルド順序に疑問を感じていますが、それについては別の機会でということにします。 こちらについては、

BeforeBuild/AfterBuildは実行順序を保証しない、外部からのターゲット実行の追加方法として利用できる機能なので、BeforeBuildで自分の手元で指定したターゲットよりXamarinのビルドタスクが先に実行される可能性があることは、否定できません。 Xamarin - Xamarin.AndroidのBeforeBuildの実行タイミングについて(57667)|teratail

とのことで、MSBuildについて詳しく見ていき、Xamarin.Android.Common.targetsを追っかけながら、適切な方法を探るということをする必要がありそうです。ただ、この<Target Name="BeforeBuild">を追加しないという手段もあるので後々考えて対処したいと思います。

Xamarin.Andoid用テストプロジェクト作成方法

Protobuildでは、Xamarin.Andoid用のテストプロジェクトを生成できません。 そのためカスタマイズする必要があるのですが、Xamarin.Andoid用のテストプロジェクトの中身を見てみました。 Libraryとの違いは、 <AndroidApplication>True</AndroidApplication>の有無のようでした。

そこで、抽出したGenerateProject.CSharp.xslt

https://github.com/Protobuild/Protobuild/blob/master/Protobuild.Internal/BuildResources/GenerateProject.CSharp.xslt#L1141

あたりに

<xsl:if test="Input/Generation/ProjectName = 'OpenMetaverse.Tests' or Input/Generation/ProjectName = 'STPTests'">
<AndroidApplication>True</AndroidApplication>
</xsl:if>

を追加し、テスト用のプロジェクトを指定して、Xamarin.Andoid用のテストプロジェクトとして生成するようにしました。

また、以下のようなTestSuiteActivityを継承したクラスを持つActivityを作り追加しました。

using System.Reflection;

using Android.App;
using Android.OS;
using Xamarin.Android.NUnitLite;

namespace OpenMetaverse.Tests
{
    [Activity(Label = "Activity1")]
    public class Activity1 : TestSuiteActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {

            AddTest(Assembly.GetExecutingAssembly());

            base.OnCreate(savedInstanceState);

        }
    }
}

サブモジュール

Protobuildでは、生成時にパッケージとしてリポジトリをcloneして、別プロジェクトとして参照を可能としています。

LibOpenMetaverseはその中で以下に示す幾つかの外部DLLを使用しています。

  • log4net
  • PrimMesher
  • XmlRpcCS
  • zlib.net

そのソースはどこにあるか不明なのですが、Xamarin.Android向けではオリジナルっぽいものや互換性のあるものを探して使用しています。特にXmlRpcCSについてはそのオリジナルのソースに手が加えられたものを使用しているようで、LibOpenMetaverse版のXmlRpcCSが存在するようです。そのため、想像で編集して対応しています。LibOpenMetaverseのメーリングリストに確認してみようと思っています。メインの管理者が今年亡くなってしまっていますが、対応された方はすでにプロジェクトを離れているものの、時々コメントすることもあるようですので、返信をくれるかもとも思っています。

以下のようにして、生成時にリポジトリをcloneすることが可能です。 Modules.xml

  <Packages>
    <Package Uri="https-git://github.com/takeshich/log4net-201310.git" Folder="log4net" GitRef="master" />
    <Package Uri="https-git://github.com/takeshich/SmartThreadPool.git" Folder="SmartThreadPool" GitRef="forandroid" />
    <Package Uri="https-git://github.com/takeshich/XmlRpcCS.git" Folder="XmlRpcCS" GitRef="forandroid" />
    <Package Uri="https-git://github.com/takeshich/PrimMesher.git" Folder="PrimMesher" GitRef="forandroid" />
    <Package Uri="https-git://github.com/takeshich/ZLIB.NET.git" Folder="zlib.net" GitRef="forandroid" />
  </Packages>
</Module>

こうすることで、生成時にgit cloneし、プロジェクトとして参照させることができます。

感想

  • めんどくさい。

Protobuildは悪くないです。当方が面倒くさがりなので。そして、手を動かしてみないとその感覚がわかりませんでした。

開発環境によってプロジェクトファイルをIDEに意識しないところで変えられてしまって、コミット時に問題になる場合もあります。 この問題を当初から見越して設計当初からXamarin(Android,iOS)が含まれるクロスプラットフォーム環境の場合は、最初からProtobuildを使用するようにすれば、それはスマートだと思います。

今回はLibOpenMetaverseがプロジェクトの自動生成を行っており、それに合わせるためにではありますが、すでにあるものが使えずにProtobuildを使用しました。その点では一から組み上げる必要があったというところがめんどくさいと感じてしまったと思います。

Protobuildについては、ドキュメントを見ながら、各プラットフォームでうまく生成されるようにするという試行を何度も繰り返しますし、プロジェクトファイルの内容について何をしているのか理解しなければならないことがあります。それ自体は良い勉強なのですが、MSBuildについて詳しくとか、Xamarin.Androidの挙動のところにも食い込んでいくので結構辛いところがありました。

初期導入の学習、構築コストはそれなりにありますが、一度組み上げてしまえば、その後の修正についてはさほど気になる程度ではないと思います。 積極的なおすすめはできないものの、いまのところ、Xamarin(Android,iOS)ではこれしかないよねという状態ですから、紹介ということにさせてください。

LibOpenMetaverse for Androidについてですが、本来このエントリ公開と同じタイミングで公開を考えていましたが、Protobuildの設定と確認とかで思いの外、時間を取られてしまい*11、コード関連の修正が終わっておりません。取りあえず動くのはあります。この時期色々とあるので来年になるかもしれませんが、進めてはいます。

*1:正確を期すなら、Mono for Android

*2:一度行ってしまえば何度も行う作業ではないので問題もないのですが、ライブラリで使用しているライブラリなどプロジェクトの数が複数あったので手間だったという印象がありました。近い時期にPSMobile用のも行ったので負の印象が増幅されているのかもしれません。

*3:teratailで中の人しか答えられない質問をしたら、中の人から回答をいただけました。 https://teratail.com/questions/56804

*4:AZ 異本grimoire of android 5.3 Xamarin.Android SDK の仕組み MSBuild によるビルド プロジェクトファイルにおけるXamarin.Android 拡張サポート指定 https://booth.pm/ja/items/275296

*5:https://github.com/MonoGame/MonoGame/issues/1722

*6:https://github.com/MonoGame/MonoGame/issues/1865

*7:https://dotnetfoundation.org/protobuild

*8:今後増減するようです。Tizenとか.NET Coreとかへの対応、それとさよならは、PSMobile!

*9:プロジェクトファイルについての知識も必要になってきます。

*10:https://github.com/Protobuild/Protobuild/issues/185

*11:そういう意味で学習コスト高いです