Skip to content

Commit

Permalink
Add some Xamarin.iOS and Xamarin.Android helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
gshackles committed Aug 28, 2014
1 parent 0e7ad3c commit fb10188
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/app/FakeLib/FakeLib.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
<Compile Include="RoundhouseHelper.fs" />
<Compile Include="FscHelper.fs" />
<Compile Include="HipChatNotificationHelper.fs" />
<Compile Include="XamarinHelper.fs" />
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
Expand Down
160 changes: 160 additions & 0 deletions src/app/FakeLib/XamarinHelper.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/// Contains tasks for building Xamarin.iOS and Xamarin.Android apps
module Fake.XamarinHelper

open System
open System.IO
open System.Text.RegularExpressions

let private executeCommand command args =
Shell.Exec(command, args)
|> fun result -> if result <> 0 then failwithf "%s exited with error %d" command result

/// The package restore paramater type
type XamarinComponentRestoreParams = {
/// Path to xamarin-component.exe, defaults to checking tools/xpkg
ToolPath: string
}

/// The default package restore parameters
let XamarinComponentRestoreDefaults = {
ToolPath = findToolInSubPath "xamarin-component.exe" (currentDirectory @@ "tools" @@ "xpkg")
}

/// Restores NuGet packages and Xamarin Components for a project or solution
/// ## Parameters
/// - `setParams` - Function used to override the default package restore parameters
let RestoreComponents setParams projectFile =
let restoreComponents project param =
executeCommand param.ToolPath ("restore " + project)

XamarinComponentRestoreDefaults
|> setParams
|> restoreComponents projectFile

/// The iOS build paramater type
type iOSBuildParams = {
/// (Required) Path to solution or project file
ProjectPath: string
/// Build target, defaults to Build
Target: string
/// Build configuration, defaults to 'Debug|iPhoneSimulator'
Configuration: string
/// Path to mdtool, defaults to Xamarin Studio's usual path
MDToolPath: string
}

/// The default iOS build parameters
let iOSBuildDefaults = {
ProjectPath = ""
Target = "Build"
Configuration = "Debug|iPhoneSimulator"
MDToolPath = "/Applications/Xamarin Studio.app/Contents/MacOS/mdtool"
}

/// Builds a project or solution using Xamarin's iOS build tools
/// ## Parameters
/// - `setParams` - Function used to override the default build parameters
let iOSBuild setParams =
let validateParams param =
if param.ProjectPath = "" then failwith "You must specify a project to build"

param

let buildProject param =
let args = String.Format(@"-v build -t:{0} ""-c:{1}"" {2}", param.Target, param.Configuration, param.ProjectPath)
executeCommand param.MDToolPath args

iOSBuildDefaults
|> setParams
|> validateParams
|> buildProject

/// The Android packaging parameter type
type AndroidPackageParams = {
/// (Required) Path to the Android project file (not the solution file!)
ProjectPath: string
/// Build configuration, defaults to 'Release'
Configuration: string
/// Output path for build, defaults to 'bin/Release'
OutputPath: string
}

/// The default Android packaging parameters
let AndroidPackageDefaults = {
ProjectPath = ""
Configuration = "Release"
OutputPath = "bin/Release"
}

/// Packages a Xamarin.Android app, returning a FileInfo object for the unsigned APK file
/// ## Parameters
/// - `setParams` - Function used to override the default build parameters
let AndroidPackage setParams =
let validateParams param =
if param.ProjectPath = "" then failwith "You must specify a project to package"

param

let createPackage param =
MSBuild param.OutputPath "PackageForAndroid" [ "Configuration", param.Configuration ] [ param.ProjectPath ] |> ignore

directoryInfo param.OutputPath
|> filesInDirMatching "*.apk"
|> Seq.sortBy (fun file -> file.LastWriteTime)
|> Seq.last

AndroidPackageDefaults
|> setParams
|> validateParams
|> createPackage

// Parameters for signing and aligning an Android package
type AndroidSignAndAlignParams = {
/// (Required) Path to keystore used to sign the app
KeystorePath: string
/// (Required) Password for keystore
KeystorePassword: string
/// (Required) Alias for keystore
KeystoreAlias: string
/// Path to jarsigner tool, defaults to assuming it is in your path
JarsignerPath: string
/// Path to zipalign tool, defaults to assuming it is in your path
ZipalignPath: string
}

/// The default Android signing and aligning parameters
let AndroidSignAndAlignDefaults = {
KeystorePath = ""
KeystorePassword = ""
KeystoreAlias = ""
JarsignerPath = "jarsigner"
ZipalignPath = "zipalign"
}

/// Signs and aligns a Xamarin.Android package, returning a FileInfo object for the signed APK file
/// ## Parameters
/// - `setParams` - Function used to override the default build parameters
/// - `apkFile` - FileInfo object for an unsigned APK file to sign and align
let AndroidSignAndAlign setParams apkFile =
let validateParams param =
if param.KeystorePath = "" then failwith "You must specify a keystore to use"
if param.KeystorePassword = "" then failwith "You must provide the keystore's password"
if param.KeystoreAlias = "" then failwith "You must provide the keystore's alias"

param

let signAndAlign (file:FileInfo) (param:AndroidSignAndAlignParams) =
let fullSignedFilePath = Regex.Replace(file.FullName, ".apk$", "-Signed.apk")
let jarsignerArgs = String.Format("-sigalg SHA1withRSA -digestalg SHA1 -keystore '{0}' -storepass {1} -signedjar '{2}' {3} {4}", param.KeystorePath, param.KeystorePassword, fullSignedFilePath, file.FullName, param.KeystoreAlias)
executeCommand param.JarsignerPath jarsignerArgs

let fullAlignedFilePath = Regex.Replace(fullSignedFilePath, "-Signed.apk$", "-SignedAndAligned.apk")
let zipalignArgs = String.Format("-f -v 4 {0} {1}", fullSignedFilePath, fullAlignedFilePath)
executeCommand param.ZipalignPath zipalignArgs

fileInfo fullAlignedFilePath

AndroidSignAndAlignDefaults
|> setParams
|> validateParams
|> signAndAlign apkFile

0 comments on commit fb10188

Please sign in to comment.