Menu

Xamarin iOS TeamCity Build

February 26, 2016 - Continuous Integration, Geek Bits, iOS Development, Mobile Development, MvvmCross, Xamarin
Xamarin iOS TeamCity Build

So this turned into a complete nightmare for a while.

TeamCity Mac Agent Push Installation

I started by trying to get TeamCity to do a push install of a new agent on my MacBook Pro and very quickly things got very, very ugly.  First off it couldn’t find a JDK (which was installed) so I was using bash to update my ~/.bash_profile with the JAVA_HOME variable, but nothing seemed to work.  I fixed that by simply downloading the latest JDK release package and installing it.

Once the JDK errors and my /.bash_profile were fixed I then got the error (this is it in its entirety) “su: Sorry” … at that point I threw in the towel.  I’ve got better things to do that battle with this crap.  I abandoned the plan to push install the agent as I simply couldn’t figure out what was wrong with no information, the error text above was all that appeared in the agents log file as well so its  anyones guess as to what the problem really was.

NOTE: Make sure you can browse to the TeamCity site on your network using the agent machine

So I dialed into my TeamCity server, grabbed the zip installer and did it all manually.  This worked first time (after amending the buildAgent properties file) so what ever the issues were with the push installation I don’t know and frankly I don’t care, JetBrains have some tiding up to do both on this.

Build Steps

Since the build for the iOS application is now happening using Xamarin Studio installed on the Mac the build process is much simpler.  At the moment my unit tests are all run during debug builds only and these occur on a PC running another build agent.  I will revisit this to start executing test runs on the Mac agent to make for a more holistic testing process.

Updating Plist Files

There are a number of ways you can update the plist data on OSX.  Some people seem to suggest using the termainal DEFAULTS command but I found that didn’t work when presented with an iOS style Info.plist.  Chiefly it seemed to be confused by the internal layouts having arrays and a dict element.

By far the simplest way I found was making use of the standard OSX tool PlistBuddy which can deal with our iOS plist data.  So I added a new build step (executed before the compile step) and have configured it to allow me to update it’s internal version numbers and bundle identifiers based on the build configuration.

I normally use a 4 element version number for .NET (major).(minor).(build).(revision) which gives full traceability back to the source control for an individual release.  But if you use this in all cases you’ll have problems as iOS uses the semantic version number format (major).(minor).(build) for the “CFBundleShortVersionString” version number.

But you can also use arbitrary values in the “CFBundleVersion”.  Lots of people seem to ignore the AssemblyInformationalVersionAttribute in .NET but this is a great feature as you can use arbitrary strings as well as the more formal version format when using it in .NET assemblies.

$ /usr/libexec/PlistBuddy -c "Set :CFBundleIndentifier (yourbundleid)" Info.plist
$ /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString %build.number%" Info.plist
$ /usr/libexec/PlistBuddy -c "Set :CFBundleVersion %build.number%.%build.vcs.number%" Info.plist

Compile – Obsolete

The build step for compiling the iOS configuration is executed using a CommandLine build runner with a simple command like this:

/Applications/Xamarin\ Studio.app/Contents/MacOS/mdtool build "--configuration:Debug|iPhone" /path/to/solution.sln

Archiving Builds – Obsolete

Once the build is complete you’ll want to automatically create your archive. When you come to distribute your application to the App Store or to TestFlight via the XCode you’ll want to use xcarchive. You can use IPA files from the Build step with the Application Loader but as far as I can tell there is no way to upload dSYM files for any symbolicate processes which is a bit crazy (unless I’ve missed something)

Create another build step and use:

/Applications/Xamarin\ Studio.app/Contents/MacOS/mdtool -v archive "--configuration:Debug|iPhone" /path/to/solution.sln

This will place an xcarchive file into ~/Library/Developer/XCode/Archives/.  You can then validate this archive via XCode -> Window -> Organizer on the Archives panel.

Bye Bye MDTOOL Hello XBUILD

So, it seems the recent versions of Xamarin Studio and the MDTOOL method of compiling and archiving have become problematic.  I started to see builds failing with some odd errors relating to my Droid project inside the build logs of the iOS builds.  Hugely confusing.  I never got to the bottom of why this was occurring and decided to review the whole process.  Both the compile and archive steps are now combined into one step and one command.  The command I’m now using is:

/Library/Frameworks/Mono.framework/Commands/xbuild /p:Configuration=AppStore /p:Platform=iPhone /p:BuildIpa=true /p:ArchiveOnBuild=true /target:Build /path/to/solution.sln

Obviously you can change any of the configuration or platform parameters to suit your requirements / project setup.

As I work through the next steps of this process I’ll keep this blog post updated – you can read the Android version here.

Share

Leave a Reply

Your email address will not be published. Required fields are marked *

*