I have Project A which has a dependency on a library (Jackson as an example). When I include Project A as a compile-time dependency of Project B, I'd like the library to be included as a runtime only dependency so that it isn't available to the developer of Project B to use directly.
What is the accepted way to achieve this using Gradle?
You can use a compileOnly configuration in Project A; it is not transitive, so will not be available to Project B. But this also means, that it will need to be listed as Project B's runtime dependency.
Official intro for Compile-Only Dependencies
Related
Previously, building multiplatform projects using Gradle relied on separate Gradle plugins per targeted platform: kotlin-platform-common, kotlin-platform-js, and kotlin-platform-jvm.
Starting from Kotlin 1.3, this is now unified using one kotlin-multiplatform plugin. The current documentation specifies how to set up multiplatform projects using this approach.
However, in my project I have multiple multiplatform projects with some dependencies between them. With the old multiplatform configuration, each different platform is a separate module and adding dependencies between projects required adding project references in each platform-specific module to corresponding modules in the other project: e.g., project(':some-library:some-library-js') to add a dependency to the JS module from within another JS module.
While migrating to the new multiplatform configuration, I now need to add a dependency from a project configured using the old configuration method to a project configured using the new kotlin-multiplatform plugin.
Given that platform-specific modules are now specified and managed by the new plugin, how do I go about this?
I'm not certain whether the following approach is the recommended method, or I overlooked any potential issues, but my projects compile and all tests pass.
In Gradle, you can add dependencies to specific project configurations:
dependencies {
implementation project(path: ':some-library', configuration: 'configName')
}
By trial and error I figured out that specifying the following configuration dependencies per platform module type works:
common: configuration: 'archives'. Without this, Gradle configuration fails as code dependencies are not found.
Without the following, compilation fails:
jvm: configuration: 'jvmDefault'
js: configuration: 'jsDefault'
For example, for the JS module as specified in the question:
dependencies {
implementation project(path: ':some-library', configuration: 'jsDefault')
}
Basically, you don't need to specify the platform in project-to-project dependencies involving Kotlin Muiltiplatform projects. The Kotlin plugin sets up dependency resolution in a way that Gradle will choose the appropriate target's artifacts automatically.
So, for example, in a Kotlin/JVM single-target project, you can just use a project("...") dependency on a Multiplatform project:
dependencies {
implementation(project(":multiplatform-library")
}
If :multiplatform-library has a JVM target, this dependency will get resolved to the JVM target's artifact. Otherwise, you will encounter a dependency resolution failure with candidate configurartions listed.
This is described in the Kotlin reference, Building Multiplatform Projects with Gradle – Adding Dependencies, but is applicable to single-platform projects, too:
<...> a project('...') dependency on another multiplatform project is resolved to an appropriate target automatically. It is enough to specify a single project('...') dependency in a source set's dependencies, and the compilations that include the source set will receive a corresponding platform-specific artifact of that project, given that it has a compatible target.
If this does not happen for you, please post the specific dependency resolution failure log, or file an issue at https://kotl.in/issue.
In an ordinary Netbeans project, I can specify a library as an implementation dependency so I can access its private packages.
However, in a Maven netbeans project, the menu for libraries (where I would set this) is not there, and the dependency system is different. Is there an equivalent way in Maven to access private packages of a dependency?
you want to read this section of the nbm-maven-plugin documentation. http://www.mojohaus.org/nbm-maven-plugin/manifest-mojo.html#moduleDependencies
An implementation dependency cannot be deduced from pom's dependencies section and you need to explicitly declare it as part of the plugin configuration.
I've the following project structure A --> B --> C. I've given all dependent jars in dependencyManagement of Project A POM and version of those jars are maintained using property project.version. I was able to access the versions using property ${project.version} in B. But I'm not able to get the dependency version in Project C. Is there a way to inherit the dependency version in project C from project A?
Does Maven install the necessary dependencies when adding a plugin to the pom file?
For example, when adding the following code to a pom file, does maven download the necessary dependencies for that plugin?
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>2.7</version>
</plugin>
Yes to both questions. Sub-dependencies are called Transitive Dependencies and are handled natively in Maven 2.0. You can read about it more on the Maven website.
Specifically:
Transitive dependencies are a new feature in Maven 2.0. This allows
you to avoid needing to discover and specify the libraries that your
own dependencies require, and including them automatically.
This feature is facilitated by reading the project files of your
dependencies from the remote repositories specified. In general, all
dependencies of those projects are used in your project, as are any
that the project inherits from its parents, or from its dependencies,
and so on.
There is no limit to the number of levels that dependencies can be
gathered from, and will only cause a problem if a cyclic dependency is
discovered.
With transitive dependencies, the graph of included libraries can
quickly grow quite large. For this reason, there are some additional
features that will limit which dependencies are included:
Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are
encountered. Currently, Maven 2.0 only supports using the "nearest
definition" which means that it will use the version of the closest
dependency to your project in the tree of dependencies. You can always
guarantee a version by declaring it explicitly in your project's POM.
Note that if two dependency versions are at the same depth in the
dependency tree, until Maven 2.0.8 it was not defined which one would
win, but since Maven 2.0.9 it's the order in the declaration that
counts: the first declaration wins.
"nearest definition" means that the version used will be the closest one to your project in the tree of dependencies, eg. if
dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A
-> E -> D 1.0, then D 1.0 will be used when building A because the path from A to D through E is shorter. You could explicitly add a
dependency to D 2.0 in A to force the use of D 2.0
Dependency management - this allows project authors to directly specify the versions of artifacts to be used when they are encountered
in transitive dependencies or in dependencies where no version has
been specified. In the example in the preceding section a dependency
was directly added to A even though it is not directly used by A.
Instead, A can include D as a dependency in its dependencyManagement
section and directly control which version of D is used when, or if,
it is ever referenced.
Dependency scope - this allows you to only include dependencies appropriate for the current stage of the build. This is described in
more detail below.
Excluded dependencies - If project X depends on project Y, and project Y depends on project Z, the owner of project X can explicitly
exclude project Z as a dependency, using the "exclusion" element.
Optional dependencies - If project Y depends on project Z, the owner
of project Y can mark project Z as an optional dependency, using the
"optional" element. When project X depends on project Y, X will depend
only on Y and not on Y's optional dependency Z. The owner of project X
may then explicitly add a dependency on Z, at her option. (It may be
helpful to think of optional dependencies as "excluded by default.")
If you take a look at the plugin pom
http://repo1.maven.org/maven2/org/codehaus/sonar/sonar-maven-plugin/2.7/sonar-maven-plugin-2.7.pom
Maven will pull all relevant dependencies for the plugin according to
<dependencies>
section of the plugin pom
I have two Android apps that share a subproject. The build.gradle in the subproject contains a dependency like this:
dependencies {
compile "my.library.dependency:${version}"
}
What I'd like is to use this dependency at compile time, but not runtime. This is because the two apps need to link against slightly different versions of the dependency (same API).
The Gradle docs describe dependency configurations like this:
compile The dependencies required to compile the production source of
the project.
runtime The dependencies required by the production classes at
runtime. By default, also includes the compile time dependencies.
If runtime also includes compile dependencies, does this mean the library is exported from the subproject to the parent projects (and included in my apk)? If so, how do I prevent this? I assume it's possible because it says "by default".
Thanks in advance...
It's not clear if your subproject is using the android-library plugin, but if it is, v0.8 has added a provided scope -- see http://tools.android.com/recent/androidstudio043released.
This should work:
dependencies {
provided "my.library.dependency:${version}"
}
If you upgrade to 0.8 of the plugin, you'll need to run Gradle 1.10 (update gradle-wrapper.properties if you're using the wrapper), and if you're using Android Studio, upgrade to 0.4.3.