All Projects → mverleg → kotlin_multiplatform_gradle_demo

mverleg / kotlin_multiplatform_gradle_demo

Licence: other
My attempt to get Gradle to work with multiplatform Kotlin while using subprojects.

Programming Languages

kotlin
9241 projects
HTML
75241 projects

Labels

Projects that are alternatives of or similar to kotlin multiplatform gradle demo

gradle-jenkins-jobdsl-plugin
A plugin for Gradle to manage Jenkins Job DSL projects.
Stars: ✭ 48 (+100%)
Mutual labels:  gradle
OkOne
基于okhttp库的网络性能优化框架
Stars: ✭ 88 (+266.67%)
Mutual labels:  gradle
Android-GradlePlugin-Demo
Android Studio 自定义 Gradle Plugin
Stars: ✭ 27 (+12.5%)
Mutual labels:  gradle
spark-gradle-template
Apache Spark in your IDE with gradle
Stars: ✭ 39 (+62.5%)
Mutual labels:  gradle
static-code-analysis-plugin
A plugin to simplify Static Code Analysis on Gradle. Not restricted to, but specially useful, in Android projects, by making sure all analysis can access the SDK classes.
Stars: ✭ 36 (+50%)
Mutual labels:  gradle
gradle-helm-plugin
A Gradle plugin for building, publishing and managing Helm charts.
Stars: ✭ 42 (+75%)
Mutual labels:  gradle
gradle-aem-multi
Example Multi-Module AEM application built by Gradle Build System
Stars: ✭ 31 (+29.17%)
Mutual labels:  gradle
spring-boot-microservice-best-practices
Best practices and integrations available for Spring Boot based Microservice in a single repository.
Stars: ✭ 139 (+479.17%)
Mutual labels:  gradle
gatling-gradle-plugin-demo
Showcase of the Gatling Plugin for Gradle
Stars: ✭ 17 (-29.17%)
Mutual labels:  gradle
SetupBuilder
Gradle plugin for building setups for different platforms.
Stars: ✭ 75 (+212.5%)
Mutual labels:  gradle
swaggerhub-gradle-plugin
Gradle plugin for SwaggerHub
Stars: ✭ 14 (-41.67%)
Mutual labels:  gradle
base-android
🏗 Collection of common utility classes and setup I use in my Android apps
Stars: ✭ 47 (+95.83%)
Mutual labels:  gradle
Entitas-Java
Entity Component System (ECS) in Java 8
Stars: ✭ 37 (+54.17%)
Mutual labels:  gradle
dagger2-kotlin
dagger2,querydsl kotlin 1.5.x annotation processor, gradle 7.x
Stars: ✭ 56 (+133.33%)
Mutual labels:  gradle
openjfx-docs
Getting started guide for JavaFX 11
Stars: ✭ 70 (+191.67%)
Mutual labels:  gradle
gradle-build-info-plugin
Gradle plugin to include build information such as Git commit ID to your JAR. It can be used to show Git commit information with Spring Boot Actuator.
Stars: ✭ 33 (+37.5%)
Mutual labels:  gradle
connection checker
Android library for checking the internet connectivity of a device.
Stars: ✭ 26 (+8.33%)
Mutual labels:  gradle
androidScientificCalculator
➕An elegant feature-packed scientific calculator app for Android. Published on the Google Play Store.
Stars: ✭ 23 (-4.17%)
Mutual labels:  gradle
sonatype-publish-plugin
Gradle Plugin for publishing artifacts to Sonatype and Nexus
Stars: ✭ 17 (-29.17%)
Mutual labels:  gradle
spring-boot-angular2-starter
Starter application. Spring Boot, Angular 2, TypeScript, Gulp, Gradle, SCSS.
Stars: ✭ 35 (+45.83%)
Mutual labels:  gradle

Please be aware that this was created in early 2018. Some of it may still be useful, but please realize that parts will have stopped working or become deprecated. I am no longer updating it (though PRs are welcome).

Example of using Gradle sub-projects together with Kotlin multi-platform support

This project is an example of one way to set up a multi-platform Kotlin project separated into Gradle submodules.

The code itself is super simple, with just a platform-dependent method (expect/actual).

To run the code:

gradle wrapper
./gradlew run

Or to run only one platform (jvm in this example):

./gradlew -p alpha/alpha-jvm run

This should show (between a bunch of Gradle stuff):

Hello from JVM
Hello from JS

To collect the Javascript files in build/js, use the collectWeb task.

What I learned

  • Every 'normal' (common) module has one platform module for each platform.

  • For common module alpha, the javascript platform module must be called alpha-js (similar for -jvm).

  • If there is no platform specific code, this module can be just a gradle file in a directory.

  • The platform modules can be conveniently placed inside of the common module directory (so alpha:alpha-js).

  • The common module should not refer to the platform modules; the platform modules have a dependency expectedBy project(":the_common_module").

  • If module alpha depends on beta, then

    • alpha must have dependencies { compile project(":beta") }
    • alpha-js must have dependencies { compile project(":beta:beta-js") } (in addition to expectedBy)
    • alpha-jvm must have dependencies { compile project(":beta:beta-jvm") } (in addition to expectedBy) etc
  • Only the top module has settings.gradle, which includes ALL submodules (including platform ones).

  • Make sure to get the names right, as incorrect ones don't cause an error, they just fail silently. (It seems ridiculous but I guess there is a reason.)

  • Just because the build completes and creates jars does not mean it worked; the jar might only contain .kjsm and .kotlin_metadata files.

  • This demo uses the top level build.gradle for coordinating submodules; the top level doesn't contain code or platforms.

  • It's not hard to put shared functionality per level together at the top level (except buildscript which is inherited), possibly with one gradle file per platform.

  • If you don't mind using string manipulation and adhering to a naming scheme (you have to anyway), you can specify the dependencies in dependencies.gradle and not repeat them for every platform.

Some errors and solutions

  • If you get Could not find method expectedBy() for arguments ..., move the dependencies block lower in the file.
  • If you get unresolved reference errors, make sure that the target module has a package statement, and check all the above.
  • If you get npm errors, make sure the .npm directory for your system is writable.
  • If you get e: No class roots are found in the JDK path: /usr/lib/jvm/java-9-openjdk-amd64 or similar, set JAVA_HOME environment variable to where java 8 jdk is (for example /usr/lib/jvm/java-8-openjdk-amd64/).
  • If you get TypeError: Cannot read property 'config' of undefined, probably qunit did not see your test file. Maybe there are no tests (should be caught by Gradle) or there is something wrong with the pattern (absolute paths don't work, for example).
  • If you get Error: Cannot find module on JS tests, set NODE_PATH to the js dir, because imports aren't relative to the file of the current dir but only to path & node modules.
  • If your jar file does not work because it does not contain .class files, make sure you're looking at the jvm platform project, not the common or javascript one.
  • If the test code cannot find the main code on JVM, it could mean that you're trying to use a shared build directory for multiple projects, which leads to errors and non-determinism.
  • If you get java.lang.NoClassDefFoundError, this happens because of shared build dir (doing a clean build works too, but not a long-term solution). Adding hamcrest to dependencies does not work.
  • If stuck on a problem for a long time, remove build, gradle, .gradle, gradlew, gradlew.bat and try again... (Yes, sage advice).

For the future

  • Make NPM faster (~1.5s even if already the correct version).
  • Get errors when including non-existing submodules (Gradle strict mode?).
  • Put platform projects in alpha:js instead of alpha:alpha-js (I tried but they couldn't see each other).
  • Avoid having to make platform modules when there is no platform specific code.
  • Stop IntelliJ IDEA from creating a lot of extra modules (or understand why it's useful) => fixed amount of 9 per module; I guess it's necessary.
  • Try to get rid of w: Module "[...]-js" is defined in more than one file which is shown for all js modules.
  • Try to get rid of w: Classpath entry points to a non-existent location: /home/mark/gradle_demo/alpha/build/classes/java/main.
  • Make the distribution into jvm, js and common modules not depend on the name.
  • Remove any non-determinism, since it feels like the same build sometimes works and sometimes doesn't... (caching?) => some of this was due to using a single build file for all projects.
  • Clearer error message when failing because a module has no tests

Tests

Currently the tests just use kotlin.test, and are ran by JUnit on JVM and QUnit in Javascript. They are included in ./gradlew run.

More info

Inspiration from:

These paragraphs from the documentation may be useful:

A multiplatform project consists of three types of modules:

  • A common module contains code that is not specific to any platform, as well as declarations without implementation of platform-dependent APIs. Those declarations allow common code to depend on platform-specific implementations.
  • A platform module contains implementations of platform-dependent declarations in the common module for a specific platform, as well as other platform-dependent code. A platform module is always an implementation of a single common module.
  • A regular module. Such modules target a specific platform and can either be dependencies of platform modules or depend on platform modules.

A common module can depend only on other common modules and libraries, including the common version of the Kotlin standard library (kotlin-stdlib-common). Common modules contain only Kotlin code, and not code in any other languages.

A platform module can depend on any modules and libraries available on the given platform (including Java libraries in case of Kotlin/JVM and JS libraries for Kotlin/JS). Platform modules targeting Kotlin/JVM can also contain code in Java and other JVM languages.

(Force-pushed on 27 jan 2018, sorry about that)

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].