{"id":13992231,"url":"https://github.com/handstandsam/kmp4free","last_synced_at":"2025-04-05T04:31:23.242Z","repository":{"id":38441137,"uuid":"496821777","full_name":"handstandsam/kmp4free","owner":"handstandsam","description":"A Gradle Plugin that allows seamless switching between Kotlin JVM and the Kotlin Multiplatform Plugins","archived":false,"fork":false,"pushed_at":"2022-09-14T14:03:55.000Z","size":464,"stargazers_count":62,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-20T22:18:43.220Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/handstandsam.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-05-27T01:16:37.000Z","updated_at":"2024-01-24T19:46:07.000Z","dependencies_parsed_at":"2022-07-12T15:30:37.014Z","dependency_job_id":null,"html_url":"https://github.com/handstandsam/kmp4free","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/handstandsam%2Fkmp4free","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/handstandsam%2Fkmp4free/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/handstandsam%2Fkmp4free/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/handstandsam%2Fkmp4free/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/handstandsam","download_url":"https://codeload.github.com/handstandsam/kmp4free/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289382,"owners_count":20914463,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-09T14:01:53.425Z","updated_at":"2025-04-05T04:31:18.212Z","avatar_url":"https://github.com/handstandsam.png","language":"Kotlin","funding_links":[],"categories":["Kotlin"],"sub_categories":[],"readme":"# 🆓 kmp4free\n[![LICENSE](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/handstandsam/kmp4free/blob/main/LICENSE)\n[![Latest Stable](https://img.shields.io/badge/dynamic/xml?url=https://repo1.maven.org/maven2/com/handstandsam/kmp4free/kmp4free/maven-metadata.xml\u0026label=Latest%20Stable\u0026color=blue\u0026query=.//versioning/latest)](https://repo1.maven.org/maven2/com/handstandsam/kmp4free/kmp4free/)\n[![Latest Snapshot](https://img.shields.io/badge/dynamic/xml?url=https://s01.oss.sonatype.org/content/repositories/snapshots/com/handstandsam/kmp4free/kmp4free/maven-metadata.xml\u0026label=Latest%20Snapshot\u0026color=orange\u0026query=.//versioning/latest)](https://s01.oss.sonatype.org/content/repositories/snapshots/com/handstandsam/kmp4free/com.handstandsam.kmp4free.gradle.plugin/)\n[![CI](https://github.com/handstandsam/kmp4free/workflows/CI/badge.svg)](https://github.com/handstandsam/kmp4free/actions?query=branch%3Amain)\n\nAllows you to toggle between Kotlin JVM Plugin -\u003e Kotlin Multiplatform with a Gradle Property `kmp4free=true`.\n\nThis Gradle Plugin was built to support gradual adoption of Kotlin Multiplatform.  It's called `kmp4free` because you are able to take a normal Kotlin JVM module, and with a single line change, enable or disable the Kotlin Multiplatform Plugin.\n\nThere is always a risk of adding something new, especially with a large project. The introduction of a technology that is not at a stable version yet can block the adoption of a new technology.  The goal of this plugin is to reduce risk to a single line change.\n\n## Plugin Installation\nAdd the Snapshot Repo in your project's `settings.gradle.kts`\n```kotlin\npluginManagement {\n    repositories {\n        // ...\n        maven { url = \"https://s01.oss.sonatype.org/content/repositories/snapshots/\" }\n    }\n}\n```\n\nAdd the Plugin on your project's `build.gradle.kts`\n```kotlin\nplugins {\n    id(\"com.handstandsam.kmp4free\") version \"${latest_version}\"\n}\n```\n\n## Usage\nJust replace `kotlin(\"jvm\")` with `id(\"com.handstandsam.kmp4free\")` in the `plugins` block of your module's `build.gradle.kts` file.\n\n### Enabling Multiplatform\nYou can set `kmp4free=true` in your `gradle.properties` or send it in as a command-line parameter to gradle with `-Pkmp4free=true`.\n\nThis enables property the Kotlin Multiplatform Plugin, along with the additional changes required to support seamless switching between the Kotlin JVM Plugin.\n\nAny code in the `main` sourceSet needs to be `commonMain` compatible when `multiplatform` is enabled, otherwise the build will fail about not being able to resolve JVM dependencies.  This isn't a bad thing though, as you will then be able to identify what you need to change to make your code multiplatform compatible.\n\n#### SourceSet Mapping\n* `src/main` ➡️ `src/commonMain`\n* `src/test` ➡️ `src/jvmTest`\n\n#### Configuration Mapping\n* `implementation` ➡️ `commonMainImplementation`\n* `api` ➡️ `commonMainApi`\n* `testImplementation` ➡️ `jvmTestImplementation`\n* `testApi` ➡️ `jvmTestApi`\n\nWhen tests are already written with JVM Libraries like JUnit and Google's Truth library, it would be a lot of work to migrate those tests over to `commonTest`, so these tests will only run on the JVM with `kmp4free`.  Additionally, this task alias means that your scripts that run Gradle Tasks do not have to update either when the plugin is enabled, since the `test` task will be available.\n\n#### Task Aliasing\n* `:module:test` ➡️ `:module:jvmTest`\n\n## Disabling Multiplatform\nThis uses the Kotlin JVM Plugin, and bypasses Kotlin Multiplatform entirely.\n\n#### SourceSet Mapping\n* `src/commonMain` ➡️ `src/main`\n* `src/jvmMain` ➡️ `src/main`\n* `src/commonTest` ➡️ `src/test`\n* `src/jvmTest` ➡️ `src/test`\n\n\n#### Configuration Mapping\n* `commonMainImplementation` ➡️ `implementation`\n* `commonMainApi` ➡️ `api`\n* `commonTestImplementation` ➡️ `testImplementation`\n* `commonTestApi` ➡️ `testApi`\n* `jvmTestImplementation` ➡️ `testImplementation`\n* `jvmTestApi` ➡️ `testApi`\n\nYou can set the following properties in your `gradle.properties`\n\n## Related Content\n\nDroidcon SF Presentation: [Embracing `commonMain` for Android Development](https://speakerdeck.com/handstandsam/embracing-commonmain-for-android-development-droidcon-sf-2022)\n\n[![](docs/images/embracing_common_main_presentation_cover.png)](https://speakerdeck.com/handstandsam/embracing-commonmain-for-android-development-droidcon-sf-2022)\n\n## FAQ\n\n#### Why do I need to use `maybeCreate()`?\nYou may typically see source sets defined like `val commonMain by getting`.  Because with `kmp4free` we toggle the multiplatform plugin on/off, that Source Set will be sometimes be already there, and other times may not be. Therefore we use `maybeCreate(\"commonMain\")` to avoid the error.\n\n#### What Configurations are Mapped?\n* api\n* implementation\n* compileOnly\n* runtimeOnly\n* apiDependenciesMetadata\n* implementationDependenciesMetadata\n* compileOnlyDependenciesMetadata\n* runtimeOnlyDependenciesMetadata\n\n#### Can I use `kmp4free` on an Android Library?\n\nNo. `kmp4free` is a step in the journey of migrating a `kotlin(\"jvm\")` module to `kotlin(\"multiplatform\")` with a `commonMain` SourceSet without adding any plugin changes when disabled.\n\nThe reason why you can't is because a `kotlin(\"jvm\")` module means you cannot have resources in the `res` directory, an `AndroidManifest.xml` and not use Android APIs.  You may find that your Android Library doesn't have any of those.  If that's true, just convert it to a `kotlin(\"jvm\")` module, and then you can use the plugin!\n\nSee [Issue #6](https://github.com/handstandsam/kmp4free/issues/6) for more discussion on this topic.\n\n\n#### How do I configure my Source Sets?\nYou are able to use `jvm` or `multiplatform` style configuration.  Note: will want to use the `maybeCreate(\"commonMain\")` call instead of `val commonMain by getting` when accessing Source Sets.\n\nThat is because sometimes the configuration is there when enabled, but off when disabled.  When you are ready, you can migrate away from the `kmp4free` plugin and start using the standard `kotlin(\"jvm\")` project with just a `jvm()` target.\n\n#### How do I configure my iOS and JS Targets?\n\nYou can only apply your configuration IF the `kotlin(\"multiplatform\")` plugin has been added.  That is because this plugin allows it to be on \u0026 off.\n\nLook up the `KotlinMultiplatformExtension`, and if not null (Checked by the `?.` operator), you can supply your configuration like this:\n```kotlin\nimport org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension\n\nproject.extensions.findByType(KotlinMultiplatformExtension::class.java)?.apply {\n    ios()\n}\n```\n\nYou can find more information in [Issue #2](https://github.com/handstandsam/kmp4free/issues/2).  I'm thinking this would be a lambda in the plugin configuration block for each target.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhandstandsam%2Fkmp4free","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhandstandsam%2Fkmp4free","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhandstandsam%2Fkmp4free/lists"}