Background
My team and I are building a Xamarin Forms mobile application that includes iOS and Android projects. I've set up automated CI builds and I've created some custom build configurations for CI and Production (Store) builds. The idea is to use one solution level build configuration that configures both iOS and Android projects appropriately with one build script.Here's the Ad-hoc (deploy to test devices) Build Config:
(The first project is the PCL which simply the App name with no suffix).
Here's the Production (Store) Build Config:
This all works great in Visual Studio. But not in Bitrise (my chosen online mobile build system).
The Error Message
Here's the command line used to build the Android project extracted from the build output in Bitrise:xbuild /t:PackageForAndroid /p:Configuration"PlayStore" "./XXXXXXXX/XXXXXXXX.Droid/XXXXXXXX.Droid.csproj" /verbosity:minimal /nologo
Within a few seconds produces this error message.
/Library/Frameworks/Mono.framework/Versions/4.4.0/lib/mono/4.5/Microsoft.Common.targets: error : 'OutputPath' property is not set for this project. Usually this is caused by invalid Configuration/Platform combination. Original values: Configuration: PlayStore Platform: AnyCPU.
There's been reports of this error on the Xamarin Forums (and here) that include other build system like Jenkins. It looks like there has been bugs in xbuild and Xamarin Studio that have been investigated and fixed. So its no fault of Bitrise.
The build is given "AppStore" as the target build config, and "RealDevices" as the platform. The solution file is successfully parsed and based on what we can see from the command line above, it has passed the right target and platform to xbuild (see Store Build Config screenshot above).
The iOS project builds fine.
The diagnostic process on Bitrise
It seems unlikely that the bugs discussed in the forum posts mentioned above are still a problem, the posts are dated some time ago. The suggestions center around App code problems rather than real bugs with Xamarin or Mono.
Bitrise only offers limited options to pass parameters to the Xamarin-Builder step. Basically only build configuration, platform, and solution path. This is where their generic Script step comes in handy. Delete the Xamarin-Builder step and replace it with the Script step and use the command line to invoke xbuild directly:
Bitrise only offers limited options to pass parameters to the Xamarin-Builder step. Basically only build configuration, platform, and solution path. This is where their generic Script step comes in handy. Delete the Xamarin-Builder step and replace it with the Script step and use the command line to invoke xbuild directly:
xbuild /t:PackageForAndroid /p:Configuration="PlayStore" /p:Platform="AnyCPU" "./XXXXXX/XXXXXXXX.Droid/XXXXXXXX.Droid.csproj" /verbosity:detailed /nologo /p:OutputPath="bin/PlayStore"
This produced the same results, with nothing new of value.
This produced the same results, with nothing new of value.
Running it locally on a Mac also produced the same results.
I then realised that because the build of the Android project is triggered with a build config of "PlayStore" it is passing this value to the its dependency the PCL project. But its supposed to be built in "Store" config according to the solution file. It doesn't have a config in it's csproj file named "PlayStore" hence the error.
The Solution
xbuild is not building the solution in the same was as msbuild, Visual Studio or Xamarin Studio. It is using the Android csproj file as its entry point not the solution file. So the Build Config name provided to build the Android project has to be the same Config name provided to build the PCL.
I added a "PlayStore" Build Config to the PCL and bingo.
The only downside is that I have two Build Configs to maintain for the PCL: PlayStore and AppStore.