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
1 change: 1 addition & 0 deletions AnkiDroid/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ dependencies {
annotationProcessor libs.auto.service

// modules
implementation project(":anki-common")
implementation project(":common")
implementation project(":common:android")
implementation project(":compat")
Expand Down
23 changes: 23 additions & 0 deletions anki-common/README.md
Original file line number Diff line number Diff line change
@@ -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.
20 changes: 20 additions & 0 deletions anki-common/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: 2026 David Allison <davidallisongithub@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later

import com.android.build.api.dsl.LibraryExtension

plugins {
id("ankidroid.android.library")
}

configure<LibraryExtension> {
// 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"))
}
6 changes: 6 additions & 0 deletions anki-common/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- SPDX-FileCopyrightText: 2026 David Allison <davidallisongithub@gmail.com> -->
<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
<manifest>

</manifest>
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencyResolutionManagement {

// alphabetical ordering rather than dependency-tree ordering to avoid bikeshedding
include(
":anki-common",
":api",
":AnkiDroid",
":common",
Expand Down
Loading