Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions example/thirdparty/androidtodo/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ object app
def mvnDeps = super.mvnDeps() ++ composeDeps ++ Seq(
mvn"junit:junit:4.13.2",
mvn"androidx.arch.core:core-testing:2.2.0",
mvn"org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0",
mvn"org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0",
mvn"androidx.navigation:navigation-testing:2.8.5",
mvn"androidx.test.espresso:espresso-core:3.6.1",
Expand Down Expand Up @@ -185,7 +184,6 @@ object app
// Dependencies for Android unit tests
mvn"junit:junit:4.13.2",
mvn"org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0",
mvn"org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0",
// AndroidX Test - Instrumented testing
mvn"androidx.test:core-ktx:1.6.1",
mvn"androidx.test.ext:junit-ktx:1.2.1",
Expand Down Expand Up @@ -227,7 +225,7 @@ object `shared-test` extends AndroidKotlinModule, AndroidHiltSupport {

def androidEnableCompose = true

def androidNamespace = "com.example.android.architecture.blueprints.todoapp.daemon.test"
def androidNamespace = "com.example.android.architecture.blueprints.todoapp.shared.test"

def kotlinSymbolProcessors: T[Seq[Dep]] = Seq(
mvn"androidx.room:room-compiler:2.7.1",
Expand All @@ -237,7 +235,6 @@ object `shared-test` extends AndroidKotlinModule, AndroidHiltSupport {
def mvnDeps = super.mvnDeps() ++ Seq(
mvn"junit:junit:4.13.2",
mvn"androidx.arch.core:core-testing:2.2.0",
mvn"org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0",
mvn"org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0",
mvn"androidx.test:core-ktx:1.6.1",
mvn"androidx.test.ext:junit-ktx:1.2.1",
Expand Down
31 changes: 18 additions & 13 deletions libs/androidlib/src/mill/androidlib/AndroidAppModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,7 @@ trait AndroidAppModule extends AndroidModule { outer =>

}

def knownProguardRules: T[String] = Task {
def androidKnownProguardRules: T[String] = Task {
// TODO need also pick proguard files from
// [[moduleDeps]]
androidUnpackArchives()
Expand All @@ -833,15 +833,13 @@ trait AndroidAppModule extends AndroidModule { outer =>
.mkString("\n")
}

override def androidProguard: T[PathRef] = Task {
val inheritedProguardFile = super.androidProguard()
val proguardFile = Task.dest / "proguard-rules.pro"

os.write(proguardFile, os.read(inheritedProguardFile.path))

os.write.append(proguardFile, knownProguardRules())

PathRef(proguardFile)
/**
* File names that are provided by the Android SDK in `androidSdkModule().androidProguardPath().path`
*
* For now, it's only used by [[AndroidR8AppModule]]
*/
def androidDefaultProguardFileNames: Task[Seq[String]] = Task.Anon {
Seq.empty[String]
}

// uses the d8 tool to generate the dex file, when minification is disabled
Expand Down Expand Up @@ -896,6 +894,9 @@ trait AndroidAppModule extends AndroidModule { outer =>

override def androidIsDebug: T[Boolean] = Task { true }

override def moduleDeps: Seq[JavaModule] = Seq.empty
override def compileModuleDeps: Seq[JavaModule] = Seq(outer)

override def resolutionParams: Task[ResolutionParams] = Task.Anon(outer.resolutionParams())

override def androidApplicationId: String = s"${outer.androidApplicationId}.test"
Expand All @@ -913,6 +914,10 @@ trait AndroidAppModule extends AndroidModule { outer =>

def androidResources: T[Seq[PathRef]] = Task.Sources("src/androidTest/res")

override def androidDefaultProguardFileNames: Task[Seq[String]] = Task.Anon {
outer.androidDefaultProguardFileNames()
}

override def testFramework: T[String] = Task {
"androidx.test.runner.AndroidJUnitRunner"
}
Expand Down Expand Up @@ -1063,15 +1068,15 @@ trait AndroidAppModule extends AndroidModule { outer =>
* as its apk is installed separately
*/
def androidTransitiveTestClasspath: T[Seq[PathRef]] = Task {
Task.traverse(transitiveModuleCompileModuleDeps) {
Task.traverse(transitiveRunModuleDeps) {
m =>
Task.Anon(m.localRunClasspath())
}().flatten
}

/** The instrumented dex should just contain the test dependencies and locally tested files */
override def androidPackagedClassfiles: T[Seq[PathRef]] = Task {
(testClasspath() ++ androidTransitiveTestClasspath())
androidTransitiveTestClasspath()
.map(_.path).filter(os.isDir)
.flatMap(os.walk(_))
.filter(os.isFile)
Expand All @@ -1080,7 +1085,7 @@ trait AndroidAppModule extends AndroidModule { outer =>
}

override def androidPackagedDeps: T[Seq[PathRef]] = Task {
androidResolvedMvnDeps()
androidResolvedRunMvnDeps()
}

/**
Expand Down
24 changes: 21 additions & 3 deletions libs/androidlib/src/mill/androidlib/AndroidModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,11 @@ trait AndroidModule extends JavaModule { outer =>

/**
* Gets all the compiled Android resources (typically in res/ directory)
* from the [[transitiveModuleCompileModuleDeps]]
* from the [[transitiveModuleRunModuleDeps]]
* @return a sequence of PathRef to the compiled resources
*/
def androidTransitiveCompiledResources: T[Seq[PathRef]] = Task {
Task.traverse(transitiveModuleCompileModuleDeps) {
Task.traverse(transitiveModuleRunModuleDeps) {
case m: AndroidModule =>
Task.Anon(m.androidCompiledModuleResources())
case _ =>
Expand Down Expand Up @@ -264,7 +264,7 @@ trait AndroidModule extends JavaModule { outer =>
override def compileClasspath: T[Seq[PathRef]] = Task {
// TODO process metadata shipped with Android libs. It can have some rules with Target SDK, for example.
// TODO support baseline profiles shipped with Android libs.
androidDepsClasspath() ++ androidTransitiveLibRClasspath()
androidDepsClasspath() ++ androidTransitiveLibRClasspath() ++ androidTransitiveModuleRClasspath()
}

/**
Expand Down Expand Up @@ -522,6 +522,24 @@ trait AndroidModule extends JavaModule { outer =>
}().flatten
}

def androidTransitiveModuleRClasspath: T[Seq[PathRef]] = Task {
Task.traverse(compileModuleDepsChecked) {
case m: AndroidModule =>
Task.Anon(Seq(m.androidProcessedResources()))
case _ =>
Task.Anon(Seq.empty[PathRef])
}().flatten
}

def androidTransitiveCompileOnlyClasspath: T[Seq[PathRef]] = Task {
Task.traverse(compileModuleDepsChecked) {
case m: AndroidModule =>
Task.Anon(Seq(m.compile().classes))
case _ =>
Task.Anon(Seq.empty[PathRef])
}().flatten
}

/**
* Namespace of the Android module.
* Used in manifest package and also used as the package to place the generated R sources
Expand Down
47 changes: 28 additions & 19 deletions libs/androidlib/src/mill/androidlib/AndroidR8AppModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ trait AndroidR8AppModule extends AndroidAppModule {
}

def androidLibraryProguardConfigs: Task[Seq[PathRef]] = Task {
androidUnpackArchives()
androidUnpackRunArchives()
// TODO need also collect rules from other modules,
// but Android lib module doesn't yet exist
.flatMap(_.proguardRules)
Expand All @@ -71,6 +71,27 @@ trait AndroidR8AppModule extends AndroidAppModule {
androidDefaultProguardFiles() ++ androidProjectProguardFiles() ++ androidLibraryProguardConfigs()
}

/**
* Creates a file for letting know R8 that [[compileModuleDeps]] and
* [[compileMvnDeps]] are in compile classpath only and not packaged with the apps.
* Useful for dependencies that are provided in devices and compile only module deps
* such as for avoiding to package main sources in the androidTest apk.
*/
def androidR8CompileOnlyClasspath: T[Option[PathRef]] = Task {
val resolvedCompileMvnDeps =
androidResolvedCompileMvnDeps() ++ androidTransitiveCompileOnlyClasspath() ++ androidTransitiveModuleRClasspath()
if (!resolvedCompileMvnDeps.isEmpty) {
val compiledMvnDepsFile = Task.dest / "compile-only-classpath.txt"
os.write.over(
compiledMvnDepsFile,
resolvedCompileMvnDeps.map(_.path.toString()).mkString("\n")
)
Some(PathRef(compiledMvnDepsFile))
} else
None

}

/** Concatenates all rules into one file */
override def androidProguard: T[PathRef] = Task {
val inheritedProguardFile = super.androidProguard()
Expand Down Expand Up @@ -98,14 +119,6 @@ trait AndroidR8AppModule extends AndroidAppModule {
)
}

/**
* File names that are provided by the Android SDK in `androidSdkModule().androidProguardPath().path`
* @return
*/
def androidDefaultProguardFileNames: Task[Seq[String]] = Task.Anon {
Seq.empty[String]
}

private def androidDefaultProguardFiles: Task[Seq[PathRef]] = Task.Anon {
val dest = Task.dest
androidDefaultProguardFileNames().map { fileName =>
Expand Down Expand Up @@ -242,18 +255,14 @@ trait AndroidR8AppModule extends AndroidAppModule {

r8ArgsBuilder ++= pgArgs

val resolvedCompileMvnDeps = androidResolvedCompileMvnDeps()
if (!resolvedCompileMvnDeps.isEmpty) {
val compiledMvnDepsFile = Task.dest / "compiled-mvndeps.txt"
os.write.over(
compiledMvnDepsFile,
androidResolvedCompileMvnDeps().map(_.path.toString()).mkString("\n")
)
r8ArgsBuilder ++= Seq(
val compileOnlyClasspath = androidR8CompileOnlyClasspath()

r8ArgsBuilder ++= compileOnlyClasspath.toSeq.flatMap(compiledMvnDepsFile =>
Seq(
"--classpath",
"@" + compiledMvnDepsFile.toString
"@" + compiledMvnDepsFile.path.toString
)
}
)

r8ArgsBuilder ++= androidR8Args()

Expand Down