diff --git a/README.md b/README.md index 8dfc5c02d..771da189a 100755 --- a/README.md +++ b/README.md @@ -45,11 +45,11 @@ implement all your UI in Kotlin with Jetpack Compose and MOKO resources. ## Requirements -- Gradle version 7.5+ -- Kotlin 1.9.20+ -- Android Gradle Plugin 7.4.2+ +- Gradle version 8.4+ +- Kotlin 2.1.0+ +- Android Gradle Plugin 8.3.0+ - Android API 16+ -- iOS version 11.0+ +- iOS version 12.0+ - Compose Multiplatform 1.6.0+ ## Installation diff --git a/gradle.properties b/gradle.properties index 8ee9c08ce..02fd79765 100755 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,6 @@ org.gradle.caching=true kotlin.code.style=official kotlin.mpp.stability.nowarn=true -kotlin.mpp.androidGradlePluginCompatibility.nowarn=true kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.mpp.applyDefaultHierarchyTemplate=false kotlin.mpp.enableCInteropCommonization=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6139bb42c..bf3645866 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,11 +1,23 @@ [versions] -kotlinVersion = "1.9.25" -androidGradleVersion = "8.1.4" -androidSdkCommonVersion = "31.1.2" +# --- Runtime versions --- +# Minimum compatibility baseline for library modules (resources, compose, etc.). +# Allows users to use moko-resources WITHOUT forcing them to update their projects. +kotlinVersion = "2.1.0" +androidGradleVersion = "8.3.0" +androidSdkCommonVersion = "31.13.2" + +# --- Plugin versions (Tooling only) --- +# Used EXCLUSIVELY in the generator plugin module via 'compileOnly'. +# We use current APIs (available in 8.13.2+) to ensure compatibility with +# the widest range of AGP versions: from the minimum (8.3) +# to the current (9.0+ at this time). +pluginKotlinVersion = "2.3.0" +pluginAndroidGradleVersion = "8.13.2" + # kotlinx kotlinxSerializationVersion = "1.6.1" -kotlinxCoroutinesVersion = "1.8.0" +kotlinxCoroutinesVersion = "1.9.0" kotlinxBrowserVersion = "0.3" # android @@ -55,11 +67,18 @@ commonsCodec = { module = "commons-codec:commons-codec", version.ref = "commonsC icu4j = { module = "com.ibm.icu:icu4j", version.ref = "icu4jVersion" } # gradle +pluginKotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "pluginKotlinVersion" } +pluginAndroidGradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "pluginAndroidGradleVersion" } +pluginKotlinCompilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "pluginKotlinVersion" } +pluginAndroidMultiplatformLibraryPlugin = { module = "com.android.kotlin.multiplatform.library: com.android.kotlin.multiplatform.library.gradle.plugin", version.ref = "pluginAndroidGradleVersion" } + kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlinVersion" } androidGradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "androidGradleVersion" } androidSdkCommon = { module = "com.android.tools:sdk-common", version.ref = "androidSdkCommonVersion" } -kotlinCompilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlinVersion" } detektGradlePlugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version.ref = "detektVersion" } mokoMultiplatformPlugin = { module = "dev.icerock:mobile-multiplatform", version.ref = "mokoMultiplatformPluginVersion" } composeJetBrainsPlugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "composeJetbrainsVersion" } nexusPublishing = { module = "io.github.gradle-nexus:publish-plugin", version = "2.0.0" } + +[plugins] +composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlinVersion" } \ No newline at end of file diff --git a/gradle/moko.versions.toml b/gradle/moko.versions.toml index c2be03d4b..0e6ef849b 100644 --- a/gradle/moko.versions.toml +++ b/gradle/moko.versions.toml @@ -1,5 +1,5 @@ [versions] -resourcesVersion = "0.25.2" +resourcesVersion = "0.26.0" [libraries] resources = { module = "dev.icerock.moko:resources", version.ref = "resourcesVersion" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d99d8671b..4dba919db 100755 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ #Tue Jul 25 10:40:31 NOVT 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 5de3b3164..e6d65ee39 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -100,28 +100,12 @@ dependencies: "@types/node" "*" -"@types/eslint-scope@^3.7.3": - version "3.7.7" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" - integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "9.6.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.1.tgz#d5795ad732ce81715f27f75da913004a56751584" - integrity sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*", "@types/estree@^1.0.0": +"@types/estree@^1.0.5": version "1.0.8" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== -"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -133,7 +117,7 @@ dependencies: undici-types "~7.8.0" -"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.11.5": +"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.12.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== @@ -199,7 +183,7 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ== -"@webassemblyjs/wasm-edit@^1.11.5": +"@webassemblyjs/wasm-edit@^1.12.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" integrity sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ== @@ -234,7 +218,7 @@ "@webassemblyjs/wasm-gen" "1.14.1" "@webassemblyjs/wasm-parser" "1.14.1" -"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.11.5": +"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.12.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== @@ -254,17 +238,17 @@ "@webassemblyjs/ast" "1.14.1" "@xtuc/long" "4.2.2" -"@webpack-cli/configtest@^2.1.0": +"@webpack-cli/configtest@^2.1.1": version "2.1.1" resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== -"@webpack-cli/info@^2.0.1": +"@webpack-cli/info@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== -"@webpack-cli/serve@^2.0.3": +"@webpack-cli/serve@^2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== @@ -279,11 +263,6 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -abab@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" - integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== - accepts@~1.3.4: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -292,10 +271,10 @@ accepts@~1.3.4: mime-types "~2.1.34" negotiator "0.6.3" -acorn-import-assertions@^1.7.6: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== acorn@^8.14.0, acorn@^8.7.1: version "8.15.0" @@ -341,10 +320,10 @@ ajv@^8.0.0, ajv@^8.9.0: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== ansi-regex@^5.0.1: version "5.0.1" @@ -381,6 +360,11 @@ base64id@2.0.0, base64id@~2.0.0: resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== +baseline-browser-mapping@^2.9.0: + version "2.9.11" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz#53724708c8db5f97206517ecfe362dbe5181deea" + integrity sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ== + bcp-47@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/bcp-47/-/bcp-47-2.1.0.tgz#7e80734c3338fe8320894981dccf4968c3092df6" @@ -435,20 +419,21 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.1.1" -browser-stdout@1.3.1: +browser-stdout@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -browserslist@^4.14.5: - version "4.25.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.25.0.tgz#986aa9c6d87916885da2b50d8eb577ac8d133b2c" - integrity sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA== +browserslist@^4.21.10: + version "4.28.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" + integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== dependencies: - caniuse-lite "^1.0.30001718" - electron-to-chromium "^1.5.160" - node-releases "^2.0.19" - update-browserslist-db "^1.1.3" + baseline-browser-mapping "^2.9.0" + caniuse-lite "^1.0.30001759" + electron-to-chromium "^1.5.263" + node-releases "^2.0.27" + update-browserslist-db "^1.2.0" buffer-from@^1.0.0: version "1.1.2" @@ -481,10 +466,10 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001718: - version "1.0.30001724" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001724.tgz#312e163553dd70d2c0fb603d74810c85d8ed94a0" - integrity sha512-WqJo7p0TbHDOythNTqYujmaJTvtYRZrjpP8TCvH6Vb9CYJerJNKamKzIWOM4BkQatWj9H2lYulpdAQNBe7QhNA== +caniuse-lite@^1.0.30001759: + version "1.0.30001761" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz#4ca4c6e3792b24e8e2214baa568fc0e43de28191" + integrity sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g== chalk@^4.1.0: version "4.1.2" @@ -494,22 +479,7 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chokidar@3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chokidar@^3.5.1: +chokidar@^3.5.1, chokidar@^3.5.3: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -652,13 +622,6 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - debug@^4.3.4: version "4.4.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" @@ -666,7 +629,14 @@ debug@^4.3.4: dependencies: ms "^2.1.3" -debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: +debug@^4.3.5, debug@~4.4.1: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +debug@~4.3.1, debug@~4.3.4: version "4.3.7" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== @@ -693,10 +663,10 @@ di@^0.0.1: resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== -diff@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== +diff@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== dom-serialize@^2.2.1: version "2.2.1" @@ -722,10 +692,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.5.160: - version "1.5.173" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.173.tgz#1aeba57204fe19425921a29946ef543653f5e896" - integrity sha512-2bFhXP2zqSfQHugjqJIDFVwa+qIxyNApenmXTp9EjaKtdPrES5Qcn9/aSFy/NaP2E+fWG/zxKu/LBvY36p5VNQ== +electron-to-chromium@^1.5.263: + version "1.5.267" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz#5d84f2df8cdb6bfe7e873706bb21bd4bfb574dc7" + integrity sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw== emoji-regex@^8.0.0: version "8.0.0" @@ -757,10 +727,10 @@ engine.io@~6.6.0: engine.io-parser "~5.2.1" ws "~8.17.1" -enhanced-resolve@^5.13.0: - version "5.18.2" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz#7903c5b32ffd4b2143eeb4b92472bd68effd5464" - integrity sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ== +enhanced-resolve@^5.17.1: + version "5.18.4" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz#c22d33055f3952035ce6a144ce092447c525f828" + integrity sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -812,7 +782,7 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== -escape-string-regexp@4.0.0: +escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== @@ -897,14 +867,6 @@ finalhandler@1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-up@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - find-up@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -913,6 +875,14 @@ find-up@^4.0.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" @@ -998,36 +968,35 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== +glob@^7.1.3, glob@^7.1.7: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@^7.1.7: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== +glob@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.1.1" + minimatch "^5.0.1" once "^1.3.0" - path-is-absolute "^1.0.0" gopd@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -1056,7 +1025,7 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" -he@1.2.0: +he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -1231,10 +1200,10 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" -js-yaml@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== +js-yaml@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== dependencies: argparse "^2.0.1" @@ -1281,19 +1250,19 @@ karma-sourcemap-loader@0.4.0: dependencies: graceful-fs "^4.2.10" -karma-webpack@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.0.tgz#2a2c7b80163fe7ffd1010f83f5507f95ef39f840" - integrity sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA== +karma-webpack@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.1.tgz#4eafd31bbe684a747a6e8f3e4ad373e53979ced4" + integrity sha512-oo38O+P3W2mSPCSUrQdySSPv1LvPpXP+f+bBimNomS5sW+1V4SuhCuW8TfJzV+rDv921w2fDSDw0xJbPe6U+kQ== dependencies: glob "^7.1.3" - minimatch "^3.0.4" + minimatch "^9.0.3" webpack-merge "^4.1.5" -karma@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.2.tgz#a983f874cee6f35990c4b2dcc3d274653714de8e" - integrity sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ== +karma@6.4.4: + version "6.4.4" + resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.4.tgz#dfa5a426cf5a8b53b43cd54ef0d0d09742351492" + integrity sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w== dependencies: "@colors/colors" "1.5.0" body-parser "^1.19.0" @@ -1314,7 +1283,7 @@ karma@6.4.2: qjobs "^1.2.0" range-parser "^1.2.1" rimraf "^3.0.2" - socket.io "^4.4.1" + socket.io "^4.7.2" source-map "^0.6.1" tmp "^0.2.1" ua-parser-js "^0.7.30" @@ -1325,6 +1294,13 @@ kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +kotlin-web-helpers@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/kotlin-web-helpers/-/kotlin-web-helpers-2.0.0.tgz#b112096b273c1e733e0b86560998235c09a19286" + integrity sha512-xkVGl60Ygn/zuLkDPx+oHj7jeLR7hCvoNF99nhwXMn8a3ApB4lLiC9pk4ol4NHPjyoCbvQctBqvzUcp8pkqyWw== + dependencies: + format-util "^1.0.5" + loader-runner@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" @@ -1349,7 +1325,7 @@ lodash@^4.17.15, lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@4.1.0: +log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -1412,13 +1388,6 @@ mini-css-extract-plugin@2.7.5: dependencies: schema-utils "^4.0.0" -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - minimatch@^3.0.4, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -1426,6 +1395,20 @@ minimatch@^3.0.4, minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" +minimatch@^5.0.1, minimatch@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.3: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.3, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -1438,32 +1421,31 @@ mkdirp@^0.5.5: dependencies: minimist "^1.2.6" -mocha@10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" - integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - nanoid "3.3.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" +mocha@10.7.3: + version "10.7.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.7.3.tgz#ae32003cabbd52b59aece17846056a68eb4b0752" + integrity sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A== + dependencies: + ansi-colors "^4.1.3" + browser-stdout "^1.3.1" + chokidar "^3.5.3" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^8.1.0" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^16.2.0" + yargs-parser "^20.2.9" + yargs-unparser "^2.0.0" moo@^0.5.1: version "0.5.2" @@ -1475,21 +1457,11 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.3: +ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -nanoid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== - nanoid@^3.3.11: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" @@ -1505,10 +1477,10 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -node-releases@^2.0.19: - version "2.0.19" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" - integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== +node-releases@^2.0.27: + version "2.0.27" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -1801,7 +1773,7 @@ safe-regex-test@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -schema-utils@^3.1.2: +schema-utils@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== @@ -1825,13 +1797,6 @@ semver@^7.3.8: resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== -serialize-javascript@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - serialize-javascript@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" @@ -1919,15 +1884,15 @@ socket.io-parser@~4.2.4: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" -socket.io@^4.4.1: - version "4.8.1" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.8.1.tgz#fa0eaff965cc97fdf4245e8d4794618459f7558a" - integrity sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg== +socket.io@^4.7.2: + version "4.8.3" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.8.3.tgz#ca6ba1431c69532e1e0a6f496deebeb601dbc4df" + integrity sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A== dependencies: accepts "~1.3.4" base64id "~2.0.0" cors "~2.8.5" - debug "~4.3.2" + debug "~4.4.1" engine.io "~6.6.0" socket.io-adapter "~2.5.2" socket.io-parser "~4.2.4" @@ -1937,12 +1902,11 @@ source-map-js@^1.0.2, source-map-js@^1.2.1: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== -source-map-loader@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-4.0.1.tgz#72f00d05f5d1f90f80974eda781cbd7107c125f2" - integrity sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA== +source-map-loader@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-5.0.0.tgz#f593a916e1cc54471cfc8851b905c8a845fc7e38" + integrity sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA== dependencies: - abab "^2.0.6" iconv-lite "^0.6.3" source-map-js "^1.0.2" @@ -1994,7 +1958,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-json-comments@3.1.1: +strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -2004,13 +1968,6 @@ style-loader@3.3.2: resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.2.tgz#eaebca714d9e462c19aa1e3599057bc363924899" integrity sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw== -supports-color@8.1.1, supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -2018,6 +1975,13 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.0.0, supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -2028,10 +1992,10 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.2.tgz#ab4984340d30cb9989a490032f086dbb8b56d872" integrity sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg== -terser-webpack-plugin@^5.3.7: - version "5.3.14" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz#9031d48e57ab27567f02ace85c7d690db66c3e06" - integrity sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw== +terser-webpack-plugin@^5.3.10: + version "5.3.16" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz#741e448cc3f93d8026ebe4f7ef9e4afacfd56330" + integrity sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q== dependencies: "@jridgewell/trace-mapping" "^0.3.25" jest-worker "^27.4.5" @@ -2074,10 +2038,10 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typescript@5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" - integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== +typescript@5.5.4: + version "5.5.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" + integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== ua-parser-js@^0.7.30: version "0.7.40" @@ -2099,10 +2063,10 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-browserslist-db@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" - integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== +update-browserslist-db@^1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== dependencies: escalade "^3.2.0" picocolors "^1.1.1" @@ -2134,23 +2098,23 @@ void-elements@^2.0.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== -watchpack@^2.4.0: - version "2.4.4" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.4.tgz#473bda72f0850453da6425081ea46fc0d7602947" - integrity sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA== +watchpack@^2.4.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.5.0.tgz#fa115d5ccaa4bf3aa594f586257c0bc4768939fd" + integrity sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" -webpack-cli@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.0.tgz#abc4b1f44b50250f2632d8b8b536cfe2f6257891" - integrity sha512-a7KRJnCxejFoDpYTOwzm5o21ZXMaNqtRlvS183XzGDUPRdVEzJNImcQokqYZ8BNTnk9DkKiuWxw75+DCCoZ26w== +webpack-cli@5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== dependencies: "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^2.1.0" - "@webpack-cli/info" "^2.0.1" - "@webpack-cli/serve" "^2.0.3" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" colorette "^2.0.14" commander "^10.0.1" cross-spawn "^7.0.3" @@ -2182,34 +2146,33 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.3.3.tgz#d4bf7f9909675d7a070ff14d0ef2a4f3c982c723" integrity sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg== -webpack@5.82.0: - version "5.82.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.82.0.tgz#3c0d074dec79401db026b4ba0fb23d6333f88e7d" - integrity sha512-iGNA2fHhnDcV1bONdUu554eZx+XeldsaeQ8T67H6KKHl2nUSwX8Zm7cmzOA46ox/X1ARxf7Bjv8wQ/HsB5fxBg== +webpack@5.94.0: + version "5.94.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.94.0.tgz#77a6089c716e7ab90c1c67574a28da518a20970f" + integrity sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg== dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^1.0.0" - "@webassemblyjs/ast" "^1.11.5" - "@webassemblyjs/wasm-edit" "^1.11.5" - "@webassemblyjs/wasm-parser" "^1.11.5" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" + acorn-import-attributes "^1.9.5" + browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.13.0" + enhanced-resolve "^5.17.1" es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" + graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.1.2" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.3.7" - watchpack "^2.4.0" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" webpack-sources "^3.2.3" which@^1.2.1: @@ -2231,10 +2194,10 @@ wildcard@^2.0.0: resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== +workerpool@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" + integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== wrap-ansi@^7.0.0: version "7.0.0" @@ -2260,17 +2223,12 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yargs-parser@20.2.4: - version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" - integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== - -yargs-parser@^20.2.2: +yargs-parser@^20.2.2, yargs-parser@^20.2.9: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-unparser@2.0.0: +yargs-unparser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== @@ -2280,7 +2238,7 @@ yargs-unparser@2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@16.2.0, yargs@^16.1.1: +yargs@^16.1.1, yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== diff --git a/local-samples-check.sh b/local-samples-check.sh index 332161df9..368045993 100755 --- a/local-samples-check.sh +++ b/local-samples-check.sh @@ -17,3 +17,4 @@ set -e (cd samples/kotlin-2-dynamic-sample && ./local-check.sh) (cd samples/kotlin-2-tests && ./local-check.sh) (cd samples/cm-resources-sample && ./local-check.sh) +(cd samples/gradle-agp-9-sample && ./local-check.sh) diff --git a/resources-build-logic/src/main/kotlin/android-base-convention.gradle.kts b/resources-build-logic/src/main/kotlin/android-base-convention.gradle.kts index d6f8fa3e9..d15212515 100644 --- a/resources-build-logic/src/main/kotlin/android-base-convention.gradle.kts +++ b/resources-build-logic/src/main/kotlin/android-base-convention.gradle.kts @@ -5,11 +5,11 @@ import com.android.build.gradle.BaseExtension configure { - compileSdkVersion(33) + compileSdkVersion(34) defaultConfig { minSdk = 16 - targetSdk = 33 + targetSdk = 34 } compileOptions { diff --git a/resources-build-logic/src/main/kotlin/apple-bundle-searcher-convention.gradle.kts b/resources-build-logic/src/main/kotlin/apple-bundle-searcher-convention.gradle.kts index 0eac3665d..2558866f5 100644 --- a/resources-build-logic/src/main/kotlin/apple-bundle-searcher-convention.gradle.kts +++ b/resources-build-logic/src/main/kotlin/apple-bundle-searcher-convention.gradle.kts @@ -5,6 +5,8 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.konan.target.KonanTarget +import java.util.Locale +import java.util.Locale.getDefault plugins { id("org.jetbrains.kotlin.multiplatform") @@ -52,12 +54,12 @@ kotlin.targets val sdkPath: String = getSdkPath(sdk) - val libsDir = File(buildDir, "moko-resources/cinterop/$name") + val libsDir = layout.buildDirectory.dir("moko-resources/cinterop/$name").get().asFile libsDir.mkdirs() val sourceFile = File(projectDir, "src/appleMain/objective-c/MRResourcesBundle.m") val objectFile = File(libsDir, "MRResourcesBundle.o") val libFile = File(libsDir, "libMRResourcesBundle.a") - val kotlinTargetPostfix: String = this.name.capitalize() + val kotlinTargetPostfix: String = this.name.replaceFirstChar { it.titlecase() } val compileStaticLibrary = tasks.register("mokoBundleSearcherCompile$kotlinTargetPostfix", Exec::class) { group = "moko-resources" diff --git a/resources-build-logic/src/main/kotlin/multiplatform-library-convention.gradle.kts b/resources-build-logic/src/main/kotlin/multiplatform-library-convention.gradle.kts index a6adc3791..bcff92800 100644 --- a/resources-build-logic/src/main/kotlin/multiplatform-library-convention.gradle.kts +++ b/resources-build-logic/src/main/kotlin/multiplatform-library-convention.gradle.kts @@ -4,6 +4,7 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl plugins { id("com.android.library") @@ -14,16 +15,20 @@ plugins { kotlin { jvm() - androidTarget() + androidTarget { + publishAllLibraryVariants() + } iosX64() iosArm64() iosSimulatorArm64() macosX64() macosArm64() - js(IR) { + js { browser() useCommonJs() } + + @OptIn(ExperimentalWasmDsl::class) wasmJs { browser() useCommonJs() diff --git a/resources-compose/build.gradle.kts b/resources-compose/build.gradle.kts index 58aa3c595..7f05737c8 100644 --- a/resources-compose/build.gradle.kts +++ b/resources-compose/build.gradle.kts @@ -13,6 +13,7 @@ plugins { id("org.jetbrains.compose") id("javadoc-stub-convention") id("publication-convention") + alias(libs.plugins.composeCompiler) } android { @@ -31,12 +32,9 @@ kotlin { iosSimulatorArm64() macosX64() macosArm64() - js(IR) { - browser() - } - wasmJs { - browser() - } + js { browser() } + @OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class) + wasmJs { browser() } sourceSets { commonMain { diff --git a/resources-generator/build.gradle.kts b/resources-generator/build.gradle.kts index a5e1bb43d..bec1e64c1 100644 --- a/resources-generator/build.gradle.kts +++ b/resources-generator/build.gradle.kts @@ -4,14 +4,15 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinVersion +import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile plugins { - id("org.jetbrains.kotlin.jvm") version ("1.9.25") + id("org.jetbrains.kotlin.jvm") version ("2.3.0") id("detekt-convention") id("publication-convention") id("com.gradle.plugin-publish") version ("1.2.0") id("java-gradle-plugin") - kotlin("plugin.serialization") version ("1.9.25") + kotlin("plugin.serialization") version ("2.3.0") id("nexus-publication-convention") } @@ -20,9 +21,10 @@ version = moko.versions.resourcesVersion.get() dependencies { implementation(gradleKotlinDsl()) - compileOnly(libs.kotlinGradlePlugin) - compileOnly(libs.androidGradlePlugin) - compileOnly(libs.kotlinCompilerEmbeddable) + compileOnly(libs.pluginKotlinGradlePlugin) + compileOnly(libs.pluginAndroidGradlePlugin) + compileOnly(libs.pluginAndroidMultiplatformLibraryPlugin) + compileOnly(libs.pluginKotlinCompilerEmbeddable) compileOnly(libs.androidSdkCommon) implementation(libs.kotlinPoet) implementation(libs.kotlinxSerialization) @@ -44,11 +46,12 @@ kotlin { jvmToolchain(11) } -tasks.withType() - .configureEach { - compilerOptions.jvmTarget.set(JvmTarget.JVM_11) - compilerOptions.languageVersion.set(KotlinVersion.KOTLIN_1_9) +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_11) + languageVersion.set(KotlinVersion.fromVersion("2.0")) } +} gradlePlugin { plugins { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/MultiplatformResourcesPlugin.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/MultiplatformResourcesPlugin.kt index 05388001d..0eaae4c31 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/MultiplatformResourcesPlugin.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/MultiplatformResourcesPlugin.kt @@ -5,7 +5,10 @@ package dev.icerock.gradle import com.android.build.api.dsl.AndroidSourceSet +import com.android.build.api.extension.impl.CurrentAndroidGradlePluginVersion import dev.icerock.gradle.extra.getOrRegisterGenerateResourcesTask +import dev.icerock.gradle.generator.platform.android.AGP_8_11_0 +import dev.icerock.gradle.generator.platform.android.AndroidPluginType import dev.icerock.gradle.generator.platform.android.getAndroidSourceSetOrNull import dev.icerock.gradle.generator.platform.android.setupAndroidTasks import dev.icerock.gradle.generator.platform.android.setupAndroidVariantsSync @@ -17,6 +20,8 @@ import dev.icerock.gradle.generator.platform.apple.setupFrameworkResources import dev.icerock.gradle.generator.platform.js.setupJsKLibResources import dev.icerock.gradle.generator.platform.js.setupJsResourcesWithLinkTask import dev.icerock.gradle.tasks.GenerateMultiplatformResourcesTask +import dev.icerock.gradle.utils.enableAndroidResources +import dev.icerock.gradle.utils.hasMinimalVersion import dev.icerock.gradle.utils.kotlinSourceSetsObservable import org.gradle.api.Plugin import org.gradle.api.Project @@ -29,11 +34,12 @@ import org.gradle.kotlin.dsl.withType import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper -import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.KotlinTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget +import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile @@ -61,6 +67,18 @@ open class MultiplatformResourcesPlugin : Plugin { setupAndroidVariantsSync(project = project) setupGradleSync(project = project) } + + // Enable android resources for "com.android.kotlin.multiplatform.library" plugin + project.plugins.withId(AndroidPluginType.KmpLibrary.pluginId) { + val hasEnableAndroidResourcesFlag = hasMinimalVersion( + minVersion = AGP_8_11_0, + currentVersion = CurrentAndroidGradlePluginVersion.CURRENT_AGP_VERSION.version + ) + + if (hasEnableAndroidResourcesFlag) { + project.enableAndroidResources() + } + } } private fun setupGradleSync(project: Project) { @@ -172,6 +190,7 @@ open class MultiplatformResourcesPlugin : Plugin { } } + @OptIn(ExperimentalKotlinGradlePluginApi::class) private fun setupSourceSets( target: KotlinTarget, sourceSet: KotlinSourceSet, @@ -179,13 +198,13 @@ open class MultiplatformResourcesPlugin : Plugin { ) { sourceSet.kotlin.srcDir(genTaskProvider.map { it.outputSourcesDir }) - when (target.platformType) { - KotlinPlatformType.jvm, KotlinPlatformType.js -> { + when (target) { + is KotlinJsIrTarget, is KotlinJvmTarget -> { sourceSet.resources.srcDir(genTaskProvider.map { it.outputResourcesDir }) sourceSet.resources.srcDir(genTaskProvider.map { it.outputAssetsDir }) } - KotlinPlatformType.androidJvm -> { + is KotlinAndroidTarget -> { // Fix: android sourceSets indexation in IDE // Usage of api of v2.model in AGP broken for IDE resources indexing // For correct indexing of resources set resource directory @@ -196,12 +215,11 @@ open class MultiplatformResourcesPlugin : Plugin { androidSourceSet.res.srcDir(genTaskProvider.map { it.outputResourcesDir }) // Assets added in variants for correct generation - // see: dev.icerock.gradle.generator.platform.android.SetupAndroidUtilsKt.addGenerationTaskDependency + // see: dev.icerock.gradle.generator.platform.android + // .SetupAndroidUtilsKt.addGenerationTaskDependency // androidSourceSet.assets.srcDir(genTaskProvider.map { it.outputAssetsDir }) } - - KotlinPlatformType.common, KotlinPlatformType.native, - KotlinPlatformType.wasm -> Unit + else -> Unit } } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/MultiplatformResourcesPluginExtension.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/MultiplatformResourcesPluginExtension.kt index 959bae574..05eb28220 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/MultiplatformResourcesPluginExtension.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/MultiplatformResourcesPluginExtension.kt @@ -5,6 +5,7 @@ package dev.icerock.gradle import dev.icerock.gradle.generator.platform.apple.registerCopyXCFrameworkResourcesToAppTask +import dev.icerock.gradle.utils.capitalize import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project import org.gradle.api.file.SourceDirectorySet @@ -21,7 +22,7 @@ abstract class MultiplatformResourcesPluginExtension { abstract val resourcesSourceSets: NamedDomainObjectContainer fun Project.configureCopyXCFrameworkResources(xcFrameworkName: String = name) { - NativeBuildType.values() + NativeBuildType.entries .map { it.name.lowercase().capitalize() } .plus("") .map { xcFrameworkName.capitalize() + it + "XCFramework" } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/extra/mokoResourcesGenTask.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/extra/mokoResourcesGenTask.kt index 6b324abc1..e3ff9f47f 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/extra/mokoResourcesGenTask.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/extra/mokoResourcesGenTask.kt @@ -111,10 +111,18 @@ private fun registerGenerateTask( task as GenerateMultiplatformResourcesTask val platform: String = task.platformType.get() + if (platform != KotlinPlatformType.androidJvm.name) return@onlyIf true val flavor: String = task.androidSourceSetName.get() - flavor in listOf("main", "test", "androidTest") + + flavor in listOf( + "androidMain", + "androidTest", + "androidInstrumentedTest", + "main", + "test" + ) } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AddAndroidGeneratedSources.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AddAndroidGeneratedSources.kt new file mode 100644 index 000000000..f6639b9f3 --- /dev/null +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AddAndroidGeneratedSources.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2025 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator.platform.android + +import com.android.build.api.variant.Sources +import dev.icerock.gradle.tasks.GenerateMultiplatformResourcesTask +import org.gradle.api.tasks.TaskProvider + +/** + * Registers generated Kotlin sources and assets for Android variants when using the + * classic AGP plugin (`com.android.library`). + * + * The generated resource directory (`res`) is not attached here; it is added later during + * source set configuration, as required by the legacy AGP source set wiring model. + * + * Use this function only with the traditional Android plugin. + */ +internal fun Sources.addLegacyAndroidGeneratedSources( + provider: TaskProvider +) { + kotlin?.addGeneratedSourceDirectory( + taskProvider = provider, + wiredWith = GenerateMultiplatformResourcesTask::outputSourcesDir + ) + + // Resources doesn't add in android variants for IDE indexing + // Resource directory set here: + // dev.icerock.gradle.MultiplatformResourcesPlugin.setupSourceSets + // res?.addGeneratedSourceDirectory( + // taskProvider = provider, + // wiredWith = GenerateMultiplatformResourcesTask::outputResourcesDir + // ) + + // Assets add here, for correct compilation + assets?.addGeneratedSourceDirectory( + taskProvider = provider, + wiredWith = GenerateMultiplatformResourcesTask::outputAssetsDir + ) +} + +/** + * Registers generated Kotlin sources, Java sources, resources and assets for Android targets + * when using the Kotlin Multiplatform Android plugin (`com.android.kotlin.multiplatform.library`). + * + * In this integration model, Android units of code are exposed through both Kotlin and Java + * source sets. To ensure that generated directories are consistently discovered by the IDE and + * the build system, the generated Kotlin sources are registered in both source sets. + * + * This function provides the full set of generated directories required for proper indexing + * and compilation under the KMP Android plugin. + */ +internal fun Sources.addKmpAndroidGeneratedSources( + provider: TaskProvider +) { + kotlin?.addGeneratedSourceDirectory( + taskProvider = provider, + wiredWith = GenerateMultiplatformResourcesTask::outputSourcesDir + ) + + // Generated Kotlin sources must also be added to the Java source set so that + // the IDE and build system treat the generated directory as part of the Android target. + // Note: this behavior may become incompatible with AGP 10+, according to guidance + // shared by the AGP team in public issue tracker discussions. + java?.addGeneratedSourceDirectory( + taskProvider = provider, + wiredWith = GenerateMultiplatformResourcesTask::outputSourcesDir + ) + + assets?.addGeneratedSourceDirectory( + taskProvider = provider, + wiredWith = GenerateMultiplatformResourcesTask::outputAssetsDir + ) + + res?.addGeneratedSourceDirectory( + taskProvider = provider, + wiredWith = GenerateMultiplatformResourcesTask::outputResourcesDir + ) +} diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AgpConstants.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AgpConstants.kt new file mode 100644 index 000000000..539efd7b2 --- /dev/null +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AgpConstants.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2025 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator.platform.android + +internal const val AGP_8_10_0 = "8.10.0" +internal const val AGP_8_11_0 = "8.11.0" diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AndroidPluginType.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AndroidPluginType.kt new file mode 100644 index 000000000..4357e5406 --- /dev/null +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AndroidPluginType.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2025 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator.platform.android + +import org.gradle.api.Project + +/** + * Enumeration of supported Android Gradle Plugin (AGP) types. + * + * @property pluginId The string identifier of the plugin (e.g., "com.android.application"). + */ +internal enum class AndroidPluginType(val pluginId: String) { + /** Plugin for building executable Android applications. */ + Application(pluginId = "com.android.application"), + + /** Plugin for building standard Android libraries. */ + Library(pluginId = "com.android.library"), + + /** Plugin for building Android libraries within a Kotlin Multiplatform project. */ + KmpLibrary(pluginId = "com.android.kotlin.multiplatform.library") +} + +/** + * Returns a list of all Android plugin identifiers defined in [AndroidPluginType]. + * + * @return A list of plugin IDs. + */ +internal fun androidPlugins(): List { + return AndroidPluginType.entries.map { it.pluginId } +} + +/** + * Checks if any of the Android plugins are applied to this project. + * + * @return `true` if any plugin from [AndroidPluginType] is found. + */ +internal fun Project.hasAnyAndroidPlugin(): Boolean { + return androidPlugins().any { plugins.findPlugin(it) != null } +} + +/** + * Checks if the Android Kotlin Multiplatform Library plugin is applied to the project. + * + * @return `true` if "com.android.kotlin.multiplatform.library" is applied. + */ +internal fun Project.hasAndroidKmpLibraryPlugin(): Boolean { + return plugins.hasPlugin(AndroidPluginType.KmpLibrary.pluginId) +} + +/** + * Checks if the Android Application plugin is applied to the project. + * + * @return `true` if "com.android.application" is applied. + */ +internal fun Project.hasAndroidApplicationPlugin(): Boolean { + return plugins.hasPlugin(AndroidPluginType.Application.pluginId) +} + +/** + * Checks if the Android Library plugin is applied to the project. + * + * @return `true` if "com.android.library" is applied. + */ +internal fun Project.hasAndroidLibraryPlugin(): Boolean { + return plugins.hasPlugin(AndroidPluginType.Library.pluginId) +} diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/SetupAndroidMultiplatformLibraryTargetSources.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/SetupAndroidMultiplatformLibraryTargetSources.kt new file mode 100644 index 000000000..2af559aad --- /dev/null +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/SetupAndroidMultiplatformLibraryTargetSources.kt @@ -0,0 +1,111 @@ +/* + * Copyright 2025 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator.platform.android + +import com.android.build.api.dsl.KotlinMultiplatformAndroidCompilation +import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget +import com.android.build.api.extension.impl.CurrentAndroidGradlePluginVersion +import com.android.build.api.variant.KotlinMultiplatformAndroidComponentsExtension +import com.android.build.api.variant.KotlinMultiplatformAndroidVariant +import com.android.build.api.variant.Variant +import dev.icerock.gradle.tasks.GenerateMultiplatformResourcesTask +import dev.icerock.gradle.utils.hasMinimalVersion +import org.gradle.api.GradleException +import org.gradle.api.tasks.TaskProvider +import org.gradle.kotlin.dsl.findByType +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation +import org.jetbrains.kotlin.gradle.plugin.KotlinTarget + +/** + * Configures the source sets and task dependencies for the Android target within + * a Kotlin Multiplatform Library project. + * + * This function specifically integrates the [GenerateMultiplatformResourcesTask] + * into the Android variant lifecycle, ensuring that generated resources are + * correctly recognized by the Android build system. + * + * ### AGP Compatibility + * To support multiple versions of the Android Gradle Plugin, this function: + * - Uses the unified variant API available in **AGP 8.10.0** and later. + * - Falls back to the deprecated `onVariant` API for older AGP versions. + * + * @param target The [KotlinTarget] to configure. If the target is not a + * [KotlinMultiplatformAndroidLibraryTarget], this function will return early. + * @param genTaskProvider The [TaskProvider] for the resource generation task + * that needs to be wired to the Android variants. + * @param compilation The [KotlinCompilation] associated with the current target. + * * @throws GradleException If the [KotlinMultiplatformAndroidComponentsExtension] + * is missing in a project applying the `com.android.kotlin.multiplatform.library` plugin. + */ +fun setupAndroidMultiplatformLibraryTargetSources( + target: KotlinTarget, + genTaskProvider: TaskProvider, + compilation: KotlinCompilation<*>, +) { + if (target !is KotlinMultiplatformAndroidLibraryTarget) { + return + } + + val androidExtension: KotlinMultiplatformAndroidComponentsExtension = + target.project.extensions.findByType() ?: throw GradleException( + "KotlinMultiplatformAndroidComponentsExtension not found " + + "in project with 'com.android.kotlin.multiplatform.library'" + ) + + val hasNewVariantApi: Boolean = hasMinimalVersion( + minVersion = AGP_8_10_0, + currentVersion = CurrentAndroidGradlePluginVersion.CURRENT_AGP_VERSION.version + ) + + if (hasNewVariantApi) { + androidExtension.onVariants { variant: KotlinMultiplatformAndroidVariant -> + variantHandler( + variant = variant, + genTaskProvider = genTaskProvider, + compilation = compilation + ) + } + } else { + // Remove this 'else' branch and the 'hasNewVariantApi' + // check when dropping support for AGP < 8.10.0. + // The 'onVariant' API is scheduled for removal in AGP 9.0. + @Suppress("DEPRECATION") + androidExtension.onVariant { variant: KotlinMultiplatformAndroidVariant -> + variantHandler( + variant = variant, + genTaskProvider = genTaskProvider, + compilation = compilation + ) + } + } +} + +/** + * Configures a single Android variant for use with generated resources when building under the + * Kotlin Multiplatform Android plugin. + * + * For variants associated with a `KotlinMultiplatformAndroidCompilation`, this function: + * - registers all generated source, resource, and asset directories into the variant's + * source sets via [addKmpAndroidGeneratedSources]; + * - configures the resource generation task with the variant’s Android source set name. + * + * Only the variant whose name matches the compilation’s component name is configured. + * Errors during task configuration are logged but do not fail the build. + */ +private fun variantHandler( + variant: Variant, + genTaskProvider: TaskProvider, + compilation: KotlinCompilation<*>, +) { + if (compilation !is KotlinMultiplatformAndroidCompilation) return + + if (variant.name == compilation.componentName) { + variant.sources.addKmpAndroidGeneratedSources(genTaskProvider) + + genTaskProvider.configure { + it.androidSourceSetName.set(variant.name) + } + } +} diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/SetupAndroidTargetSources.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/SetupAndroidTargetSources.kt new file mode 100644 index 000000000..9328a0f47 --- /dev/null +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/SetupAndroidTargetSources.kt @@ -0,0 +1,82 @@ +/* + * Copyright 2025 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator.platform.android + +import com.android.build.api.dsl.AndroidSourceSet +import com.android.build.api.variant.Variant +import dev.icerock.gradle.tasks.GenerateMultiplatformResourcesTask +import org.gradle.api.GradleException +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.Project +import org.gradle.api.tasks.TaskProvider +import org.gradle.kotlin.dsl.extra +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.KotlinTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation +import org.jetbrains.kotlin.gradle.plugin.sources.android.findAndroidSourceSet + +/** + * Configures resource generation for standard Android targets (Application and Library). + * + * This function performs the "heavy lifting" for standard AGP projects: + * 1. Maps the [KotlinSourceSet] to the corresponding [AndroidSourceSet]. + * 2. Injects the generated source directories into the Android [Variant] API. + * 3. Handles nested components like unit tests or custom test fixtures. + * + * It relies on the variants collected by [setupAndroidVariantsSync] and ensures that + * the [GenerateMultiplatformResourcesTask] is aware of the specific Android source + * set it is serving. + * + * @param target The [KotlinTarget], expected to be a [KotlinAndroidTarget]. + * @param sourceSet The source set containing the resources. + * @param genTaskProvider The provider for the generation task. + * @param compilation The current Android-specific Kotlin compilation. + */ +@OptIn(ExperimentalKotlinGradlePluginApi::class) +internal fun setupAndroidTargetSources( + target: KotlinTarget, + sourceSet: KotlinSourceSet, + genTaskProvider: TaskProvider, + compilation: KotlinCompilation<*>, +) { + if (target !is KotlinAndroidTarget) { + return + } + + val project: Project = target.project + + val androidCompilation = compilation as KotlinJvmAndroidCompilation + + // 1. Identify the corresponding Android source set (e.g., "main", "debug"). + val androidSourceSet: AndroidSourceSet = project.findAndroidSourceSet( + kotlinSourceSet = sourceSet + ) ?: throw GradleException("can't find android source set for $sourceSet") + + // Inform the task which Android source set it's working with. + genTaskProvider.configure { it.androidSourceSetName.set(androidSourceSet.name) } + + // 2. Access the variants collected during the synchronization phase. + @Suppress("UNCHECKED_CAST") + val androidVariants: NamedDomainObjectContainer = project.extra + .get(VARIANTS_EXTRA_NAME) as NamedDomainObjectContainer + + // 3. Wire generated sources into the AGP Variant API. + androidVariants.configureEach { variant: Variant -> + // Direct variant match (e.g., "debug" == "debug") + if (variant.name == androidCompilation.name) { + variant.sources.addLegacyAndroidGeneratedSources(genTaskProvider) + } + + // Check nested components (e.g., unit tests associated with the variant) + variant.nestedComponents.forEach { component -> + if (component.name == androidCompilation.name) { + component.sources.addLegacyAndroidGeneratedSources(genTaskProvider) + } + } + } +} diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/SetupAndroidUtils.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/SetupAndroidUtils.kt index 7ce37a4d1..679e9f745 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/SetupAndroidUtils.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/SetupAndroidUtils.kt @@ -8,11 +8,9 @@ import com.android.build.api.dsl.AndroidSourceSet import com.android.build.api.variant.AndroidComponentsExtension import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.android.build.api.variant.LibraryAndroidComponentsExtension -import com.android.build.api.variant.Sources import com.android.build.api.variant.Variant import com.android.build.gradle.BaseExtension import dev.icerock.gradle.tasks.GenerateMultiplatformResourcesTask -import org.gradle.api.GradleException import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project import org.gradle.api.tasks.TaskProvider @@ -22,13 +20,29 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.KotlinTarget -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation import org.jetbrains.kotlin.gradle.plugin.sources.android.androidSourceSetInfoOrNull -import org.jetbrains.kotlin.gradle.plugin.sources.android.findAndroidSourceSet -private const val VARIANTS_EXTRA_NAME = "dev.icerock.moko.resources.android-variants" +internal const val VARIANTS_EXTRA_NAME = "dev.icerock.moko.resources.android-variants" +/** + * Orchestrates Android-specific wiring for multiplatform resource generation. + * + * This function integrates the [GenerateMultiplatformResourcesTask] into the Android + * build pipeline based on the applied plugins: + * + * - **Standard Android Plugins** (`com.android.application` / `com.android.library`): + * Registers generated sources and assets via the standard Android target logic. + * - **KMP Android Plugin** (`com.android.kotlin.multiplatform.library`): + * Integrates with the Kotlin Multiplatform Android variant API. + * + * Additionally, it ensures that resource generation occurs before the `preBuild` + * phase to prevent issues with Lint, resource merging, and packaging. + * + * @param target The [KotlinTarget] being configured. + * @param sourceSet The specific [KotlinSourceSet] participating in the Android compilation. + * @param genTaskProvider The provider for the resource generation task. + * @param compilation The [KotlinCompilation] associated with this setup. + */ @OptIn(ExperimentalKotlinGradlePluginApi::class) internal fun setupAndroidTasks( target: KotlinTarget, @@ -36,80 +50,68 @@ internal fun setupAndroidTasks( genTaskProvider: TaskProvider, compilation: KotlinCompilation<*>, ) { - if (target !is KotlinAndroidTarget) return - - compilation as KotlinJvmAndroidCompilation - val project: Project = target.project - val androidSourceSet: AndroidSourceSet = project.findAndroidSourceSet(sourceSet) - ?: throw GradleException("can't find android source set for $sourceSet") - - // save android sourceSet name to skip build type specific tasks - @Suppress("UnstableApiUsage") - genTaskProvider.configure { it.androidSourceSetName.set(androidSourceSet.name) } - - // connect generateMR task with android tasks - val androidVariants: NamedDomainObjectContainer = project.extra - .get(VARIANTS_EXTRA_NAME) as NamedDomainObjectContainer - - androidVariants - .configureEach { variant -> - if (variant.name == compilation.name) { - variant.sources.addGenerationTaskDependency(genTaskProvider) - } + // 1. Setup for Standard AGP (Application or Library) + if (project.hasAndroidApplicationPlugin() || project.hasAndroidLibraryPlugin()) { + setupAndroidTargetSources( + target = target, + sourceSet = sourceSet, + genTaskProvider = genTaskProvider, + compilation = compilation + ) + } - variant.nestedComponents.forEach { component -> - if (component.name == compilation.name) { - component.sources.addGenerationTaskDependency(genTaskProvider) - } - } - } + // 2. Setup for Kotlin Multiplatform Android Library + if (project.hasAndroidKmpLibraryPlugin()) { + setupAndroidMultiplatformLibraryTargetSources( + target = target, + genTaskProvider = genTaskProvider, + compilation = compilation + ) + } - // to fix issues with android lint - depends on preBuild + // Wiring to preBuild: + // This is crucial for Android as it ensures resources are ready before Lint or + // any code analysis tasks start looking for them. project.tasks .matching { it.name == "preBuild" } .configureEach { it.dependsOn(genTaskProvider) } } -internal fun Sources.addGenerationTaskDependency(provider: TaskProvider) { - @Suppress("UnstableApiUsage") - kotlin?.addGeneratedSourceDirectory( - taskProvider = provider, - wiredWith = GenerateMultiplatformResourcesTask::outputSourcesDir - ) - - // Resources doesn't add in android variants for IDE indexing - // Resource directory set here: - // dev.icerock.gradle.MultiplatformResourcesPlugin.setupSourceSets - // res?.addGeneratedSourceDirectory( - // taskProvider = provider, - // wiredWith = GenerateMultiplatformResourcesTask::outputResourcesDir - // ) - - // Assets add here, for correct compilation - assets?.addGeneratedSourceDirectory( - taskProvider = provider, - wiredWith = GenerateMultiplatformResourcesTask::outputAssetsDir - ) -} - +/** + * Synchronizes Android variants by collecting them into a observable container. + * + * Since Android variants are created and configured during the late stages of + * the Gradle configuration phase, this function uses the [AndroidComponentsExtension.onVariants] + * callback to capture each [Variant] object as it becomes available. + * + * The collected variants are stored in a [NamedDomainObjectContainer] within the + * project's extra properties ([VARIANTS_EXTRA_NAME]). This allows other parts of + * the plugin to react to or query Android variants without directly depending on + * the AGP extension in every call site. + * + * @param project The Gradle project to configure. + * @throws org.gradle.api.GradleException if the [AndroidComponentsExtension] cannot be resolved + * after an Android plugin has been applied. + */ internal fun setupAndroidVariantsSync(project: Project) { - listOf( - "com.android.application", - "com.android.library" - ).forEach { - project.plugins.withId(it) { + androidPlugins().forEach { pluginId -> + project.plugins.withId(pluginId) { + // Create a container to store variants lazily val androidVariants: NamedDomainObjectContainer = project.objects.domainObjectContainer(Variant::class.java) + // Store the container in extra properties for cross-plugin/task access project.extra.set(VARIANTS_EXTRA_NAME, androidVariants) - val componentsExtension: AndroidComponentsExtension<*, *, *> = project.extensions - .findByType() - ?: project.extensions.findByType() - ?: error("can't find AndroidComponentsExtension") + val componentsExtension: AndroidComponentsExtension<*, *, *> = + project.extensions.findByType(LibraryAndroidComponentsExtension::class.java) + ?: project.extensions.findByType(ApplicationAndroidComponentsExtension::class.java) + ?: project.extensions.findByType(AndroidComponentsExtension::class.java) + ?: error("can't find AndroidComponentsExtension") + // Register the callback to populate our container componentsExtension.onVariants { variant: Variant -> androidVariants.add(variant) } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/AndroidTargetExt.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/AndroidTargetExt.kt new file mode 100644 index 000000000..d959c3db1 --- /dev/null +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/AndroidTargetExt.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2025 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.utils + +import com.android.build.gradle.BaseExtension +import org.gradle.api.Project +import org.gradle.kotlin.dsl.findByType + +/** + * Resolves the Android package name (namespace) for standard Android application + * and library modules. + * + * This function retrieves the namespace defined in the `android { ... }` DSL. + * + * @param project The Gradle project instance to inspect. + * @return The resolved namespace [String], or `null` if the extension is missing + * or the namespace is not defined. + */ +internal fun getAndroidTargetRClassPackage(project: Project): String? { + return project.extensions.findByType()?.namespace +} diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/KotlinMultiplatformAndroidLibraryExt.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/KotlinMultiplatformAndroidLibraryExt.kt new file mode 100644 index 000000000..5551847a1 --- /dev/null +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/KotlinMultiplatformAndroidLibraryExt.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2025 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.utils + +import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryExtension +import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget +import org.gradle.api.Project +import org.gradle.kotlin.dsl.findByType +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension + +/** + * Resolves the Android R-class package name (namespace) specifically for + * Kotlin Multiplatform (KMP) Android Library projects. + * + * It looks up the [KotlinMultiplatformAndroidLibraryExtension] within the + * [KotlinProjectExtension] to retrieve the configured `namespace`. + * + * @param project The Gradle project to inspect. + * @return The resolved namespace [String], or `null` if the KMP Android + * extension is missing or the namespace property has not been set. + */ +internal fun getAndroidKmpRClassPackage(project: Project): String? { + val kotlinProjectExtension = project.extensions.findByType() + val androidLibraryExtension: KotlinMultiplatformAndroidLibraryExtension = kotlinProjectExtension + ?.extensions + ?.findByType() + ?: return null + + return androidLibraryExtension.namespace +} + +/** + * Enables Android resources support for all [KotlinMultiplatformAndroidLibraryTarget] targets + * in this project. + * + * This function does **not** track plugin application and assumes that + * the caller invokes it only after the `com.android.kotlin.multiplatform.library` plugin + * has already been applied. + * + * It configures each Android library target to have `androidResources.enable = true`, + * which allows the module to use Android resource folders (`res/`, `assets/`, etc.) + * in the Kotlin Multiplatform Android source sets. + */ +internal fun Project.enableAndroidResources() { + val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java) + + kmpExtension.targets.withType() + .configureEach { target -> + target.androidResources.enable = true + } +} diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/KotlinPlatformTypeExt.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/KotlinPlatformTypeExt.kt old mode 100644 new mode 100755 diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/ProjectExt.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/ProjectExt.kt index 9e43361e2..ef7a25c1f 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/ProjectExt.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/ProjectExt.kt @@ -4,45 +4,55 @@ package dev.icerock.gradle.utils -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.api.AndroidSourceSet +import dev.icerock.gradle.generator.platform.android.AndroidPluginType +import dev.icerock.gradle.generator.platform.android.hasAndroidApplicationPlugin +import dev.icerock.gradle.generator.platform.android.hasAndroidKmpLibraryPlugin +import dev.icerock.gradle.generator.platform.android.hasAndroidLibraryPlugin +import dev.icerock.gradle.generator.platform.android.hasAnyAndroidPlugin import org.gradle.api.Project import org.gradle.api.provider.Provider -import org.gradle.api.tasks.SourceSet -import org.gradle.kotlin.dsl.findByType -import org.w3c.dom.Document -import org.w3c.dom.Node -import org.w3c.dom.NodeList -import java.io.File -import javax.xml.parsers.DocumentBuilder -import javax.xml.parsers.DocumentBuilderFactory +/** + * Resolves the Android R-class package name (namespace) for the current project. + * + * This function determines the package name used for generated Android resource classes. + * The resolution is performed lazily within a [Provider] to ensure it captures + * configuration changes during the Gradle configuration phase. + * + * The logic evaluates plugins in the following order: + * 1. **KMP Android Library**: Checks for `com.android.kotlin.multiplatform.library`. + * 2. **Standard AGP**: Checks for `com.android.application` or `com.android.library`. + * + * @return A [Provider] supplying: + * - The resolved package name (e.g., "com.example.project"). + * - `null`: If no supported Android plugins are applied. + * + * @throws IllegalStateException If an Android plugin is present but the namespace + * cannot be resolved through supported methods. + */ internal fun Project.getAndroidRClassPackage(): Provider { return provider { - // before call android specific classes we should ensure that android plugin in classpath at all - // it's required to support gradle projects without android target - val isAndroidEnabled = listOf( - "com.android.library", - "com.android.application" - ).any { project.plugins.findPlugin(it) != null } - if (!isAndroidEnabled) return@provider null - - val androidExt: BaseExtension = project.extensions.findByType() - ?: return@provider null - androidExt.namespace ?: getAndroidPackage(androidExt.mainSourceSet.manifest.srcFile) + // Before accessing Android-specific classes, ensure an Android plugin is on the classpath. + // This prevents NoClassDefFoundError in non-Android projects or modules. + if (!project.hasAnyAndroidPlugin()) { + return@provider null + } + + // 1. Check for Kotlin Multiplatform Android Library + if (project.hasAndroidKmpLibraryPlugin()) { + return@provider getAndroidKmpRClassPackage(project) + } + + // 2. Check for standard Android Application or Android Library + if (project.hasAndroidApplicationPlugin() || project.hasAndroidLibraryPlugin()) { + return@provider getAndroidTargetRClassPackage(project) + } + + error( + "Android R class package not found for project '${project.path}'. " + + "Expected one of Android plugins:" + + " ${AndroidPluginType.entries.joinToString { it.pluginId }}," + + " and configured android namespace." + ) } } - -private fun getAndroidPackage(manifestFile: File): String { - val dbFactory: DocumentBuilderFactory = DocumentBuilderFactory.newInstance() - val dBuilder: DocumentBuilder = dbFactory.newDocumentBuilder() - val doc: Document = dBuilder.parse(manifestFile) - - val manifestNodes: NodeList = doc.getElementsByTagName("manifest") - val manifest: Node = manifestNodes.item(0) - - return manifest.attributes.getNamedItem("package").textContent -} - -internal val BaseExtension.mainSourceSet: AndroidSourceSet - get() = this.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/VersionUtils.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/VersionUtils.kt new file mode 100644 index 000000000..b36ef4b50 --- /dev/null +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/VersionUtils.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2025 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.utils + +/** + * Checks if the [currentVersion] is greater than or equal to the [minVersion]. + * + * Both versions are expected to be in the format `major.minor.patch` (e.g., "9.0.0"). + * Pre-release suffixes such as "-beta", "-alpha", "-rc" are ignored. + * + * The comparison rules are: + * 1. Compare major versions. If current major > min major, return true; if less, return false. + * 2. If majors are equal, compare minor versions similarly. + * 3. If both major and minor are equal, compare patch versions. + * + * Examples: + * ``` + * hasMinimalVersion("8.1.0", "8.11.1") // true + * hasMinimalVersion("9.0.0", "8.11.1") // false + * hasMinimalVersion("9.0.0", "9.0.0-beta3") // true + * ``` + * + * @param minVersion the minimal required version (inclusive) + * @param currentVersion the version to check against the minimal version + * @return true if [currentVersion] is greater than or equal to [minVersion], false otherwise + */ +internal fun hasMinimalVersion(minVersion: String, currentVersion: String): Boolean { + val (minMaj, minMin, minPatch) = parseVersion(minVersion) + val (curMaj, curMin, curPatch) = parseVersion(currentVersion) + + return when { + curMaj > minMaj -> true + curMaj < minMaj -> false + + curMin > minMin -> true + curMin < minMin -> false + + else -> curPatch >= minPatch + } +} + +/** + * Parses a version string into a Triple of integers representing major, minor, and patch numbers. + * + * Pre-release suffixes such as "-beta", "-alpha", "-rc" are ignored. + * Missing minor or patch numbers default to 0. + * + * Examples: + * ``` + * parseVersion("9.0.0-beta3") // Triple(9,0,0) + * parseVersion("8.11") // Triple(8,11,0) + * parseVersion("7") // Triple(7,0,0) + * ``` + * + * @param raw the version string to parse + * @return a [Triple] containing major, minor, and patch numbers + */ +private fun parseVersion(raw: String): Triple { + val core: String = raw.substringBefore('-') // remove alpha/beta/rc/etc + val parts: List = core.split('.') + + val major: Int = parts.getOrNull(0)?.toIntOrNull() ?: 0 + val minor: Int = parts.getOrNull(1)?.toIntOrNull() ?: 0 + val patch: Int = parts.getOrNull(2)?.toIntOrNull() ?: 0 + + return Triple(major, minor, patch) +} diff --git a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/VersionCompareTest.kt b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/VersionCompareTest.kt new file mode 100644 index 000000000..7311dc76f --- /dev/null +++ b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/VersionCompareTest.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2025 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator + +import dev.icerock.gradle.utils.hasMinimalVersion +import kotlin.test.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class VersionCompareTest { + + @Test + fun `current major greater than min`() { + assertTrue(hasMinimalVersion("8.0.0", "9.0.0")) + } + + @Test + fun `current major less than min`() { + assertFalse(hasMinimalVersion("9.0.0", "8.11.1")) + } + + @Test + fun `current minor greater than min`() { + assertTrue(hasMinimalVersion("8.1.0", "8.11.1")) + } + + @Test + fun `current minor less than min`() { + assertFalse(hasMinimalVersion("8.11.1", "8.1.0")) + } + + @Test + fun `current patch greater than min`() { + assertTrue(hasMinimalVersion("8.11.0", "8.11.1")) + } + + @Test + fun `current patch equal to min`() { + assertTrue(hasMinimalVersion("8.11.1", "8.11.1")) + } + + @Test + fun `current patch less than min`() { + assertFalse(hasMinimalVersion("8.11.2", "8.11.1")) + } + + @Test + fun `current with beta greater or equal`() { + assertTrue(hasMinimalVersion("9.0.0", "9.0.0-beta3")) + assertTrue(hasMinimalVersion("9.0.0-beta3", "9.0.0-beta3")) + } + + @Test + fun `current with beta less than min`() { + assertFalse(hasMinimalVersion("9.0.1", "9.0.0-beta3")) + } + + @Test + fun `minVersion without patch`() { + assertTrue(hasMinimalVersion("9.0", "9.0.1")) + assertTrue(hasMinimalVersion("9.0", "9.0.0-beta3")) + assertFalse(hasMinimalVersion("9.1", "9.0.0")) + } +} diff --git a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/FileResource.kt b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/FileResource.kt index fd3585e06..2463529ef 100644 --- a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/FileResource.kt +++ b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/FileResource.kt @@ -4,6 +4,7 @@ package dev.icerock.moko.resources +import kotlinx.cinterop.BetaInteropApi import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.ObjCObjectVar import kotlinx.cinterop.alloc @@ -32,7 +33,7 @@ actual open class FileResource( subdirectory = "files" )!! - @OptIn(ExperimentalForeignApi::class) + @OptIn(ExperimentalForeignApi::class, BetaInteropApi::class) fun readText(): String { val filePath = path val (result: String?, error: NSError?) = memScoped { diff --git a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/FontResource.kt b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/FontResource.kt index 081c0f8c2..e30a17be7 100644 --- a/resources/src/appleMain/kotlin/dev/icerock/moko/resources/FontResource.kt +++ b/resources/src/appleMain/kotlin/dev/icerock/moko/resources/FontResource.kt @@ -46,6 +46,7 @@ actual class FontResource( val bundle: NSBundle = NSBundle.mainBundle, ) { @OptIn(ExperimentalForeignApi::class, UnsafeNumber::class) + @Suppress("UNCHECKED_CAST") internal val fontRef: CGFontRef by lazy { val fontData: NSData = this.data val cfDataRef: CPointer<__CFData>? = CFDataCreate( diff --git a/samples/android-mpp-app/app/build.gradle.kts b/samples/android-mpp-app/app/build.gradle.kts index 0ef351c3a..b4b3259ee 100644 --- a/samples/android-mpp-app/app/build.gradle.kts +++ b/samples/android-mpp-app/app/build.gradle.kts @@ -34,6 +34,10 @@ android { kotlin { androidTarget() + + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } } dependencies { diff --git a/samples/android-mpp-app/build.gradle.kts b/samples/android-mpp-app/build.gradle.kts index 32282e78f..2576bf44f 100644 --- a/samples/android-mpp-app/build.gradle.kts +++ b/samples/android-mpp-app/build.gradle.kts @@ -11,7 +11,7 @@ buildscript { } dependencies { classpath(moko.resourcesGradlePlugin) - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.0") classpath("com.android.tools.build:gradle:8.1.0") } } diff --git a/samples/auto-manifest/build.gradle.kts b/samples/auto-manifest/build.gradle.kts index a4bbb97ab..34999c216 100644 --- a/samples/auto-manifest/build.gradle.kts +++ b/samples/auto-manifest/build.gradle.kts @@ -11,8 +11,8 @@ buildscript { } dependencies { classpath(moko.resourcesGradlePlugin) - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0") - classpath("com.android.tools.build:gradle:8.0.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0") + classpath("com.android.tools.build:gradle:8.3.0") classpath("com.gradleup:auto-manifest-plugin:2.0") } } diff --git a/samples/auto-manifest/gradle/wrapper/gradle-wrapper.properties b/samples/auto-manifest/gradle/wrapper/gradle-wrapper.properties index ac72c34e8..175551e6c 100755 --- a/samples/auto-manifest/gradle/wrapper/gradle-wrapper.properties +++ b/samples/auto-manifest/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,8 @@ +#Mon Dec 29 01:05:15 NOVT 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/samples/auto-manifest/mpp-library/build.gradle.kts b/samples/auto-manifest/mpp-library/build.gradle.kts index e503fa240..07cc750b1 100644 --- a/samples/auto-manifest/mpp-library/build.gradle.kts +++ b/samples/auto-manifest/mpp-library/build.gradle.kts @@ -19,6 +19,10 @@ android { kotlin { androidTarget() + + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } } dependencies { diff --git a/samples/cm-resources-sample/build.gradle.kts b/samples/cm-resources-sample/build.gradle.kts index 7fa07b8c9..7c90de5c5 100644 --- a/samples/cm-resources-sample/build.gradle.kts +++ b/samples/cm-resources-sample/build.gradle.kts @@ -1,6 +1,7 @@ plugins { alias(libs.plugins.multiplatform).apply(false) alias(libs.plugins.compose).apply(false) + alias(libs.plugins.kotlin.compose).apply(false) alias(libs.plugins.android.application).apply(false) } diff --git a/samples/cm-resources-sample/composeApp/build.gradle.kts b/samples/cm-resources-sample/composeApp/build.gradle.kts index cadf76000..9a4354a1f 100644 --- a/samples/cm-resources-sample/composeApp/build.gradle.kts +++ b/samples/cm-resources-sample/composeApp/build.gradle.kts @@ -7,6 +7,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree plugins { alias(libs.plugins.multiplatform) alias(libs.plugins.compose) + alias(libs.plugins.kotlin.compose) alias(libs.plugins.android.application) id("dev.icerock.mobile.multiplatform-resources") } @@ -50,6 +51,10 @@ kotlin { } } + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } + sourceSets { all { languageSettings { diff --git a/samples/cm-resources-sample/gradle/libs.versions.toml b/samples/cm-resources-sample/gradle/libs.versions.toml index f355ff62b..965d336f4 100644 --- a/samples/cm-resources-sample/gradle/libs.versions.toml +++ b/samples/cm-resources-sample/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] -kotlin = "1.9.23" -compose = "1.6.10-rc01" +kotlin = "2.1.0" +compose = "1.6.11" agp = "8.3.1" androidx-activityCompose = "1.8.2" androidx-uiTest = "1.6.4" @@ -16,4 +16,5 @@ androidx-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } compose = { id = "org.jetbrains.compose", version.ref = "compose" } +kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } android-application = { id = "com.android.application", version.ref = "agp" } diff --git a/samples/compose-jvm-app/build.gradle.kts b/samples/compose-jvm-app/build.gradle.kts index 17377f439..b4a2725f7 100644 --- a/samples/compose-jvm-app/build.gradle.kts +++ b/samples/compose-jvm-app/build.gradle.kts @@ -7,7 +7,8 @@ buildscript { } dependencies { classpath(moko.resourcesGradlePlugin) - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10") - classpath("org.jetbrains.compose:compose-gradle-plugin:1.5.11") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0") + classpath("org.jetbrains.compose:compose-gradle-plugin:1.6.11") + classpath("org.jetbrains.kotlin:compose-compiler-gradle-plugin:2.1.0") } } diff --git a/samples/compose-jvm-app/common/build.gradle.kts b/samples/compose-jvm-app/common/build.gradle.kts index f70abfede..8f658e0cd 100644 --- a/samples/compose-jvm-app/common/build.gradle.kts +++ b/samples/compose-jvm-app/common/build.gradle.kts @@ -1,6 +1,7 @@ plugins { kotlin("multiplatform") id("org.jetbrains.compose") + kotlin("plugin.compose") id("dev.icerock.mobile.multiplatform-resources") } @@ -36,6 +37,10 @@ kotlin { } val desktopTest by getting } + + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } } multiplatformResources { diff --git a/samples/compose-jvm-app/gradle/wrapper/gradle-wrapper.properties b/samples/compose-jvm-app/gradle/wrapper/gradle-wrapper.properties index 37aef8d3f..701972df4 100644 --- a/samples/compose-jvm-app/gradle/wrapper/gradle-wrapper.properties +++ b/samples/compose-jvm-app/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,8 @@ +#Mon Dec 29 01:13:27 NOVT 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/samples/compose-resources-gallery/shared/build.gradle.kts b/samples/compose-resources-gallery/shared/build.gradle.kts index 953ea426c..80275c6bd 100644 --- a/samples/compose-resources-gallery/shared/build.gradle.kts +++ b/samples/compose-resources-gallery/shared/build.gradle.kts @@ -1,3 +1,6 @@ +@file:OptIn(ExperimentalWasmDsl::class) + +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.tasks.DummyFrameworkTask plugins { @@ -22,9 +25,7 @@ kotlin { macosX64() jvm("desktop") - js(IR) { - browser() - } + js { browser() } wasmJs { browser() binaries.executable() @@ -43,6 +44,10 @@ kotlin { extraSpecAttributes["resource"] = "'build/cocoapods/framework/shared.framework/*.bundle'" } + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } + @Suppress("UNUSED_VARIABLE") sourceSets { val commonMain by getting { diff --git a/samples/default-hierarchy-gallery-mobile/build.gradle.kts b/samples/default-hierarchy-gallery-mobile/build.gradle.kts index 48b847875..b13fcfcb5 100644 --- a/samples/default-hierarchy-gallery-mobile/build.gradle.kts +++ b/samples/default-hierarchy-gallery-mobile/build.gradle.kts @@ -15,9 +15,9 @@ buildscript { } dependencies { classpath(moko.resourcesGradlePlugin) - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.21") - classpath("org.jetbrains.compose:compose-gradle-plugin:1.5.11") - classpath("com.android.tools.build:gradle:8.1.4") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.10") + classpath("org.jetbrains.compose:compose-gradle-plugin:1.7.3") + classpath("com.android.tools.build:gradle:8.3.2") } } diff --git a/samples/default-hierarchy-gallery-mobile/mpp-library/build.gradle.kts b/samples/default-hierarchy-gallery-mobile/mpp-library/build.gradle.kts index 023e388a0..716bde93b 100644 --- a/samples/default-hierarchy-gallery-mobile/mpp-library/build.gradle.kts +++ b/samples/default-hierarchy-gallery-mobile/mpp-library/build.gradle.kts @@ -43,6 +43,10 @@ kotlin { export(moko.resources) } } + + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } } dependencies { diff --git a/samples/gradle-agp-9-sample/.gitignore b/samples/gradle-agp-9-sample/.gitignore new file mode 100644 index 000000000..fdbf6bc0d --- /dev/null +++ b/samples/gradle-agp-9-sample/.gitignore @@ -0,0 +1,11 @@ +*.iml +.gradle +.idea +.DS_Store +.kotlin +build +captures +.externalNativeBuild +.cxx +local.properties +xcuserdata \ No newline at end of file diff --git a/samples/gradle-agp-9-sample/README.md b/samples/gradle-agp-9-sample/README.md new file mode 100644 index 000000000..c095b4155 --- /dev/null +++ b/samples/gradle-agp-9-sample/README.md @@ -0,0 +1,6 @@ +# Sample of project with Gradle and Android Gradle Plugin 9+ + +## Build + +1. publish moko-resources to local maven - `./gradlew publishToMavenLocal` in `moko-resources` root +2. build sample (in IDE or by `./gradlew build`) diff --git a/samples/gradle-agp-9-sample/androidApp/build.gradle.kts b/samples/gradle-agp-9-sample/androidApp/build.gradle.kts new file mode 100644 index 000000000..854f424f0 --- /dev/null +++ b/samples/gradle-agp-9-sample/androidApp/build.gradle.kts @@ -0,0 +1,41 @@ +plugins { + alias(libs.plugins.androidApplication) + alias(libs.plugins.compose.compiler) +} + +android { + namespace = "com.gradle9.android" + compileSdk = 36 + + defaultConfig { + applicationId = "app.gradle9.android" + minSdk = 26 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" + } + + buildFeatures { + compose = true + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } + buildTypes { + getByName("release") { + isMinifyEnabled = false + } + } +} + +dependencies { + implementation(projects.shared) + implementation(libs.compose.ui) + implementation(libs.compose.ui.tooling.preview) + implementation(libs.compose.material3) + implementation(libs.androidx.activity.compose) + implementation(moko.resourcesCompose) + debugImplementation(libs.compose.ui.tooling) +} \ No newline at end of file diff --git a/samples/gradle-agp-9-sample/androidApp/src/main/AndroidManifest.xml b/samples/gradle-agp-9-sample/androidApp/src/main/AndroidManifest.xml new file mode 100644 index 000000000..9b4600fea --- /dev/null +++ b/samples/gradle-agp-9-sample/androidApp/src/main/AndroidManifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/gradle-agp-9-sample/androidApp/src/main/java/com/gradle9sample/android/MainActivity.kt b/samples/gradle-agp-9-sample/androidApp/src/main/java/com/gradle9sample/android/MainActivity.kt new file mode 100644 index 000000000..301caa0c3 --- /dev/null +++ b/samples/gradle-agp-9-sample/androidApp/src/main/java/com/gradle9sample/android/MainActivity.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2025 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package com.gradle9sample.android + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.gradle9sample.Greeting +import com.gradle9sample.android.library.R +import dev.icerock.moko.resources.compose.localized + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + MyApplicationTheme { + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background + ) { + Column { + GreetingView(Greeting().greet()) + Text(text = Greeting().getMR().localized()) + Text(text = stringResource(id = R.string.hello_world)) + } + } + } + } + } +} + +@Composable +fun GreetingView(text: String) { + Text(text = text) +} + +@Preview +@Composable +fun DefaultPreview() { + MyApplicationTheme { + GreetingView("Hello, Android!") + } +} diff --git a/samples/gradle-agp-9-sample/androidApp/src/main/java/com/gradle9sample/android/MyApplicationTheme.kt b/samples/gradle-agp-9-sample/androidApp/src/main/java/com/gradle9sample/android/MyApplicationTheme.kt new file mode 100644 index 000000000..ba49b809e --- /dev/null +++ b/samples/gradle-agp-9-sample/androidApp/src/main/java/com/gradle9sample/android/MyApplicationTheme.kt @@ -0,0 +1,55 @@ +package com.gradle9sample.android + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Shapes +import androidx.compose.material3.Typography +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun MyApplicationTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + content: @Composable () -> Unit +) { + val colors = if (darkTheme) { + darkColorScheme( + primary = Color(0xFFBB86FC), + secondary = Color(0xFF03DAC5), + tertiary = Color(0xFF3700B3) + ) + } else { + lightColorScheme( + primary = Color(0xFF6200EE), + secondary = Color(0xFF03DAC5), + tertiary = Color(0xFF3700B3) + ) + } + val typography = Typography( + bodyMedium = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp + ) + ) + val shapes = Shapes( + small = RoundedCornerShape(4.dp), + medium = RoundedCornerShape(4.dp), + large = RoundedCornerShape(0.dp) + ) + + MaterialTheme( + colorScheme = colors, + typography = typography, + shapes = shapes, + content = content + ) +} diff --git a/samples/gradle-agp-9-sample/androidApp/src/main/res/values/styles.xml b/samples/gradle-agp-9-sample/androidApp/src/main/res/values/styles.xml new file mode 100644 index 000000000..6b4fa3d08 --- /dev/null +++ b/samples/gradle-agp-9-sample/androidApp/src/main/res/values/styles.xml @@ -0,0 +1,3 @@ + +