diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index ba20335a58ff..955b2b57fab9 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -403,6 +403,7 @@ dependencies { annotationProcessor libs.auto.service // modules + implementation project(":anki-common") implementation project(":common") implementation project(":common:android") implementation project(":compat") diff --git a/anki-common/README.md b/anki-common/README.md new file mode 100644 index 000000000000..263938655726 --- /dev/null +++ b/anki-common/README.md @@ -0,0 +1,23 @@ +# `:anki-common` + +This module exists to break circular dependencies when `:AnkiDroid` is split into feature modules. + +## What belongs here + +- Common types and features which depend on `:libanki` and are not part of [`pylib`](https://github.com/ankitects/anki/blob/main/pylib/) + +## What does not belong here + +- Feature-specific business logic should be in `:AnkiDroid` or feature modules. +- Common code which does not depend on `:libanki` should be in `:common` + +## Why this module exists + +- `:libanki` aims to be a 1:1 implementation of upstream `pylib` which defines domain types (`CardId` etc...). + - AnkiDroid specific extensions need strong justification for inclusion in `:libanki` +- `:libanki` depends on `:common`. Common code which needs domain types would cause a circular dependency if placed in `:common`. + +## Future direction + +This module is currently an Android library because `:libanki` is. +When `:libanki` becomes a JVM library, this module splits into a pure-JVM half and an Android half (mirroring the existing `:common` / `:common:android` pair), with the JVM half holding everything that doesn't require the Android framework. diff --git a/anki-common/build.gradle.kts b/anki-common/build.gradle.kts new file mode 100644 index 000000000000..09aac2d0f3b0 --- /dev/null +++ b/anki-common/build.gradle.kts @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2026 David Allison +// SPDX-License-Identifier: GPL-3.0-or-later + +import com.android.build.api.dsl.LibraryExtension + +plugins { + id("ankidroid.android.library") +} + +configure { + // code should live inside com.ichi2.anki + // namespace must be unique for resources generation. + namespace = "com.ichi2.anki.ankicommon" + buildFeatures.buildConfig = false +} + +dependencies { + implementation(project(":common")) + implementation(project(":libanki")) +} diff --git a/anki-common/src/main/AndroidManifest.xml b/anki-common/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..e3417b8d8c8f --- /dev/null +++ b/anki-common/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/build.gradle.kts b/build.gradle.kts index c25296c9a189..47107a016974 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -121,7 +121,7 @@ subprojects { compilerArgs += "-XXLanguage:+ExplicitBackingFields" } - if (project.path !in listOf(":api", ":common", ":common:android")) { + if (project.path !in listOf(":anki-common", ":api", ":common", ":common:android")) { compilerArgs += "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi" } if (project.path != ":api") { diff --git a/settings.gradle.kts b/settings.gradle.kts index f372454ea9a4..1e64b9d48d80 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,6 +19,7 @@ dependencyResolutionManagement { // alphabetical ordering rather than dependency-tree ordering to avoid bikeshedding include( + ":anki-common", ":api", ":AnkiDroid", ":common",