diff --git a/.gitignore b/.gitignore index ba124b7b..a6aae0f0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ sbt-test/*/*/project/auto_plugins.sbt sbt-test/*/*/project/build.properties sbt-test/*/*/*/project/build.properties sbt-test/*/*/*/project/auto_plugins.sbt +.idea/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 26f43fbc..a72629a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,11 @@ os: - linux jdk: - oraclejdk8 - env: + matrix: + - TEST_COMMAND="scripted android-sdk-plugin/*1of2" + - TEST_COMMAND="scripted android-sdk-plugin/*2of2" + - TEST_COMMAND="scripted gradle-build/*" global: - ANDROID_EMU_API_LEVEL=24 - ANDROID_API_LEVEL=26 @@ -48,6 +51,6 @@ before_script: script: - curl -o sbt-launcher.sh https://raw.githubusercontent.com/paulp/sbt-extras/master/sbt - chmod a+x ./sbt-launcher.sh - - ./sbt-launcher.sh publish-local - - ./sbt-launcher.sh gradlebuild/publish-local - - ./sbt-launcher.sh "scripted android-sdk-plugin/* gradle-build/*" + - ./sbt-launcher.sh publishLocal + - ./sbt-launcher.sh gradlebuild/publishLocal + - ./sbt-launcher.sh "$TEST_COMMAND" diff --git a/build.sbt b/build.sbt index c3c1bb54..cc2e5b32 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,5 @@ -import ScriptedPlugin._ - -val pluginVersion = "1.8.0-SNAPSHOT" -val gradleBuildVersion = "1.4.0-SNAPSHOT" +val pluginVersion = "2.0.0-SNAPSHOT" +val gradleBuildVersion = "2.0.0-SNAPSHOT" val androidToolsVersion = "2.3.0" val gradleToolingApi = "2.6" @@ -57,7 +55,7 @@ val gradle = project.in(file("gradle-plugin")).settings( Nil ).dependsOn(model % "compile-internal") -val gradlebuild = project.in(file("gradle-build")).enablePlugins(BuildInfoPlugin).settings( +val gradlebuild = project.in(file("gradle-build")).enablePlugins(BuildInfoPlugin, SbtPlugin).settings( version := gradleBuildVersion, resolvers ++= Seq( "Gradle Releases Repository" at "https://repo.gradle.org/gradle/libs-releases-local/" @@ -68,8 +66,7 @@ val gradlebuild = project.in(file("gradle-build")).enablePlugins(BuildInfoPlugin organization := "org.scala-android", scalacOptions ++= Seq("-deprecation","-Xlint","-feature"), libraryDependencies ++= Seq( - "com.hanhuy.sbt" %% "bintray-update-checker" % "0.2", - "com.google.code.findbugs" % "jsr305" % "3.0.1" % "compile-internal", + "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile-internal", "org.gradle" % "gradle-tooling-api" % gradleToolingApi % "provided", "org.slf4j" % "slf4j-api" % "1.7.10" // required by gradle-tooling-api ), @@ -79,10 +76,10 @@ val gradlebuild = project.in(file("gradle-build")).enablePlugins(BuildInfoPlugin val t = crossTarget.value val m = (managedClasspath in Compile).value val g = t / "gradle-tooling-api" - val apiJar = m.collect { + val apiJar = m.collectFirst { case j if j.get(moduleID.key).exists(_.organization == "org.gradle") && j.get(moduleID.key).exists(_.name == "gradle-tooling-api") => j.data - }.headOption + } FileFunction.cached(streams.value.cacheDirectory / "gradle-tooling-api", FilesInfo.lastModified) { in => in foreach (IO.unzip(_, g, { n: String => !n.startsWith("META-INF") })) (g ** "*.class").get.toSet @@ -119,25 +116,26 @@ unmanagedBase := baseDirectory(_ / "libs").value resourceDirectory in Compile := baseDirectory(_ / "resources").value libraryDependencies ++= Seq( - "org.ow2.asm" % "asm-all" % "5.0.4", - "com.google.code.findbugs" % "jsr305" % "3.0.1" % "compile-internal", - "org.javassist" % "javassist" % "3.20.0-GA", - "com.hanhuy.sbt" %% "bintray-update-checker" % "0.2", // 1.0 missing + "org.ow2.asm" % "asm-all" % "5.2", + "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile-internal", + "org.javassist" % "javassist" % "3.22.0-GA", "com.android.tools.build" % "builder" % androidToolsVersion, "com.android.tools.build" % "manifest-merger" % "25.3.0", - "org.bouncycastle" % "bcpkix-jdk15on" % "1.51", + "org.bouncycastle" % "bcpkix-jdk15on" % "1.59", "com.android.tools.build" % "gradle-core" % androidToolsVersion excludeAll ExclusionRule(organization = "net.sf.proguard"), "com.android.tools.lint" % "lint" % "25.3.0", // "com.android.tools.external.com-intellij" % "uast" % "145.597.4", // because google didn't sync the correct version... - "net.orfjackal.retrolambda" % "retrolambda" % "2.5.1" + "io.argonaut" %% "argonaut" % "6.2.3", + "net.orfjackal.retrolambda" % "retrolambda" % "2.5.3", + "org.scalaz" %% "scalaz-core" % "7.2.20" ) aggregate := false sbtPlugin := true -enablePlugins(BuildInfoPlugin) +enablePlugins(BuildInfoPlugin, SbtPlugin) // build info plugin @@ -168,16 +166,21 @@ pomExtra := -// scripted-test settings -scriptedSettings // remove for 1.0 - -scriptedLaunchOpts ++= Seq("-Xmx1024m", "-Dplugin.version=" + version.value) +scriptedLaunchOpts ++= Seq( + "-Xmx1024m", + "-Dplugin.version=" + version.value, + "-DgradlePlugin.version=" + gradleBuildVersion +) -//scriptedBufferLog := false sbtTestDirectory := baseDirectory(_ / "sbt-test").value // TODO reorganize tests better, ditch android-sdk-plugin prefix // group by test config type + +// TODO these scriptedDependencies blocks can be removed since sbt scripted uses the current +// sbt version in scripted tests and you can use `sys.props("plugin.version")` to fetch +// the current plugin version, rather than adding a task to automatically create these files. +// Leaving a modified version for now to clean up old versions of the files left behind in local workspaces. scriptedDependencies := { val dir = sbtTestDirectory.value val s = streams.value @@ -197,11 +200,6 @@ scriptedDependencies := { val propertiesFile = project / "build.properties" pluginsFile.delete() propertiesFile.delete() - IO.writeLines(pluginsFile, - """addSbtPlugin("%s" %% "%s" %% "%s")""".format(org, n, v) :: - Nil) - IO.write(propertiesFile, """sbt.version=%s""" format sbtv) } } - scriptedDependencies := (scriptedDependencies dependsOn publishLocal).value diff --git a/gradle-build/src/main/scala/android/GradleBuild.scala b/gradle-build/src/main/scala/android/GradleBuild.scala index e4cc721d..1f5920cb 100644 --- a/gradle-build/src/main/scala/android/GradleBuild.scala +++ b/gradle-build/src/main/scala/android/GradleBuild.scala @@ -1,14 +1,13 @@ package android -import java.io.{File, OutputStream} +import java.io.{ File, OutputStream } import java.util.concurrent.TimeUnit import android.Keys._ -import com.android.builder.model.{PackagingOptions => _, _} +import com.android.builder.model.{ PackagingOptions => _, _ } import com.hanhuy.gradle.discovery.GradleBuildModel -import com.hanhuy.sbt.bintray.UpdateChecker import org.gradle.tooling.internal.consumer.DefaultGradleConnector -import org.gradle.tooling.{GradleConnector, ProjectConnection} +import org.gradle.tooling.{ GradleConnector, ModelBuilder, ProjectConnection } import sbt.Keys._ import sbt._ @@ -19,6 +18,9 @@ import scala.util.Try import Serializer._ import com.android.tools.lint.LintCliFlags import com.android.tools.lint.detector.api.Severity +import sbt.librarymanagement.MavenRepository + +import scala.util.matching.Regex /** * @author pfnguyen */ @@ -27,7 +29,7 @@ object AndroidGradlePlugin extends AutoPlugin { val Gradle = sbt.config("gradle") override def trigger = allRequirements - override def requires = android.AndroidGlobalPlugin + override def requires: AndroidGlobalPlugin.type = android.AndroidGlobalPlugin override def buildSettings = List( onLoad in Global := (onLoad in Global).value andThen { s => @@ -67,7 +69,7 @@ object AndroidGradlePlugin extends AutoPlugin { } } - val generatedScript = file(".") / "00-gradle-generated.sbt" + val generatedScript: File = file(".") / "00-gradle-generated.sbt" def inGradleProject(project: String)(ss: Seq[Setting[_]]): Seq[Setting[_]] = ss map VariantSettings.fixProjectScope(ProjectRef(file(".").getCanonicalFile, project)) @@ -130,8 +132,8 @@ object AndroidGradlePlugin extends AutoPlugin { checkGeneratedScript() - val nullsink = new OutputStream { - override def write(b: Int) = () + val nullsink: OutputStream = new OutputStream { + override def write(b: Int): Unit = () } /** load gradle options from properties file, quoted/spaced options are not supported */ @@ -140,17 +142,17 @@ object AndroidGradlePlugin extends AutoPlugin { Option(properties.getProperty("gradle.options")).fold(List.empty[String])(_.split("\\s+").toList) } - def modelBuilder[A](c: ProjectConnection, model: Class[A]) = { + def modelBuilder[A](c: ProjectConnection, model: Class[A]): ModelBuilder[A] = { c.model(model) .setStandardOutput(nullsink) .setStandardError(nullsink) } - def initScriptModelBuilder[A](c: ProjectConnection, model: Class[A], initscript: File) = { + def initScriptModelBuilder[A](c: ProjectConnection, model: Class[A], initscript: File): ModelBuilder[A] = { val options = "--init-script" :: initscript.getAbsolutePath :: gradleOptions modelBuilder(c, model).withArguments(options: _*) } - def gradleBuildModel(c: ProjectConnection, initscript: File) = + def gradleBuildModel(c: ProjectConnection, initscript: File): GradleBuildModel = initScriptModelBuilder(c, classOf[GradleBuildModel], initscript).get() import GradleBuildSerializer._ @@ -329,11 +331,11 @@ object AndroidGradlePlugin extends AutoPlugin { } val v = ap.getVariants.asScala.head val art = v.getMainArtifact - def libraryDependency(m: MavenCoordinates, isProvided: Boolean) = { + def libraryDependency(m: MavenCoordinates, isProvided: Boolean): ModuleID = { val module = m.getGroupId % m.getArtifactId % m.getVersion intransitive() val mID = if (m.getPackaging == "jar") module else module.artifacts( - Artifact(m.getArtifactId, m.getPackaging, m.getPackaging, Option(m.getClassifier), Nil, None)) - if (isProvided) mID.copy(configurations = Some("provided")) else mID + Artifact(m.getArtifactId, m.getPackaging, m.getPackaging, Option(m.getClassifier), Vector.empty, None)) + if (isProvided) mID.withConfigurations(configurations = Some("provided")) else mID } val androidLibraries = art.getDependencies.getLibraries.asScala.toList @@ -382,14 +384,14 @@ object AndroidGradlePlugin extends AutoPlugin { javacOptions in Compile /++= "-source" :: sourceVersion :: "-target" :: targetVersion :: Nil, debugIncludesTests /:= false, // default because can't express it easily otherwise projectLayout /:= new ProjectLayout.Wrapped(ProjectLayout(base)) { - override def manifest = sourceProvider.getManifestFile - override def javaSource = sourceProvider.getJavaDirectories.asScala.head - override def resources = sourceProvider.getResourcesDirectories.asScala.head - override def res = sourceProvider.getResDirectories.asScala.head - override def renderscript = sourceProvider.getRenderscriptDirectories.asScala.head - override def aidl = sourceProvider.getAidlDirectories.asScala.head - override def assets = sourceProvider.getAssetsDirectories.asScala.head - override def jniLibs = sourceProvider.getJniLibsDirectories.asScala.head + override def manifest: File = sourceProvider.getManifestFile + override def javaSource: File = sourceProvider.getJavaDirectories.asScala.head + override def resources: File = sourceProvider.getResourcesDirectories.asScala.head + override def res: File = sourceProvider.getResDirectories.asScala.head + override def renderscript: File = sourceProvider.getRenderscriptDirectories.asScala.head + override def aidl: File = sourceProvider.getAidlDirectories.asScala.head + override def assets: File = sourceProvider.getAssetsDirectories.asScala.head + override def jniLibs: File = sourceProvider.getJniLibsDirectories.asScala.head } ) ++ extraDirectories(sourceProvider.getJavaDirectories, unmanagedSourceDirectories in Compile) ++ extraDirectories(sourceProvider.getResDirectories, extraResDirectories) ++ @@ -417,10 +419,10 @@ object Serializer { def encode(t: T): String } - implicit val stringEncoder = new Encoder[String] { + implicit val stringEncoder: Encoder[String] = new Encoder[String] { // broke ass """ won't handle \ u properly, SI-4706 // def encode(s: String) = "raw\"\"\"" + s + "\"\"\"" - def quote(s: String) = s.map { + def quote(s: String): String = s.map { case '"' => "\\\"" case '\\' => "\\\\" case '\b' => "\\b" @@ -430,10 +432,10 @@ object Serializer { case '\t' => "\\t" case c => c }.mkString("\"", "", "\"") - def encode(s: String) = quote(s) + def encode(s: String): String = quote(s) } - implicit val moduleEncoder = new Encoder[ModuleID] { - def encode(m: ModuleID) = { + implicit val moduleEncoder: Encoder[sbt.ModuleID] = new Encoder[ModuleID] { + def encode(m: ModuleID): String = { val base = s""""${m.organization}" % "${m.name}" % "${m.revision}"""" base + m.configurations.fold("")(c => s""" % "$c"""") + m.explicitArtifacts.map( a => @@ -444,39 +446,39 @@ object Serializer { ).mkString("") + (if (m.isTransitive) "" else " intransitive()") } } - implicit def seqEncoder[T : Encoder] = new Encoder[Seq[T]] { - def encode(l: Seq[T]) = if (l.isEmpty) "Nil" else "Seq(" + l.map(i => enc(i)).mkString(",") + ")" + implicit def seqEncoder[T : Encoder]: Encoder[Seq[T]] = new Encoder[Seq[T]] { + def encode(l: Seq[T]): String = if (l.isEmpty) "Nil" else "Seq(" + l.map(i => enc(i)).mkString(",") + ")" } - implicit def setEncoder[T : Encoder] = new Encoder[Set[T]] { - def encode(l: Set[T]) = if (l.isEmpty) "Set.empty" else "Set(" + l.map(i => enc(i)).mkString(",") + ")" + implicit def setEncoder[T : Encoder]: Encoder[Set[T]] = new Encoder[Set[T]] { + def encode(l: Set[T]): String = if (l.isEmpty) "Set.empty" else "Set(" + l.map(i => enc(i)).mkString(",") + ")" } - implicit val packagingOptionsEncoding = new Encoder[PackagingOptions] { + implicit val packagingOptionsEncoding: Encoder[PackagingOptions] = new Encoder[PackagingOptions] { def encode(p: PackagingOptions) = s"android.Keys.PackagingOptions(${enc(p.excludes)}, ${enc(p.pickFirsts)}, ${enc(p.merges)})" } - implicit val fileEncoder = new Encoder[File] { + implicit val fileEncoder: Encoder[File] = new Encoder[File] { def encode(f: File) = s"file(${enc(f.getCanonicalPath)})" } - implicit def mutableSettingEncoder[T] = new Encoder[MutableSetting[T]] { + implicit def mutableSettingEncoder[T]: Encoder[MutableSetting[T]] = new Encoder[MutableSetting[T]] { def encode(m: MutableSetting[T]) = "NO OP THIS SHOULD NOT HAPPEN" } - implicit def optionEncoder[T : Encoder] = new Encoder[Option[T]] { - def encode(l: Option[T]) = if (l.isEmpty) "None" else "Some(" + enc(l.get) + ")" + implicit def optionEncoder[T : Encoder]: Encoder[Option[T]] = new Encoder[Option[T]] { + def encode(l: Option[T]): String = if (l.isEmpty) "None" else "Some(" + enc(l.get) + ")" } - implicit def someEncoder[T : Encoder] = new Encoder[Some[T]] { - def encode(l: Some[T]) = "Some(" + enc(l.get) + ")" + implicit def someEncoder[T : Encoder]: Encoder[Some[T]] = new Encoder[Some[T]] { + def encode(l: Some[T]): String = "Some(" + enc(l.get) + ")" } - implicit val antProjectLayoutEncoding = new Encoder[ProjectLayout.Ant] { + implicit val antProjectLayoutEncoding: Encoder[ProjectLayout.Ant] = new Encoder[ProjectLayout.Ant] { def encode(p: ProjectLayout.Ant) = s"ProjectLayout.Ant(${enc(p.base)})" } - implicit val gradleProjectLayoutEncoding = new Encoder[ProjectLayout.Gradle] { + implicit val gradleProjectLayoutEncoding: Encoder[ProjectLayout.Gradle] = new Encoder[ProjectLayout.Gradle] { def encode(p: ProjectLayout.Gradle) = s"ProjectLayout.Gradle(${enc(p.base)})" } - implicit val ProjectLayoutEncoding = new Encoder[ProjectLayout] { - def encode(p: ProjectLayout) = p match { + implicit val ProjectLayoutEncoding: Encoder[ProjectLayout] = new Encoder[ProjectLayout] { + def encode(p: ProjectLayout): String = p match { case x: ProjectLayout.Ant => enc(x) case x: ProjectLayout.Gradle => enc(x) case x: ProjectLayout.Wrapped => @@ -507,54 +509,54 @@ object Serializer { |""".stripMargin } } - implicit val boolEncoder = new Encoder[Boolean] { - def encode(b: Boolean) = b.toString + implicit val boolEncoder: Encoder[Boolean] = new Encoder[Boolean] { + def encode(b: Boolean): String = b.toString } - implicit val signingConfigEncoding = new Encoder[ApkSigningConfig] { - override def encode(t: ApkSigningConfig) = t match { + implicit val signingConfigEncoding: Encoder[ApkSigningConfig] = new Encoder[ApkSigningConfig] { + override def encode(t: ApkSigningConfig): String = t match { case PlainSigningConfig(ks, sp, al, kp, st, v1, v2) => s"PlainSigningConfig(${enc(ks)}, ${enc(sp)}, ${enc(al)}, ${enc(kp)}, ${enc(st)}, ${enc(v1)}, ${enc(v2)})" case PromptPasswordsSigningConfig(ks, al, st, v1, v2) => s"PromptPasswords(${enc(ks)}, ${enc(al)}, ${enc(st)}, ${enc(v1)}, ${enc(v2)})" } } - implicit val wrappedProjectLayoutEncoding = new Encoder[ProjectLayout.Wrapped] { + implicit val wrappedProjectLayoutEncoding: Encoder[ProjectLayout.Wrapped] = new Encoder[ProjectLayout.Wrapped] { def encode(p: ProjectLayout.Wrapped) = s"new ProjectLayout.Wrapped(${enc(p.wrapped)})" } - implicit val intEncoder = new Encoder[Int] { - def encode(i: Int) = i.toString + implicit val intEncoder: Encoder[Int] = new Encoder[Int] { + def encode(i: Int): String = i.toString } - implicit val literalEncoder = new Encoder[Literal] { - def encode(literal: Literal) = literal.value + implicit val literalEncoder: Encoder[Literal] = new Encoder[Literal] { + def encode(literal: Literal): String = literal.value } - implicit def listEncoder[T : Encoder] = new Encoder[List[T]] { - def encode(l: List[T]) = if (l.isEmpty) "Nil" else "List(\n " + l.map(i => enc(i)).mkString(",\n ") + ")" + implicit def listEncoder[T : Encoder]: Encoder[List[T]] = new Encoder[List[T]] { + def encode(l: List[T]): String = if (l.isEmpty) "Nil" else "List(\n " + l.map(i => enc(i)).mkString(",\n ") + ")" } - implicit val resolverEncoder = new Encoder[Resolver] { - def encode(r: Resolver) = r match { - case MavenRepository(n, root) => enc(n) + " at " + enc(root) + implicit val resolverEncoder: Encoder[sbt.Resolver] = new Encoder[Resolver] { + def encode(r: Resolver): String = r match { + case maven: MavenRepository => enc(maven.name) + " at " + enc(maven.root) case _ => throw new UnsupportedOperationException("Cannot handle: " + r) } } - implicit def tuple3Encoder[A : Encoder,B : Encoder,C : Encoder] = new Encoder[(A,B,C)] { + implicit def tuple3Encoder[A : Encoder,B : Encoder,C : Encoder]: Encoder[(A, B, C)] = new Encoder[(A,B,C)] { override def encode(t: (A, B, C)) = s"(${enc(t._1)}, ${enc(t._2)}, ${enc(t._3)})" } - implicit def tuple2Encoder[A : Encoder,B : Encoder] = new Encoder[(A,B)] { + implicit def tuple2Encoder[A : Encoder,B : Encoder]: Encoder[(A, B)] = new Encoder[(A,B)] { override def encode(t: (A, B)) = s"(${enc(t._1)}, ${enc(t._2)})" } - implicit def mapEncoder[A : Encoder,B : Encoder] = new Encoder[Map[A,B]] { - override def encode(t: Map[A, B]) = if (t.isEmpty) "Map.empty" else s"Map(${t.toList.map(e => enc(e)).mkString(",\n ")})" + implicit def mapEncoder[A : Encoder,B : Encoder]: Encoder[Map[A, B]] = new Encoder[Map[A,B]] { + override def encode(t: Map[A, B]): String = if (t.isEmpty) "Map.empty" else s"Map(${t.toList.map(e => enc(e)).mkString(",\n ")})" } - implicit def attributedEncoder[T : Encoder] = new Encoder[Attributed[T]] { + implicit def attributedEncoder[T : Encoder]: Encoder[sbt.Attributed[T]] = new Encoder[Attributed[T]] { def encode(l: Attributed[T]) = s"Attributed.blank(${enc(l.data)})" } - implicit val severityEncoder = new Encoder[Severity] { - override def encode(t: Severity) = "Severity." + t.toString + implicit val severityEncoder: Encoder[Severity] = new Encoder[Severity] { + override def encode(t: Severity): String = "Severity." + t.toString } - implicit val lintCliFlagsEncoder = new Encoder[LintCliFlags] { - override def encode(t: LintCliFlags) = + implicit val lintCliFlagsEncoder: Encoder[LintCliFlags] = new Encoder[LintCliFlags] { + override def encode(t: LintCliFlags): String = s"""{ | import collection.JavaConverters._ | import com.android.tools.lint.detector.api.Severity @@ -581,21 +583,21 @@ object Serializer { def serialized: String } - def serialize[T : Manifest, U : Encoder](k: SettingKey[T], op: String, value: U) = + def serialize[T : Manifest, U : Encoder](k: SettingKey[T], op: String, value: U): String = key(k) + " " + op + " " + enc(value) - def serialize[T : Manifest, U : Encoder](k: TaskKey[T], op: String, value: U) = + def serialize[T : Manifest, U : Encoder](k: TaskKey[T], op: String, value: U): String = key(k) + " " + op + " " + enc(value) def config(s: Scope) = s.config.toOption.fold("")(c => s""" in ${c.name.capitalize}""") - val COLLECTIONS = """scala\.collection\.(\w+)""".r - val IMMUTABLE_COLLECTIONS = """scala\.collection\.immutable\.(\w+)""".r - val SBT = """sbt\.(\w+)""".r - val ANDROID_KEY = """android\.Keys\.(\w+)""".r - val ANDROID = """android\.(\w+)""".r - val JAVA = """java\.lang\.(\w+)""".r - val SCALA = """scala\.(\w+)""".r + val COLLECTIONS: Regex = """scala\.collection\.(\w+)""".r + val IMMUTABLE_COLLECTIONS: Regex = """scala\.collection\.immutable\.(\w+)""".r + val SBT: Regex = """sbt\.(\w+)""".r + val ANDROID_KEY: Regex = """android\.Keys\.(\w+)""".r + val ANDROID: Regex = """android\.(\w+)""".r + val JAVA: Regex = """java\.lang\.(\w+)""".r + val SCALA: Regex = """scala\.(\w+)""".r val FILE = """java.io.File""" - val TUPLES = """scala.(Tuple\d+)""".r + val TUPLES: Regex = """scala.(Tuple\d+)""".r // TODO handle tuple naming def typeName[T](implicit manifest: Manifest[T]): String = { def capitalized(m: Manifest[_]) = { @@ -637,18 +639,18 @@ object Serializer { object GradleBuildSerializer { case class SbtFlavor(name: String, settings: List[SbtSetting]) { - def serializedSettings = settings map (_.serialized) mkString ",\n " + def serializedSettings: String = settings map (_.serialized) mkString ",\n " - def serialized = + def serialized: String = s""" | flavors += ((${enc(name)}, List( | $serializedSettings))) |""".stripMargin } case class SbtBuildType(name: String, settings: List[SbtSetting]) { - def serializedSettings = settings map (_.serialized) mkString ",\n " + def serializedSettings: String = settings map (_.serialized) mkString ",\n " - def serialized = + def serialized: String = s""" | buildTypes += ((${enc(name)}, List( | $serializedSettings))) @@ -658,7 +660,7 @@ object GradleBuildSerializer { dependencies: Set[String], buildTypes: Seq[SbtBuildType], flavors: Seq[SbtFlavor], settings: Seq[SbtSetting]) { override def toString = s"SbtProject(id=$id, base=$base, dependencies=$dependencies)" - def escaped(s: String) = { + def escaped(s: String): String = { val needEscape = s.zipWithIndex exists { case (c, i) => (i == 0 && !Character.isJavaIdentifierStart(c)) || (i != 0 && !Character.isJavaIdentifierPart(c)) } @@ -666,16 +668,16 @@ object GradleBuildSerializer { s"`$s`" } else s } - lazy val serializedBuildTypes = { + lazy val serializedBuildTypes: String = { buildTypes.map(".settings(" + _.serialized + ")").mkString("") } - lazy val serializedFlavors = { + lazy val serializedFlavors: String = { flavors.map(".settings(" + _.serialized + ")").mkString("") } - def dependsOnProjects = { + def dependsOnProjects: String = { if (dependencies.nonEmpty) ".dependsOn(" + dependencies.map(escaped).mkString(",") + ")" else "" } - def serialized = + def serialized: String = s""" |val ${escaped(id)} = project.in( | ${enc(base)} @@ -718,22 +720,19 @@ object GradleBuildSerializer { } implicit class SerializableSettingKey[T : Encoder : Manifest](val k: SettingKey[T]) { - def /:=(t: T) = Op := (k, t) - def /:=(t: Literal) = Op := (k, t) - def /+=[U : Encoder](u: U) = Op += (k, u) - def /+=(u: Literal) = Op += (k, u) - def /++=[U : Encoder](u: U) = Op ++= (k, u) - def /++=(u: Literal) = Op ++= (k, u) + def /:=(t: T): SbtSetting = Op := (k, t) + def /:=(t: Literal): SbtSetting = Op := (k, t) + def /+=[U : Encoder](u: U): SbtSetting = Op += (k, u) + def /+=(u: Literal): SbtSetting = Op += (k, u) + def /++=[U : Encoder](u: U): SbtSetting = Op ++= (k, u) + def /++=(u: Literal): SbtSetting = Op ++= (k, u) } implicit class SerializableTaskKey[T : Encoder : Manifest](val k: TaskKey[T]) { - def /:=(t: T) = Op := (k, t) - def /:=(t: Literal) = Op := (k, t) - def /+=[U : Encoder](u: U) = Op += (k, u) - def /+=(u: Literal) = Op += (k, u) - def /++=[U : Encoder](u: U) = Op ++= (k, u) - def /++=(u: Literal) = Op ++= (k, u) + def /:=(t: T): SbtSetting = Op := (k, t) + def /:=(t: Literal): SbtSetting = Op := (k, t) + def /+=[U : Encoder](u: U): SbtSetting = Op += (k, u) + def /+=(u: Literal): SbtSetting = Op += (k, u) + def /++=[U : Encoder](u: U): SbtSetting = Op ++= (k, u) + def /++=(u: Literal): SbtSetting = Op ++= (k, u) } } - -@deprecated("No longer necessary to auto-import gradle, remove", "1.2.0") -trait GradleBuild diff --git a/project/bintray.sbt b/project/bintray.sbt index d13f8acd..9f5cc30d 100644 --- a/project/bintray.sbt +++ b/project/bintray.sbt @@ -3,4 +3,4 @@ resolvers += Resolver.url( url("https://dl.bintray.com/content/sbt/sbt-plugin-releases"))( Resolver.ivyStylePatterns) -addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.1") +addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.4") diff --git a/project/build.properties b/project/build.properties index c091b86c..c0bab049 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.16 +sbt.version=1.2.8 diff --git a/project/plugins.sbt b/project/plugins.sbt index b1019ed9..7ba3088a 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,8 +1,5 @@ resolvers += "typesafe" at "http://repo.typesafe.com/typesafe/releases" -// 1.0: -//libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value -// 0.13: -libraryDependencies += "org.scala-sbt" % "scripted-plugin" % sbtVersion.value +libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value -addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0") +addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.8.0") diff --git a/sbt-test/android-sdk-plugin/android-test-kit/build.sbt b/sbt-test/android-sdk-plugin/android-test-kit/build.sbt index d57ac005..70d68e19 100644 --- a/sbt-test/android-sdk-plugin/android-test-kit/build.sbt +++ b/sbt-test/android-sdk-plugin/android-test-kit/build.sbt @@ -1,5 +1,6 @@ -lazy val root = project.in(file(".")).settings(androidBuild:_*) -lazy val flavor1 = android.Plugin.flavorOf(root, "flavor1", +lazy val root = project.in(file(".")).enablePlugins(AndroidApp) + +lazy val flavor1 = android.flavorOf(root, "flavor1", debugIncludesTests in Android := true, libraryDependencies ++= "com.android.support.test" % "runner" % "0.2" % "androidTest" :: diff --git a/sbt-test/android-sdk-plugin/android-test-kit/project/plugins.sbt b/sbt-test/android-sdk-plugin/android-test-kit/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/android-test-kit/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/gen-android/project/empty-file b/sbt-test/android-sdk-plugin/gen-android/project/empty-file deleted file mode 100644 index e69de29b..00000000 diff --git a/sbt-test/android-sdk-plugin/gen-android/project/plugins.sbt b/sbt-test/android-sdk-plugin/gen-android/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/gen-android/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/hello-jni/project/plugins.sbt b/sbt-test/android-sdk-plugin/hello-jni/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/hello-jni/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/hello-jni/test b/sbt-test/android-sdk-plugin/hello-jni/test index 547e01b1..cb40d73c 100644 --- a/sbt-test/android-sdk-plugin/hello-jni/test +++ b/sbt-test/android-sdk-plugin/hello-jni/test @@ -1,6 +1,6 @@ > android:package $ exists bin/output/hello-jni-debug.apk -> javah-finder +> javahFinder $ exists bin/generated/source/com_example_hellojni_HelloJni.h > android:test > android:uninstall diff --git a/sbt-test/android-sdk-plugin/hello-jni/test.sbt b/sbt-test/android-sdk-plugin/hello-jni/test.sbt index 66d19b29..991b058d 100644 --- a/sbt-test/android-sdk-plugin/hello-jni/test.sbt +++ b/sbt-test/android-sdk-plugin/hello-jni/test.sbt @@ -1,4 +1,4 @@ -TaskKey[Unit]("javah-finder") <<= (baseDirectory, streams) map { (b,s) => - val headers = (b ** "*.h").get - s.log.info("Headers: " + (headers mkString ",")) +TaskKey[Unit]("javah-finder") := { + val headers = (baseDirectory.value ** "*.h").get + streams.value.log.info("Headers: " + (headers mkString ",")) } diff --git a/sbt-test/android-sdk-plugin/hello-multidex/build.sbt b/sbt-test/android-sdk-plugin/hello-multidex/build.sbt index b71ad1ef..82cc53e7 100644 --- a/sbt-test/android-sdk-plugin/hello-multidex/build.sbt +++ b/sbt-test/android-sdk-plugin/hello-multidex/build.sbt @@ -1,6 +1,8 @@ import android.Keys._ -android.Plugin.androidBuild +enablePlugins(AndroidApp) + +scalaVersion := "2.11.11" platformTarget in Android := "android-17" diff --git a/sbt-test/android-sdk-plugin/hello-multidex/project/jcenter.sbt b/sbt-test/android-sdk-plugin/hello-multidex/project/jcenter.sbt index 07f552de..a7c128f1 100644 --- a/sbt-test/android-sdk-plugin/hello-multidex/project/jcenter.sbt +++ b/sbt-test/android-sdk-plugin/hello-multidex/project/jcenter.sbt @@ -3,4 +3,4 @@ resolvers += Resolver.url( url("http://dl.bintray.com/content/sbt/sbt-plugin-releases"))( Resolver.ivyStylePatterns) -addSbtPlugin("me.lessis" % "bintray-sbt" % "0.1.2") \ No newline at end of file +addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.4") diff --git a/sbt-test/android-sdk-plugin/hello-multidex/project/plugins.sbt b/sbt-test/android-sdk-plugin/hello-multidex/project/plugins.sbt index 9b612eb0..51eb2b16 100644 --- a/sbt-test/android-sdk-plugin/hello-multidex/project/plugins.sbt +++ b/sbt-test/android-sdk-plugin/hello-multidex/project/plugins.sbt @@ -1,11 +1 @@ -{ - val ver = System.getProperty("plugin.version") - if (ver == null) - throw new RuntimeException(""" - |The system property 'plugin.version' is not defined. - |Specify this property using scriptedLaunchOpts -Dplugin.version.""" - .stripMargin) - else addSbtPlugin("org.scala-android" % "sbt-android" % ver) -} - - +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/hello-multidex/test b/sbt-test/android-sdk-plugin/hello-multidex/test index 05d6e934..22ee612d 100644 --- a/sbt-test/android-sdk-plugin/hello-multidex/test +++ b/sbt-test/android-sdk-plugin/hello-multidex/test @@ -5,4 +5,4 @@ $ exists target/android/intermediates/dex/classes2.dex > clean > android:package $ exists target/android/intermediates/dex/maindexlist.txt -> check-list +> checkList diff --git a/sbt-test/android-sdk-plugin/hello-multidex/tests.sbt b/sbt-test/android-sdk-plugin/hello-multidex/tests.sbt index 9439aecc..4d7940e6 100644 --- a/sbt-test/android-sdk-plugin/hello-multidex/tests.sbt +++ b/sbt-test/android-sdk-plugin/hello-multidex/tests.sbt @@ -1,4 +1,4 @@ TaskKey[Unit]("check-list") := { val mainClasses = IO.readLines((dexMainClassesConfig in Android).value).toList - if (mainClasses.isEmpty) android.Plugin.fail("No good") + if (mainClasses.isEmpty) android.fail("No good") } diff --git a/sbt-test/android-sdk-plugin/hello-world-gradle-layout/build.sbt b/sbt-test/android-sdk-plugin/hello-world-gradle-layout/build.sbt index cb2c5aa0..f1457a1a 100644 --- a/sbt-test/android-sdk-plugin/hello-world-gradle-layout/build.sbt +++ b/sbt-test/android-sdk-plugin/hello-world-gradle-layout/build.sbt @@ -1,6 +1,6 @@ import android.Keys._ -android.Plugin.androidBuild +enablePlugins(AndroidApp) platformTarget in Android := "android-17" diff --git a/sbt-test/android-sdk-plugin/hello-world-gradle-layout/project/plugins.sbt b/sbt-test/android-sdk-plugin/hello-world-gradle-layout/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/hello-world-gradle-layout/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/hello-world-gradle-layout/test.sbt b/sbt-test/android-sdk-plugin/hello-world-gradle-layout/test.sbt index 37c031d5..bc5b391a 100644 --- a/sbt-test/android-sdk-plugin/hello-world-gradle-layout/test.sbt +++ b/sbt-test/android-sdk-plugin/hello-world-gradle-layout/test.sbt @@ -1,20 +1,22 @@ import android.Keys._ import android.BuildOutput._ -TaskKey[Unit]("check-test-dex") <<= ( SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android - , projectLayout in Android - , outputLayout in Android - , streams - ) map { - (p,layout, o, s) => +import sys.process._ + +TaskKey[Unit]("check-test-dex") := { + val p = ( SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android).value + val layout = (projectLayout in Android).value + val o = (outputLayout in Android).value + val s = streams.value + implicit val output = o val tools = p(s.log).getTargetInfo.getBuildTools.getLocation val dexdump = tools / "dexdump" val lines = Seq( dexdump.getAbsolutePath, - (layout.dex / "classes.dex").getAbsolutePath).lines + (layout.dex / "classes.dex").getAbsolutePath).lineStream val hasJunit = lines exists { l => l.trim.startsWith("Class descriptor") && l.trim.endsWith("junit/Assert;'")} if (!hasJunit) - error("JUnit not found\n" + (lines mkString "\n")) + sys.error("JUnit not found\n" + (lines mkString "\n")) } diff --git a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/build.sbt b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/build.sbt index 6a7c974d..f455eec5 100644 --- a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/build.sbt +++ b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/build.sbt @@ -1,6 +1,7 @@ import android.Keys._ +import scalariform.formatter.preferences._ -android.Plugin.androidBuild +enablePlugins(AndroidApp) platformTarget in Android := "android-17" @@ -9,3 +10,33 @@ name := "hello-world" javacOptions in Compile ++= Seq("-source", "1.6", "-target", "1.6") showSdkProgress in Android := false + +lazy val androidScala = Project( + "tims-scala-android", + file(".")).settings(commonSettings ++ Seq( + libraryDependencies ++= Seq() + ) +) + +scalariformPreferences := scalariformPreferences.value + .setPreference(RewriteArrowSymbols, true) + .setPreference(AlignParameters, true) + .setPreference(AlignSingleLineCaseStatements, true) + .setPreference(PlaceScaladocAsterisksBeneathSecondAsterisk, true) + .setPreference(CompactControlReadability, false) + +def commonSettings = Seq( + organization := "com.optrak", + scalaVersion := Version.scala, + scalacOptions ++= Seq( + "-unchecked", + "-deprecation", + "-Xlint", + "-language:_", + "-encoding", "UTF-8" + ), + libraryDependencies ++= Seq( + Dependency.Compile.shapeless, + Dependency.Compile.scalazCore + ) + ) diff --git a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/project/Dependencies.scala b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/project/Dependencies.scala new file mode 100644 index 00000000..976f0da7 --- /dev/null +++ b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/project/Dependencies.scala @@ -0,0 +1,21 @@ +import sbt._ + +object Settings extends AutoPlugin { + object autoImport { + object Version { + val scala = "2.10.2" + } + + object Dependency { + object Compile { + val shapeless = "com.chuusai" % "shapeless" % "2.0.0-M1" cross CrossVersion.full + val scalazCore = "org.scalaz" %% "scalaz-core" % "7.0.3" + } + + object Test { + val specs2 = "org.specs2" %% "specs2" % "2.2" % "test" + } + } + + } +} diff --git a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/project/build.scala b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/project/build.scala deleted file mode 100644 index 4d51a068..00000000 --- a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/project/build.scala +++ /dev/null @@ -1,66 +0,0 @@ -import sbt._ -import sbt.Keys._ -import com.typesafe.sbt.SbtScalariform._ - -object Build extends Build { - - lazy val androidScala = Project( - "tims-scala-android", - file("."), - settings = commonSettings ++ Seq( - libraryDependencies ++= Seq() - ) - ) - - lazy val formatSettings = scalariformSettings ++ Seq( - ScalariformKeys.preferences in Compile := formattingPreferences, - ScalariformKeys.preferences in Test := formattingPreferences - ) - - def formattingPreferences = { - import scalariform.formatter.preferences._ - FormattingPreferences() - .setPreference(RewriteArrowSymbols, true) - .setPreference(AlignParameters, true) - .setPreference(AlignSingleLineCaseStatements, true) - .setPreference(PlaceScaladocAsterisksBeneathSecondAsterisk, true) - .setPreference(CompactControlReadability, false) - } - - def commonSettings = Defaults.defaultSettings ++ formatSettings ++ - Seq( - organization := "com.optrak", - scalaVersion := Version.scala, - scalacOptions ++= Seq( - "-unchecked", - "-deprecation", - "-Xlint", - "-language:_", - "-encoding", "UTF-8" - )/*, - libraryDependencies ++= Seq( - Dependency.Compile.shapeless, - Dependency.Compile.scalazCore - ) - */ - ) - - object Version { - val scala = "2.10.2" - } - - object Dependency { - - object Compile { - val shapeless = "com.chuusai" % "shapeless" % "2.0.0-M1" cross CrossVersion.full - val scalazCore = "org.scalaz" % "scalaz-core_2.10" % "7.0.3" - } - - object Test { - val specs2 = "org.specs2" % "specs2_2.10" % "2.2" % "test" - } - - } - -} - diff --git a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/project/plugins.sbt b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/project/plugins.sbt index b7ffd7ce..e98c0eea 100644 --- a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/project/plugins.sbt +++ b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/project/plugins.sbt @@ -1 +1,2 @@ -addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.0") +addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2") +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) diff --git a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/test b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/test index 5fb2757c..a96e5a62 100644 --- a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/test +++ b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/test @@ -2,6 +2,6 @@ $ exists target/android/output/hello-world-debug.apk $ exists target/android/generated/source/com/example/app/TR.scala $ exists target/android/intermediates/proguard/classes.proguard.jar -> check-dex -> check-tr -> check-resource +> checkDex +> checkTr +> checkResource diff --git a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/tests.sbt b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/tests.sbt index 96e91fae..dbab40e6 100644 --- a/sbt-test/android-sdk-plugin/hello-world-oscarvarto/tests.sbt +++ b/sbt-test/android-sdk-plugin/hello-world-oscarvarto/tests.sbt @@ -2,36 +2,38 @@ import android.Keys._ import java.util.zip._ import java.io._ import android.BuildOutput._ +import sys.process._ -TaskKey[Unit]("check-dex") <<= ( SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android - , projectLayout in Android - , outputLayout in Android - , streams - ) map { - (p,layout, o, s) => +TaskKey[Unit]("check-dex") := { + val p = ( SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android).value + val layout = (projectLayout in Android).value + val o = (outputLayout in Android).value + val s = streams.value implicit val output = o val tools = p(s.log).getTargetInfo.getBuildTools.getLocation val dexdump = tools / "dexdump" val lines = Seq( dexdump.getAbsolutePath, - (layout.dex / "classes.dex").getAbsolutePath).lines + (layout.dex / "classes.dex").getAbsolutePath).lineStream val hasMainActivity = lines exists { l => l.trim.startsWith("Class descriptor") && l.trim.endsWith("MainActivity;'")} if (!hasMainActivity) - error("MainActivity not found\n" + (lines mkString "\n")) + sys.error("MainActivity not found\n" + (lines mkString "\n")) } -TaskKey[Unit]("check-tr") <<= ( projectLayout in Android ) map { layout => +TaskKey[Unit]("check-tr") := { + val layout = (projectLayout in Android ).value val tr = layout.gen / "com" / "example" / "app" / "TR.scala" val lines = IO.readLines(tr) val expected = "final val hello = TypedLayout[android.widget.FrameLayout](R.layout.hello)" val hasTextView = lines exists (_.trim == expected) if (!hasTextView) - error("Could not find TR.test_textview\n" + (lines mkString "\n")) + sys.error("Could not find TR.test_textview\n" + (lines mkString "\n")) } -TaskKey[Unit]("check-resource") <<= ( sbt.Keys.`package` in Android ) map { apk => +TaskKey[Unit]("check-resource") := { + val apk = ( sbt.Keys.`package` in Android ).value val zip = new ZipInputStream(new FileInputStream(apk)) val names = Stream.continually(zip.getNextEntry()).takeWhile(_ != null).map { _.getName @@ -39,6 +41,6 @@ TaskKey[Unit]("check-resource") <<= ( sbt.Keys.`package` in Android ) map { apk val exists = names exists (_.endsWith("test.conf")) zip.close() if (!exists) { - error("Could not find test.conf\n" + (names mkString "\n")) + sys.error("Could not find test.conf\n" + (names mkString "\n")) } } diff --git a/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/build.sbt b/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/build.sbt index 51936273..8bcc3ca9 100644 --- a/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/build.sbt +++ b/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/build.sbt @@ -1,6 +1,6 @@ import android.Keys._ -android.Plugin.androidBuild +enablePlugins(AndroidApp) platformTarget in Android := "android-17" diff --git a/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/project/plugins.sbt b/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/test b/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/test index 0d7c877f..39fcc431 100644 --- a/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/test +++ b/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/test @@ -2,5 +2,5 @@ $ exists target/android/output/hello-world-debug.apk $ exists target/android/generated/source/com/example/app/TR.scala $ exists target/android/intermediates/proguard/classes.proguard.jar -> check-dex -> check-tr +> checkDex +> checkTr diff --git a/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/tests.sbt b/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/tests.sbt index 9b81e7cf..4147c2fd 100644 --- a/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/tests.sbt +++ b/sbt-test/android-sdk-plugin/hello-world-scala-gradle-layout/tests.sbt @@ -1,30 +1,32 @@ import android.Keys._ import android.BuildOutput._ -TaskKey[Unit]("check-dex") <<= ( SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android - , projectLayout in Android - , outputLayout in Android - , streams - ) map { - (p,layout, o, s) => +import sys.process._ + +TaskKey[Unit]("check-dex") := { + val p = (SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android).value + val layout = (projectLayout in Android).value + val o = (outputLayout in Android).value + val s = streams.value implicit val output = o val tools = p(s.log).getTargetInfo.getBuildTools.getLocation val dexdump = tools / "dexdump" val lines = Seq( dexdump.getAbsolutePath, - (layout.dex / "classes.dex").getAbsolutePath).lines + (layout.dex / "classes.dex").getAbsolutePath).lineStream val hasMainActivity = lines exists { l => l.trim.startsWith("Class descriptor") && l.trim.endsWith("MainActivity;'")} if (!hasMainActivity) - error("MainActivity not found\n" + (lines mkString "\n")) + sys.error("MainActivity not found\n" + (lines mkString "\n")) } -TaskKey[Unit]("check-tr") <<= ( projectLayout in Android ) map { layout => +TaskKey[Unit]("check-tr") := { + val layout = (projectLayout in Android).value val tr = layout.gen / "com" / "example" / "app" / "TR.scala" val lines = IO.readLines(tr) val expected = "final val hello = TypedLayout[android.widget.FrameLayout](R.layout.hello)" val hasTextView = lines exists (_.trim == expected) if (!hasTextView) - error("Could not find TR.hello\n" + (lines mkString "\n")) + sys.error("Could not find TR.hello\n" + (lines mkString "\n")) } diff --git a/sbt-test/android-sdk-plugin/lib-with-resources/build.sbt b/sbt-test/android-sdk-plugin/lib-with-resources/build.sbt index 677f0ecf..e63ad2bd 100644 --- a/sbt-test/android-sdk-plugin/lib-with-resources/build.sbt +++ b/sbt-test/android-sdk-plugin/lib-with-resources/build.sbt @@ -1,6 +1,6 @@ import android.Keys._ -android.Plugin.androidBuild +enablePlugins(AndroidApp) name := "lib-with-resources" diff --git a/sbt-test/android-sdk-plugin/lib-with-resources/project/plugins.sbt b/sbt-test/android-sdk-plugin/lib-with-resources/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/lib-with-resources/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/lib-with-resources/test b/sbt-test/android-sdk-plugin/lib-with-resources/test index a32b8c74..982ea604 100644 --- a/sbt-test/android-sdk-plugin/lib-with-resources/test +++ b/sbt-test/android-sdk-plugin/lib-with-resources/test @@ -1,6 +1,6 @@ > android:package $ exists target/android/output/lib-with-resources-debug.apk -> check-for-properties -> check-for-bin +> checkForProperties +> checkForBin > last android:apkbuild -> show list-apk +> show listApk diff --git a/sbt-test/android-sdk-plugin/lib-with-resources/tests.sbt b/sbt-test/android-sdk-plugin/lib-with-resources/tests.sbt index 0b37f000..98ebe1ba 100644 --- a/sbt-test/android-sdk-plugin/lib-with-resources/tests.sbt +++ b/sbt-test/android-sdk-plugin/lib-with-resources/tests.sbt @@ -1,16 +1,19 @@ import android.Keys._ import Tests._ -TaskKey[Unit]("check-for-properties") <<= (apkFile in Android) map { a => +TaskKey[Unit]("check-for-properties") := { + val a = (apkFile in Android).value val found = findInArchive(a) (_ == "com/example/lib/file.properties") - if (!found) error("Properties not found in APK\n" + listArchive(a)) + if (!found) sys.error("Properties not found in APK\n" + listArchive(a)) } -TaskKey[Unit]("check-for-bin") <<= (apkFile in Android) map { a => +TaskKey[Unit]("check-for-bin") := { + val a = (apkFile in Android).value val found = findInArchive(a) (_ == "com/example/lib/library.bin") - if (!found) error("Bin file not found in APK") + if (!found) sys.error("Bin file not found in APK") } -TaskKey[Seq[String]]("list-apk") <<= (apkFile in Android) map { a => +TaskKey[Seq[String]]("list-apk") := { + val a = (apkFile in Android).value listArchive(a) } diff --git a/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/build.sbt b/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/build.sbt new file mode 100644 index 00000000..0713a885 --- /dev/null +++ b/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/build.sbt @@ -0,0 +1,61 @@ +import android.Keys._ +import Tests._ + +scalaVersion in ThisBuild := "2.11.12" + +// meta project +lazy val root = project.in(file(".")).aggregate(guidemate, geophon, guidemate_lib) + +// android application project +lazy val guidemate = Project(id = "app", base = file("app")).enablePlugins(AndroidApp).dependsOn(guidemate_lib).settings(appSettings:_*) +lazy val geophon = Project(id = "app2", base = file("app2")).enablePlugins(AndroidApp).dependsOn(guidemate_lib).settings(appSettings :_*) + +val guidemate_lib = Project(id = "lib", + base = file("lib-with-resources")) + .enablePlugins(AndroidLib) + .settings(libraryDependencies ++= Seq( + "org.scalatest" %% "scalatest" % "3.0.8" % "test", + "com.pivotallabs" % "robolectric" % "1.1" % "test", + "junit" % "junit" % "4.10" % "test", + "commons-io" % "commons-io" % "2.1", + "com.javadocmd" % "simplelatlng" % "1.0.0", + "org.joda" % "joda-convert" % "1.2", + "joda-time" % "joda-time" % "2.0", + "commons-lang" % "commons-lang" % "2.6", + "org.osmdroid" % "osmdroid-android" % "3.0.10", + "org.slf4j" % "slf4j-simple" % "1.7.5")) + +lazy val appSettings = List( + showSdkProgress in Android := false, + platformTarget in Android := "android-17", + useProguard in Android := true, + useProguardInDebug in Android := true, + proguardScala in Android := true, + proguardOptions in Android += "-dontwarn **", + packagingOptions in Android := PackagingOptions(excludes = Seq( + "META-INF/LICENSE.txt", + "META-INF/NOTICE.txt"))) + +lazy val checkForProperties = TaskKey[Unit]("check-for-properties") + +checkForProperties := { + val a = (apkFile in (guidemate, Android)).value + val found = findInArchive(a) (_ == "com/example/lib/file.properties") + if (!found) sys.error("Properties not found in APK") +} + +lazy val checkForBin = TaskKey[Unit]("check-for-bin") + +checkForBin := { + val a = (apkFile in (guidemate,Android)).value + val found = findInArchive(a) (_ == "com/example/lib/library.bin") + if (!found) sys.error("Bin file not found in APK") +} + +lazy val listApk = TaskKey[Seq[String]]("list-apk") + +listApk := { + val a = (apkFile in (guidemate, Android)).value + listArchive(a) +} + diff --git a/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/project/build.scala b/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/project/build.scala deleted file mode 100644 index ba7bba83..00000000 --- a/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/project/build.scala +++ /dev/null @@ -1,45 +0,0 @@ -import sbt._ -import sbt.Keys._ -import android.Dependencies.LibraryProject -import android.Keys._ - -object MyProjectBuild extends Build { - - // meta project - lazy val root = Project(id = "gmroot", base = file(".")).settings( - install <<= ( // install all apps - install in (guidemate, Android), - install in (geophon, Android)) map { (_,_) => () } - ).aggregate(guidemate, geophon, guidemate_lib) - - - // android application project - lazy val guidemate = Project(id = "app", base = file("app")).androidBuildWith(guidemate_lib).settings(appSettings:_*) - lazy val geophon = Project(id = "app2", base = file("app2")).androidBuildWith(guidemate_lib).settings(appSettings :_*) - - val guidemate_lib = Project(id = "lib", - base = file("lib-with-resources")).settings( - android.Plugin.androidBuildAar: _*) - .settings(libraryDependencies ++= Seq( - "org.scalatest" % "scalatest_2.10" % "1.9.1" % "test", - "com.pivotallabs" % "robolectric" % "1.1" % "test", - "junit" % "junit" % "4.10" % "test", - "commons-io" % "commons-io" % "2.1", - "com.javadocmd" % "simplelatlng" % "1.0.0", - "org.joda" % "joda-convert" % "1.2", - "joda-time" % "joda-time" % "2.0", - "commons-lang" % "commons-lang" % "2.6", - "org.osmdroid" % "osmdroid-android" % "3.0.10", - "org.slf4j" % "slf4j-simple" % "1.7.5")) - - lazy val appSettings = List( - showSdkProgress in Android := false, - platformTarget in Android := "android-17", - useProguard in Android := true, - useProguardInDebug in Android := true, - proguardScala in Android := true, - proguardOptions in Android += "-dontwarn **", - packagingOptions in Android := PackagingOptions(excludes = Seq( - "META-INF/LICENSE.txt", - "META-INF/NOTICE.txt"))) -} diff --git a/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/project/plugins.sbt b/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/test b/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/test index 43793a57..af253c5e 100644 --- a/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/test +++ b/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/test @@ -1,5 +1,5 @@ > app/android:package $ exists app/bin/output/app-debug.apk > last app/android:apkbuild -> check-for-properties -> check-for-bin +> checkForProperties +> checkForBin diff --git a/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/tests.sbt b/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/tests.sbt deleted file mode 100644 index 5da40b8f..00000000 --- a/sbt-test/android-sdk-plugin/multiproject-lib-with-resources/tests.sbt +++ /dev/null @@ -1,16 +0,0 @@ -import android.Keys._ -import Tests._ - -TaskKey[Unit]("check-for-properties") <<= (apkFile in (guidemate,Android)) map { a => - val found = findInArchive(a) (_ == "com/example/lib/file.properties") - if (!found) sys.error("Properties not found in APK") -} - -TaskKey[Unit]("check-for-bin") <<= (apkFile in (guidemate,Android)) map { a => - val found = findInArchive(a) (_ == "com/example/lib/library.bin") - if (!found) sys.error("Bin file not found in APK") -} - -TaskKey[Seq[String]]("list-apk") <<= (apkFile in (guidemate,Android)) map { a => - listArchive(a) -} diff --git a/sbt-test/android-sdk-plugin/multiproject-retrolambda/project/plugins.sbt b/sbt-test/android-sdk-plugin/multiproject-retrolambda/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/multiproject-retrolambda/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/multiproject-retrolambda/sub/client/build.sbt b/sbt-test/android-sdk-plugin/multiproject-retrolambda/sub/client/build.sbt index d99bce5d..1fd3d4ae 100644 --- a/sbt-test/android-sdk-plugin/multiproject-retrolambda/sub/client/build.sbt +++ b/sbt-test/android-sdk-plugin/multiproject-retrolambda/sub/client/build.sbt @@ -2,7 +2,7 @@ import android.Keys._ name := "test-client" -android.Plugin.androidBuild +enablePlugins(AndroidApp) platformTarget in Android := "android-19" diff --git a/sbt-test/android-sdk-plugin/multiproject-same-dependencies/build.sbt b/sbt-test/android-sdk-plugin/multiproject-same-dependencies/build.sbt index 58dd89b4..33209cd5 100644 --- a/sbt-test/android-sdk-plugin/multiproject-same-dependencies/build.sbt +++ b/sbt-test/android-sdk-plugin/multiproject-same-dependencies/build.sbt @@ -2,13 +2,13 @@ javacOptions in Global ++= List("-source", "1.7", "-target", "1.7") val sharedSettings = Seq(platformTarget := "android-23", showSdkProgress in Android := false, buildToolsVersion := Some("26.0.1")) -val b = project.settings(androidBuildAar:_*).settings(sharedSettings: _*) +val b = project.settings(sharedSettings: _*).enablePlugins(AndroidLib) -val c = project.settings(androidBuildAar:_*).settings(sharedSettings: _*) +val c = project.settings(sharedSettings: _*).enablePlugins(AndroidLib) -val d = project.settings(androidBuildAar:_*).settings(sharedSettings: _*) +val d = project.settings(sharedSettings: _*).enablePlugins(AndroidLib) -val a = project.androidBuildWith(b,c,d).settings(sharedSettings: _*) +val a = project.enablePlugins(AndroidApp).dependsOn(b,c,d).settings(sharedSettings: _*) libraryDependencies in b += "com.android.support" % "appcompat-v7" % "23.1.1" diff --git a/sbt-test/android-sdk-plugin/multiproject-same-dependencies/project/plugins.sbt b/sbt-test/android-sdk-plugin/multiproject-same-dependencies/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/multiproject-same-dependencies/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/multiproject-with-resources/android-core/project/Build.scala b/sbt-test/android-sdk-plugin/multiproject-with-resources/android-core/project/Build.scala deleted file mode 100644 index 7346c343..00000000 --- a/sbt-test/android-sdk-plugin/multiproject-with-resources/android-core/project/Build.scala +++ /dev/null @@ -1,14 +0,0 @@ -import sbt._ -import sbt.Keys._ - -object CoreBuild extends Build { - - lazy val androidCore = Project( - id = "android-core", - base = file("."), - settings = Defaults.defaultSettings ++ Seq( - name := "Android Core", - exportJars := true - ) - ) -} diff --git a/sbt-test/android-sdk-plugin/multiproject-with-resources/build.sbt b/sbt-test/android-sdk-plugin/multiproject-with-resources/build.sbt new file mode 100644 index 00000000..58f61ea5 --- /dev/null +++ b/sbt-test/android-sdk-plugin/multiproject-with-resources/build.sbt @@ -0,0 +1,28 @@ +import sbt._ +import sbt.Keys._ +import android._ +import android.Keys._ +import Tests._ + +scalaVersion in ThisBuild := "2.10.2" + +val core = Project("android-core", file("android-core")).settings( + name := "Android Core", + exportJars := true +) + +lazy val androidScala = Project("android-main", file(".")).settings( + libraryDependencies ++= Seq( + "com.scalatags" %% "scalatags" % "0.2.4" + ), + javacOptions in Compile ++= Seq("-source", "1.6", "-target", "1.6"), + showSdkProgress in Android := false +).enablePlugins(AndroidApp).dependsOn(core) + +lazy val checkForNothing = TaskKey[Unit]("check-lib-for-nothing") + +checkForNothing := { + val j = (sbt.Keys.`package` in (core, Compile)).value + val found = findInArchive(j) (_ == "nothing.txt") + if (!found) sys.error("nothing.txt not found in library") +} diff --git a/sbt-test/android-sdk-plugin/multiproject-with-resources/project/Build.scala b/sbt-test/android-sdk-plugin/multiproject-with-resources/project/Build.scala deleted file mode 100644 index b0b3c39e..00000000 --- a/sbt-test/android-sdk-plugin/multiproject-with-resources/project/Build.scala +++ /dev/null @@ -1,21 +0,0 @@ -import sbt._ -import sbt.Keys._ -import android.Keys._ - -object Build extends Build { - val core = ProjectRef(uri("android-core"), "android-core") - - lazy val androidScala = Project( - id = "android-main", - base = file("."), - settings = Defaults.defaultSettings ++ android.Plugin.androidBuild ++ Seq( - libraryDependencies ++= Seq( - "com.scalatags" % "scalatags_2.10" % "0.2.4" - ), - scalaVersion := "2.10.2", - javacOptions in Compile ++= Seq("-source", "1.6", "-target", "1.6"), - showSdkProgress in Android := false - ) - ) dependsOn core - -} diff --git a/sbt-test/android-sdk-plugin/multiproject-with-resources/project/plugins.sbt b/sbt-test/android-sdk-plugin/multiproject-with-resources/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/multiproject-with-resources/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/multiproject-with-resources/test b/sbt-test/android-sdk-plugin/multiproject-with-resources/test index e4b8d6f9..9b4b685c 100644 --- a/sbt-test/android-sdk-plugin/multiproject-with-resources/test +++ b/sbt-test/android-sdk-plugin/multiproject-with-resources/test @@ -1,6 +1,6 @@ > android:package > last android:apkbuild $ exists bin/output/android-main-debug-unaligned.apk -> show list-apk -> check-lib-for-nothing -> check-for-nothing +> show listApk +> checkLibForNothing +> checkForNothing diff --git a/sbt-test/android-sdk-plugin/multiproject-with-resources/tests.sbt b/sbt-test/android-sdk-plugin/multiproject-with-resources/tests.sbt index 5043d370..174e97b5 100644 --- a/sbt-test/android-sdk-plugin/multiproject-with-resources/tests.sbt +++ b/sbt-test/android-sdk-plugin/multiproject-with-resources/tests.sbt @@ -1,16 +1,13 @@ import android.Keys._ import Tests._ -TaskKey[Unit]("check-lib-for-nothing") <<= (sbt.Keys.`package` in (core, Compile)) map { j => - val found = findInArchive(j) (_ == "nothing.txt") - if (!found) error("nothing.txt not found in library") -} - -TaskKey[Unit]("check-for-nothing") <<= (apkFile in Android) map { a => +TaskKey[Unit]("check-for-nothing") := { + val a = (apkFile in Android).value val found = findInArchive(a) (_ == "nothing.txt") - if (!found) error("nothing.txt not found in APK") + if (!found) sys.error("nothing.txt not found in APK") } -TaskKey[Seq[String]]("list-apk") <<= (apkFile in Android) map { a => +TaskKey[Seq[String]]("list-apk") := { + val a = (apkFile in Android).value listArchive(a) } diff --git a/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/project/plugins.sbt b/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/test b/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/test index 32400d0c..e8002ac6 100644 --- a/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/test +++ b/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/test @@ -2,11 +2,11 @@ $ exists target/android/output/proguard-cache-duplicate-classes-debug.apk $ exists target/android/generated/source/com/example/proguardcache/TR.scala $ exists target/android/intermediates/proguard/classes.proguard.jar -> last android:proguard-inputs +> last android:proguardInputs > last android:proguard -> check-dex -> check-cache +> checkDex +> checkCache $ copy-file MainActivity.scala-tmp src/main/scala/com/example/proguardcache/MainActivity.scala > android:proguardCache > android:package -> check-dex +> checkDex diff --git a/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/tests.sbt b/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/tests.sbt index bf5438e5..ac5cf657 100644 --- a/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/tests.sbt +++ b/sbt-test/android-sdk-plugin/proguard-cache-duplicate-classes/tests.sbt @@ -1,30 +1,32 @@ import android.Keys._ import android.BuildOutput._ -TaskKey[Unit]("check-dex") <<= ( SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android - , projectLayout in Android - , outputLayout in Android - , streams - ) map { - (p,layout, o, s) => +import sys.process._ + +TaskKey[Unit]("check-dex") := { + val p = ( SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android).value + val layout = (projectLayout in Android).value + val o = (outputLayout in Android).value + val s = streams.value implicit val output = o val tools = p(s.log).getTargetInfo.getBuildTools.getLocation val dexdump = tools / "dexdump" val lines = Seq( dexdump.getAbsolutePath, - (layout.dex / "classes.dex").getAbsolutePath).lines + (layout.dex / "classes.dex").getAbsolutePath).lineStream val hasAbstractSuite = lines exists { l => l.trim.startsWith("Class descriptor") && l.trim.endsWith("AbstractSuite$class;'")} if (!hasAbstractSuite) - error("AbstractSuite not found") + sys.error("AbstractSuite not found") } -TaskKey[Unit]("check-cache") <<= (TaskKey[ProguardInputs]("proguard-inputs") in Android) map { c => +TaskKey[Unit]("check-cache") := { import java.io._ import java.util.zip._ + val c = (TaskKey[ProguardInputs]("proguard-inputs") in Android).value val in = new ZipInputStream(new FileInputStream(c.proguardCache.get)) val suite = Stream.continually(in.getNextEntry) takeWhile ( _ != null) exists { e => e.getName.endsWith("AbstractSuite$class.class") } - if (!suite) error("AbstractSuite not found in cache") + if (!suite) sys.error("AbstractSuite not found in cache") in.close() } diff --git a/sbt-test/android-sdk-plugin/proguard-cache/build.sbt b/sbt-test/android-sdk-plugin/proguard-cache/build.sbt index a4596af5..6d954a59 100644 --- a/sbt-test/android-sdk-plugin/proguard-cache/build.sbt +++ b/sbt-test/android-sdk-plugin/proguard-cache/build.sbt @@ -1,6 +1,8 @@ import android.Keys._ -android.Plugin.androidBuild +enablePlugins(AndroidApp) + +scalaVersion := "2.11.12" platformTarget in Android := "android-17" diff --git a/sbt-test/android-sdk-plugin/proguard-cache/project/plugins.sbt b/sbt-test/android-sdk-plugin/proguard-cache/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/proguard-cache/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/proguard-cache/test b/sbt-test/android-sdk-plugin/proguard-cache/test index 15c9e7ca..d10dddcd 100644 --- a/sbt-test/android-sdk-plugin/proguard-cache/test +++ b/sbt-test/android-sdk-plugin/proguard-cache/test @@ -2,10 +2,10 @@ $ exists target/android/output/hello-world-debug.apk $ exists target/android/generated/source/com/example/app/TR.scala $ exists target/android/intermediates/proguard/classes.proguard.jar -# > last android:proguard-inputs +# > last android:proguardInputs # > last android:proguard -> check-dex -> check-cache +> checkDex +> checkCache $ copy-file MainActivity.scala-tmp src/main/scala/com/example/app/MainActivity.scala > android:package -> check-dex +> checkDex diff --git a/sbt-test/android-sdk-plugin/proguard-cache/tests.sbt b/sbt-test/android-sdk-plugin/proguard-cache/tests.sbt index 0ab2aace..572e45bf 100644 --- a/sbt-test/android-sdk-plugin/proguard-cache/tests.sbt +++ b/sbt-test/android-sdk-plugin/proguard-cache/tests.sbt @@ -1,30 +1,32 @@ import android.Keys._ import android.BuildOutput._ -TaskKey[Unit]("check-dex") <<= ( SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android - , projectLayout in Android - , outputLayout in Android - , streams - ) map { - (p,layout, o, s) => +import sys.process._ + +TaskKey[Unit]("check-dex") := { + val p = ( SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android).value + val layout = (projectLayout in Android).value + val o = (outputLayout in Android).value + val s = streams.value implicit val output = o val tools = p(s.log).getTargetInfo.getBuildTools.getLocation val dexdump = tools / "dexdump" val lines = Seq( dexdump.getAbsolutePath, - (layout.dex / "classes.dex").getAbsolutePath).lines + (layout.dex / "classes.dex").getAbsolutePath).lineStream val hasViewPager = lines exists { l => l.trim.startsWith("Class descriptor") && l.trim.endsWith("ViewPager;'")} if (!hasViewPager) - error("ViewPager not found") + sys.error("ViewPager not found") } -TaskKey[Unit]("check-cache") <<= (TaskKey[ProguardInputs]("proguard-inputs") in Android) map { c => +TaskKey[Unit]("check-cache") := { import java.io._ import java.util.zip._ + val c = (TaskKey[ProguardInputs]("proguard-inputs") in Android).value val in = new ZipInputStream(new FileInputStream(c.proguardCache.get)) val pager = Stream.continually(in.getNextEntry) takeWhile ( _ != null) exists { e => e.getName.endsWith("ViewPager.class") } - if (!pager) error("ViewPager not found in cache") + if (!pager) sys.error("ViewPager not found in cache") in.close() } diff --git a/sbt-test/android-sdk-plugin/renderscript-support-v8/build.sbt b/sbt-test/android-sdk-plugin/renderscript-support-v8/build.sbt index 5a0f3827..1e17ebcb 100644 --- a/sbt-test/android-sdk-plugin/renderscript-support-v8/build.sbt +++ b/sbt-test/android-sdk-plugin/renderscript-support-v8/build.sbt @@ -1,6 +1,6 @@ import android.Keys._ -android.Plugin.androidBuild +enablePlugins(AndroidApp) name := "renderscript-support-v8" diff --git a/sbt-test/android-sdk-plugin/renderscript-support-v8/project/plugins.sbt b/sbt-test/android-sdk-plugin/renderscript-support-v8/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/renderscript-support-v8/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/renderscript-support-v8/test b/sbt-test/android-sdk-plugin/renderscript-support-v8/test index f5a48daf..826ca4e8 100644 --- a/sbt-test/android-sdk-plugin/renderscript-support-v8/test +++ b/sbt-test/android-sdk-plugin/renderscript-support-v8/test @@ -1,12 +1,12 @@ -> check-target-api -> check-support-mode +> checkTargetApi +> checkSupportMode > android:package -# > android:package-aar +# > android:packageAar $ exists target/android/output/renderscript-support-v8-debug.apk # $ exists target/android/output/renderscript-support-v8.aar -> check-apk-for-resource -#> check-aar-for-resource -# > check-aar-for-libs -> check-apk-for-libs +> checkApkForResource +#> checkAarForResource +# > checkAarForLibs +> checkApkForLibs > last android:apkbuild -> show list-apk +> show listApk diff --git a/sbt-test/android-sdk-plugin/renderscript-support-v8/tests.sbt b/sbt-test/android-sdk-plugin/renderscript-support-v8/tests.sbt index 78598e44..b493ec61 100644 --- a/sbt-test/android-sdk-plugin/renderscript-support-v8/tests.sbt +++ b/sbt-test/android-sdk-plugin/renderscript-support-v8/tests.sbt @@ -2,8 +2,9 @@ import android.Keys._ import Tests._ TaskKey[Unit]("check-target-api") := { - if ((rsTargetApi in Android).value != "18") - sys.error("Renderscript targetApi not equal to 18: " + (rsTargetApi in Android).value) + val targetAPI = (rsTargetApi in Android).value + if (targetAPI != "18") + sys.error("Renderscript targetApi not equal to 18: " + targetAPI) } TaskKey[Unit]("check-support-mode") := { @@ -11,17 +12,18 @@ TaskKey[Unit]("check-support-mode") := { sys.error("Renderscript support mode was not set from project.properties") } -TaskKey[Unit]("check-apk-for-resource") <<= (apkFile in Android) map { a => +TaskKey[Unit]("check-apk-for-resource") := { + val a = (apkFile in Android).value val found = findInArchive(a) (_ == "res/raw/invert.bc") - if (!found) error("Renderscript resource not found in APK\n" + listArchive(a)) + if (!found) sys.error("Renderscript resource not found in APK\n" + listArchive(a)) } -//TaskKey[Unit]("check-aar-for-resource") <<= (packageAar in Android) map { a => +//TaskKey[Unit]("check-aar-for-resource") := (packageAar in Android) map { a => // val found = findInArchive(a) (_ == "res/raw/invert.bc") -// if (!found) error("Renderscript resource not found in Aar\n" + listArchive(a)) +// if (!found) sys.error("Renderscript resource not found in Aar\n" + listArchive(a)) //} -val jniLibs = Seq( +val jniLibs = Seq( "x86/librs.invert.so", "x86/librsjni.so", "x86/libRSSupport.so", @@ -33,22 +35,25 @@ val jniLibs = Seq( def checkLibsInArchive(a: File, libs: Seq[String]) = { val entries = listArchive(a).toSet libs foreach { lib => - if (!entries.contains(lib)) error(s"Library: $lib missing in archive: $a") + if (!entries.contains(lib)) sys.error(s"Library: $lib missing in archive: $a") } } -//TaskKey[Unit]("check-aar-for-libs") := { -// checkLibsInArchive((packageAar in Android).value, "libs/renderscript-v8.jar" +: (jniLibs.map("jni/" + _))) +//TaskKey[Unit]("check-aar-for-libs") := { +// val a = (packageAar in Android).value +// checkLibsInArchive(a, "libs/renderscript-v8.jar" +: (jniLibs.map("jni/" + _))) //} -TaskKey[Unit]("check-apk-for-libs") := { - checkLibsInArchive((apkFile in Android).value, jniLibs.map("lib/" + _)) +TaskKey[Unit]("check-apk-for-libs") := { + val a = (apkFile in Android).value + checkLibsInArchive(a, jniLibs.map("lib/" + _)) } -TaskKey[Seq[String]]("list-apk") <<= (apkFile in Android) map { a => +TaskKey[Seq[String]]("list-apk") := { + val a = (apkFile in Android).value listArchive(a) } -//TaskKey[Seq[String]]("list-aar") <<= (packageAar in Android) map { a => +//TaskKey[Seq[String]]("list-aar") := (packageAar in Android) map { a => // listArchive(a) //} diff --git a/sbt-test/android-sdk-plugin/renderscript/build.sbt b/sbt-test/android-sdk-plugin/renderscript/build.sbt index d75ddada..dc2fb23c 100644 --- a/sbt-test/android-sdk-plugin/renderscript/build.sbt +++ b/sbt-test/android-sdk-plugin/renderscript/build.sbt @@ -1,6 +1,6 @@ import android.Keys._ -android.Plugin.androidBuild +enablePlugins(AndroidApp) name := "renderscript" diff --git a/sbt-test/android-sdk-plugin/renderscript/project/plugins.sbt b/sbt-test/android-sdk-plugin/renderscript/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/renderscript/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/renderscript/test b/sbt-test/android-sdk-plugin/renderscript/test index a5c028cb..e7b9e75e 100644 --- a/sbt-test/android-sdk-plugin/renderscript/test +++ b/sbt-test/android-sdk-plugin/renderscript/test @@ -1,10 +1,10 @@ -> check-target-api-equals-min +> checkTargetApiEqualsMin > android:package # > android:package-aar $ exists target/android/output/renderscript-debug.apk # $ exists target/android/output/renderscript.aar -> check-apk-for-resource -# > check-aar-for-resource -# > check-aar-no-libs +> checkApkForResource +# > checkAarForResource +# > checkAarNoLibs > last android:apkbuild -> show list-apk +> show listApk diff --git a/sbt-test/android-sdk-plugin/renderscript/tests.sbt b/sbt-test/android-sdk-plugin/renderscript/tests.sbt index 60ab5c7f..1f8341b4 100644 --- a/sbt-test/android-sdk-plugin/renderscript/tests.sbt +++ b/sbt-test/android-sdk-plugin/renderscript/tests.sbt @@ -2,29 +2,33 @@ import android.Keys._ import Tests._ TaskKey[Unit]("check-target-api-equals-min") := { - if ((rsTargetApi in Android).value != "17") - sys.error("Renderscript targetApi: " + (rsTargetApi in Android).value + " not equal to minSdkVersion") + val targetAPI = (rsTargetApi in Android).value + if (targetAPI != "17") + sys.error("Renderscript targetApi: " + targetAPI + " not equal to minSdkVersion") } -TaskKey[Unit]("check-apk-for-resource") <<= (apkFile in Android) map { a => +TaskKey[Unit]("check-apk-for-resource") := { + val a = (apkFile in Android).value val found = findInArchive(a) (_ == "res/raw/invert.bc") - if (!found) error("Renderscript resource not found in APK\n" + listArchive(a)) + if (!found) sys.error("Renderscript resource not found in APK\n" + listArchive(a)) } -//TaskKey[Unit]("check-aar-for-resource") <<= (packageAar in Android) map { a => +//TaskKey[Unit]("check-aar-for-resource") := (packageAar in Android) map { a => // val found = findInArchive(a) (_ == "res/raw/invert.bc") -// if (!found) error("Renderscript resource not found in Aar\n" + listArchive(a)) +// if (!found) sys.error("Renderscript resource not found in Aar\n" + listArchive(a)) //} -//TaskKey[Unit]("check-aar-no-libs") <<= (packageAar in Android) map { a => +//TaskKey[Unit]("check-aar-no-libs") := (packageAar in Android) map { a => // val found = findInArchive(a) (_.contains("libs")) -// if (found) error("Some library was included in aar\n" + listArchive(a)) +// if (found) sys.error("Some library was included in aar\n" + listArchive(a)) //} -TaskKey[Seq[String]]("list-apk") <<= (apkFile in Android) map { a => +TaskKey[Seq[String]]("list-apk") := { + val a = (apkFile in Android).value listArchive(a) } -TaskKey[Seq[String]]("list-apk") <<= (apkFile in Android) map { a => +TaskKey[Seq[String]]("list-apk") := { + val a = (apkFile in Android).value listArchive(a) } diff --git a/sbt-test/android-sdk-plugin/robo-junit-test/project/plugins.sbt b/sbt-test/android-sdk-plugin/robo-junit-test/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/robo-junit-test/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/sbt-structure-compatibility/build.sbt b/sbt-test/android-sdk-plugin/sbt-structure-compatibility/build.sbt index bb3e11c4..2a514fd1 100644 --- a/sbt-test/android-sdk-plugin/sbt-structure-compatibility/build.sbt +++ b/sbt-test/android-sdk-plugin/sbt-structure-compatibility/build.sbt @@ -1,7 +1,9 @@ -androidBuild +import org.jetbrains.sbt.StructureKeys._ + +enablePlugins(AndroidApp) javacOptions in Compile ++= "-source" :: "1.7" :: "-target" :: "1.7" :: Nil -SettingKey[Option[File]]("sbt-structure-output-file") in Global := Some(baseDirectory.value / "structure.xml") +sbtStructureOutputFile in Global := Some(baseDirectory.value / "structure.xml") -SettingKey[String]("sbt-structure-options") in Global := "download prettyPrint" +sbtStructureOptions in Global := "download prettyPrint" diff --git a/sbt-test/android-sdk-plugin/sbt-structure-compatibility/project/lib/sbt-structure-0.13.jar b/sbt-test/android-sdk-plugin/sbt-structure-compatibility/project/lib/sbt-structure-0.13.jar deleted file mode 100644 index 6af0e14b..00000000 Binary files a/sbt-test/android-sdk-plugin/sbt-structure-compatibility/project/lib/sbt-structure-0.13.jar and /dev/null differ diff --git a/sbt-test/android-sdk-plugin/sbt-structure-compatibility/project/plugins.sbt b/sbt-test/android-sdk-plugin/sbt-structure-compatibility/project/plugins.sbt new file mode 100644 index 00000000..f8e03129 --- /dev/null +++ b/sbt-test/android-sdk-plugin/sbt-structure-compatibility/project/plugins.sbt @@ -0,0 +1,2 @@ +addSbtPlugin("org.jetbrains" % "sbt-structure-extractor" % "2018.2.1") +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) diff --git a/sbt-test/android-sdk-plugin/sbt-structure-compatibility/test b/sbt-test/android-sdk-plugin/sbt-structure-compatibility/test index 5d01301b..1df58abb 100644 --- a/sbt-test/android-sdk-plugin/sbt-structure-compatibility/test +++ b/sbt-test/android-sdk-plugin/sbt-structure-compatibility/test @@ -1,3 +1,2 @@ -> apply -cp project/lib/sbt-structure-0.13.jar org.jetbrains.sbt.CreateTasks > dumpStructure > checkStructure diff --git a/sbt-test/android-sdk-plugin/simple-ant-layout/build.sbt b/sbt-test/android-sdk-plugin/simple-ant-layout/build.sbt index 91e6b594..f3054394 100644 --- a/sbt-test/android-sdk-plugin/simple-ant-layout/build.sbt +++ b/sbt-test/android-sdk-plugin/simple-ant-layout/build.sbt @@ -1,6 +1,6 @@ import android.Keys._ -android.Plugin.androidBuild +enablePlugins(AndroidApp) platformTarget in Android := "android-17" diff --git a/sbt-test/android-sdk-plugin/simple-ant-layout/project/plugins.sbt b/sbt-test/android-sdk-plugin/simple-ant-layout/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/simple-ant-layout/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/simple-ant-layout/test b/sbt-test/android-sdk-plugin/simple-ant-layout/test index 5d1730c3..6fbc4a80 100644 --- a/sbt-test/android-sdk-plugin/simple-ant-layout/test +++ b/sbt-test/android-sdk-plugin/simple-ant-layout/test @@ -1,2 +1,2 @@ -> android:proguard-cache -> android:platform-target +> android:proguardCache +> android:platformTarget diff --git a/sbt-test/android-sdk-plugin/simple-gradle-layout/build.sbt b/sbt-test/android-sdk-plugin/simple-gradle-layout/build.sbt index 46ed94b0..28040372 100644 --- a/sbt-test/android-sdk-plugin/simple-gradle-layout/build.sbt +++ b/sbt-test/android-sdk-plugin/simple-gradle-layout/build.sbt @@ -1,6 +1,6 @@ import android.Keys._ -android.Plugin.androidBuild +enablePlugins(AndroidApp) platformTarget in Android := "android-17" diff --git a/sbt-test/android-sdk-plugin/simple-gradle-layout/project/plugins.sbt b/sbt-test/android-sdk-plugin/simple-gradle-layout/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/simple-gradle-layout/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/simple-gradle-layout/test b/sbt-test/android-sdk-plugin/simple-gradle-layout/test index b5c098a2..dc62ebd1 100644 --- a/sbt-test/android-sdk-plugin/simple-gradle-layout/test +++ b/sbt-test/android-sdk-plugin/simple-gradle-layout/test @@ -1,8 +1,8 @@ -> android:proguard-cache -> android:platform-target -> verify-package +> android:proguardCache +> android:platformTarget +> verifyPackage > show android:aars -> check-global-aar +> checkGlobalAar > android:resValuesGenerator $ exists target/android/generated/res/values/generated.xml -> verify-res-values +> verifyResValues diff --git a/sbt-test/android-sdk-plugin/simple-gradle-layout/tests.sbt b/sbt-test/android-sdk-plugin/simple-gradle-layout/tests.sbt index ae49de95..97f44ba2 100644 --- a/sbt-test/android-sdk-plugin/simple-gradle-layout/tests.sbt +++ b/sbt-test/android-sdk-plugin/simple-gradle-layout/tests.sbt @@ -2,13 +2,15 @@ import android.Keys._ import android.BuildOutput._ import scala.xml._ -TaskKey[Unit]("verify-package") <<= (applicationId in Android) map { p => - if (p != "com.example.app") error("wrong package: " + p) +TaskKey[Unit]("verify-package") := { + val p = (applicationId in Android).value + if (p != "com.example.app") sys.error("wrong package: " + p) () } -TaskKey[Unit]("verify-res-values") <<= ( - projectLayout in Android, outputLayout in Android) map { (p, o) => +TaskKey[Unit]("verify-res-values") := { + val p = (projectLayout in Android).value + val o = (outputLayout in Android).value implicit val output = o val res = p.generatedRes / "values" / "generated.xml" val root = XML.loadFile(res) @@ -23,5 +25,5 @@ TaskKey[Unit]("verify-res-values") <<= ( TaskKey[Unit]("check-global-aar") := Def.task { val path = Path.userHome / ".android/sbt/exploded-aars/com.google.android.gms-play-services-4.3.23/com.google.android.gms-play-services-4.3.23.jar" - if (!path.isFile) android.Plugin.fail("path does not exist: " + path) + if (!path.isFile) android.fail("path does not exist: " + path) } diff --git a/sbt-test/android-sdk-plugin/simple-jar/build.sbt b/sbt-test/android-sdk-plugin/simple-jar/build.sbt index 4270851e..576ccf7b 100644 --- a/sbt-test/android-sdk-plugin/simple-jar/build.sbt +++ b/sbt-test/android-sdk-plugin/simple-jar/build.sbt @@ -1,4 +1,4 @@ -androidBuildJar +enablePlugins(AndroidJar) platformTarget in Android := "android-22" diff --git a/sbt-test/android-sdk-plugin/simple-jar/project/plugins.sbt b/sbt-test/android-sdk-plugin/simple-jar/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/simple-jar/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/simple-retrolambda/project/plugins.sbt b/sbt-test/android-sdk-plugin/simple-retrolambda/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/simple-retrolambda/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/simple-retrolambda/test b/sbt-test/android-sdk-plugin/simple-retrolambda/test index e710f288..7203d845 100644 --- a/sbt-test/android-sdk-plugin/simple-retrolambda/test +++ b/sbt-test/android-sdk-plugin/simple-retrolambda/test @@ -1,5 +1,5 @@ > android:package $ exists target/android/intermediates/dex/retrolambda-processed.jar -> check-jar +> checkJar > android:test > android:uninstall diff --git a/sbt-test/android-sdk-plugin/simple-retrolambda/test.sbt b/sbt-test/android-sdk-plugin/simple-retrolambda/test.sbt index 8376bfed..0a4295c0 100644 --- a/sbt-test/android-sdk-plugin/simple-retrolambda/test.sbt +++ b/sbt-test/android-sdk-plugin/simple-retrolambda/test.sbt @@ -1,5 +1,5 @@ -TaskKey[Unit]("check-jar") <<= ( dexInputs in Android) map { - case ((inc, list)) => +TaskKey[Unit]("check-jar") := { + val (inc, list) = (Android / dexInputs).value //Seq("jar", "tf", list(0).getAbsolutePath) ! () } diff --git a/sbt-test/android-sdk-plugin/typed-resources/build.sbt b/sbt-test/android-sdk-plugin/typed-resources/build.sbt index b3f79589..dc0086d2 100644 --- a/sbt-test/android-sdk-plugin/typed-resources/build.sbt +++ b/sbt-test/android-sdk-plugin/typed-resources/build.sbt @@ -1,5 +1,7 @@ enablePlugins(AndroidApp) +scalaVersion := "2.11.11" + javacOptions in Compile ++= "-source" :: "1.7" :: "-target" :: "1.7" :: Nil minSdkVersion := "8" diff --git a/sbt-test/android-sdk-plugin/typed-resources/project/plugins.sbt b/sbt-test/android-sdk-plugin/typed-resources/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/typed-resources/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/android-sdk-plugin/typed-resources/test b/sbt-test/android-sdk-plugin/typed-resources/test index 8e8fa755..148bf5ad 100644 --- a/sbt-test/android-sdk-plugin/typed-resources/test +++ b/sbt-test/android-sdk-plugin/typed-resources/test @@ -1,4 +1,4 @@ -> android:typed-resources-generator +> android:typedResourcesGenerator > compile > android:test > android:uninstall diff --git a/sbt-test/android-sdk-plugin/with-scalatest/project/plugins.sbt b/sbt-test/android-sdk-plugin/with-scalatest/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/android-sdk-plugin/with-scalatest/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/sbt-test/gradle-build/materialedittext/gradle.properties b/sbt-test/gradle-build/materialedittext/gradle.properties index d36abb85..7fbd00d1 100644 --- a/sbt-test/gradle-build/materialedittext/gradle.properties +++ b/sbt-test/gradle-build/materialedittext/gradle.properties @@ -13,6 +13,6 @@ POM_LICENCE_DIST=repo POM_DEVELOPER_ID=rengwuxian POM_DEVELOPER_NAME=Kai Zhu -ANDROID_BUILD_TARGET_SDK_VERSION=22 +ANDROID_BUILD_TARGET_SDK_VERSION=26 ANDROID_BUILD_TOOLS_VERSION=25.0.2 -ANDROID_BUILD_SDK_VERSION=22 +ANDROID_BUILD_SDK_VERSION=26 diff --git a/sbt-test/gradle-build/materialedittext/project/plugins.sbt b/sbt-test/gradle-build/materialedittext/project/plugins.sbt index 44752150..de1bf8cb 100644 --- a/sbt-test/gradle-build/materialedittext/project/plugins.sbt +++ b/sbt-test/gradle-build/materialedittext/project/plugins.sbt @@ -1,2 +1,2 @@ -addSbtPlugin("org.scala-android" % "sbt-android-gradle" % "1.4.0-SNAPSHOT") -addSbtPlugin("org.scala-android" % "sbt-android" % "1.8.0-SNAPSHOT") +addSbtPlugin("org.scala-android" % "sbt-android-gradle" % sys.props("gradlePlugin.version")) +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) diff --git a/sbt-test/gradle-build/plaid/app/build.gradle b/sbt-test/gradle-build/plaid/app/build.gradle index db4dffd3..09604a24 100644 --- a/sbt-test/gradle-build/plaid/app/build.gradle +++ b/sbt-test/gradle-build/plaid/app/build.gradle @@ -22,13 +22,13 @@ def gitTag = "deadbeef" def gitCommitCount = 100 android { - compileSdkVersion 23 + compileSdkVersion 26 buildToolsVersion '25.0.2' defaultConfig { applicationId "io.plaidapp" minSdkVersion 21 - targetSdkVersion 23 + targetSdkVersion 26 versionCode gitCommitCount versionName gitTag buildConfigField "String", "GIT_SHA", "\"${gitSha}\"" diff --git a/sbt-test/gradle-build/plaid/project/plugins.sbt b/sbt-test/gradle-build/plaid/project/plugins.sbt index 44752150..de1bf8cb 100644 --- a/sbt-test/gradle-build/plaid/project/plugins.sbt +++ b/sbt-test/gradle-build/plaid/project/plugins.sbt @@ -1,2 +1,2 @@ -addSbtPlugin("org.scala-android" % "sbt-android-gradle" % "1.4.0-SNAPSHOT") -addSbtPlugin("org.scala-android" % "sbt-android" % "1.8.0-SNAPSHOT") +addSbtPlugin("org.scala-android" % "sbt-android-gradle" % sys.props("gradlePlugin.version")) +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) diff --git a/sbt-test/gradle-build/plaid/third_party/bypass/build.gradle b/sbt-test/gradle-build/plaid/third_party/bypass/build.gradle index bcbae23d..80b75654 100644 --- a/sbt-test/gradle-build/plaid/third_party/bypass/build.gradle +++ b/sbt-test/gradle-build/plaid/third_party/bypass/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 23 + compileSdkVersion 26 buildToolsVersion "25.0.2" defaultConfig { diff --git a/sbt-test/gradle-build/u2020/build.gradle b/sbt-test/gradle-build/u2020/build.gradle index 897172ab..f57c263c 100644 --- a/sbt-test/gradle-build/u2020/build.gradle +++ b/sbt-test/gradle-build/u2020/build.gradle @@ -47,7 +47,7 @@ def isCi = "true".equals(System.getenv("CI")) def preDexEnabled = "true".equals(System.getProperty("pre-dex", "true")) android { - compileSdkVersion 23 + compileSdkVersion 26 buildToolsVersion '25.0.2' dexOptions { @@ -66,7 +66,7 @@ android { defaultConfig { minSdkVersion 15 - targetSdkVersion 23 + targetSdkVersion 26 versionCode versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild versionName "${versionMajor}.${versionMinor}.${versionPatch}" diff --git a/sbt-test/gradle-build/u2020/project/plugins.sbt b/sbt-test/gradle-build/u2020/project/plugins.sbt index 44752150..de1bf8cb 100644 --- a/sbt-test/gradle-build/u2020/project/plugins.sbt +++ b/sbt-test/gradle-build/u2020/project/plugins.sbt @@ -1,2 +1,2 @@ -addSbtPlugin("org.scala-android" % "sbt-android-gradle" % "1.4.0-SNAPSHOT") -addSbtPlugin("org.scala-android" % "sbt-android" % "1.8.0-SNAPSHOT") +addSbtPlugin("org.scala-android" % "sbt-android-gradle" % sys.props("gradlePlugin.version")) +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) diff --git a/sbt-test/gradle-build/viewserver/project/gradle.sbt b/sbt-test/gradle-build/viewserver/project/gradle.sbt index 44752150..de1bf8cb 100644 --- a/sbt-test/gradle-build/viewserver/project/gradle.sbt +++ b/sbt-test/gradle-build/viewserver/project/gradle.sbt @@ -1,2 +1,2 @@ -addSbtPlugin("org.scala-android" % "sbt-android-gradle" % "1.4.0-SNAPSHOT") -addSbtPlugin("org.scala-android" % "sbt-android" % "1.8.0-SNAPSHOT") +addSbtPlugin("org.scala-android" % "sbt-android-gradle" % sys.props("gradlePlugin.version")) +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) diff --git a/sbt-test/gradle-build/viewserver/viewserver-sample/build.gradle b/sbt-test/gradle-build/viewserver/viewserver-sample/build.gradle index 23d148b2..ac6c618f 100644 --- a/sbt-test/gradle-build/viewserver/viewserver-sample/build.gradle +++ b/sbt-test/gradle-build/viewserver/viewserver-sample/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 21 + compileSdkVersion 26 buildToolsVersion "25.0.2" defaultConfig { diff --git a/sbt-test/gradle-build/viewserver/viewserver/build.gradle b/sbt-test/gradle-build/viewserver/viewserver/build.gradle index 38ab9cf6..c72f427c 100644 --- a/sbt-test/gradle-build/viewserver/viewserver/build.gradle +++ b/sbt-test/gradle-build/viewserver/viewserver/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 21 + compileSdkVersion 26 buildToolsVersion "25.0.2" } diff --git a/sbt-test/no-travis/protify-compatibility/project/plugins.sbt b/sbt-test/no-travis/protify-compatibility/project/plugins.sbt new file mode 100644 index 00000000..51eb2b16 --- /dev/null +++ b/sbt-test/no-travis/protify-compatibility/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-android" % "sbt-android" % sys.props("plugin.version")) \ No newline at end of file diff --git a/src/AndroidAppSettings.scala b/src/AndroidAppSettings.scala index e9c8e3d4..b08ca899 100644 --- a/src/AndroidAppSettings.scala +++ b/src/AndroidAppSettings.scala @@ -117,7 +117,7 @@ trait AndroidAppSettings extends AutoPlugin { packageRelease := (packageRelease dependsOn setRelease).value, zipalignPath := { val p = sdkPath.value - val m = sdkManager.value + val _ = sdkManager.value val bt = buildToolInfo.value val s = sLog.value diff --git a/src/AndroidLint.scala b/src/AndroidLint.scala index fc98cf60..11f361e0 100644 --- a/src/AndroidLint.scala +++ b/src/AndroidLint.scala @@ -69,10 +69,10 @@ object AndroidLint { strict: Boolean, s: TaskStreams) extends Reporter(_client, null) { lazy val fmt = new MessageFormat("{0} {1}{0,choice,0#s|1#|1 !f.getName.matches("R\\W+.*class") @@ -98,7 +97,7 @@ trait AndroidProjectSettings extends AutoPlugin { javaSource := projectLayout.value.javaSource, unmanagedJars := unmanagedJarsTaskDef.value, // doesn't work properly yet, not for intellij integration - //managedClasspath <<= managedClasspathTaskDef, + //managedClasspath := managedClasspathTaskDef, sourceGenerators := sourceGenerators.value ++ List( rGenerator.taskValue, viewHoldersGenerator.taskValue, @@ -162,7 +161,7 @@ trait AndroidProjectSettings extends AutoPlugin { true }, lint := { - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value AndroidLint(projectLayout.value, (classDirectory in Compile).value, lintFlags.value, lintDetectors.value, lintStrict.value, minSdkVersion.value, targetSdkVersion.value, streams.value) @@ -188,20 +187,19 @@ trait AndroidProjectSettings extends AutoPlugin { // productX := Nil is a necessity to use Classpaths.configSettings exportedProducts := Nil, products := Nil, - classpathConfiguration := config("compile"), + classpathConfiguration := Compile, // end for Classpaths.configSettings // hack since it doesn't take in dependent project's libs dependencyClasspath := Def.taskDyn { val cp = (dependencyClasspath in Runtime).value val layout = projectLayout.value - implicit val out = outputLayout.value + implicit val out: Converter = outputLayout.value if (apkbuildDebug.value() && debugIncludesTests.?.value.getOrElse(false)) Def.task { val s = streams.value val tcp = (externalDependencyClasspath in AndroidTest).value cp foreach { a => - s.log.debug("%s => %s: %s" format(a.data.getName, - a.get(configuration.key), a.get(moduleID.key))) + s.log.debug(s"${a.data.getName} => ${a.get(configuration.key)}: ${a.get(moduleID.key)}") } val newcp = cp ++ tcp newcp.distinct.filterNot(_.data == layout.classesJar) @@ -264,7 +262,7 @@ trait AndroidProjectSettings extends AutoPlugin { val d = (classDirectory in Compile).value val s = streams.value - implicit val output = o + implicit val output: Converter = o FileFunction.cached(s.cacheDirectory / "clean-for-r", FilesInfo.hash, FilesInfo.exists) { in => if (in.nonEmpty) { @@ -337,7 +335,7 @@ trait AndroidProjectSettings extends AutoPlugin { mergeManifests := true, manifestPlaceholders := Map.empty, manifestOverlays := Seq.empty, - processManifest := (processManifestTaskDef storeAs processManifest).value, + processManifest := processManifestTaskDef.storeAs(processManifest).value, manifest := (manifestPath map { m => if (!m.exists) fail("cannot find AndroidManifest.xml: " + m) @@ -345,15 +343,8 @@ trait AndroidProjectSettings extends AutoPlugin { }).value, versionCode := manifest.value.attribute(ANDROID_NS, "versionCode").map(_.head.text.toInt), versionName := manifest.value.attribute(ANDROID_NS, "versionName").map(_.head.text) orElse Some(version.value), - packageForR := (manifest map { m => m.attribute("package").get.head.text}).value, - applicationId := - Def.task { - Forwarder.deprecations.packageName.?.value.fold(manifest.value.attribute("package").head.text) { p => - streams.value.log.warn( - "'packageName in Android' is deprecated, use 'applicationId'") - p - } - }.storeAs(applicationId).value, + packageForR := manifest.map(m => m.attribute("package").get.head.text).value, + applicationId := packageForR.value, targetSdkVersion := { val m = manifest.value val usesSdk = m \ "uses-sdk" @@ -396,13 +387,13 @@ trait AndroidProjectSettings extends AutoPlugin { sdkPath := SdkInstaller.sdkPath(sLog.value, properties.value), ndkPath := { - val p = thisProject.value + val _ = thisProject.value val props = properties.value val spath = sdkPath.value val log = sLog.value val cache = SdkLayout.androidNdkHomeCache - def storePathInCache(path: String) = { + def storePathInCache(path: String): Unit = { cache.getParentFile.mkdirs() IO.writeLines(cache, path :: Nil) } @@ -433,11 +424,11 @@ trait AndroidProjectSettings extends AutoPlugin { sdkLoader := DefaultSdkLoader.getLoader(sdkManager.value.getLocation), libraryRequests := Nil, builder := { - val ldr = sdkLoader.value - val m = sdkManager.value + val ldr = sdkLoader.value + val _sm = sdkManager.value val n = name.value val l_ = ilogger.value - val b = buildToolInfo.value + val _b = buildToolInfo.value val t = platform.value val reqs = libraryRequests.value val log = sLog.value @@ -567,14 +558,4 @@ trait AndroidProjectSettings extends AutoPlugin { (path ** filter).get } }.value ) - - private[this] object Forwarder { - @deprecated("forwarding", "1.6.0") - trait deprecations { - val packageName = Keys.packageName - } - - object deprecations extends deprecations - } - } diff --git a/src/AndroidTestSettings.scala b/src/AndroidTestSettings.scala index 31f36297..14f67b0e 100644 --- a/src/AndroidTestSettings.scala +++ b/src/AndroidTestSettings.scala @@ -1,10 +1,12 @@ package android +import sbt._ +import sbt.Keys._ + import Keys._ import Keys.Internal._ import Tasks._ -import sbt.{Def, _} -import sbt.Keys._ + /** * @author pfnguyen */ @@ -32,7 +34,6 @@ trait AndroidTestSettings extends AutoPlugin { scalacOptions := (scalacOptions in Compile).value, javacOptions := (javacOptions in Compile).value, manipulateBytecode := compileIncremental.value, - TaskKey[Option[xsbti.Reporter]]("compilerReporter") := None, compileIncremental := Defaults.compileIncrementalTask.value, compile := Def.taskDyn { if (executionRoots.value.size == 1) { @@ -48,18 +49,45 @@ trait AndroidTestSettings extends AutoPlugin { } else Defaults.compileTask }.value, compileIncSetup := { - Compiler.IncSetup( - Defaults.analysisMap((dependencyClasspath in AndroidTestInternal).value), - definesClass.value, + val lookup = new xsbti.compile.PerClasspathEntryLookup { + private val cachedAnalysisMap = + Defaults.analysisMap((dependencyClasspath in AndroidTestInternal).value) + private val cachedPerEntryDefinesClassLookup = sbt.Keys.classpathEntryDefinesClass.value // ??? FIXME + + override def analysis(classpathEntry: File): java.util.Optional[xsbti.compile.CompileAnalysis] = + sbt.util.InterfaceUtil.toOptional(cachedAnalysisMap(classpathEntry)) + override def definesClass(classpathEntry: File): xsbti.compile.DefinesClass = + cachedPerEntryDefinesClassLookup(classpathEntry) + } + + xsbti.compile.Setup.of( + lookup, (skip in compile).value, - // TODO - this is kind of a bad way to grab the cache directory for streams... streams.value.cacheDirectory / compileAnalysisFilename.value, compilerCache.value, - incOptions.value) + incOptions.value, + sbt.SbtInternals.reporter.value, + java.util.Optional.empty[xsbti.compile.CompileProgress], + Array.empty) }, compileInputs in compile := { - val cp = classDirectory.value +: Attributed.data((dependencyClasspath in AndroidTestInternal).value) - Compiler.inputs(cp, sources.value, classDirectory.value, scalacOptions.value, javacOptions.value, maxErrors.value, sourcePositionMappers.value, compileOrder.value)(compilers.value, compileIncSetup.value, streams.value.log) + val cp = (classDirectory.value +: Attributed.data((dependencyClasspath in AndroidTestInternal).value)).toArray + + def foldMappers[A](mappers: Seq[A => Option[A]]) = + mappers.foldRight({p: A => p}) { (mapper, mappers) => {p: A => mapper(p).getOrElse(mappers(p))}} + + val compileOptions = xsbti.compile.CompileOptions.of( + cp, + sources.value.toArray, + classDirectory.value, + scalacOptions.value.toArray, + javacOptions.value.toArray, + maxErrors.value, + sbt.util.InterfaceUtil.toJavaFunction(foldMappers(sourcePositionMappers.value)), + compileOrder.value + ) + + xsbti.compile.Inputs.of(compilers.value, compileOptions, compileIncSetup.value, previousCompile.value) }, compileAnalysisFilename := { // Here, if the user wants cross-scala-versioning, we also append it @@ -79,4 +107,5 @@ trait AndroidTestSettings extends AutoPlugin { )) ++ List( dependencyClasspath in AndroidTestInternal := (dependencyClasspath in AndroidTest).value ++ (dependencyClasspath in Runtime).value ) + } diff --git a/src/DeprecatedPluginCompat.scala b/src/DeprecatedPluginCompat.scala deleted file mode 100644 index 9959af84..00000000 --- a/src/DeprecatedPluginCompat.scala +++ /dev/null @@ -1,35 +0,0 @@ -package android -import sbt._ -/** - * @author pfnguyen - */ -trait DeprecatedPluginCompat { - @deprecated("use `android.flavorOf`", "1.7.0") - def flavorOf(p: Project, id: String, settings: Setting[_]*): Project = android.flavorOf(p, id, settings:_*) - - @deprecated("use `android.withVariant`", "1.7.0") - def withVariant(project: String, - buildType: Option[String] = None, - flavor: Option[String] = None): Setting[_] = - android.withVariant(project, buildType, flavor) - - @deprecated("use `android.withVariant`", "1.7.0") - def withVariant(p: ProjectReference, - buildType: Option[String], - flavor: Option[String]): Setting[_] = android.withVariant(p, buildType, flavor) - - @deprecated("use `enablePlugins(AndroidApp)`", "1.7.0") - def androidBuild: Seq[Setting[_]] = AndroidProject.projectSettings ++ AndroidApp.projectSettings - - @deprecated("Use `enablePlugins(AndroidApp)`", "1.7.0") - def buildWith(projects: ProjectReference*): Seq[Setting[_]] = android.buildWith(projects) - - @deprecated("use `enablePlugins(AndroidJar)`", "1.7.0") - def androidBuildJar: Seq[Setting[_]] = AndroidProject.projectSettings ++ AndroidJar.projectSettings - @deprecated("use `enablePlugins(AndroidLib)`", "1.7.0") - def androidBuildAar: Seq[Setting[_]] = AndroidProject.projectSettings ++ AndroidLib.projectSettings - - @deprecated("use android.useSupportVectors", "1.7.0") - def useSupportVectors = android.useSupportVectors - -} diff --git a/src/Dex.scala b/src/Dex.scala index a634ab3b..a9124592 100644 --- a/src/Dex.scala +++ b/src/Dex.scala @@ -7,6 +7,7 @@ import com.android.builder.core.AndroidBuilder import com.android.ide.common.process.{CachedProcessOutputHandler, ProcessInfoBuilder} import com.android.sdklib.BuildToolInfo import sbt._ +import sbt.io.Using import scala.language.postfixOps import scala.xml.{Elem, XML} diff --git a/src/Keys.scala b/src/Keys.scala index bc26126b..256509c2 100644 --- a/src/Keys.scala +++ b/src/Keys.scala @@ -3,6 +3,7 @@ package android import com.android.tools.lint.LintCliFlags import com.android.tools.lint.detector.api.Issue import sbt._ +import sbt.librarymanagement.Configuration import scala.xml.Elem import java.io.File @@ -17,7 +18,7 @@ import com.android.sdklib.repository.AndroidSdkHandler import language.implicitConversions -object Keys extends DeprecatedPluginCompat { +object Keys { // alias types that got refactored out type ProjectLayout = android.ProjectLayout val ProjectLayout = android.ProjectLayout @@ -39,7 +40,8 @@ object Keys extends DeprecatedPluginCompat { val Android = config("android") val AndroidTest = config("androidTest").extend(Runtime).hide - val AndroidTestInternal = Configurations.fullInternal(AndroidTest) + val AndroidTestInternal = + Configuration.of(AndroidTest.id + "Internal", AndroidTest.name + "-internal").extend(Optional, Provided).hide // build-environment keys // automatically set from ANDROID_HOME or *.properties ("sdk.dir") @@ -179,9 +181,6 @@ object Keys extends DeprecatedPluginCompat { // manifest-related keys val applicationId = TaskKey[String]("application-id", "apk pkg id, is android:packageName if set, otherwise manifest package name") in Android - @deprecated("Use `applicationId in Android` instead", "1.4.6") - val packageName = SettingKey[String]("package-name", - "Deprecated android application ID, use android:application-id instead") in Android val manifest = TaskKey[Elem]("manifest", "android manifest xml object, read-only, do not modify") in Android val processManifest = TaskKey[File]("process-manifest", @@ -298,8 +297,6 @@ object Keys extends DeprecatedPluginCompat { val lintDetectors = SettingKey[Seq[Issue]]("lint-issues", "Issues to detect, default: ApiDetectors") in Android - implicit def toRichProject(project: Project): RichProject = RichProject(project) - case class PackagingOptions(excludes: Seq[String] = Nil, pickFirsts: Seq[String] = Nil, merges: Seq[String] = Nil, doNotStrip: Seq[String] = Nil) { import collection.JavaConverters._ def asAndroid = new com.android.builder.model.PackagingOptions { diff --git a/src/MethodCounter.scala b/src/MethodCounter.scala index 138e8ad3..8c2551e5 100644 --- a/src/MethodCounter.scala +++ b/src/MethodCounter.scala @@ -1,10 +1,9 @@ package android -import language.postfixOps - import javassist.util.proxy.{MethodHandler, MethodFilter, ProxyFactory} import sbt._ +import sbt.io.Using import org.objectweb.asm._ import org.objectweb.asm.signature.SignatureVisitor diff --git a/src/NativeFinder.scala b/src/NativeFinder.scala index 6bab366a..f54006bb 100644 --- a/src/NativeFinder.scala +++ b/src/NativeFinder.scala @@ -3,7 +3,7 @@ package android import javassist.util.proxy.{MethodHandler, MethodFilter, ProxyFactory} import sbt._ -import language.postfixOps +import sbt.io.Using import org.objectweb.asm._ @@ -39,7 +39,7 @@ object NativeFinder { } factory.create(Array(classOf[Int]), Array(Opcodes.ASM4.asInstanceOf[AnyRef]), h) match { case x: ClassVisitor => - (classDir ** "*.class" get) foreach { entry => + (classDir ** "*.class").get foreach { entry => Using.fileInputStream(entry) { in => try { val r = new ClassReader(in) diff --git a/src/Packaging.scala b/src/Packaging.scala index 532b6271..c1602e36 100644 --- a/src/Packaging.scala +++ b/src/Packaging.scala @@ -5,7 +5,8 @@ import java.util.concurrent.{LinkedBlockingDeque, ThreadPoolExecutor, TimeUnit} import java.util.jar.JarFile import java.util.zip.{Deflater, ZipEntry} -import android.Keys.PackagingOptions +import scala.collection.JavaConverters._ + import com.android.SdkConstants import com.android.apkzlib.zfile.{ApkCreatorFactory, ApkZFileCreatorFactory} import com.android.apkzlib.zip.ZFileOptions @@ -19,11 +20,15 @@ import com.android.ide.common.res2.FileStatus import com.android.ide.common.signing.KeystoreHelper import com.android.utils.ILogger import com.google.common.collect.ImmutableMap + +import sbt._ import sbt.Def.Classpath import sbt.Keys.moduleID -import sbt._ +import sbt.io.Using +import sbt.util.CacheStoreFactory + +import android.Keys.PackagingOptions -import scala.collection.JavaConverters._ /** * @author pfnguyen @@ -33,9 +38,9 @@ object Packaging { , unmanaged: Classpath , depenendices: Classpath) { - def isScalaLang(module: ModuleID) = module.organization == "org.scala-lang" + def isScalaLang(module: ModuleID): Boolean = module.organization == "org.scala-lang" val providedConfigurations = Set("provided", "compile-internal", "plugin->default(compile)") - def isProvidedDependency(module: ModuleID) = module.configurations exists providedConfigurations + def isProvidedDependency(module: ModuleID): Boolean = module.configurations exists providedConfigurations // filtering out org.scala-lang should not cause an issue // they should not be changing on us anyway @@ -49,28 +54,6 @@ object Packaging { }.flatten.map (_.data).toList } - @deprecated("Use apkbuild(bldr: AndroidBuilder, jars: Packaging.Jars, ...) instead", "1.6.1") - def apkbuild( bldr: AndroidBuilder - , managed: Classpath - , unmanaged: Classpath - , dependenciesCp: Classpath - , isLib: Boolean - , aggregateOptions: Aggregate.Apkbuild - , abiFilter: Set[String] - , collectJniOut: File - , resFolder: File - , collectResourceFolder: File - , collectAssetsFolder: File - , output: File - , logger: ILogger - , s: sbt.Keys.TaskStreams): File = { - apkbuild( - bldr, Jars(managed, unmanaged, dependenciesCp), isLib, - aggregateOptions, abiFilter, collectJniOut, resFolder, - collectResourceFolder, collectAssetsFolder, output, logger, s - ) - } - def apkbuild( bldr: AndroidBuilder , dependencyJars: Jars , isLib: Boolean @@ -155,23 +138,23 @@ object Packaging { var result = Option.empty[ImmutableMap[RelativeFile,FileStatus]] s.log.debug("Checking for changes in " + files.mkString(",")) - FileFunction.cached(s.cacheDirectory / cacheName)(FilesInfo.lastModified, FilesInfo.exists) { (ins, _) => - s.log.debug("Found changes!") - val ds = if (ins.added == ins.checked) ins.added.toList.map { f => - new RelativeFile(base(f), f) -> FileStatus.NEW - } else { - ins.added.toList.map { f => - new RelativeFile(base(f), f) -> FileStatus.NEW - } ++ ins.removed.toList.map { f => - new RelativeFile(base(f), f) -> FileStatus.REMOVED - } ++ (ins.modified -- ins.added).toList.map { f => - new RelativeFile(base(f), f) -> FileStatus.CHANGED - } - } + FileFunction.cached( + CacheStoreFactory(s.cacheDirectory / cacheName), + FilesInfo.lastModified, + FilesInfo.exists) { (ins, _) => + s.log.debug("Found changes!") + val ds = + if (ins.added == ins.checked) + ins.added.toList.map(f => new RelativeFile(base(f), f) -> FileStatus.NEW) + else { + ins.added.toList.map(f => new RelativeFile(base(f), f) -> FileStatus.NEW) ++ + ins.removed.toList.map(f => new RelativeFile(base(f), f) -> FileStatus.REMOVED) ++ + (ins.modified -- ins.added).toList.map(f => new RelativeFile(base(f), f) -> FileStatus.CHANGED) + } - result = Some(ImmutableMap.copyOf(ds.toMap.asJava)) + result = Some(ImmutableMap.copyOf(ds.toMap.asJava)) - ins.checked + ins.checked }(files.toSet) result.getOrElse(ImmutableMap.of()) diff --git a/src/Plugin.scala b/src/Plugin.scala deleted file mode 100644 index 50896f38..00000000 --- a/src/Plugin.scala +++ /dev/null @@ -1,84 +0,0 @@ -package android - -import sbt._ - -import Keys._ -import Keys.Internal._ - -@deprecated("android.Plugin should no longer be used", "1.7.0") -object Plugin extends PluginFail { - - // android build steps - // * handle library dependencies (android.library.reference.N) - // * ndk - // * aidl - // * renderscript - // * BuildConfig.java - // * aapt - // * compile - // * obfuscate - // * dex - // * png crunch - // * package resources - // * package apk - // * sign - // * zipalign - - /** - * create a new project flavor, build outputs will go in "id/android" - */ - @deprecated("use `android.flavor` and `android.buildType` instead", "1.7.0") - def flavorOf(p: Project, id: String, settings: Setting[_]*): Project = android.flavorOf(p, id, settings:_*) - @deprecated("use android.withVariant", "1.7.0") - def withVariant(project: String, - buildType: Option[String] = None, - flavor: Option[String] = None): Setting[_] = - android.withVariant(project, buildType, flavor) - - @deprecated("use android.withVariant", "1.7.0") - def withVariant(p: ProjectReference, - buildType: Option[String], - flavor: Option[String]): Setting[_] = android.withVariant(p, buildType, flavor) - - @deprecated("use `enablePlugins(AndroidApp)`", "1.7.0") - lazy val androidBuild: Seq[Setting[_]] = AndroidProject.projectSettings ++ AndroidApp.projectSettings - - @deprecated("Use `enablePlugins(AndroidApp)`", "1.7.0") - def buildWith(projects: ProjectReference*): Seq[Setting[_]] = android.buildWith(projects) - - @deprecated("use `enablePlugins(AndroidJar)`", "1.7.0") - lazy val androidBuildJar: Seq[Setting[_]] = androidBuild ++ buildJar - - @deprecated("use `enablePlugins(AndroidLib)`", "1.7.0") - lazy val androidBuildAar: Seq[Setting[_]] = androidBuildAar() - - @deprecated("use `enablePlugins(AndroidLib)`", "1.7.0") - def androidBuildAar(projects: ProjectReference*): Seq[Setting[_]] = { - androidBuild(projects:_*) ++ buildAar - } - - @deprecated("Use aar files instead", "gradle compatibility") - lazy val androidBuildApklib: Seq[Setting[_]] = androidBuildApklib() - - @deprecated("Use aar files instead", "gradle compatibility") - def androidBuildApklib(projects: ProjectReference*): Seq[Setting[_]] = { - androidBuild(projects:_*) ++ buildApklib - } - - @deprecated("Use Project.androidBuildWith(subprojects) instead", "1.3.3") - private[this] def androidBuild(projects: ProjectReference*): Seq[Setting[_]] = - Plugin.androidBuild ++ buildWith(projects: _*) - - @deprecated("use android.useSupportVectors", "1.7.0") - def useSupportVectors = android.useSupportVectors - - @deprecated("use `enablePlugins(AndroidJar)`", "1.7.0") - def buildJar = AndroidJar.projectSettings - - @deprecated("Use `enablePlugins(AndroidLib)`", "1.7.0") - def buildAar = AndroidLib.projectSettings - - @deprecated("Stop using apklib", "1.7.0") - def buildApklib = Seq(libraryProject := true) ++ - addArtifact(apklibArtifact, packageApklib) -} diff --git a/src/ReferenceFinder.scala b/src/ReferenceFinder.scala index ce5d319a..9129e28c 100644 --- a/src/ReferenceFinder.scala +++ b/src/ReferenceFinder.scala @@ -3,6 +3,7 @@ package android import javassist.util.proxy.{MethodHandler, MethodFilter, ProxyFactory} import sbt._ +import sbt.io.Using import org.objectweb.asm._ import org.objectweb.asm.signature.SignatureVisitor diff --git a/src/Resources.scala b/src/Resources.scala index a6a71146..d48e0223 100644 --- a/src/Resources.scala +++ b/src/Resources.scala @@ -1,29 +1,29 @@ package android -import android.Dependencies.{AarLibrary, ApkLibrary, LibraryDependency} +import scala.util.Try +import scala.util.matching.Regex +import scala.xml.XML +import scala.collection.JavaConverters._ + import com.android.builder.core.{AndroidBuilder, VariantType} import com.android.builder.model.{AaptOptions, AndroidLibrary} import com.android.builder.png.VectorDrawableRenderer -import com.android.ide.common.res2._ -import com.android.resources.Density -import com.android.utils.ILogger -import sbt.Keys.TaskStreams -import sbt.{File, _} - -import collection.JavaConverters._ -import language.postfixOps -import Dependencies.LibrarySeqOps import com.android.builder.dependency.level2.AndroidDependency import com.android.builder.internal.aapt.{Aapt, AaptPackageConfig} import com.android.builder.internal.aapt.v1.AaptV1 import com.android.builder.internal.aapt.v2.OutOfProcessAaptV2 +import com.android.ide.common.res2._ import com.android.ide.common.process.DefaultProcessExecutor import com.android.sdklib.BuildToolInfo -import sbt.classpath.ClasspathUtilities +import com.android.resources.Density +import com.android.utils.ILogger -import scala.util.Try -import scala.util.matching.Regex -import scala.xml.XML +import sbt.Keys.TaskStreams +import sbt.{File, _} +import sbt.internal.inc.classpath.ClasspathUtilities +import sbt.util.CacheStoreFactory + +import android.Dependencies.{AarLibrary, ApkLibrary, LibraryDependency, LibrarySeqOps} object Resources { val ANDROID_NS = "http://schemas.android.com/apk/res/android" @@ -140,8 +140,11 @@ object Resources { } } - val inputs = (respaths flatMap { case (_,r) => (r ***) get }) filter (n => - !n.getName.startsWith(".") && !n.getName.startsWith("_")) + val inputs = + respaths + .flatMap { case (_,r) => r.allPaths.get } + .filter(n => !n.getName.startsWith(".") && !n.getName.startsWith("_")) + var needsFullResourceMerge = false FileFunction.cached(cache / "nuke-res-if-changed", FilesInfo.lastModified) { in => @@ -149,14 +152,20 @@ object Resources { IO.delete(resTarget) in }(nonGeneratingRes) - FileFunction.cached(cache / "collect-resources")( - FilesInfo.lastModified, FilesInfo.exists) { (inChanges,outChanges) => - s.log.info("Collecting resources") - incrResourceMerge(layout, minSdk, resTarget, isLib, cache / "collect-resources", - logger, bldr, sets, pngcrunch, png9crunch, vectorprocessor, inChanges, needsFullResourceMerge, s.log) - ((resTarget ** FileOnlyFilter).get ++ (layout.generatedVectors ** FileOnlyFilter).get).toSet - }(inputs.toSet) + FileFunction.cached( + CacheStoreFactory(cache / "collect-resources"), + FilesInfo.lastModified, + FilesInfo.exists) { (inChanges, outChanges) => + + s.log.info("Collecting resources") + + incrResourceMerge( + layout, minSdk, resTarget, isLib, cache / "collect-resources", logger, bldr, + sets, pngcrunch, png9crunch, vectorprocessor, inChanges, needsFullResourceMerge, s.log) + + ((resTarget ** FileOnlyFilter).get ++ (layout.generatedVectors ** FileOnlyFilter).get).toSet + }(inputs.toSet) (assetBin, resTarget) } @@ -222,7 +231,7 @@ object Resources { status match { case FileStatus.NEW => case FileStatus.CHANGED => - if (targetFile.exists) IO.copy(copy, false, true) + if (targetFile.exists) IO.copy(copy, overwrite = false, preserveLastModified = true, preserveExecutable = true) case FileStatus.REMOVED => targetFile.delete() } // end workaround @@ -266,7 +275,7 @@ object Resources { mergeTemp.mkdirs() val l = SbtILogger() l(logger) - val aaptv1 = new AaptV1(new DefaultProcessExecutor(l), SbtProcessOutputHandler(logger), bldr.getTarget.getBuildToolInfo, l, AaptV1.PngProcessMode.ALL, 2) + val _ = new AaptV1(new DefaultProcessExecutor(l), SbtProcessOutputHandler(logger), bldr.getTarget.getBuildToolInfo, l, AaptV1.PngProcessMode.ALL, 2) new MergedResourceWriter(resTarget, layout.publicTxt, layout.mergeBlame, preprocessor, makeAapt(bldr, bldr.getTarget.getBuildToolInfo, @@ -439,14 +448,14 @@ object Resources { FileFunction.cached(s.cacheDirectory / "typed-resources-generator", FilesInfo.hash) { in => if (in.nonEmpty) { s.log.info("Regenerating TR.scala because R.java has changed") - val layouts = (r ** "layout*" ** "*.xml" get) ++ + val layouts = (r ** "layout*" ** "*.xml").get ++ (for { lib <- l filterNot { case a: AarLibrary => !includeAar case p: Dependencies.Pkg => ignores(p.pkg) case _ => false } - xml <- lib.getResFolder ** "layout*" ** "*.xml" get + xml <- (lib.getResFolder ** "layout*" ** "*.xml").get } yield xml) s.log.debug("Layouts: " + layouts) @@ -663,7 +672,7 @@ object Resources { def attributeText(n: xml.Node, attr: String): Option[String] = n.attribute(attr).flatMap(_.headOption).map(_.text) def processValuesXml(resdirs: Seq[File], s: TaskStreams): ResourceMap = { - val valuesxmls = resdirs flatMap { d => d * "values*" * "*.xml" get } + val valuesxmls = resdirs flatMap { d => (d * "values*" * "*.xml").get } val rms = valuesxmls.map { xml => val values = XML.loadFile(xml) @@ -715,7 +724,7 @@ object Resources { } def processMenuItems(resdirs: Seq[File], re: Regex, s: TaskStreams): ResourceMap = { - val menuxmls = resdirs flatMap { d => d * "menu" * "*.xml" get } + val menuxmls = resdirs flatMap { d => (d * "menu" * "*.xml").get } val menuItems = for { b <- menuxmls menu = XML loadFile b @@ -807,10 +816,10 @@ object Resources { case p: Dependencies.Pkg => ig(p.pkg) case _ => false } - val files = (layout.res ** "layout*" ** "*.xml" get) ++ + val files = (layout.res ** "layout*" ** "*.xml").get ++ (for { lib <- libsToProcess - xml <- lib.getResFolder ** "layout*" ** "*.xml" get + xml <- (lib.getResFolder ** "layout*" ** "*.xml").get } yield xml) diff --git a/src/SbtInternals.scala b/src/SbtInternals.scala new file mode 100644 index 00000000..c837712f --- /dev/null +++ b/src/SbtInternals.scala @@ -0,0 +1,9 @@ +package sbt + +import sbt.Keys._ + +object SbtInternals { + def reporter: Def.Initialize[Task[xsbti.Reporter]] = Def.task { + (Compile / compile / compilerReporter).value + } +} diff --git a/src/SignAndroidJar.scala b/src/SignAndroidJar.scala new file mode 100644 index 00000000..2486bfe8 --- /dev/null +++ b/src/SignAndroidJar.scala @@ -0,0 +1,40 @@ +package android + +import java.io.File +import java.net.URL + +object SignAndroidJar { + final class SignOption private[SignAndroidJar] (val toList: List[String], val signOnly: Boolean) { + override def toString = toList.mkString(" ") + } + def keyStore(url: URL): SignOption = new SignOption("-keystore" :: url.toExternalForm :: Nil, true) + def signedJar(p: File): SignOption = new SignOption("-signedjar" :: p.getAbsolutePath :: Nil, true) + def verbose = new SignOption("-verbose" :: Nil, false) + def sigFile(name: String) = new SignOption("-sigfile" :: name :: Nil, true) + def storeType(t: String): SignOption = new SignOption("-storetype" :: t :: Nil, false) + def provider(p: String) = new SignOption("-provider" :: p :: Nil, false) + def providerName(p: String) = new SignOption("-providerName" :: p :: Nil, false) + def storePassword(p: String): SignOption = new SignOption("-storepass" :: p :: Nil, true) + def keyPassword(p: String): SignOption = new SignOption("-keypass" :: p :: Nil, true) + + private def VerifyOption = "-verify" + + /** Uses jarsigner to sign the given jar. */ + def sign(jarPath: File, alias: String, options: Seq[SignOption])(fork: (String, List[String]) => Int) { + require(!alias.trim.isEmpty, "Alias cannot be empty") + val arguments = options.toList.flatMap(_.toList) ::: jarPath.getAbsolutePath :: alias :: Nil + execute("signing", arguments)(fork) + } + /** Uses jarsigner to verify the given jar.*/ + def verify(jarPath: File, options: Seq[SignOption])(fork: (String, List[String]) => Int) { + val arguments = options.filter(!_.signOnly).toList.flatMap(_.toList) ::: VerifyOption :: jarPath.getAbsolutePath :: Nil + execute("verifying", arguments)(fork) + } + private def execute(action: String, arguments: List[String])(fork: (String, List[String]) => Int) { + val exitCode = fork(CommandName, arguments) + if (exitCode != 0) + sys.error("Error " + action + " jar (exit code was " + exitCode + ".)") + } + + private val CommandName = "jarsigner" +} \ No newline at end of file diff --git a/src/TaskBase.scala b/src/TaskBase.scala index 71b3e1cd..228ae417 100644 --- a/src/TaskBase.scala +++ b/src/TaskBase.scala @@ -1,16 +1,18 @@ package android + import java.io.File import java.util.Properties +import sbt.io.{FileFilter, PathFinder, Using} + /** * @author pfnguyen */ private[android] trait TaskBase { def loadProperties(path: File): Properties = { - import sbt._ val p = new Properties - (path * "*.properties").get.foreach(Using.fileInputStream(_)(p.load)) + (PathFinder(path) * FileFilter.globFilter("*.properties")).get.foreach(Using.fileInputStream(_)(p.load)) p } } diff --git a/src/UpdateChecker.scala b/src/UpdateChecker.scala new file mode 100644 index 00000000..dea2f73c --- /dev/null +++ b/src/UpdateChecker.scala @@ -0,0 +1,49 @@ +package android + +import java.io.{InputStreamReader, BufferedReader, StringWriter} + +import argonaut._, Argonaut._ + +import scala.concurrent.Future +import scala.util.{Failure, Success} + +object UpdateChecker { + import scala.concurrent.ExecutionContext.Implicits.global + type Result = (Set[String],String) + type Callback[A] = Either[Throwable,Result] => A + + def apply[A](user: String, repo: String, name: String)(result: Callback[A]): Unit = { + val bintray = new java.net.URL( + s"https://api.bintray.com/packages/$user/$repo/$name") + Future { + val uc = bintray.openConnection() + val in = new BufferedReader(new InputStreamReader(uc.getInputStream, "utf-8")) + try { + val sw = new StringWriter + val buf = Array.ofDim[Char](8192) + Stream.continually(in.read(buf, 0, 8192)) takeWhile ( + _ != -1) foreach (sw.write(buf, 0, _)) + sw.toString + } finally { + in.close() + } + } onComplete { + case Success(json) => + val res: Either[Throwable, Result] = json.decode[PackageInfo] match { + case Left(Left(str)) => + Left(new IllegalArgumentException(str)) + case Left(Right(cursorHistory)) => + Left(new IllegalArgumentException(cursorHistory._1)) + case Right(packageInfo) => + Right(packageInfo.versions.toSet -> packageInfo.version) + } + result(res) + case Failure(t) => result(Left(t)) + } + } + + implicit def PackageInfoCodecJson: CodecJson[PackageInfo] = casecodec3( + PackageInfo.apply, PackageInfo.unapply)("name", "latest_version", "versions") + + case class PackageInfo(name: String, version: String, versions: List[String]) +} \ No newline at end of file diff --git a/src/VariantSettings.scala b/src/VariantSettings.scala index e98c0e2f..7e9d0bfb 100644 --- a/src/VariantSettings.scala +++ b/src/VariantSettings.scala @@ -1,6 +1,9 @@ package android import sbt._ +import sbt.compat.Load +import sbt.internal.{BuildStructure, SessionSettings} + import VariantSettings._ /** @@ -46,9 +49,9 @@ object VariantSettings { override def apply[T](a: Def.ScopedKey[T]) = { val scope0 = if (a.scope.project == This) a.scope.copy(project = Select(prj)) else a.scope - val scope1 = if (scope0.task == This) scope0.copy(task = Global) else scope0 - val scope2 = if (scope1.extra == This) scope1.copy(extra = Global) else scope1 - val scope3 = if (scope2.config == This) scope2.copy(config = Global) else scope2 + val scope1 = if (scope0.task == This) scope0.copy(task = Zero) else scope0 + val scope2 = if (scope1.extra == This) scope1.copy(extra = Zero) else scope1 + val scope3 = if (scope2.config == This) scope2.copy(config = Zero) else scope2 a.copy(scope = scope3) } } @@ -133,7 +136,7 @@ object VariantSettings { val e = Project.extract(s) val appendSettings = Load.transformSettings(Load.projectScope(e.currentRef), e.currentRef.build, e.rootProject, ss) val newSettings = e.session.original ++ appendSettings - val newStructure = Load.reapply(newSettings, e.structure)(Project.showContextKey(e.session, e.structure)) + val newStructure = Load.reapply(newSettings, e.structure)(Project.showContextKey2(e.session)) Project.setProject(e.session.copy(original = newSettings), newStructure, s.put(originalSettings, s.get(originalSettings).getOrElse(e.session.original) ++ appendSettings).put(onUnloadSkip, true)) } @@ -143,7 +146,6 @@ object VariantSettings { private[this] val ref = new java.lang.ref.WeakReference(s.globalLogging.full) private[this] def slog: Logger = Option(ref.get) getOrElse sys.error("Settings logger used after project was loaded.") - override val ansiCodesSupported = slog.ansiCodesSupported override def trace(t: => Throwable) = slog.trace(t) override def success(message: => String) = slog.success(message) override def log(level: Level.Value, message: => String) = slog.log(level, message) @@ -156,7 +158,7 @@ object VariantSettings { } def showContextKey(session: SessionSettings, structure: BuildStructure, keyNameColor: Option[String] = None): Show[ScopedKey[_]] = - Def.showRelativeKey(session.current, structure.allProjects.size > 1, keyNameColor) + Def.showRelativeKey2(session.current, keyNameColor) def setProject(variants: VariantSettings, session: SessionSettings, originals: Seq[Setting[_]], structure: BuildStructure, s: State): State = { val unloaded = Project.runUnloadHooks(s.put(onUnloadSkip, true)) val (onLoad, onUnload) = Project.getHooks(structure.data) @@ -175,17 +177,15 @@ object VariantSettings { if (hasExplicitGlobalLogLevels(s)) s else { - val logging = s.globalLogging - def get[T](key: SettingKey[T]) = key in GlobalScope get data - def transfer(l: AbstractLogger, traceKey: SettingKey[Int], levelKey: SettingKey[Level.Value]) { - get(traceKey).foreach(l.setTrace) - get(levelKey).foreach(l.setLevel) - } - logging.full match { - case a: AbstractLogger => transfer(a, sbt.Keys.traceLevel, sbt.Keys.logLevel) - case _ => () - } - transfer(logging.backed, sbt.Keys.persistTraceLevel, sbt.Keys.persistLogLevel) + // FIXME: https://github.com/sbt/sbt/blob/05c2c506b2b218d8ed8befcef843951391c07be6/main/src/main/scala/sbt/internal/LogManager.scala#L204-L222 + //def get[T](key: SettingKey[T]) = key in GlobalScope get data + //def transfer(l: AbstractLogger, traceKey: SettingKey[Int], levelKey: SettingKey[Level.Value]) { + // get(traceKey).foreach(l.setTrace) + // get(levelKey).foreach(l.setLevel) + //} + //val logging = s.globalLogging + //transfer(logging.full, sbt.Keys.traceLevel, sbt.Keys.logLevel) + //transfer(logging.backed, sbt.Keys.persistTraceLevel, sbt.Keys.persistLogLevel) s } diff --git a/src/androidRepo.scala b/src/androidRepo.scala index 78012bf7..24a826fe 100644 --- a/src/androidRepo.scala +++ b/src/androidRepo.scala @@ -3,17 +3,18 @@ package android import java.io.{File, InputStream} import java.net.{HttpURLConnection, URL} +import scala.collection.JavaConverters._ +import scala.concurrent.duration._ + import com.android.repository.api._ -import com.android.repository.impl.generated.v1.{LocalPackage => _, _} import com.android.repository.io.FileOp import com.android.sdklib.repository.AndroidSdkHandler import com.android.repository.api.{RemotePackage => RepoRemotePackage} import com.android.sdklib.repository.generated.repository.v1.PlatformDetailsType import com.android.sdklib.repository.installer.SdkInstallerUtil -import sbt.{IO, Logger, Using} -import collection.JavaConverters._ -import concurrent.duration._ +import sbt.{IO, Logger} +import sbt.io.Using object SdkInstaller extends TaskBase { implicit val packageOrder: Ordering[com.android.repository.api.RemotePackage] = diff --git a/src/autoPlugin.scala b/src/autoPlugin.scala index 4d04f457..1cb0103e 100644 --- a/src/autoPlugin.scala +++ b/src/autoPlugin.scala @@ -17,11 +17,6 @@ object AndroidProject extends AutoPlugin with AndroidProjectSettings { override def requires = plugins.JvmPlugin } -@deprecated("use `enablePlugins(AndroidApp)`", "1.7.0") -object AndroidPlugin extends AutoPlugin { - override def requires = AndroidProject -} - // AndroidLib should support `android:test` as well. no install, run, etc. object AndroidLib extends AutoPlugin with AndroidLibSettings { override def requires = AndroidProject diff --git a/src/commands.scala b/src/commands.scala index 2d8d1a7e..f7c0760a 100644 --- a/src/commands.scala +++ b/src/commands.scala @@ -1,23 +1,25 @@ package android +import java.io.File import java.util.Locale import com.android.ddmlib.FileListingService.FileEntry -import sbt._ -import sbt.complete.{Parser, Parsers} -import complete.DefaultParsers._ -import java.io.File - -import com.android.ddmlib._ import scala.annotation.tailrec import scala.util.Try -import language.postfixOps import scala.util.matching.Regex +import scala.sys.process._ + +import com.android.ddmlib._ + +import sbt._ +import sbt.complete.{Parser, Parsers} +import sbt.complete.DefaultParsers._ +import sbt.internal.util.ConsoleAppender object Commands { - val COLORS_ENABLED: Boolean = ConsoleLogger.formatEnabled + val COLORS_ENABLED: Boolean = ConsoleAppender.formatEnabledInEnv val LOGCAT_COMMAND = "logcat -v brief -d" var defaultDevice: Option[String] = None @@ -307,7 +309,7 @@ object Commands { val sdk = sdkpath(state) val adbPath = SdkLayout.adb(sdk).getCanonicalPath state.get(wifiState).map { ip => - val r = Seq(adbPath, "connect", ip) ! + val r = Seq(adbPath, "connect", ip).! if (r != 0) { PluginFail("failed to reconnect to ADB-over-wifi") @@ -330,7 +332,7 @@ object Commands { val d = targetDevice(sdk, state.log).get if (adbWifiOn) { state.log.info("turning ADB-over-wifi off") - Seq(adbPath, "-s", d.getSerialNumber, "usb") ! + Seq(adbPath, "-s", d.getSerialNumber, "usb").! state.remove(wifiState) } else { @@ -344,9 +346,9 @@ object Commands { if (ip.nonEmpty) { state.log.debug("device ip: %s" format ip) - Seq(adbPath, "-s", d.getSerialNumber, "tcpip", "5555") ! + Seq(adbPath, "-s", d.getSerialNumber, "tcpip", "5555").! - val r = Seq(adbPath, "connect", ip) ! + val r = Seq(adbPath, "connect", ip).! if (r != 0) PluginFail("failed to connect ADB-over-wifi") @@ -396,7 +398,7 @@ object Commands { val pluginSbt = build / "android.sbt" val plugin = s"""addSbtPlugin("org.scala-android" % "sbt-android" % "${BuildInfo.version}")""".stripMargin val version = Project.extract(state).get(sbt.Keys.sbtVersion) - val useVersion = if (compareSbtVersion(version)) version else "0.13.16" + val useVersion = if (compareSbtVersion(version)) version else "1.2.8" if ((build * "*.sbt").get.isEmpty) { IO.writeLines(pluginSbt, plugin :: Nil) } else { @@ -428,7 +430,7 @@ object Commands { " Nil" :: Nil val plat = platform.toList.flatMap(p => "" :: s"""platformTarget := "$p"""" :: Nil) - val javacOption = if (util.Properties.isJavaAtLeast("1.8")) { + val javacOption = if (scala.util.Properties.isJavaAtLeast("1.8")) { "" :: """ |javacOptions in Compile ++= "-source" :: "1.7" :: "-target" :: "1.7" :: Nil @@ -437,16 +439,16 @@ object Commands { IO.writeLines(projectBuild, buildSettings ++ plat ++ javacOption ++ libs) if (state.remainingCommands.nonEmpty) - Command.process("reload", state) + "reload" :: state else state } val createProjectSbtAction: (State,Option[String]) => State = (state,platform) => { - createProjectSbt(false, state, platform) + createProjectSbt(multi = false, state, platform) } val createMultiProjectSbtAction: (State,Option[String]) => State = (state,platform) => { - createProjectSbt(true, state, platform) + createProjectSbt(multi = true, state, platform) } val createProjectParser: State => Parser[Either[Unit, (String, String)]] = state => { @@ -656,7 +658,7 @@ object Commands { if (tagMatch.nonEmpty|| msgMatch.nonEmpty) Some(highlightMatch(tagMatch, msgMatch, l)) else None }) - val v = deviceApiLevel(d) + val _ = deviceApiLevel(d) val logcat = pidcatCommand(d) d.executeShellCommand(logcat, receiver) receiver.flush() diff --git a/src/compat.scala b/src/compat.scala new file mode 100644 index 00000000..59672953 --- /dev/null +++ b/src/compat.scala @@ -0,0 +1,6 @@ +package sbt + +package object compat { + type Load = sbt.internal.Load.type + val Load = sbt.internal.Load +} diff --git a/src/dependencies.scala b/src/dependencies.scala index 572ea544..11623aad 100644 --- a/src/dependencies.scala +++ b/src/dependencies.scala @@ -9,6 +9,7 @@ import BuildOutput._ import com.android.builder.dependency.level2.AndroidDependency import com.android.builder.model.{AndroidLibrary, JavaLibrary, MavenCoordinates} import com.android.manifmerger.ManifestProvider +import sbt.internal.BuildStructure object Dependencies { // excludes are temporary until everything/one uses libraryDependencies @@ -174,14 +175,6 @@ object Dependencies { override def hashCode(): Int = path.getCanonicalFile.hashCode } - @deprecated("`dependsOn(project)` now adds transitive settings automatically", "1.7.0") - implicit class RichProject(val project: Project) extends AnyVal { - @deprecated("use `enablePlugins(AndroidApp).dependsOn(deps)`", "1.7.0") - def androidBuildWith(deps: ProjectReference*): Project = { - project.enablePlugins(AndroidApp).dependsOn(deps map { x => x: ClasspathDep[ProjectReference] }: _*) - } - } - implicit class ModuleIDOps(id: ModuleID) { def revMatches(other: String): Boolean = { def partMatches(p: (String, String)) = p._1 == p._2 || p._1 == "+" diff --git a/src/dsl.scala b/src/dsl.scala index 50573d05..c755fb49 100644 --- a/src/dsl.scala +++ b/src/dsl.scala @@ -1,10 +1,8 @@ package android -import java.io.File - -import sbt.{Configuration, Task, Def, Setting} +import sbt.{Configuration, Def} +import Def.Setting import scala.language.experimental.macros -import scala.util.{Failure, Success, Try} package object dsl { def list[A](body: Seq[A]): List[A] = macro dsl.Macros.listImplN[A] @@ -24,100 +22,6 @@ package object dsl { def scalacFlags(config: Configuration)(opts: String*) = stringFlags(sbt.Keys.scalacOptions, config, opts) - @deprecated("use android.useLibrary", "1.7.0") - def useLibrary(library: String) = - Keys.libraryRequests += ((library, true)) - - @deprecated("use android.buildTools", "1.7.0") - def buildTools(version: String) = - Keys.buildToolsVersion := Option(version) - - private def extendVariant(key: sbt.SettingKey[Map[String,Seq[Setting[_]]]], name: String, ss: Seq[Setting[_]]) = - key := key { vs => - val ss2 = vs(name) - vs + ((name, ss2 ++ ss)) - }.value - - @deprecated("use android.extendFlavor", "1.7.0") - def extendFlavor(name: String)(ss: Setting[_]*): Setting[_] = - extendVariant(Keys.flavors, name, ss) - - @deprecated("use android.flavor", "1.7.0") - def flavor(name: String)(ss: Setting[_]*): Setting[_] = - Keys.flavors += ((name, ss)) - - @deprecated("use android.extendBuildType", "1.7.0") - def extendBuildType(name: String)(ss: Setting[_]*): Setting[_] = - extendVariant(Keys.buildTypes, name, ss) - - @deprecated("use android.buildType", "1.7.0") - def buildType(name: String)(ss: Setting[_]*) = - Keys.buildTypes += ((name, ss)) - - @deprecated("use android.buildConfig", "1.7.0") - def buildConfig(`type`: String, name: String, value: Def.Initialize[Task[String]]) = - Keys.buildConfigOptions += (value map { v => (`type`, name, v) }).value - @deprecated("use android.buildConfig", "1.7.0") - def buildConfig(`type`: String, name: String, value: String) = - Keys.buildConfigOptions += ((`type`, name, value)) - - @deprecated("use android.resValue", "1.7.0") - def resValue(`type`: String, name: String, value: String) = - Keys.resValues += ((`type`, name, value)) - @deprecated("use android.resValue", "1.7.0") - def resValue(`type`: String, name: String, value: Def.Initialize[Task[String]]) = - Keys.resValues += (value map { v => (`type`, name, v) }).value - - @deprecated("use android.signingConfig", "1.7.0") - def signingConfig(keystore: File, - alias: String, - storePass: Option[String] = None, - keyPass: Option[String] = None, - singlePass: Boolean = true, - storeType: String = "jks") = { - val sp = storePass orElse keyPass - val config = if (sp.isEmpty) { - if (singlePass) - PromptStorepassSigningConfig(keystore, alias, storeType) - else - PromptPasswordsSigningConfig(keystore, alias, storeType) - } else - PlainSigningConfig(keystore, sp.get, alias, keyPass, storeType) - - Keys.apkSigningConfig := Some(config) - } - - @deprecated("use android.apkExclude", "1.7.0") - def apkExclude(name: String*) = Keys.packagingOptions := { - val opts = Keys.packagingOptions.value - opts.copy(excludes = opts.excludes ++ name) - } - @deprecated("use android.apkPickFirst", "1.7.0") - def apkPickFirst(name: String*) = Keys.packagingOptions := { - val opts = Keys.packagingOptions.value - opts.copy(pickFirsts = opts.pickFirsts ++ name) - } - @deprecated("use android.apkMerge", "1.7.0") - def apkMerge(name: String*) = Keys.packagingOptions := { - val opts = Keys.packagingOptions.value - opts.copy(merges = opts.merges ++ name) - } - - @deprecated("use android.manifestPlaceholder", "1.7.0") - def manifestPlaceholder(key: String, value: String) = - Keys.manifestPlaceholders += ((key,value)) - @deprecated("use android.manifestPlaceholder", "1.7.0") - def manifestPlaceholder(key: String, value: Def.Initialize[Task[String]]) = - Keys.manifestPlaceholders += (value map { v => (key,v) }).value - @deprecated("use android.apkVersionName", "1.7.0") - def apkVersionName(name: String) = Keys.versionName := Option(name) - @deprecated("use android.apkVersionCode", "1.7.0") - def apkVersionCode(code: Int) = Keys.versionCode := Option(code) - @deprecated("use android.apkVersionName", "1.7.0") - def apkVersionName(name: Def.Initialize[Task[String]]) = Keys.versionName := (name map Option.apply).value - @deprecated("use android.apkVersionCode", "1.7.0") - def apkVersionCode(code: Def.Initialize[Task[Int]]) = Keys.versionCode := (code map Option.apply).value - def dexMainClassList(classes: String*) = Keys.dexMainClassesConfig := { val layout = Keys.projectLayout.value implicit val out = Keys.outputLayout.value @@ -127,13 +31,13 @@ package object dsl { } package dsl { private[android] object Macros { - import scala.reflect.macros.Context + import scala.reflect.macros.blackbox.Context def listImplN[A](c: Context)(body: c.Expr[Seq[A]])(implicit ev: c.WeakTypeTag[A]): c.Expr[List[A]] = { import c.universe._ val xs = body.tree.children if (xs.isEmpty) - c.Expr[List[A]](Apply(Select(body.tree, newTermName("toList")), Nil)) + c.Expr[List[A]](Apply(Select(body.tree, TermName("toList")), Nil)) else commonImpl(c)(body) } @@ -144,7 +48,7 @@ private[android] object Macros { import c.universe._ val xs = body.tree.children if (xs.isEmpty) - c.Expr[List[A]](Apply(Ident(newTermName("List")), body.tree :: Nil)) + c.Expr[List[A]](Apply(Ident(TermName("List")), body.tree :: Nil)) else commonImpl(c)(body) } @@ -154,12 +58,12 @@ private[android] object Macros { val seqA = c.weakTypeOf[Seq[A]] c.Expr[List[A]](body.tree.children.reduce { (a,ch) => val acc = if (a.tpe != null && a.tpe <:< ev.tpe) { - Apply(Ident(newTermName("List")), a :: Nil) + Apply(Ident(TermName("List")), a :: Nil) } else a if (ch.tpe <:< seqA) - Apply(Select(acc, newTermName("$plus$plus")), List(ch)) + Apply(Select(acc, TermName("$plus$plus")), List(ch)) else if (ch.tpe <:< ev.tpe) - Apply(Select(acc, newTermName("$colon$plus")), List(ch)) + Apply(Select(acc, TermName("$colon$plus")), List(ch)) else c.abort(ch.pos, s"Unexpected type: ${ch.tpe}, needed ${ev.tpe}") }) } diff --git a/src/package.scala b/src/package.scala index fa0b3127..c76749a2 100644 --- a/src/package.scala +++ b/src/package.scala @@ -1,13 +1,17 @@ -import sbt.{Def, _} -import sbt.Keys._ import android.Keys._ + +import sbt._ +import sbt.Keys._ + +import Def.Setting + package object android extends PluginFail { import android.Keys.Internal._ @deprecated("use `android.flavor` and `android.buildType` instead", "1.7.0") def flavorOf(p: Project, id: String, settings: Setting[_]*): Project = { val base = p.base / id - p.copy(id = id, base = base).settings(Seq( + p.withId(id).in(base).settings(Seq( projectLayout := ProjectLayout(p.base.getCanonicalFile, Some(base.getCanonicalFile)), sbt.Keys.target := base) ++ settings:_*) } diff --git a/src/parsers.scala b/src/parsers.scala index 54d3bd1c..9ecd57e2 100644 --- a/src/parsers.scala +++ b/src/parsers.scala @@ -2,19 +2,21 @@ package android import java.io.File -import sbt.complete.{Parser, Parsers} -import Parser._ -import Parsers._ +import scala.collection.JavaConverters._ +import scala.xml.{Elem, Node, NodeSeq, XML} + import sbt.{Def, State, TaskKey} +import sbt.Def.Initialize +import sbt.complete.Parser +import sbt.complete.Parser._ +import sbt.complete.Parsers._ import sbt.Defaults.loadFromContext -import Def.Initialize +import sbt.CacheImplicits.StringJsonFormat + import com.android.sdklib.repository.AndroidSdkHandler -import scala.xml.{Elem, Node, NodeSeq, XML} -import sbt.Cache.StringFormat -import sbinary.{Format, Input, Output} +import sjsonnew.{Builder, JsonFormat, Unbuilder} -import collection.JavaConverters._ /** * @author pfnguyen @@ -80,16 +82,16 @@ private[android] object parsers { token("all").map(Option.apply), token(StringBasic).examples(updates:_*)) } - private[android] implicit val sbinaryFileFormat: sbinary.Format[File] = new sbinary.Format[File] { - override def writes(out: Output, value: File): Unit = StringFormat.writes(out, value.getCanonicalPath) - override def reads(in: Input): File = sbt.file(StringFormat.reads(in)) + private[android] implicit val sjsonFileFormat: JsonFormat[File] = new JsonFormat[File] { + override def write[J](obj: File, builder: Builder[J]): Unit = StringJsonFormat.write(obj.getCanonicalPath, builder) + override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): File = sbt.file(StringJsonFormat.read(jsOpt, unbuilder)) } - def loadForParser2[P, T: Format, T2: Format] + def loadForParser2[P, T: JsonFormat, T2: JsonFormat] (task: TaskKey[T], task2: TaskKey[T2]) (f: (State, Option[T], Option[T2]) => Parser[P]): Initialize[State => Parser[P]] = loadForParserI2(task, task2)(Def.value(f)) - def loadForParserI2[P, T : Format, T2 : Format] + def loadForParserI2[P, T : JsonFormat, T2 : JsonFormat] (task: TaskKey[T], task2: TaskKey[T2]) (init: Initialize[(State, Option[T], Option[T2]) => Parser[P]]): Initialize[State => Parser[P]] = Def.setting{ diff --git a/src/proguard.scala b/src/proguard.scala index c7bb73aa..aa4cc613 100644 --- a/src/proguard.scala +++ b/src/proguard.scala @@ -4,13 +4,13 @@ import java.io.{File, FileInputStream, FileOutputStream} import java.lang.reflect.{Constructor, Method} import java.util.jar.{JarInputStream, JarOutputStream} +import scala.util.Try + import com.android.builder.core.AndroidBuilder -import sbt._ -import sbt.classpath.ClasspathUtilities -import scala.language.postfixOps -import scala.util.Try -import language.existentials +import sbt._ +import sbt.io.Using +import sbt.internal.inc.classpath.ClasspathUtilities case class ProguardInputs(injars: Seq[Attributed[File]], libraryjars: Seq[File], @@ -49,11 +49,12 @@ object ProguardUtil { if (!jarfile.data.isFile) Nil else { Using.fileInputStream(jarfile.data)(Using.jarInputStream(_) { jin => - val classes = Iterator.continually(jin.getNextJarEntry) takeWhile ( - _ != null) map (_.getName) filter { n => - // R.class (and variants) are irrelevant - n.endsWith(".class") && !n.matches(".*/R\\W+.*class") - } toList + val classes = + Iterator.continually(jin.getNextJarEntry) + .takeWhile(_ != null) + .map(_.getName) + .filter(n => n.endsWith(".class") && !n.matches(".*/R\\W+.*class")) // R.class (and variants) are irrelevant + .toList classes }) @@ -87,28 +88,27 @@ object Proguard { out.mkdirs() // TODO cache resutls of jar listing - val cacheJars = injars filter (listjar(_) exists (inPackages(_, pc))) toSet - val filtered = injars filterNot cacheJars - - val indeps = filtered map { - f => deps / (f.data.getName + "-" + - Hash.toHex(Hash(f.data.getAbsolutePath))) - } - - val todep = indeps zip filtered filter { case (dep,j) => - !dep.exists || dep.lastModified < j.data.lastModified - } - todep foreach { case (dep,j) => - st.log.info("Finding dependency references for: " + - (j.get(sbt.Keys.moduleID.key) getOrElse j.data.getName)) - IO.write(dep, ReferenceFinder(j.data, pc.map(_.replace('.','/'))) mkString "\n") - } - - val alldeps = (indeps flatMap { - dep => IO.readLines(dep) }).sortWith(_>_).distinct.mkString("\n") - - val allhash = Hash.toHex(Hash((pgConfig ++ pgOptions).mkString("\n") + - "\n" + pc.mkString(":") + "\n" + alldeps)) + val cacheJars = injars.filter(listjar(_).exists(inPackages(_, pc))).toSet + val filtered = injars.filterNot(cacheJars) + + val indeps = filtered.map(f => deps / (f.data.getName + "-" + Hash.toHex(Hash(f.data.getAbsolutePath)))) + + indeps + .zip(filtered) + .filter { case (dep,j) => !dep.exists || dep.lastModified < j.data.lastModified } + .foreach { case (dep,j) => + st.log.info("Finding dependency references for: " + (j.get(sbt.Keys.moduleID.key) getOrElse j.data.getName)) + IO.write(dep, ReferenceFinder(j.data, pc.map(_.replace('.','/'))) mkString "\n") + } + + val alldeps = + indeps + .flatMap(dep => IO.readLines(dep)) + .sortWith(_>_) + .distinct + .mkString("\n") + + val allhash = Hash.toHex(Hash((pgConfig ++ pgOptions).mkString("\n") + "\n" + pc.mkString(":") + "\n" + alldeps)) val cacheJar = out / ("proguard-cache-" + allhash + ".jar") FileFunction.cached(st.cacheDirectory / s"cacheJar-$allhash", FilesInfo.hash) { in => diff --git a/src/retrolambda.scala b/src/retrolambda.scala index 0b1fdc6b..f40a8984 100644 --- a/src/retrolambda.scala +++ b/src/retrolambda.scala @@ -4,7 +4,8 @@ import java.io.FileInputStream import java.nio.ByteBuffer import sbt._ -import language.postfixOps +import sbt.io.Using +import sbt.util.CacheStoreFactory import net.orfjackal.retrolambda.{Main => RMain, SystemPropertiesConfig, Retrolambda} @@ -14,6 +15,24 @@ import net.orfjackal.retrolambda.{Main => RMain, SystemPropertiesConfig, Retrola object RetrolambdaSupport { def isAvailable: Boolean = RMain.isRunningJava8 def processedJar(target: File) = target / "retrolambda-processed.jar" + def jarUsesJava8(jar: File): Boolean = { + Using.fileInputStream(jar)(Using.jarInputStream(_) { jin => + val buf = Array.ofDim[Byte](8) + Iterator.continually(jin.getNextJarEntry) takeWhile (_ != null) exists { j => + if (j.getName.endsWith(".class")) { + jin.read(buf) + jin.closeEntry() + val b = ByteBuffer.wrap(buf) + val magic = b.getInt() + if (magic != 0xcafebabe) + PluginFail("Invalid java class file: " + j.getName) + val _ = b.getShort() + val major = b.getShort() + major >= 52 // java8 + } else false + } + }) + } def apply(target: File, classpath: Seq[File], forkClasspath: Seq[File], bootClasspath: Seq[File], s: sbt.Keys.TaskStreams): Seq[File] = synchronized { val cp = bootClasspath ++ classpath @@ -22,7 +41,7 @@ object RetrolambdaSupport { val finalJar = processedJar(target) indir.mkdirs() outdir.mkdirs() - val java8jars = classpath filter Java8Detector.apply + val java8jars = classpath filter jarUsesJava8 s.log.debug("Java8 jars detected for retrolambda processing: " + java8jars) FileFunction.cached(s.cacheDirectory / "retrolambda-jars", FilesInfo.lastModified) { in => val currentfiles = in.foldLeft(Set.empty[File])(_ ++ IO.unzip(_, indir)) @@ -31,7 +50,10 @@ object RetrolambdaSupport { }(java8jars.toSet) if (java8jars.nonEmpty) { - FileFunction.cached(s.cacheDirectory / ("retro-" + target.getName))(FilesInfo.lastModified, FilesInfo.exists) { (in1,out) => + FileFunction.cached( + CacheStoreFactory(s.cacheDirectory / ("retro-" + target.getName)), + FilesInfo.lastModified, + FilesInfo.exists) { (in1,out) => val removedfiles = in1.removed.toList.flatMap(Path.rebase(indir, outdir)(_).toList) removedfiles.foreach { r => val parent = r.getParentFile @@ -39,12 +61,9 @@ object RetrolambdaSupport { IO.delete((parent * s"$base$$$$Lambda$$*.class").get) } val in = in1.checked - val options = ForkOptions( - runJVMOptions = Seq( - "-noverify", - "-classpath", forkClasspath map ( - _.getAbsoluteFile) mkString java.io.File.pathSeparator - )) + val options = + ForkOptions() + .withRunJVMOptions(Vector("-noverify", "-classpath", forkClasspath.map(_.getAbsoluteFile).mkString(java.io.File.pathSeparator))) val config = s.cacheDirectory / "retro-config.properties" val p = new java.util.Properties @@ -62,8 +81,8 @@ object RetrolambdaSupport { IO.delete(config) if (r != 0) PluginFail(s"Retrolambda failure: exit $r") in - }((indir ** "*.class" get).toSet) - IO.jar((PathFinder(outdir) ***) pair rebase(outdir, "") filter ( + }((indir ** "*.class").get.toSet) + IO.jar(PathFinder(outdir).allPaths pair Path.rebase(outdir, "") filter ( _._1.getName endsWith ".class"), finalJar, new java.util.jar.Manifest) finalJar :: (classpath.toSet -- java8jars).toList } else { @@ -72,26 +91,7 @@ object RetrolambdaSupport { } } -object Java8Detector { - def apply(jar: File): Boolean = { - Using.fileInputStream(jar)(Using.jarInputStream(_) { jin => - val buf = Array.ofDim[Byte](8) - Iterator.continually(jin.getNextJarEntry) takeWhile (_ != null) exists { j => - if (j.getName.endsWith(".class")) { - jin.read(buf) - jin.closeEntry() - val b = ByteBuffer.wrap(buf) - val magic = b.getInt() - if (magic != 0xcafebabe) - PluginFail("Invalid java class file: " + j.getName) - val _ = b.getShort() - val major = b.getShort() - major >= 52 // java8 - } else false - } - }) - } -} + object RetroMain { def main(args: Array[String]): Unit = { diff --git a/src/sdkInterfaces.scala b/src/sdkInterfaces.scala index b5448682..aa372dd2 100644 --- a/src/sdkInterfaces.scala +++ b/src/sdkInterfaces.scala @@ -159,11 +159,12 @@ object SbtJavaProcessExecutor extends JavaProcessExecutor { case SbtProcessOutputHandler(logger) => sbt.LoggedOutput(logger) case _ => sbt.CustomOutput(processOutputHandler.createOutput.getStandardOutput) }) - val options = ForkOptions( - envVars = javaProcessInfo.getEnvironment.asScala.map { case ((x, y)) => x -> y.toString }.toMap, - outputStrategy = outputStrategy, - runJVMOptions = javaProcessInfo.getJvmArgs.asScala ++ - ("-cp" :: javaProcessInfo.getClasspath :: Nil)) + val options = + ForkOptions() + .withEnvVars(javaProcessInfo.getEnvironment.asScala.map { case ((x, y)) => x -> y.toString }.toMap) + .withOutputStrategy(outputStrategy) + .withRunJVMOptions(javaProcessInfo.getJvmArgs.asScala.toVector ++ ("-cp" :: javaProcessInfo.getClasspath :: Nil)) + val args = (javaProcessInfo.getMainClass :: Nil) ++ javaProcessInfo.getArgs.asScala val r = Fork.java(options, args) diff --git a/src/tasks.scala b/src/tasks.scala index e0a56b0f..abdbbdd1 100644 --- a/src/tasks.scala +++ b/src/tasks.scala @@ -1,33 +1,37 @@ package android -import com.android.builder.internal.ClassFieldImpl -import com.android.manifmerger.ManifestMerger2 -import sbt._ -import sbt.Keys._ +import java.util.Properties +import java.io.File +import java.net.URLEncoder import scala.collection.JavaConverters._ import scala.util.Try import scala.xml._ -import language.postfixOps -import java.util.Properties -import java.io.File +import scala.sys.process._ import com.android.builder.core._ -import com.android.ddmlib.{DdmPreferences, IDevice} -import com.android.ddmlib.testrunner.ITestRunListener +import com.android.builder.compiling.{BuildConfigGenerator, ResValueGenerator} +import com.android.builder.internal.ClassFieldImpl +import com.android.manifmerger.ManifestMerger2 +import com.android.sdklib.repository.AndroidSdkHandler import com.android.sdklib.{IAndroidTarget, SdkVersionInfo} import com.android.sdklib.BuildToolInfo.PathId +import com.android.ddmlib.{DdmPreferences, IDevice} +import com.android.ddmlib.testrunner.ITestRunListener + + +import sbt._ +import sbt.Keys._ +import sbt.internal.BuildStructure + import Keys._ import Keys.Internal._ import Dependencies.{AutoLibraryProject => _, LibraryProject => _, _} -import com.android.builder.compiling.{BuildConfigGenerator, ResValueGenerator} -import java.net.URLEncoder + import Resources.{ANDROID_NS, resourceUrl} -import com.android.builder.model.AaptOptions -import com.android.builder.packaging.PackagingUtils -import com.android.sdklib.repository.AndroidSdkHandler -import com.google.common.base.Predicates +import android.BuildOutput.Converter + object Tasks extends TaskBase { val TOOLS_NS = "http://schemas.android.com/tools" @@ -54,7 +58,7 @@ object Tasks extends TaskBase { } val buildConfigGeneratorTaskDef = Def.task { - val t = platformTarget.value + val _ = platformTarget.value val layout = projectLayout.value val l = libraryProjects.value val p = packageForR.value @@ -78,7 +82,7 @@ object Tasks extends TaskBase { } b.generate() } - layout.gen ** "BuildConfig.java" get + (layout.gen ** "BuildConfig.java").get } def moduleForFile(u: UpdateReport, f: File): ModuleID = { @@ -87,13 +91,13 @@ object Tasks extends TaskBase { val map: Map[File,ModuleID] = { val fm = u.configurations.flatMap { c => c.modules.flatMap { mr => - val module = mr.module.copy(configurations = Some(c.configuration)) + val module = mr.module.withConfigurations(Some(c.configuration.name)) mr.artifacts.map { case (_, file) => (file, module) } } } fm.foldLeft(Map.empty[File,ModuleID]) { case (m, (k, mid)) => val mid2 = m.getOrElse(k, mid) - m.updated(k, mid2.copy(configurations = concat(mid.configurations, mid2.configurations))) + m.updated(k, mid2.withConfigurations(concat(mid.configurations, mid2.configurations))) } } @@ -101,7 +105,7 @@ object Tasks extends TaskBase { } // takeWhile hack to bypass cross versions, I hope no real artifacts have // underscores in the name as a delimiter - def moduleString(m: ModuleID) = + def moduleString(m: ModuleID): String = m.organization + ":" + m.name.takeWhile(_ != '_') val aarsTaskDef = Def.task { @@ -187,7 +191,7 @@ object Tasks extends TaskBase { val fs = ns.map(file) fs.forall(_.exists) } - val lib = AarLibrary(dest) + val _ = AarLibrary(dest) if (dest.lastModified < aar.lastModified || !checkmanifest(dest)) { IO.delete(dest) val mfile = Dependencies.moduleIdFile(dest) @@ -207,7 +211,7 @@ object Tasks extends TaskBase { val o = outputLayout.value val isLib = libraryProject.value val bldr = builder.value - val logger = ilogger.value + val _ = ilogger.value val debug = apkbuildDebug.value val cfgs = resConfigs.value val aparams = aaptAdditionalParams.value @@ -222,14 +226,13 @@ object Tasks extends TaskBase { // TODO collect resources from apklibs and aars // doCollectResources(bldr, true, true, Seq.empty, lib.layout, // logger, file("/"), s) - Resources.aapt(bldr(s.log), lib.getManifest, null, aparams, cfgs, Seq.empty, true, debug(), - pseudo, lib.getResFolder, lib.getAssetsFolder, null, + Resources.aapt(bldr(s.log), lib.getManifest, null, aparams, cfgs, Seq.empty, lib = true, debug = debug(), + pseudoLocalize = pseudo, lib.getResFolder, lib.getAssetsFolder, null, lib.layout.gen, lib.getProguardRules, layout.aaptTemp, s.log) def copyDirectory(src: File, dst: File) { - IO.copy(((src ***) --- (src ** "R.txt")) pair Path.rebase(src, dst), - false, true) + IO.copy((src.allPaths --- (src ** "R.txt")) pair Path.rebase(src, dst), overwrite = false, preserveLastModified = true, preserveExecutable = true) } if (isLib) copyDirectory(lib.layout.gen, layout.gen) @@ -248,7 +251,7 @@ object Tasks extends TaskBase { val s = streams.value val agg = aaptAggregate.value - implicit val output = o + implicit val output: Converter = o val libs = u.matching(artifactFilter(`type` = "apklib")) val dest = layout.apklibs val deps = d.filterNot(_.configurations.exists( @@ -264,15 +267,14 @@ object Tasks extends TaskBase { IO.unzip(l, d) Resources.aapt(agg.builder(s.log), lib.getManifest, null, - agg.additionalParams, agg.resConfigs, Seq.empty, true, agg.debug, - agg.pseudoLocalize, + agg.additionalParams, agg.resConfigs, Seq.empty, lib = true, debug = agg.debug, + pseudoLocalize = agg.pseudoLocalize, lib.getResFolder, lib.getAssetsFolder, null, lib.layout.gen, lib.getProguardRules, layout.aaptTemp, s.log) } def copyDirectory(src: File, dst: File) { - IO.copy(((src ***) --- (src ** "R.txt")) pair Path.rebase(src, dst), - false, true) + IO.copy((src.allPaths --- (src ** "R.txt")) pair Path.rebase(src, dst), overwrite = false, preserveLastModified = true, preserveExecutable = true) } if (isLib) copyDirectory(lib.layout.gen, layout.gen) @@ -285,15 +287,14 @@ object Tasks extends TaskBase { } } - implicit class OrgArtRepOps(report: OrganizationArtifactReport) - { - def ids = report.modules map(_.module) + implicit class OrgArtRepOps(report: OrganizationArtifactReport) { + def ids: Seq[ModuleID] = report.modules map(_.module) - def latest = ids.max.revision + def latest: String = ids.max.revision } - implicit val revOrdering = new Ordering[ModuleID] { - def comparePart(part: (String, String)) = { + implicit val revOrdering: Ordering[ModuleID] = new Ordering[ModuleID] { + def comparePart(part: (String, String)): Int = { val (a, b) = part Try((a.toInt, b.toInt)) match { case scala.util.Success((l, r)) ⇒ @@ -303,7 +304,7 @@ object Tasks extends TaskBase { } } - def compare(a: ModuleID, b: ModuleID) = { + def compare(a: ModuleID, b: ModuleID): Int = { val aParts = a.revision.split('.') val bParts = b.revision.split('.') aParts.zip(bParts) @@ -314,16 +315,16 @@ object Tasks extends TaskBase { } val resolvedAars = Def.task { - (update in Compile).value.configuration("compile") + (update in Compile).value.configuration(ConfigRef("compile")) .map(_.details) .getOrElse(Nil) .filter(_.modules.exists(_.artifacts.exists(_._1.`type` == "aar"))) } val checkAarsTaskDef = Def.task { - implicit val log = streams.value.log - implicit val struct = buildStructure.value - implicit val projects = thisProjectRef.value.deepDeps + implicit val log: Logger = streams.value.log + implicit val struct: BuildStructure = buildStructure.value + implicit val projects: Seq[ProjectRef] = thisProjectRef.value.deepDeps val resolved = resolvedAars.value transitiveAars.value .collect { case a: AarLibrary ⇒ a → resolved.find(_.name == a.moduleID.name) } @@ -331,8 +332,9 @@ object Tasks extends TaskBase { .foreach(reportIncompatibleAars) } - def reportIncompatibleAars(aar: OrganizationArtifactReport) - (implicit log: Logger, struct: BuildStructure, projects: Seq[ProjectRef]) = { + def reportIncompatibleAars + (aar: OrganizationArtifactReport) + (implicit log: Logger, struct: BuildStructure, projects: Seq[ProjectRef]): Unit = { log.warn(s"aar ${aar.name} older than latest version ${aar.latest}") aar.ids foreach { id ⇒ val dpds = projects filter(_.dependsOn(id)) map(_.project) @@ -368,8 +370,9 @@ object Tasks extends TaskBase { def ndkbuild(manager: AndroidSdkHandler, layout: ProjectLayout, args: Seq[String], envs: Seq[(String,String)], ndkHome: Option[String], srcs: File, - showProgress: Boolean, log: Logger, debug: Boolean)(implicit m: BuildOutput.Converter) = { - val hasJni = (layout.jni ** "Android.mk" get).nonEmpty + showProgress: Boolean, log: Logger, debug: Boolean) + (implicit m: BuildOutput.Converter): Option[File] = { + val hasJni = (layout.jni ** "Android.mk").get.nonEmpty if (hasJni) { val ndk = ndkHome.getOrElse { val bundlePath = SdkLayout.ndkBundle(manager.getLocation.getAbsolutePath) @@ -377,7 +380,7 @@ object Tasks extends TaskBase { bundlePath.getAbsolutePath } val inputs = (layout.jni ** FileOnlyFilter).get.toSet - FileFunction.cached(layout.ndkObj, FilesInfo.lastModified) { in => + FileFunction.cached(layout.ndkObj, FilesInfo.lastModified) { _ => val env = Seq("NDK_PROJECT_PATH" -> (layout.jni / "..").getAbsolutePath, "NDK_OUT" -> layout.ndkObj.getAbsolutePath, "NDK_LIBS_OUT" -> layout.ndkBin.getAbsolutePath, @@ -393,7 +396,7 @@ object Tasks extends TaskBase { if (debug) "NDK_DEBUG=1" else "NDK_DEBUG=0" ) ++ args - val rc = Process(ndkBuildInvocation, layout.base, env: _*) ! + val rc = Process(ndkBuildInvocation, layout.base, env: _*).! if (rc != 0) PluginFail("ndk-build failed!") @@ -406,7 +409,7 @@ object Tasks extends TaskBase { val ndkJavahTaskDef = Def.task { val src = (sourceManaged in Compile).value - val c = (compile in Compile).value + val _ = (compile in Compile).value val classes = (classDirectory in Compile).value val cp = (fullClasspath in Compile).value val boot = bootClasspath.value @@ -422,12 +425,12 @@ object Tasks extends TaskBase { s.log.debug(javah mkString " ") - val rc = javah ! + val rc = javah.! if (rc != 0) PluginFail("Failed to execute: " + (javah mkString " ")) - src ** "*.h" get + (src ** "*.h").get } else Seq.empty } val ndkbuildAggregateTaskDef = Def.task { @@ -445,7 +448,7 @@ object Tasks extends TaskBase { val s = streams.value val debug = apkbuildDebug.value - implicit val output = o + implicit val output: Converter = o val subndk = libs flatMap { l => ndkbuild(sdk, l.layout, agg.args, agg.env, agg.path, srcs, showProgress, s.log, debug()).toSeq } @@ -455,12 +458,12 @@ object Tasks extends TaskBase { val collectProjectJniTaskDef = Def.task { val layout = projectLayout.value - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value ndkBuild.value ++ Seq(layout.jniLibs, layout.rsLib).filter(_.isDirectory) } val collectJniTaskDef = Def.task { - implicit val out = outputLayout.value + implicit val output: Converter = outputLayout.value def libJni(lib: LibraryDependency): Seq[File] = Seq(lib.getJniFolder, lib.layout.rsLib).filter(_.isDirectory) ++ lib.getLibraryDependencies.asScala.flatMap(l => libJni(l.asInstanceOf[LibraryDependency])) @@ -486,7 +489,7 @@ object Tasks extends TaskBase { val c = aaptPngCrunch.value val c9 = aapt9PngCrunch.value val s = streams.value - implicit val output = cra.outputLayout + implicit val output: Converter = cra.outputLayout val layout = cra.projectLayout val er = cra.extraResDirectories val ea = cra.extraAssetDirectories @@ -496,7 +499,7 @@ object Tasks extends TaskBase { SdkVersionInfo.getApiByBuildCode(minSdk, true) // hack because cached can only return Set[File] val out = (layout.mergedAssets, layout.mergedRes) - val assets = layout.assets +: ea.map(_.getCanonicalFile).distinct flatMap (_ ** FileOnlyFilter get) + val assets = layout.assets +: ea.map(_.getCanonicalFile).distinct.flatMap(a => (a ** FileOnlyFilter).get) withCachedRes(s, "collect-resources-task", assets ++ normalres(layout, er, libs), genres(layout, libs)) { val res = Resources.doCollectResources(bldr(s.log), cra.packageForR, minLevel, noTestApk, isLib, libs, layout, ea, layout.generatedRes +: er, rv, c, c9, logger(s.log), @@ -510,18 +513,18 @@ object Tasks extends TaskBase { val packageApklibMappings = Def.task { val layout = projectLayout.value - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value import layout._ - (PathFinder(layout.processedManifest) pair flat) ++ - (PathFinder(javaSource) ** "*.java" pair rebase(javaSource, "src")) ++ - (PathFinder(scalaSource) ** "*.scala" pair rebase(scalaSource, "src")) ++ - ((PathFinder(libs) ***) pair rebase(libs, "libs")) ++ - ((PathFinder(res) ***) pair rebase(res, "res")) ++ - ((PathFinder(assets) ***) pair rebase(assets, "assets")) + (PathFinder(layout.processedManifest) pair Path.flat) ++ + (PathFinder(javaSource) ** "*.java" pair Path.rebase(javaSource, "src")) ++ + (PathFinder(scalaSource) ** "*.scala" pair Path.rebase(scalaSource, "src")) ++ + (PathFinder(libs).allPaths pair Path.rebase(libs, "libs")) ++ + (PathFinder(res).allPaths pair Path.rebase(res, "res")) ++ + (PathFinder(assets).allPaths pair Path.rebase(assets, "assets")) } val packageApklibTaskDef = Def.task { - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value val outfile = projectLayout.value.outputApklibFile(name.value) streams.value.log.info("Packaging " + outfile.getName) val mapping = (mappings in packageApklib).value @@ -530,7 +533,7 @@ object Tasks extends TaskBase { } val packageAarMappings = Def.task { - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value val layout = projectLayout.value import layout._ @@ -539,20 +542,20 @@ object Tasks extends TaskBase { val rsLibs = layout.rsLib val rsRes = layout.rsRes - (PathFinder(layout.processedManifest) pair flat) ++ - (PathFinder(layout.rTxt) pair flat) ++ - (PathFinder(layout.proguardTxt) pair flat) ++ - (PathFinder(j) pair flat) ++ - ((PathFinder(libs) ** "*.jar") pair rebase(libs, "libs")) ++ - ((PathFinder(rsLibs) * "*.jar") pair rebase(rsLibs, "libs")) ++ - ((PathFinder(res) ***) pair rebase(res, "res")) ++ - ((PathFinder(rsRes) ***) pair rebase(rsRes, "res")) ++ - ((PathFinder(assets) ***) pair rebase(assets, "assets")) ++ - so.flatMap { d => (PathFinder(d) ** "*.so") pair rebase(d, "jni") } + (PathFinder(layout.processedManifest) pair Path.flat) ++ + (PathFinder(layout.rTxt) pair Path.flat) ++ + (PathFinder(layout.proguardTxt) pair Path.flat) ++ + (PathFinder(j) pair Path.flat) ++ + ((PathFinder(libs) ** "*.jar") pair Path.rebase(libs, "libs")) ++ + ((PathFinder(rsLibs) * "*.jar") pair Path.rebase(rsLibs, "libs")) ++ + (PathFinder(res).allPaths pair Path.rebase(res, "res")) ++ + (PathFinder(rsRes).allPaths pair Path.rebase(rsRes, "res")) ++ + (PathFinder(assets).allPaths pair Path.rebase(assets, "assets")) ++ + so.flatMap { d => (PathFinder(d) ** "*.so") pair Path.rebase(d, "jni") } } val packageAarTaskDef = Def.task { - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value val outfile = projectLayout.value.outputAarFile(name.value) val mapping = (mappings in packageAar).value streams.value.log.info("Packaging " + outfile.getName) @@ -573,7 +576,7 @@ object Tasks extends TaskBase { val libs = libraryProjects.value val s = streams.value - implicit val o = output + implicit val o: Converter = output val p = layout.resApk(agg.debug) withCachedRes(s, p.getName, layout.manifest +: normalres(layout, extrares, libs), genres(layout, libs)) { layout.proguardTxt.getAbsolutePath @@ -591,18 +594,18 @@ object Tasks extends TaskBase { // collect un-merged resources for cached(), // post-collectResources has modified timestamps // this breaks for `extraResDirectories` in sub projects - def normalres(layout: ProjectLayout, extrares: Seq[File], libs: Seq[LibraryDependency]) = - (libs flatMap { _.getResFolder ** FileOnlyFilter get }) ++ - (layout.res ** FileOnlyFilter get) ++ - (extrares.map(_.getCanonicalFile).distinct flatMap (_ ** FileOnlyFilter get)) + def normalres(layout: ProjectLayout, extrares: Seq[File], libs: Seq[LibraryDependency]): Seq[File] = + libs.flatMap(l => (l.getResFolder ** FileOnlyFilter).get) ++ + (layout.res ** FileOnlyFilter).get ++ + extrares.map(_.getCanonicalFile).distinct.flatMap(a => (a ** FileOnlyFilter).get) def genres(layout: ProjectLayout, libs: Seq[LibraryDependency]) - (implicit out: BuildOutput.Converter) = + (implicit out: BuildOutput.Converter): Seq[File] = (libs flatMap { case lp: LibraryProject => - lp.layout.generatedRes ** FileOnlyFilter get + (lp.layout.generatedRes ** FileOnlyFilter).get case _ => Nil - }) ++ (layout.generatedRes ** FileOnlyFilter get) + }) ++ (layout.generatedRes ** FileOnlyFilter).get val apkbuildAggregateTaskDef = Def.task { Aggregate.Apkbuild(packagingOptions.value, @@ -612,7 +615,7 @@ object Tasks extends TaskBase { } val apkbuildTaskDef = Def.task { - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value val layout = projectLayout.value val a = apkbuildAggregate.value val n = name.value @@ -635,13 +638,13 @@ object Tasks extends TaskBase { val o = outputLayout.value val s = streams.value - implicit val output = o + implicit val output: Converter = o if (d()) { s.log.info("Debug package does not need signing: " + a.getName) a } else { c map { cfg => - import SignJar._ + import SignAndroidJar._ val signed = l.signedApk(a) val options = Seq( storeType(cfg.storeType) , storePassword(cfg.storePass) @@ -652,7 +655,7 @@ object Tasks extends TaskBase { val kp = cfg.keyPass map { p => keyPassword(p) } sign(a, cfg.alias, options ++ kp) { (jarsigner, args) => (jarsigner +: (args ++ Seq( - "-digestalg", "SHA1", "-sigalg", "MD5withRSA"))) ! + "-digestalg", "SHA1", "-sigalg", "MD5withRSA"))).! } s.log.info("Signed: " + signed.getName) @@ -672,7 +675,7 @@ object Tasks extends TaskBase { val o = outputLayout.value val s = streams.value - implicit val output = o + implicit val output: Converter = o if (r.getName.contains("-unsigned")) { s.log.warn("Package needs signing and zipaligning: " + r.getName) a.delete() @@ -680,10 +683,10 @@ object Tasks extends TaskBase { } else { val aligned = l.alignedApk(r) - val checkalign = Seq(z, "-c", "-p", "4", r.getAbsolutePath) ! + val checkalign = Seq(z, "-c", "-p", "4", r.getAbsolutePath).! if (checkalign != 0) { - val rv = Seq(z, "-f", "-p", "4", r.getAbsolutePath, aligned.getAbsolutePath) ! + val rv = Seq(z, "-f", "-p", "4", r.getAbsolutePath, aligned.getAbsolutePath).! if (rv != 0) { PluginFail("zipalign failed") @@ -701,36 +704,38 @@ object Tasks extends TaskBase { } } - val renderscriptTaskDef = Def.task { - implicit val output = outputLayout.value - val layout = projectLayout.value - val scripts = (layout.renderscript ** "*.rs").get - - FileFunction.cached(streams.value.cacheDirectory / "rs-gen", FilesInfo.lastModified) { in => - IO.delete(layout.rsBin) - val target = Try(rsTargetApi.value.toInt).getOrElse(11) max 11 - val abis = ndkAbiFilter.value.toSet - val abiFilter = if (abis.isEmpty) null else abis.asJava - val bldr = builder.value(streams.value.log) - bldr.compileAllRenderscriptFiles(Seq(layout.renderscript).asJava, - List.empty.asJava, layout.rsSrc, layout.rsRes, layout.rsObj, - layout.rsLib, target, false, rsOptimLevel.value, false, - rsSupportMode.value, abiFilter, - SbtProcessOutputHandler(streams.value.log)) - - if (rsSupportMode.value) { // copy support library - val in = SdkLayout.renderscriptSupportLibFile(buildToolInfo.value) - val out = layout.rsLib - IO.copy( - (in * "*.jar" pair rebase(in, out)) ++ - (in / "packaged" ** "*.so" pair rebase(in / "packaged", out)) - ) - } - (layout.rsBin ***).get.filter(_.isFile).toSet - }(scripts.toSet) + val renderscriptTaskDef = + Def.task { + val str = streams.value + implicit val output: Converter = outputLayout.value + val layout = projectLayout.value + val scripts = (layout.renderscript ** "*.rs").get + + FileFunction.cached(str.cacheDirectory / "rs-gen", FilesInfo.lastModified) { _ => + IO.delete(layout.rsBin) + val target = Try(rsTargetApi.value.toInt).getOrElse(11) max 11 + val abis = ndkAbiFilter.value.toSet + val abiFilter = if (abis.isEmpty) null else abis.asJava + val bldr = builder.value(str.log) + bldr.compileAllRenderscriptFiles(Seq(layout.renderscript).asJava, + List.empty.asJava, layout.rsSrc, layout.rsRes, layout.rsObj, + layout.rsLib, target, false, rsOptimLevel.value, false, + rsSupportMode.value, abiFilter, + SbtProcessOutputHandler(str.log)) + + if (rsSupportMode.value) { // copy support library + val in = SdkLayout.renderscriptSupportLibFile(buildToolInfo.value) + val out = layout.rsLib + IO.copy( + (in * "*.jar" pair Path.rebase(in, out)) ++ + (in / "packaged" ** "*.so" pair Path.rebase(in / "packaged", out)) + ) + } + layout.rsBin.allPaths.get.filter(_.isFile).toSet + }(scripts.toSet) - (layout.rsSrc ** "*.java").get - } + (layout.rsSrc ** "*.java").get + } val aidlTaskDef = Def.task { val s = sdkPath.value @@ -742,10 +747,10 @@ object Tasks extends TaskBase { val tools = Option(m.getLatestBuildTool(SbtAndroidProgressIndicator(l.log), false)) val aidl = tools map (_.getPath(PathId.AIDL)) getOrElse SdkLayout.aidl(s).getCanonicalPath val frameworkAidl = p.getTarget.getPath(IAndroidTarget.ANDROID_AIDL) - val aidls = layout.aidl ** "*.aidl" get + val aidls = (layout.aidl ** "*.aidl").get aidls flatMap { idl => - val out = layout.gen ** (idl.getName.stripSuffix(".aidl") + ".java") get + val out = (layout.gen ** (idl.getName.stripSuffix(".aidl") + ".java")).get val cmd = Seq(aidl, "-p" + frameworkAidl, "-o" + layout.gen.getAbsolutePath, @@ -754,12 +759,12 @@ object Tasks extends TaskBase { // TODO FIXME this doesn't account for other dependencies if (out.isEmpty || (out exists { idl.lastModified > _.lastModified })) { - val r = cmd ! + val r = cmd.! if (r != 0) PluginFail("aidl failed") - layout.gen ** (idl.getName.stripSuffix(".aidl") + ".java") get + (layout.gen ** (idl.getName.stripSuffix(".aidl") + ".java")).get } else out } } @@ -774,7 +779,7 @@ object Tasks extends TaskBase { val layout = projectLayout.value val noTestApk = debugIncludesTests.?.value.getOrElse(false) val s = streams.value - implicit val o = outputLayout.value + implicit val o: Converter = outputLayout.value val pkg = a.applicationId val ph = a.placeholders: Map[String,Object] val vc = a.versionCode @@ -788,7 +793,7 @@ object Tasks extends TaskBase { try { bldr(s.log).mergeManifestsForApplication(layout.manifest, a.overlays.filter(_.isFile).asJava, if (merge && !isLib) libs.asJava else Seq.empty.asJava, - pkg, vc getOrElse -1, vn orNull, minSdk.toString, sdk.toString, null, + pkg, vc getOrElse -1, vn.orNull, minSdk.toString, sdk.toString, null, output.getAbsolutePath, null, null, if (isLib) ManifestMerger2.MergeType.LIBRARY else @@ -843,7 +848,7 @@ object Tasks extends TaskBase { } else top } - XML.save(output.getAbsolutePath, instrumentTag(runnerLibTag(top)), "utf-8", true, null) + XML.save(output.getAbsolutePath, instrumentTag(runnerLibTag(top)), "utf-8", xmlDecl = true, null) } output } @@ -860,7 +865,7 @@ object Tasks extends TaskBase { val libs = libraryProjects.value val s = streams.value - implicit val output = o + implicit val output: Converter = o layout.proguardTxt layout.proguardTxt.getParentFile.mkdirs() @@ -874,12 +879,12 @@ object Tasks extends TaskBase { Resources.aapt(agg.builder(s.log), manif, pkg, agg.additionalParams, agg.resConfigs, libs, lib, agg.debug, agg.pseudoLocalize, res, assets, null, layout.gen, layout.proguardTxt, layout.aaptTemp, s.log) - (layout.gen ** "R.java" get) ++ (layout.gen ** "Manifest.java" get) toSet + ((layout.gen ** "R.java").get ++ (layout.gen ** "Manifest.java").get).toSet } } def withCachedRes(s: sbt.Keys.TaskStreams, tag: String, inStamp: Seq[File], - inHash: Seq[File])(body: => Set[File]) = { + inHash: Seq[File])(body: => Set[File]): Seq[File] = { var dirty = false if (inStamp.isEmpty && inHash.isEmpty) body.toSeq else { (FileFunction.cached(s.cacheDirectory / tag, FilesInfo.lastModified) { _ => @@ -901,7 +906,7 @@ object Tasks extends TaskBase { val txa = transitiveAars.value val s = streams.value - implicit val output = out + implicit val output: Converter = out val proguardTxt = layout.proguardTxt val proguardProject = layout.proguard @@ -931,7 +936,7 @@ object Tasks extends TaskBase { } val dexMainClassesConfigTaskDef = Def.task { - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value if (libraryProject.value) PluginFail("This project cannot dex, it has set 'libraryProject := true'") Dex.dexMainClassesConfig( @@ -965,7 +970,7 @@ object Tasks extends TaskBase { val debug = apkbuildDebug.value val s = streams.value - implicit val output = o + implicit val output: Converter = o Dex.dexInputs(progOut, in, pa, ra, multiDex, b.dex, deps, b.classesJar, debug(), s) } @@ -997,14 +1002,14 @@ object Tasks extends TaskBase { val d = apkbuildDebug.value val s = streams.value - implicit val output = o + implicit val output: Converter = o if (lib) PluginFail("This project cannot dex, it has set 'libraryProject := true'") Dex.dex(bldr(s.log), dexOpts, pd, None /* unused, left for compat */, legacy, lib, bin.dex, shards, d(), s) } val predexTaskDef = Def.task { - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value val layout = projectLayout.value val opts = dexAggregate.value val inputs = opts.inputs._2 @@ -1033,7 +1038,7 @@ object Tasks extends TaskBase { val dbg = apkbuildDebug.value val st = streams.value - implicit val output = o + implicit val output: Converter = o Proguard.proguardInputs( (pa.useProguard && !dbg()) || (pa.useProguardInDebug && dbg()), pa.proguardOptions, pa.proguardConfig, @@ -1042,17 +1047,18 @@ object Tasks extends TaskBase { val resourceShrinkerTaskDef = Def.task { val jar = proguard.value - implicit val out = outputLayout.value + implicit val output: Converter = outputLayout.value val resApk = packageResources.value val doShrink = shrinkResources.value val layout = projectLayout.value val log = streams.value.log import com.android.build.gradle.tasks.ResourceUsageAnalyzer + val procMan = processManifest.value if (jar.isDefined && doShrink && !ResourceUsageAnalyzer.TWO_PASS_AAPT) { val shrunkResApk = resApk.getParentFile / ("shrunk-" + resApk.getName) val resTarget = layout.mergedRes val analyzer = new ResourceUsageAnalyzer( - layout.gen, jar.get, processManifest.value, null, resTarget, null) + layout.gen, jar.get, procMan, null, resTarget, null) analyzer.analyze() analyzer.rewriteResourceZip(resApk, shrunkResApk) val unused = analyzer.getUnusedResourceCount @@ -1086,14 +1092,14 @@ object Tasks extends TaskBase { val ra = retrolambdaAggregate.value val s = streams.value - implicit val o = output + implicit val o: Converter = output Proguard.proguard(a, bldr(s.log), l, inputs, d(), b.proguardOut, ra, s) } case class TestListener(log: Logger) extends ITestRunListener { import com.android.ddmlib.testrunner.TestIdentifier private var _failures: Seq[TestIdentifier] = Seq.empty - def failures = _failures + def failures: Seq[TestIdentifier] = _failures type TestMetrics = java.util.Map[String,String] override def testRunStarted(name: String, count: Int) { @@ -1158,7 +1164,7 @@ object Tasks extends TaskBase { val testTaskDef = Def.task { val layout = projectLayout.value - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value val agg = aaptAggregate.value val classes = classDirectory.value val sdk = sdkPath.value @@ -1225,10 +1231,10 @@ object Tasks extends TaskBase { if (!rTxt.exists) rTxt.createNewFile() Resources.aapt(bldr, processedManifest, testPackage, - agg.additionalParams, agg.resConfigs, libs, false, debug, agg.pseudoLocalize, layout.testRes, + agg.additionalParams, agg.resConfigs, libs, lib = false, debug = debug, pseudoLocalize = agg.pseudoLocalize, layout.testRes, layout.testAssets, res, classes, null, layout.aaptTemp, s.log) - val deps = tlib filterNot (clib contains) + val deps = tlib filterNot (clib.contains) val tmp = cache / "test-dex" tmp.mkdirs() val inputs = if (re && RetrolambdaSupport.isAvailable) { @@ -1245,7 +1251,7 @@ object Tasks extends TaskBase { ta.debugSigningConfig, layout.testAssets, List(dex), layout.testSources / "fake-no-jni-doesnt-exist-sbt-android", layout.testSources / "fake-no-javaresource-doesnt-exist-sbt-android", - Set.empty, true, s) + Set.empty, debug = true, s) s.log.debug("Installing test apk: " + apk) @@ -1278,7 +1284,7 @@ object Tasks extends TaskBase { val testOnlyTaskDef: Def.Initialize[InputTask[Unit]] = Def.inputTask { val layout = projectLayout.value - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value val noTestApk = debugIncludesTests.?.value.getOrElse(false) val pkg = applicationId.value val all = allDevices.?.value.getOrElse(false) @@ -1293,13 +1299,13 @@ object Tasks extends TaskBase { generateTestManifest(pkg, layout.processedTestManifest, runner) } val manifest = XML.loadFile(manifestFile) - val testPackage = manifest.attribute("package") get 0 text + val testPackage = manifest.attribute("package").get(0).text val testSelection = Def.spaceDelimited().parsed.mkString(" ") val trunner = if(noTestApk) runner else { val instr = manifest \\ "instrumentation" (instr map { i => - (i.attribute(ANDROID_NS, "name") map (_(0).text), - i.attribute(ANDROID_NS, "targetPackage") map (_(0).text)) + (i.attribute(ANDROID_NS, "name") map (_.head.text), + i.attribute(ANDROID_NS, "targetPackage") map (_.head.text)) }).headOption flatMap ( _._1) getOrElse runner } runTests(sdk, testPackage, s, trunner, timeo, all, Some(testSelection)) @@ -1330,7 +1336,7 @@ object Tasks extends TaskBase { "manifest", pkgAttr, ns, minimizeEmpty = false, usesSdk, app, instrumentation) manifestOut.getParentFile.mkdirs() - XML.save(manifestOut.getAbsolutePath, manifest, "utf-8", true, null) + XML.save(manifestOut.getAbsolutePath, manifest, "utf-8", xmlDecl = true, null) manifestOut } @@ -1389,7 +1395,7 @@ object Tasks extends TaskBase { val s = streams.value val all = allDevices.value val isLib = libraryProject.value - implicit val output = outputLayout.value + implicit val output: Converter = outputLayout.value if (isLib) PluginFail("This project is not runnable, it has set 'libraryProject := true") @@ -1461,9 +1467,9 @@ object Tasks extends TaskBase { logRate(log, "[%s] Install finished:" format apk.getName, apk.length) { withDdmTimeout(timeo) { Try(device.installPackage(apk.getAbsolutePath, true)) match { - case util.Failure(err) => + case scala.util.Failure(err) => PluginFail("Install failed: " + err.getMessage, err) - case util.Success(_) => + case scala.util.Success(_) => } } } @@ -1512,15 +1518,14 @@ object Tasks extends TaskBase { Commands.targetDevice(k, s.log) foreach uninstall } - def loadLibraryReferences(b: File, props: Properties, prefix: String = "")(implicit m: BuildOutput.Converter): - Seq[AutoLibraryProject] = { + def loadLibraryReferences(b: File, props: Properties, prefix: String = "")(implicit m: BuildOutput.Converter): Seq[AutoLibraryProject] = { val p = props.asScala - (p.keys.collect { - case k if k.startsWith("android.library.reference") => k - }.toList.sortWith { (a,b) => a < b } flatMap { k => - AutoLibraryProject(b/p(k)) +: - loadLibraryReferences(b/p(k), loadProperties(b/p(k)), k) - }) distinct + p.keys + .collect { case k if k.startsWith("android.library.reference") => k } + .toList + .sortWith { (a,b) => a < b } + .flatMap { k => AutoLibraryProject(b/p(k)) +: loadLibraryReferences(b/p(k), loadProperties(b/p(k)), k) } + .distinct } val unmanagedJarsTaskDef = Def.task { @@ -1529,7 +1534,7 @@ object Tasks extends TaskBase { val t = buildToolInfo.value val rs = rsSupportMode.value val l = libraryProjects.value - val s = streams.value + val _ = streams.value val rsJars = if (rs) SdkLayout.renderscriptSupportLibs(t).map(f => @@ -1559,7 +1564,7 @@ object Tasks extends TaskBase { j <- d.getLocalJars.asScala } yield Attributed.blank(j.getCanonicalFile).put(moduleID.key, d.moduleID)) ++ (for { d <- Seq(b / "libs", b / "lib") - j <- d * "*.jar" get + j <- (d * "*.jar").get } yield Attributed.blank(j.getCanonicalFile)) ) filter { c => !c.data.getName.startsWith("scala-library") && c.data.isFile }