Skip to content

Commit

Permalink
Add ios task classes and wire them up based on xcode project
Browse files Browse the repository at this point in the history
  • Loading branch information
Larusso committed Jun 20, 2018
1 parent 5f0b51d commit cb6cc1f
Show file tree
Hide file tree
Showing 18 changed files with 1,376 additions and 27 deletions.
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ pluginBundle {
displayName = 'Gradle Unity build plugin'
description = 'This plugin provides tasks for exporting platform projects from Unity3D projects'
}

ios {
id = 'net.wooga.build-unity-ios'
displayName = 'Gradle Unity iOS build plugin'
description = 'This plugin provides tasks for building exported iOS projects from Unity3D'
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,67 +38,67 @@ class UnityBuildPluginConsts {
static String DEFAULT_EXPORT_METHOD_NAME = "Wooga.UnityBuild.NewAutomatedBuild.Export"

/**
* Gradle property name to set the default value for {@code platforms}.
* Gradle property baseName to set the default value for {@code platforms}.
*
* @value "unityBuild.platforms"
* @see UnityBuildPluginExtension#getPlatforms()
*/
static String PLATFORMS_OPTION = "unityBuild.platforms"

/**
* Environment variable name to set the default value for {@code platforms}.
* Environment variable baseName to set the default value for {@code platforms}.
*
* @value "UNITY_BUILD_PLATFORMS"
* @see UnityBuildPluginExtension#getPlatforms()
*/
static String PLATFORMS_ENV_VAR = "UNITY_BUILD_PLATFORMS"

/**
* Gradle property name to set the default value for {@code buildPlatform}.
* Gradle property baseName to set the default value for {@code buildPlatform}.
*
* @value "unityBuild.platform"
*/
static String PLATFORM_OPTION = "unityBuild.platform"

/**
* Environment variable name to set the default value for {@code buildPlatform}.
* Environment variable baseName to set the default value for {@code buildPlatform}.
*
* @value "UNITY_BUILD_PLATFORM"
*/
static String PLATFORM_ENV_VAR = "UNITY_BUILD_PLATFORM"

/**
* Gradle property name to set the default value for {@code environments}.
* Gradle property baseName to set the default value for {@code environments}.
*
* @value "unityBuild.environments"
* @see UnityBuildPluginExtension#getEnvironments()
*/
static String ENVIRONMENTS_OPTION = "unityBuild.environments"

/**
* Environment variable name to set the default value for {@code environments}.
* Environment variable baseName to set the default value for {@code environments}.
*
* @value "unityBuild.environments"
* @see UnityBuildPluginExtension#getEnvironments()
*/
static String ENVIRONMENTS_ENV_VAR = "UNITY_BUILD_ENVIRONMENTS"

/**
* Gradle property name to set the default value for {@code buildEnvironment}.
* Gradle property baseName to set the default value for {@code buildEnvironment}.
*
* @value "unityBuild.environment"
*/
static String ENVIRONMENT_OPTION = "unityBuild.environment"

/**
* Environment variable name to set the default value for {@code buildEnvironment}.
* Environment variable baseName to set the default value for {@code buildEnvironment}.
*
* @value "UNITY_BUILD_ENVIRONMENT"
*/
static String ENVIRONMENT_ENV_VAR = "UNITY_BUILD_ENVIRONMENT"

/**
* Gradle property name to set the default value for {@code exportMethodName}.
* Gradle property baseName to set the default value for {@code exportMethodName}.
*
* @value "unityBuild.exportMethodName"
* @see UnityBuildPluginExtension#getExportMethodName()
Expand All @@ -114,7 +114,7 @@ class UnityBuildPluginConsts {
static String EXPORT_METHOD_NAME_ENV_VAR = "UNITY_BUILD_EXPORT_METHOD_NAME"

/**
* Gradle property name to set the default value for {@code toolsVersion}.
* Gradle property baseName to set the default value for {@code toolsVersion}.
*
* @value "unityBuild.toolsVersion"
* @see UnityBuildPluginExtension#getToolsVersion()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*
*/

package wooga.gradle.build.base
package wooga.gradle.build.unity.base

import org.gradle.api.Plugin
import org.gradle.api.Project
Expand Down
180 changes: 180 additions & 0 deletions src/main/groovy/wooga/gradle/build/unity/ios/IOSBuildPlugin.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package wooga.gradle.build.unity.ios

import org.gradle.api.Action
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.tasks.bundling.Zip
import org.gradle.util.GUtil
import wooga.gradle.build.unity.ios.internal.DefaultIOSBuildPluginExtension
import wooga.gradle.build.unity.ios.tasks.ImportProvisioningProfile
import wooga.gradle.build.unity.ios.tasks.KeychainTask
import wooga.gradle.build.unity.ios.tasks.ListKeychainTask
import wooga.gradle.build.unity.ios.tasks.LockKeychainTask
import wooga.gradle.build.unity.ios.tasks.XCodeArchiveTask
import wooga.gradle.build.unity.ios.tasks.XCodeExportTask

class IOSBuildPlugin implements Plugin<Project> {

private static final Logger LOG = Logging.getLogger(IOSBuildPlugin.class)
static final String EXTENSION_NAME = "iosBuild"

@Override
void apply(Project project) {
//check if system is running mac os
String osName = System.getProperty("os.name").toLowerCase()
if (!osName.contains('mac os')) {
LOG.warn("This plugin is only supported on Mac OS systems.")
return
}

project.pluginManager.apply(BasePlugin.class)
def extension = project.getExtensions().create(IOSBuildPluginExtension, EXTENSION_NAME, DefaultIOSBuildPluginExtension.class)

//register some defaults
project.tasks.withType(XCodeArchiveTask.class, new Action<XCodeArchiveTask>() {
@Override
void execute(XCodeArchiveTask task) {
def conventionMapping = task.getConventionMapping()
conventionMapping.map("version", { project.version })
conventionMapping.map("clean", { false })
conventionMapping.map("destinationDir", {
project.file("${project.buildDir}/outputs/archives")
})
conventionMapping.map("baseName", { project.name })
conventionMapping.map("extension", { "xcarchive" })
conventionMapping.map("scheme", { extension.getScheme() })
conventionMapping.map("configuration", { extension.getConfiguration() })
}
})

project.tasks.withType(KeychainTask.class, new Action<KeychainTask>() {
@Override
void execute(KeychainTask task) {
def conventionMapping = task.getConventionMapping()
conventionMapping.map("baseName", { "build" })
conventionMapping.map("extension", { "keychain" })
conventionMapping.map("password", { extension.getKeychainPassword() })
conventionMapping.map("certificatePassword", { extension.getCertificatePassphrase() })
conventionMapping.map("destinationDir", {
project.file("${project.buildDir}/sign/keychains")
})
}
})

project.tasks.withType(ImportProvisioningProfile.class, new Action<ImportProvisioningProfile>() {
@Override
void execute(ImportProvisioningProfile task) {
def conventionMapping = task.getConventionMapping()
conventionMapping.map("username", { extension.fastlaneCredentials.username })
conventionMapping.map("password", { extension.fastlaneCredentials.password })
conventionMapping.map("teamId", { extension.getTeamId() })
conventionMapping.map("appIdentifier", { extension.getAppIdentifier() })
}
})

def projects = project.fileTree(project.projectDir) { it.include("*.xcodeproj/project.pbxproj") }.files
projects.each { File xcodeProject ->
def base = xcodeProject.parentFile
def taskNameBase = base.name.replace('.xcodeproj', '').toLowerCase().replaceAll(/[-_.]/, '')
if (projects.size() == 1) {
taskNameBase = ""
}
generateBuildTasks(taskNameBase, project, base)
}
}

private static String maybeBaseName(String baseName, String taskName) {
if (GUtil.isTrue(taskName)) {
if (GUtil.isTrue(baseName)) {
return baseName + taskName.capitalize()
} else {
return taskName
}
}
return ""
}

void generateBuildTasks(final String baseName, final Project project, File xcodeProject) {
def tasks = project.tasks
def buildKeychain = tasks.create(maybeBaseName(baseName, "buildKeychain"), KeychainTask) {
it.baseName = maybeBaseName(baseName, "build")
it.certificates = project.fileTree(project.projectDir) { it.include("*.p12") }
}

def unlockKeychain = tasks.create(maybeBaseName(baseName, "unlockKeychain"), LockKeychainTask) {
it.lockAction = LockKeychainTask.LockAction.unlock
it.password = { buildKeychain.getPassword() }
it.keychain = buildKeychain
}

def lockKeychain = tasks.create(maybeBaseName(baseName, "lockKeychain"), LockKeychainTask) {
it.lockAction = LockKeychainTask.LockAction.lock
it.password = { buildKeychain.getPassword() }
it.keychain = buildKeychain
}

def addKeychain = tasks.create(maybeBaseName(baseName, "addKeychain"), ListKeychainTask) {
it.action = ListKeychainTask.Action.add
it.keychain buildKeychain
}

def removeKeychain = tasks.create(maybeBaseName(baseName, "removeKeychain"), ListKeychainTask) {
it.action = ListKeychainTask.Action.remove
it.keychain buildKeychain
}

def importProvisioningProfiles = tasks.create(maybeBaseName(baseName, "importProvisioningProfiles"), ImportProvisioningProfile) {
it.dependsOn addKeychain, unlockKeychain
it.mobileProvisioningProfile = project.file("${maybeBaseName(baseName, 'ci')}.mobileprovision")
}

def xcodeArchive = tasks.create(maybeBaseName(baseName, "xcodeArchive"), XCodeArchiveTask) {
it.dependsOn unlockKeychain
it.finalizedBy lockKeychain

it.provisioningProfile = importProvisioningProfiles
it.projectPath = xcodeProject
it.buildKeychain = buildKeychain
}

def xcodeExport = tasks.create(maybeBaseName(baseName, "xcodeExport"), XCodeExportTask) {
it.exportOptionsPlist project.file("exportOptions.plist")
it.archivePath xcodeArchive
}

def archiveDSYM = tasks.create(maybeBaseName(baseName, "archiveDSYM"), Zip) {
it.dependsOn xcodeArchive
it.archiveName = xcodeArchive.archiveName.replace(xcodeArchive.extension, 'zip')
it.destinationDir = project.file("${project.buildDir}/outputs")
it.from(project.file("$xcodeArchive.outputs.files.singleFile/dSYMs"))
}

project.artifacts {
archives(xcodeExport.artifact)
archives(archiveDSYM)
}

archiveDSYM.mustRunAfter xcodeExport // not to spend time archiving if export fails
project.tasks.getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn xcodeExport, archiveDSYM, removeKeychain
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package wooga.gradle.build.unity.ios

import org.gradle.api.Action
import org.gradle.api.credentials.PasswordCredentials

interface IOSBuildPluginExtension {

PasswordCredentials getFastlaneCredentials()
void setFastlaneCredentials(PasswordCredentials cred)

IOSBuildPluginExtension fastlaneCredentials(Closure configuration)
IOSBuildPluginExtension fastlaneCredentials(Action<PasswordCredentials> action)
IOSBuildPluginExtension fastlaneCredentials(PasswordCredentials cred)


String getKeychainPassword()
void setKeychainPassword(String value)
IOSBuildPluginExtension keychainPassword(String password)

String getCertificatePassphrase()
void setCertificatePassphrase(String passphrase)
IOSBuildPluginExtension certificatePassphrase(String passphrase)

String getAppIdentifier()
void setAppIdentifier(String identifier)
IOSBuildPluginExtension appIdentifier(String identifier)

String getTeamId()
void setTeamId(String id)
IOSBuildPluginExtension teamId(String id)

String getScheme()
void setScheme(String scheme)
IOSBuildPluginExtension scheme(String scheme)

String getConfiguration()
void setConfiguration(String configuration)
IOSBuildPluginExtension configuration(String configuration)

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
*
*/

package wooga.gradle.build.ios
package wooga.gradle.build.unity.ios

import org.gradle.api.Plugin
import org.gradle.api.Project

class IOSBuildPlugin implements Plugin<Project> {

@Override
void apply(Project project) {

}
}
enum XCAction {
build,
buildForTesting,
analyze,
archive,
test,
testWithoutBuilding,
installSrc,
install,
clean
}
Loading

0 comments on commit cb6cc1f

Please sign in to comment.