This is the fourth entry in an ongoing series about building Couchbase Lite .NET from source. As I mentioned in a previous post, I am too close and familiar with the library and I often forget that it is complicated and annoying to build without the amount of full time work that I have spent with it. This entry will feature Xamarin iOS as the target.
Couchbase Lite support iOS 9+. Any version of Xamarin AiOSndroid should work to build this but I tend to keep on a fairly modern version of it. However, as I mentioned in a previous post we need to build native components. We have chosen to support both 32 and 64-bit devices and simulators and so we need the following architectures: armv7, arm64, i386, and x86_64.
Unlike the previous platforms, iOS does not use CMake and instead relies on an Xcode project that is maintained by the developers of Couchbase Lite iOS. As such, the process for building consists of only one step: running xcodebuild. There is a script in the vendor/couchbase-lite-core/build_cmake/scripts folder and so let’s look at what it does.
First it builds the device architectures:
xcodebuild -project ../Xcode/LiteCore.xcodeproj -configuration Release -derivedDataPath ios -scheme "LiteCore dylib" -sdk iphoneos BITCODE_GENERATION_MODE=bitcode CODE_SIGNING_ALLOWED=NO
derivedDataPath is simply where we want to store the result, and the result of the switches are pretty self explanatory. The two variables at the end specify that we want full bitcode embedded and we do not want to code sign so we expressly forbid it. If the library gets signed now it causes potential issues later when signed again.
Second, it builds the simulator architectures:
xcodebuild -project ../Xcode/LiteCore.xcodeproj -configuration Release -derivedDataPath ios -scheme "LiteCore dylib" -sdk iphonesimulator CODE_SIGNING_ALLOWED=NO
This is exactly the same as above, just with -sdk iphonesimulator instead of -sdk iphoneos and no BITCODE_GENERATION_MODE define.
Now all the architectures are built but they are in two separate files and so we need to stitch them together:
lipo -create ios/Build/Products/Release-iphoneos/libLiteCore.dylib ios/Build/Products/Release-iphonesimulator/libLiteCore.dylib -output ios-fat/libLiteCore.dylib
This uses a tool called lipo to merge two libraries with different architectures into one with multiple. In this case each library had two architectures and so the resulting one has four. This is the final output artifact that will be used for CBL .NET (libsqlcipher.dylib may be added later)
At the .NET level there are two relevant projects: Couchbase.Lite and Couchbase.Lite.Support.iOS. The former is a .NET Standard 1.4 library which contains the majority of the logic for the library and the latter is a Xamarin iOS class library which houses the native builds created above as well as some support classes which are injected into the main library. The support library expects the native library in the following directory:
If you are looking to package, the nuspec files are all in the packaging/nuget directory. The nuspec files are not set up to build from source so you need to build everything first. After that you can take some cues from the do_package.bat script and run the following:
nuget pack couchbase-lite.nuspec /BasePath ..\.. /Properties version=2.0.0 nuget pack couchbase-lite-support-ios.nuspec /BasePath ..\.. /Properties version=2.0.0
This will output two Nuget packages and they will be the same as what you find in whatever Nuget feed you acquire Couchbase Lite from.
Warning: Due to a Nuget bug, the nuspec files must change the paths from using backslash ( \ ) to using forward slash ( / ) if Nuget is run on a non-Windows machine. It sucks, but there is nothing I can do about that.
Hopefully this article will be useful for anyone attempting to build from source, as I encourage everyone to do since this is an open source product and the fastest way to get an issue fixed is to point out as specifically as possible where it is ;).