mamori017.log

歴史的クソブログ

リンクとして追加したコードを含むプロジェクトをAppveyorでビルドする

f:id:mamori017:20180802111441p:plain

.NET Frameworkのプロジェクトで一部のコードを別のソリューションからリンクで参照するということはよくあるケースだと思います。 GitHubでバージョン管理している.NETプロジェクトはAppVeyorを使用してビルドしているのですが、 AppVeyorでこの関係性を持ったプロジェクトをビルドするのは厳しいと、調べもせず勝手に思っていたためビルド対象から除外していました。 *1

しかし考えてみれば、AppVeyor内のビルド環境に参照先のファイルが存在するリポジトリさえクローンできればビルドは通るはず。 感覚的にはnuget restore的に、ビルド前にAppVeyor内でgit cloneしてやれば解決するじゃないかと思ったのでやってみました。

前提として、ローカル環境のビルド対象(TargetProject)リポジトリと参照先(ReferenceProject)リポジトリは同階層にいます。

設定

appveyor.ymlのbefore_build:項目に参照したいプロジェクトのリポジトリをクローンするよう追記します。これだけ。

AppVeyor setting for .NET projects with link refer ...

これでビルド対象(TargetProject)リポジトリと参照先(ReferenceProject)リポジトリがローカル環境と同様、 同じディレクトリ内に存在することになります。

ビルド

GitHubへプッシュしたらあっさりビルドが通りました。

f:id:mamori017:20180802140447p:plain

余談というか失敗

難しく考えすぎて参照するリポジトリのクローン先をビルド対象のディレクトリ内に設定していました。 クローン先ディレクトリを作成してそこを参照させようというのが狙いです。

before_build:
  - nuget restore TargetProject.sln
  - mkdir .\TargetProject\ReferenceProject
  - git clone -q --branch=master https://githostserver/ReferenceProject.git .\TargetProject\ReferenceProject

before_buildへの記述が実行されたディレクトリの状態。

./
├ /.vs
├ /TargetProject
│ ├─ /ReferenceProject(クローン先)
│ ├─ /bin
│ ├─ /obj
│ ├─ /Properties
│ ├─ Class1.cs
│ ├─ Class2.cs
│ ├─ Class3.cs
│ └─ TargetProject.csproj
└ TargetProject.sln

これではTargetProject.slnがローカルと同様の設定のまま、参照先コードのパスだけが変わってしまっているためビルドが通りません。 クローンしたファイルを認識させるにはプロジェクトファイルの構成を変更する必要があります。

参照しているコードをReference.csとすると、TargetProject.csprojの元の状態はこのようになっています。

<ItemGroup>
  <Compile Include="..\..\ReferenceProject\ReferenceProject\Reference.cs">
    <Link>ReferenceProject\Reference.cs</Link>
  </Compile>
</ItemGroup>

ローカルのビルド環境ではこの参照パスが通りますが、AppVeyorでビルドする場合はクローン先のパスが変わってしまっているので、 ソリューション構成がDebugの時はローカル環境でのビルド、Releaseの時はAppVeyorでのビルド用に設定を変更し、それぞれで参照先が異なる状態にしました。

<ItemGroup>
  <Compile Include="..\..\ReferenceProject\ReferenceProject\Reference.cs" Condition=" '$(Configuration)' == 'Debug' ">
    <Link>ReferenceProject\Reference.cs</Link>
  </Compile>
  <Compile Include=".\ReferenceProject\ReferenceProject\Reference.cs" Condition=" '$(Configuration)' == 'Release' ">
    <Link>ReferenceProject\Reference.cs</Link>
  </Compile>
</ItemGroup>

MSBuild Conditions

これでもビルドは通るのですが、参照コードの増減があるたびに.csprojを手で書き換えないといけないので、リスクがあるうえ面倒です。 appveyor.ymlに1行追加することと比べるとデメリットしかないと思うのでこの手法は取るべきではないです。 何より早く気づけという話でした。

*1:リンクで参照せず、実体をコピーしてビルドするプロジェクトを別に作成して管理とビルドをしていた。恥ずかしい。