Presentation given at the first Nix meetup in Amsterdam. Covers deployment of Android SDK, integration with Xcode, building apps with Nix and integration with Hydra -- the Nix-based continuous integration server.
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Building mobile apps with the Nix package manager
1. Building mobile apps with the Nix package
manager
Sander van der Burg
Conference Compass
July 14, 2016
Sander van der Burg Building mobile apps with the Nix package manager
2. Apps are popular
Conference Compass provides a service to improve the way
people experience events
Most visible part of the service: apps for conference attendees
Sander van der Burg Building mobile apps with the Nix package manager
3. Apps are popular
Some features:
Conference program
Floormaps
Announcements
Each customer basically gets “their own” app.
We have a product-line to accomplish that
Sander van der Burg Building mobile apps with the Nix package manager
4. Producing apps is complex: target platforms
Sander van der Burg Building mobile apps with the Nix package manager
5. Producing apps is complex: platform versions
Android example:
Code name Version number Initial release data API level
Nougat 7.0 TBD 24
Marshmallow 6.0 October 5, 2015 23
Lollipop 5.0 – 5.1 November 12, 2014 21 – 22
KitKat 4.4 – 4.4.4 October 31, 2013 19 – 20
Jelly Bean 4.1 – 4.3 July 9, 2012 16 – 18
...
(Source: https:
//en.wikipedia.org/wiki/Android_version_history)
Sander van der Burg Building mobile apps with the Nix package manager
6. Producing apps is complex: tedious installations of
dependencies
Sander van der Burg Building mobile apps with the Nix package manager
7. Producing apps is complex: host system requirements
iOS development requires Xcode which requires Mac OS X:
Sander van der Burg Building mobile apps with the Nix package manager
8. Producing apps is complex: how to set up continuous
builds?
Sander van der Burg Building mobile apps with the Nix package manager
10. Nix package manager
Benefits for mobile app development:
Manages the build-time dependencies of mobile apps
Automates the builds of mobile apps
Reliably manages multiple versions/variants of dependencies
Conveniently reproduces app installations
Nix works on multiple operating systems, e.g. Linux and Mac
OS X
Integration with Hydra – the Nix-based continuous integration
solution comes (almost) for free
Sander van der Burg Building mobile apps with the Nix package manager
11. Android packaging in Nixpkgs
Sander van der Burg Building mobile apps with the Nix package manager
Many Android SDK components have been packaged in Nixpkgs
Platform tools
Build tools
Support libraries
Platform SDKs:
API-levels: 2 – 23
System images:
API-levels: 14 – 23
Architectures: armeabi-v7a, x86, x86 64, mips
Addons:
Google APIs, API-levels: 3 – 23
Google Play Services
Android NDK:
Versions: r8e, r10e
12. Android packaging process
The majority of the Android SDK components are open
source (Apache Software License, version 2.0), but Google
does not provide proper source releases
You can fetch sources from Git repositories:
https://android.googlesource.com
The Android SDK has its own package distribution
mechanism (XML metadata + Zip files over HTTP)
Some packages (core SDK, build tools, platform tools) have
executables that must be patched with patchelf
Sander van der Burg Building mobile apps with the Nix package manager
13. Android packaging process
Most components can be automatically transformed into Nix
packages by applying XSL transformations:
<sdk:platform>
<sdk:revision>1</sdk:revision>
<sdk:description>Android SDK Platform 6.0</sdk:description>
<sdk:version>6.0</sdk:version>
<sdk:api-level>23</sdk:api-level>
...
<sdk:archives>
<sdk:archive>
<sdk:size>70408061</sdk:size>
<sdk:checksum type="sha1">
cbccca8d3127e894845556ce999b28281de541bd
</sdk:checksum>
<sdk:url>android-23_r01.zip</sdk:url>
</sdk:archive>
</sdk:archives>
<sdk:uses-license ref="android-sdk-license"/>
</sdk:platform>
Sander van der Burg Building mobile apps with the Nix package manager
14. Android packaging process
Most components can be automatically transformed into Nix
packages by applying XSL transformations:
{fetchurl}:
{
...
platform_23 = buildPlatform {
name = "android-platform-6.0";
src = fetchurl {
url = https://dl.google.com/android/repository/android-23_r01.zip;
sha1 = "cbccca8d3127e894845556ce999b28281de541bd";
};
meta = {
description = "Android SDK Platform 6.0";
};
};
}
More details, see:
http://sandervanderburg.blogspot.com/2012/11/building-android-applications-with-nix.html
http://sandervanderburg.blogspot.com/2013/08/some-improvements-to-nix-android-build.html
Sander van der Burg Building mobile apps with the Nix package manager
15. Installing the Android SDK with Nix
Because the Android SDK is modular, there is no single Android
SDK package. You have to specify which modules you want:
with import <nixpkgs> {};
androidenv.androidsdk {
platformVersions = [ "23" ]; # Anything between 2 - 23
abiVersions = [ "armeabi-v7a" ]; # Also possible: x86, mips, x86_64
useGoogleAPIs = true;
useExtraSupportLibs = true;
useGooglePlayServices = true;
}
$ nix-env -i $(nix-build myandroidsdk.nix)
$ android -h
Sander van der Burg Building mobile apps with the Nix package manager
16. Installing the Android SDK with Nix
Nixpkgs contains a number of preconfigured compositions for
common scenarios:
Install an SDK with commonly used modules for Android 6.0:
$ nix-env -f ’<nixpkgs>’ -iA androidenv.androidsdk 6 0
Install an SDK with commonly used modules for Android 5.0:
$ nix-env -f ’<nixpkgs>’ -iA androidenv.androidsdk 5 0
Sander van der Burg Building mobile apps with the Nix package manager
17. Building Android apps with Nix
with import <nixpkgs> {};
let
repo = fetchFromGitHub {
owner = "svanderburg";
repo = "nix-androidenvtests";
rev = "79775d3facaff28a7a772a9a5a6af1866ec206f0";
sha256 = "0fl9psaxvlpg34xf5g8ci1v41jx0cl2zx9xy1wnnqc7zx4mwhrvj";
};
in
androidenv.buildApp {
name = "MyFirstApp";
src = "${repo}/src/myfirstapp";
platformVersions = [ "16" ];
}
$ nix-build myfirstapp.nix
$ ls result
MyFirstApp-debug.apk nix-support
Sander van der Burg Building mobile apps with the Nix package manager
18. Launching Android emulator instances
with import <nixpkgs> {};
androidenv.emulateApp {
name = "emulate-myfirstapp";
app = import ./myfirstapp.nix; # App built in the previous example
platformVersion = "23"; # We use a newer API-level emulator instance
abiVersion = "x86"; # Also possible: armeabi-v7a, mips, x86_64
package = "com.example.my.first.app";
activity = ".MainActivity";
# API-levels 15 and onwards support GPU acceleration
enableGPU = true;
}
$ nix-build emulatemyfirstapp.nix
The expression produces a script
Sander van der Burg Building mobile apps with the Nix package manager
19. Launching Android emulator instances
The generated script configures an emulator instance and launches
it. When the boot process has been completed it installs and starts
the app:
$ ./result/bin/run-test-emulator
Sander van der Burg Building mobile apps with the Nix package manager
20. Launching Android emulator instances
The generated script configures an emulator instance and launches
it. When the boot process has been completed, it installs and
starts the app:
$ ./result/bin/run-test-emulator
Sander van der Burg Building mobile apps with the Nix package manager
Running APKs in emulators
(You can also fetch the Angry Birds APK from your phone
and automatically start it in a generated emulator instance:
http://sandervanderburg.blogspot.com/2014/02/
reproducing-android-app-deployments-or.html)
21. iOS variability
For iOS, there are fewer concerns than Android:
Xcode version
A specific Xcode version includes a specific version of an iOS SDK:
Version iOS SDK included
7.3 iOS 9.3
7.2 iOS 9.2
7.1 iOS 9.1
7.0 iOS 9.0
6.4 iOS 8.4
...
iOS simulator version:
Xcode 7.3 supports: iOS 9.1 - 9.0, 8.4 - 8.1
Sander van der Burg Building mobile apps with the Nix package manager
22. Xcode packaging
Nothing is actually packaged in Nixpkgs :-):
Xcode may not be redistributed
It must be installed from the App store (latest version) or the
Apple developer portal (older versions)
Sander van der Burg Building mobile apps with the Nix package manager
23. Xcode packaging
{stdenv, version, xcodeBaseDir ? "/Applications/Xcode.app"}:
stdenv.mkDerivation {
name = "xcode-wrapper-"+version;
buildCommand = ’’
mkdir -p $out/bin
cd $out/bin
ln -s /usr/bin/xcode-select
ln -s /usr/bin/security
ln -s /usr/bin/codesign
ln -s "${xcodeBaseDir}/Contents/Developer/usr/bin/xcodebuild"
ln -s "${xcodeBaseDir}/Contents/Developer/usr/bin/xcrun"
ln -s "${xcodeBaseDir}/Contents/Developer/Applications/Simulator.app/Content
cd ..
ln -s "${xcodeBaseDir}/Contents/Developer/Platforms/iPhoneSimulator.platform
# Check if we have the xcodebuild version that we want
if [ -z "$($out/bin/xcodebuild -version | grep -x ’Xcode ${version}’)" ]
then
echo "We require xcodebuild version: ${version}"
exit 1
fi
’’;
}
Sander van der Burg Building mobile apps with the Nix package manager
24. Xcode packaging
We create a proxy package for Xcode:
We lose the ability to use Nix to manage a build’s
dependencies
But we can still automatically build apps, integrate with
Hydra etc.
Nix store paths still reflect the properties we care about, e.g.
Xcode version
More details, see:
http://sandervanderburg.blogspot.com/2012/12/deploying-ios-applications-with-nix.html
http://sandervanderburg.blogspot.com/2013/08/improving-testability-of-nix-ios-build.html
http://sandervanderburg.blogspot.com/2014/10/deploying-ios-applications-with-nix.html
Sander van der Burg Building mobile apps with the Nix package manager
25. Building an app for the iOS simulator
with import <nixpkgs> { system = "x86_64-darwin"; };
let
repo = fetchFromGitHub {
owner = "svanderburg";
repo = "nix-xcodeenvtests";
rev = "482c8a5fd50bd415309f46a12b72a2f07298a134";
sha256 = "1mmb805g9c8kjkkh61imjgilw0iig5a9g7i3ra91jxpy2mwagb6r";
};
in
xcodeenv.buildApp {
name = "HelloWorld";
src = "${repo}/src/HelloWorld";
scheme = "HelloWorld";
sdkVersion = "9.2";
release = false; # Indicates that we want a simulator build
}
$ nix-build firstapp.nix
$ ls result
HelloWorld.app HelloWorld.app.dSYM
Sander van der Burg Building mobile apps with the Nix package manager
26. Launching iOS simulator instances
with import <nixpkgs> { system = "x86_64-darwin"; };
xcodeenv.simulateApp {
name = "simulate-helloworld";
app = import ./firstapp.nix; # App build shown previously
bundleId = "MyCompany.HelloWorld";
}
$ nix-build simulatefirstapp.nix
The expression produces a script
Sander van der Burg Building mobile apps with the Nix package manager
27. Launching iOS simulator instances
Starting the script without parameters, shows an overview of the
available simulators, and asks you to pick an instance by its UDID:
$ ./result/bin/run-test-simulator
== Devices ==
-- iOS 9.0 --
iPhone 4s (1632E4A6-8D62-4EF7-BBBC-B95C7AD872A5) (Shutdown)
iPad 2 (65D35EC1-F62A-42C3-AC4C-7027963DA01B) (Shutdown)
...
-- iOS 9.2 --
iPhone 4s (2F8EB097-892D-484F-96A2-D68AE3D31694) (Shutdown)
iPhone 5 (9423B552-075C-4D25-A950-5B56CD069C97) (Shutdown)
iPhone 5s (2B71AD4D-6396-4C83-B73F-EB275CAB0C93) (Shutdown)
...
Please provide a UDID of a simulator:
2F8EB097-892D-484F-96A2-D68AE3D31694
Sander van der Burg Building mobile apps with the Nix package manager
28. Launching iOS simulator instances
After picking a UDID, the simulator instance gets launched:
Sander van der Burg Building mobile apps with the Nix package manager
29. Launching iOS simulator instances
After pressing enter, the app gets installed and launched:
Sander van der Burg Building mobile apps with the Nix package manager
30. Building an app for ad-hoc purposes or store releases
with import <nixpkgs> { system = "x86_64-darwin"; };
let
repo = fetchFromGitHub {
owner = "svanderburg";
repo = "nix-xcodeenvtests";
rev = "482c8a5fd50bd415309f46a12b72a2f07298a134";
sha256 = "1mmb805g9c8kjkkh61imjgilw0iig5a9g7i3ra91jxpy2mwagb6r";
};
in
xcodeenv.buildApp {
name = "HelloWorld";
src = "${repo}/src/HelloWorld";
scheme = "HelloWorld";
sdkVersion = "9.2";
release = true; # Indicates that we want a real build
generateIPA = true; # Indicates that we want an IPA bundle
certificateFile = ./mycertificate.p12;
certificatePassword = "secret";
codeSignIdentity = "iPhone Distribution: My Company";
provisioningProfile = ./my.mobileprovision;
}
Sander van der Burg Building mobile apps with the Nix package manager
31. Building an app for ad-hoc purposes or store releases
$ nix-build firstapp.nix
$ ls result
HelloWorld.app HelloWorld.app.dSYM HelloWorld.ipa nix-support
Sander van der Burg Building mobile apps with the Nix package manager
32. Building Titanium apps
Previously shown Nix funcions are relevant for native app
development
We use a cross-platform development framework: Titanium
Uses JavaScript as an implementation language
Cross-platform API for UI components that integrate with the
underlying host system
Supports multiple targets: iOS, Android, Tizen, Windows
Phone, Blackberry, Mobile web applications
Not write once run everywhere: 60% – 90% of code can be
reused among platforms
More details, Sander van der Burg Building mobile apps with the Nix package manager
33. Building Titanium apps
We can also build them with Nix! The Titanium infrastructure
reuses Android and iOS functionality from Nixpkgs!
Sander van der Burg Building mobile apps with the Nix package manager
34. Building a Titanium app for Android
with import <nixpkgs> {};
titaniumenv.buildApp {
name = "KitchenSink";
src = fetchgit {
url = https://github.com/appcelerator/KitchenSink.git;
rev = "f923be78ef415436d0e36450fbdbb3bf90028f6c";
sha256 = "1hz3605s180i3kf2m3wn0ppk1kmm96s8328my5kp6hjsq6ygld5s";
};
tiVersion = "5.1.2.GA";
target = "android"; # Build for Android
androidPlatformVersions = [ "23" ];
release = false;
}
$ nix-build kitchensink-android.nix
$ ls result
KitchenSink.apk nix-support
Sander van der Burg Building mobile apps with the Nix package manager
35. Building a Titanium app for the iOS simulator
with import <nixpkgs> { system = "x86_64-darwin"; };
titaniumenv.buildApp {
name = "KitchenSink";
src = fetchgit {
url = https://github.com/appcelerator/KitchenSink.git;
rev = "f923be78ef415436d0e36450fbdbb3bf90028f6c";
sha256 = "1hz3605s180i3kf2m3wn0ppk1kmm96s8328my5kp6hjsq6ygld5s";
};
tiVersion = "5.1.2.GA";
target = "iphone"; # Build for iOS
release = false;
}
$ nix-build kitchensink-iphone.nix
Sander van der Burg Building mobile apps with the Nix package manager
36. Distributing Android APKs with Hydra
Use your browser on your Android device to install APKs by
visiting a build result page:
Sander van der Burg Building mobile apps with the Nix package manager
37. Distributing iOS IPAs with Hydra
Use your browser on your iOS device to install IPAs by clicking on
the ’install’ build product:
(Requires installing a script that composes a itms-services:// link. See:
http://sandervanderburg.blogspot.com/2014/08/wireless-ad-hoc-distributions-of-ios.html)
Sander van der Burg Building mobile apps with the Nix package manager
38. Some facts
First version of Android build functionality: November 2012
First version of iOS build functionality: December 2012
Hydra integration: March 2013
We have built ±100 different kinds of Titanium-based
Android and iOS apps using Nix and Hydra in 2015
Sander van der Burg Building mobile apps with the Nix package manager
39. References
androidenv, xcodeenv, titaniumenv are part of Nixpkgs
(https://github.com/nixos/nixpkgs)
Simple Android test case: https:
//github.com/svanderburg/nix-androidenvtests
Simple iOS test case:
https://github.com/svanderburg/nix-xcodeenvtests
Simple Titanium test case:
pkgs/development/mobile/titaniumenv/examples
subfolder in Nixpkgs
(https://github.com/nixos/nixpkgs)
Sander van der Burg Building mobile apps with the Nix package manager