diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index bda2ccc..fa22a05 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -90,4 +90,7 @@ jobs:
uses: gradle/actions/setup-gradle@v5
- name: Build library
- run: ./gradlew assemble --no-configuration-cache
+ run: ./gradlew :deci:assemble --no-configuration-cache
+
+ - name: Compile sample (smoke check)
+ run: ./gradlew :sample:composeApp:compileKotlinJvm --no-configuration-cache
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 36e5a77..61d27c9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,39 @@
# Changelog
+## [Unreleased]
+
+### Removed
+
+- **Intel Apple targets dropped** — `iosX64` and `macosX64` klibs are no longer
+ published. Consumers targeting Intel macOS or the Intel iOS simulator must stay
+ on `0.2.2` or earlier. The Apple Silicon targets (`iosArm64`,
+ `iosSimulatorArm64`, `macosArm64`) are unaffected.
+
+### Changed
+
+- **Android `compileSdk` raised to 37** — projects depending on `deci` must now
+ compile against Android API level 37 or later.
+
+- **Build scripts modernized — no public API or runtime changes.** Migrated
+ deprecated Gradle/AGP/Kotlin/Compose DSL across all modules: the AGP KMP
+ `androidLibrary { }` block → `android { }`, `js(IR)` → `js`, the deprecated
+ `compose.*` dependency shortcuts → version-catalog coordinates, and the webpack
+ `devServer.static` property → the `static()` function. Removed unused build
+ dependencies and version-catalog entries (coroutines core/android/swing, plus
+ the `android-library`, `ktlint`, and `binary-compatibility-validator` plugin
+ aliases), and enabled Android host tests so the common test suite also runs on
+ the Android variant.
+
+## [0.2.2] - 2026-06-05
+
+### Changed
+
+- **Dependency and toolchain updates** — no public API changes. Kotlin
+ `2.3.20` → `2.4.0`, Android Gradle Plugin `9.0.1` → `9.2.1`, Compose
+ `1.10.3` → `1.11.1`, kotlinx-coroutines `1.10.2` → `1.11.0`,
+ kotlinx-serialization `1.10.0` → `1.11.0`, Kotest `6.1.9` → `6.1.11`,
+ and the Gradle wrapper `9.1.0` → `9.5.1`.
+
## [0.2.1] - 2026-03-24
### Fixed
diff --git a/README.MD b/README.MD
index f46cf1d..2294c9c 100644
--- a/README.MD
+++ b/README.MD
@@ -1,26 +1,28 @@
[](https://central.sonatype.com/artifact/org.kimplify/deci)
-[](https://kotlinlang.org)
+[](https://kotlinlang.org)
[](LICENSE)
Deci is a Kotlin Multiplatform library for high-precision decimal arithmetic. Built for money, taxes, invoicing, and any workload where `Float`/`Double` cannot be trusted.
## Features
-- **Multiplatform** -- Android, JVM, iOS, macOS, JS, WASM, Linux, Windows
+- **Multiplatform** -- Android, JVM, iOS, macOS, JS, WASM
- **Exact decimal math** -- backed by `BigDecimal`, `NSDecimalNumber`, and `decimal.js`
- **Predictable rounding** -- explicit rounding modes, no silent precision loss
- **Serialization ready** -- `kotlinx.serialization` support out of the box
## Installation
+> Use the latest version shown in the Maven Central badge above.
+
Kotlin Multiplatform:
```kotlin
kotlin {
sourceSets {
commonMain.dependencies {
- implementation("org.kimplify:deci:0.2.0")
+ implementation("org.kimplify:deci:0.2.2")
}
}
}
@@ -29,7 +31,7 @@ kotlin {
Single-platform:
```kotlin
dependencies {
- implementation("org.kimplify:deci:0.2.0")
+ implementation("org.kimplify:deci:0.2.2")
}
```
@@ -164,7 +166,6 @@ Values serialize as JSON **strings** to preserve trailing zeros and avoid lossy
| Android / JVM | `java.math.BigDecimal` |
| iOS / macOS | `NSDecimalNumber` |
| JS / WASM | `decimal.js` v10.6.0 |
-| Linux / Windows | Pure Kotlin |
## Configuration
diff --git a/build-logic/src/main/kotlin/deci.kmp.library.gradle.kts b/build-logic/src/main/kotlin/deci.kmp.library.gradle.kts
index bc2b4e3..1d6a742 100644
--- a/build-logic/src/main/kotlin/deci.kmp.library.gradle.kts
+++ b/build-logic/src/main/kotlin/deci.kmp.library.gradle.kts
@@ -15,10 +15,8 @@ kotlin {
wasmJs { browser() }
// Apple targets
- iosX64()
iosArm64()
iosSimulatorArm64()
- macosX64()
macosArm64()
applyDefaultHierarchyTemplate()
diff --git a/build.gradle.kts b/build.gradle.kts
index 52af6ae..dc6eaae 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -6,6 +6,4 @@ plugins {
alias(libs.plugins.compose.compiler).apply(false)
alias(libs.plugins.kotlinx.serialization).apply(false)
alias(libs.plugins.android.application).apply(false)
- alias(libs.plugins.ktlint).apply(false)
- alias(libs.plugins.binary.compatibility.validator).apply(false)
}
diff --git a/deci/build.gradle.kts b/deci/build.gradle.kts
index b3f5495..22e2bab 100644
--- a/deci/build.gradle.kts
+++ b/deci/build.gradle.kts
@@ -8,30 +8,22 @@ val libsCatalog = extensions.getByType().named("libs")
val deciVersion: String = libsCatalog.findVersion("version").get().requiredVersion
kotlin {
- androidLibrary {
+ android {
namespace = "org.kimplify.deci"
- compileSdk = 36
+ compileSdk = 37
minSdk = 21
+ withHostTest {}
}
sourceSets {
commonMain.dependencies {
- implementation(libs.kotlinx.coroutines.core)
- implementation(libs.kotlinx.coroutines.test)
implementation(libs.kotlinx.serialization.json)
}
commonTest.dependencies {
implementation(kotlin("test"))
implementation(libs.kotest.property)
- }
-
- androidMain.dependencies {
- implementation(libs.kotlinx.coroutines.android)
- }
-
- jvmMain.dependencies {
- implementation(libs.kotlinx.coroutines.swing)
+ implementation(libs.kotlinx.coroutines.test)
}
jsMain.dependencies {
diff --git a/gradle.properties b/gradle.properties
index 2970463..6c37d98 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -10,6 +10,7 @@ kotlin.code.style=official
kotlin.daemon.jvmargs=-Xmx4G
kotlin.native.binary.gc=cms
kotlin.incremental.wasm=true
+kotlin.native.ignoreDisabledTargets=true
#Android
android.useAndroidX=true
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 4f8e91d..0218c4a 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,22 +1,27 @@
[versions]
-version = "0.2.1"
+version = "0.2.2"
-kotlin = "2.3.20"
-agp = "9.0.1"
+kotlin = "2.4.0"
+agp = "9.2.1"
maven-publish = "0.36.0"
-compose = "1.10.3"
-kotlinx-coroutines = "1.10.2"
-kotlinx-serialization = "1.10.0"
+compose = "1.11.1"
+compose-material3 = "1.9.0"
+compose-material-icons = "1.7.3"
+kotlinx-coroutines = "1.11.0"
+kotlinx-serialization = "1.11.0"
androidx-activityCompose = "1.13.0"
ktlint-plugin = "14.2.0"
binary-compatibility-validator = "0.18.1"
-kotest = "6.1.9"
+kotest = "6.1.11"
[libraries]
-kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
-kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
-kotlinx-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" }
+compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "compose" }
+compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "compose" }
+compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "compose" }
+compose-material = { module = "org.jetbrains.compose.material:material", version.ref = "compose" }
+compose-material3 = { module = "org.jetbrains.compose.material3:material3", version.ref = "compose-material3" }
+compose-materialIconsExtended = { module = "org.jetbrains.compose.material:material-icons-extended", version.ref = "compose-material-icons" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
androidx-activityCompose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" }
@@ -29,12 +34,9 @@ bcv-gradle-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-valid
[plugins]
multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
-android-library = { id = "com.android.library", version.ref = "agp" }
maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "maven-publish" }
compose = { id = "org.jetbrains.compose", version.ref = "compose" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
android-application = { id = "com.android.application", version.ref = "agp" }
-ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint-plugin" }
-binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
android-kmp-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2e11132..5dd3c01 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock
index b3dae38..bc478d5 100644
--- a/kotlin-js-store/yarn.lock
+++ b/kotlin-js-store/yarn.lock
@@ -2870,7 +2870,16 @@ streamroller@^3.1.5:
debug "^4.3.4"
fs-extra "^8.1.0"
-"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -2902,7 +2911,14 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -3245,7 +3261,16 @@ workerpool@^9.2.0:
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-9.3.4.tgz#f6c92395b2141afd78e2a889e80cb338fe9fca41"
integrity sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
diff --git a/sample/androidApp/build.gradle.kts b/sample/androidApp/build.gradle.kts
index cbe2530..42ef4ed 100644
--- a/sample/androidApp/build.gradle.kts
+++ b/sample/androidApp/build.gradle.kts
@@ -6,7 +6,7 @@ plugins {
android {
namespace = "org.kimplify.deci.sample"
- compileSdk = 36
+ compileSdk = 37
defaultConfig {
minSdk = 24
diff --git a/sample/composeApp/build.gradle.kts b/sample/composeApp/build.gradle.kts
index 88c9a68..eca6496 100644
--- a/sample/composeApp/build.gradle.kts
+++ b/sample/composeApp/build.gradle.kts
@@ -15,13 +15,13 @@ plugins {
kotlin {
jvmToolchain(21)
- androidLibrary {
+ android {
namespace = "org.kimplify.deci.sample.shared"
- compileSdk = 36
+ compileSdk = 37
minSdk = 24
}
jvm()
- js(IR) {
+ js {
outputModuleName.set("composeApp-js")
browser {
val rootDirPath = project.rootDir.path
@@ -29,10 +29,8 @@ kotlin {
commonWebpackConfig {
outputFileName = "composeApp-js.js"
devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
- static = (static ?: mutableListOf()).apply {
- add(rootDirPath)
- add(projectDirPath)
- }
+ static(rootDirPath)
+ static(projectDirPath)
}
}
runTask {
@@ -49,17 +47,14 @@ kotlin {
commonWebpackConfig {
outputFileName = "composeApp.js"
devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
- static = (static ?: mutableListOf()).apply {
- add(rootDirPath)
- add(projectDirPath)
- }
+ static(rootDirPath)
+ static(projectDirPath)
}
}
}
binaries.executable()
}
listOf(
- iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
@@ -71,12 +66,12 @@ kotlin {
sourceSets {
commonMain.dependencies {
- implementation(compose.runtime)
- implementation(compose.ui)
- implementation(compose.foundation)
- implementation(compose.material)
- implementation(compose.material3)
- implementation(compose.materialIconsExtended)
+ implementation(libs.compose.runtime)
+ implementation(libs.compose.ui)
+ implementation(libs.compose.foundation)
+ implementation(libs.compose.material)
+ implementation(libs.compose.material3)
+ implementation(libs.compose.materialIconsExtended)
implementation(project(":deci"))
implementation(libs.kotlinx.serialization.json)
}
@@ -101,4 +96,4 @@ compose.desktop {
vendor = "Kimplify"
}
}
-}
\ No newline at end of file
+}