Does It possible to use multiple common libraries in Kotlin? - kotlin

I have tried to build project in gradle with 3 modules, where:
1) module1 - common module with expect classes
empty build.gradle dependencies
2) module2 - common module with expect classes and with dependency from module 1:
build.gradle dependencies: compile project(':module1')
2) module3 - jvm platform module
build.gradle dependencies: expectedBy project(':module2')
When I try to compile a project, it appears errors in compilation stage of module3, that classes from module2 couldn't find classes from module1.
Kotlin 1.2.30
Gradle 4.6
Java 1.8_161
Does It possible to use multiple common modules together in one project? And does it possible to have expect classes in each common module?

Currently, using common declarations from multiple common modules is not supported, but it is planned for future versions.
In particular, once the fix for KT-22864 is released, it will allow you to add both module1 and module2 as expectedBy dependencies to module3. There's currently no public preview build with the fix, please stay tuned for 1.2.40 EAPs.
If you really want to try it early, you can use a dev build (e.g. 1.2.40-dev-754 from the https://dl.bintray.com/kotlin/kotlin-dev Maven repository).
You can also try a dev build of the IDE plugin (from here) to make the IDE import and analyze multiple expectedBy dependencies properly (1.2.30 can only import one such dependency).

For this it's needed to have more than one expectedBy declaration, which for now is forbidden. But, as say in kotlin slack, it will be possible soon.
So, for now, it's needed to switch to version 1.2.40-dev-754 of kotlin, and then it will be possible to add second expectedBy to dependencies in build.gradle in module3:
expectedBy project(':module1')
expectedBy project(':module2')

Related

Kodein-DI Gradle dependency in common module

I'd like to define a Kodein-DI module in common Kotlin code (so I could import it from both JS and JVM modules).
What Gradle dependency should I add to commonMain?
My issue seems to be solved, see https://github.com/Kodein-Framework/Kodein-DI/issues/177#issuecomment-457915559 for details.

Muting Java 9 split package errors on IntelliJ

I have a JDK 9 project. When running mvn install, everything works fine. When using IntelliJ 2017.2.6 with JDK 9.0.4 I come up
with dozens of compilation errors due to split packages. For example, in my POM I set a dependency on org.apache.solr:solr-core:7.2.1. One of the errors displayed by IntelliJ is:
Error:java: module solr.core reads package org.apache.lucene.search from both lucene.misc and lucene.sandbox
The rationale for the compilation error issued by IntelliJ is:
solr-core has Maven dependencies on artifacts lucene-misc and lucene-sandbox
Both lucene-misc.jar and lucene-sandbox.jar define classes in package org.apache.lucene.search
IntelliJ considers that lucene-misc.jar and lucene-sandbox.jar are JDK 9 modules (if fact, they are not modules, they have no module-info.java file). As two JDK 9 modules cannot participate to the same package, IntelliJ issues a compilation error.
By contrast, the Maven compiler pluging issues no error, because it considers lucene-misc.jar and lucene-sandbox.jar as belonging to
the class path, not to the module path.
I obviously don't want to re-package the Lucene stuff.
So my problem boils down to the following: how can I mute IntelliJ errors Error:java: module Mod1 reads package P from both Mod2 and Mod3?
[Short]
It's impossible if you want to run your application from a module code. You have to migrate your code which depend on collision JARs to non-module code and add your collitions jar on the class path. (as suggested in comments)
[Long]
Behind the scene the Intellij try to run the JVM, so the Intellij can run your application only if the JVM can do that.
When you run an application from module jar, that means that you run your application from named module. The module must require all of its dependencies which should be name modules. Note that even automatic modules which are created from your non-module JARs are indeed named.
Java 9 does not allow split-packages for the reason of the reliable configuration, only unnamed modules are excepted from this rule.
The only way to make it works it move your collision jars to unnamed module, but named module cannot depend on unnamed module
A named module cannot, in fact, even declare a dependence upon the unnamed module. This restriction is intentional, since allowing named modules to depend upon the arbitrary content of the class path would make reliable configuration impossible.
so if you don't want repackage collision jars you have to move your modules which require collision jars to non-module jar.
Your maven plugin done with it, because as #Nicolai said:
Maven places them on the class path (where split packages don't matter), whereas IntelliJ places them on the module path (leading to the problems you observe).
See also this answer about running the application from non-module code.

Access classes from other module

I have an minecraft forge workspace that is made by gradle, I have an project in which I have an module with the mod I'm working on and one module with my library mod, I want to somehow access classes from my library mod from the other module, I imported modules by using their build.gradle and now I have 2 different modules but I can't access one module from another one.
You need to add a dependency from the working module on the library module. If this is a multi-module Gradle build where both projects are modules, you can simply add a project(':library') dependency. If those are separate Gradle builds, you need to add a normal dependency like 'your.group:library-module:1.0' and then either install the library module to some repository like the local maven repository with the mavenPublish plugin to be able to use it from the working module, or use a composite build to replace the dependency by the automatically built result of the library module. For more information on how to do either, you should read the Gradle Userguide.

What is a Kotlin module?

In the Kotlin documentation they are mentioning some kind of module for instance in the documentation for the internal modifier.
However I couldn't find any definition of the term module itself. So what is meant by module?
A module is a set of Kotlin sources compiled together:
an IntelliJ IDEA module;
a Maven project;
a Gradle source set;
a set of files compiled with one invocation of the Ant task.
This is in the same docs article about visibility modifiers. :)
From the Kotlin's documentation, a module is a set of Kotlin files compiled together:
an IntelliJ IDEA module
a Maven project;
a Gradle source set
a set of files compiled with one invocation of the <kotlinc> Ant task.
That is #hotkey's, but I would like to complement this answer.
According to Andrey Breslav, the Lead Language Designer of Kotlin:
a Kotlin module maps one-to-one to IntelliJ's module (iml-file).
According to IntelliJ's documentation:
Modules allow you to combine several technologies and frameworks in one application. In IntelliJ IDEA, you can create several modules for a project and each of them can be responsible for its own framework.
When it comes to a Maven project or a command line compilation, Andrey states:
Each compiler run, by default, is a separate module: all the binary dependencies will be treated as being not in the module being compiled at the moment.
Also, a Gradle source set is a module, with the exception that the test source set can access the internal declarations of main.
This means that if you have different build flavors in your Gradle configuration resulting in different source sets, for production and debug versions for example, then an internal class from one source set would not be available to be used in another source set.
Per Kotlin language specification ยง10.2 Modules:
A module is a concept on the boundary between the code itself and the
resulting application, thus it depends on and influences both of them.
A Kotlin module is a set of Kotlin files which are considered to be
interdependent and must be handled together during compilation.
In a simple case, a module is a set of files compiled at the same time
in a given project.
A set of files being compiled with a single Kotlin compiler invocation
A Maven module
A Gradle project
In a more complicated case involving multi-platform projects, a module
may be distributed across several compilations, projects and/or platforms.
For the purposes of Kotlin/Core, modules are important for internal
visibility. How modules influence particular platforms is
described in their respective sections of this specification.
I think you might be referring to org.koin.core.module.Module
A Koin module is a "space" to gather Koin definition. It's declared with the module function.
val myModule = module {
// Your definitions ...
}
This documentation would be helpful in that case.

Model project dependencies in Gradle: Add a dependent project to another project

I am facing the following problem. I have two Gradle projects (ProjectA and ProjectB) on the same hierarchy without any root project. Since ProjectA depends on ProjectB, I tried to model this as follows:
ProjectA's settings.gradle:
includeFlat 'ProjectB'
ProjectA's build.gradle:
dependencies {
compile project(':ProjectB')
}
However, then I am getting the following error when executing 'gradle build' on ProjectA:
* What went wrong:
A problem occurred evaluating root project 'ProjectA'.
> Could not resolve all dependencies for configuration ':compile'.
> Module version group:, module:ProjectA, version:0.0.1-SNAPSHOT, configuration:compile declares a dependency on configuration 'default' which is not declared in the module descriptor for group:ProjectA, module:ProjectB, version:unspecified
Do I have to define some kind of default configuration in ProjectB?
Do I have do defined some kind of default configuration in ProjectB?
Either that, or apply the base plugin. Many other plugins (java, groovy, scala, etc.) apply the base plugin automatically, so that you don't have to.