问题
TL;DR
I'm trying to configure two Gradle projects in a way that one project uses files built by the other one.
The first project is added to the second one by includeBuild
and the file is defined in the second project as a dependency.
Project testA
settings.gradle
:
rootProject.name = 'testA'
build.gradle
:
group = 'org.test'
version = '0.0.0.1_test'
task someZip (type: Zip) {
from './settings.gradle'
archiveName = 'xxx.zip'
destinationDir = file("${buildDir}/test")
}
artifacts {
//TODO add something here?
}
Project testB
settings.gradle
:
rootProject.name = 'testB'
if (System.getenv('LOCAL_COMPILATION') == 'true') {
includeBuild '../testA'
}
build.gradle
:
if (System.getenv('LOCAL_COMPILATION') != 'true') {
repositories {
maven { url '192.168.1.100' }
}
}
configurations {
magic
}
dependencies {
magic 'org.test:xxx:0.0.0.+@zip'
}
task ultimateZip (type: Zip) {
from configurations.magic
archiveName = 'ultimate.zip'
destinationDir = file("${buildDir}/ultimate-test")
}
Description
You may noticed that the example has an option use a maven repository. I wanted to highlight that eventually there will be a possibility to do that.
Using Maven repository is not the point of this question, though, other than the solution should not interfere with that.
(In other words you can assume that System.getenv('LOCAL_COMPILATION') == 'true'
.)
The question is how to define the artifact in a way that the other project is able to recognize it.
The preferred solution should be similar to what the Java plugin does because I'm using jar dependencies in my projects and they are working both through includeBuild
and through a repository.
回答1:
The following setup should work (tested with Gradle 5.5.1). It mostly corresponds to your original setup with the exception of the changes indicated by XXX
.
Project testA
settings.gradle
:
rootProject.name = 'testA'
build.gradle
:
group = 'org.test'
version = '0.0.0.1_test'
task someZip (type: Zip) {
from './settings.gradle'
archiveName = 'xxx.zip'
destinationDir = file("${buildDir}/test")
}
// XXX (replaced your empty "artifacts" block)
configurations.create('default')
def myArtifact = artifacts.add('default', someZip) {
name = 'xxx'
}
// XXX (only added to show that publishing works)
apply plugin: 'maven-publish'
publishing {
repositories {
maven { url = 'file:///tmp/my-repo' }
}
publications {
myPub(MavenPublication) {
artifactId myArtifact.name
artifact myArtifact
}
}
}
Project testB
settings.gradle
:
rootProject.name = 'testB'
if (System.getenv('LOCAL_COMPILATION') == 'true') {
// XXX (added a dependency substitution to let Gradle know that
// "org.test:xxx" corresponds to the testA project)
includeBuild('../testA') {
dependencySubstitution {
substitute module('org.test:xxx') with project(':')
}
}
}
build.gradle
:
if (System.getenv('LOCAL_COMPILATION') != 'true') {
repositories {
// XXX (only changed to show that resolution still works after
// publishing)
maven { url = 'file:///tmp/my-repo' }
}
}
configurations {
magic
}
dependencies {
magic 'org.test:xxx:0.0.0.+@zip'
}
task ultimateZip (type: Zip) {
from configurations.magic
archiveName = 'ultimate.zip'
destinationDir = file("${buildDir}/ultimate-test")
}
As requested in the comments, here’s some more explanation on the created default
configuration and the added artifact in project testA
.
Composite builds in Gradle currently have the limitation that substituted project dependencies “will always point to the default configuration of the target project”. In your example this means that testA
needs to publish in the default
configuration. We thus first create the default
configuration. Note that some plugins (like java
) already create this configuration; you don’t need to create it yourself when using such plugins.
It doesn’t seem to be mentioned explicitly anywhere but as you seem to have found out yourself already, the PublishedArtifact
s of a project (as declared with project.artifacts
) are important for Gradle to figure out the dependency wiring in composite builds. Hence, we make sure to declare such a PublishedArtifact
in testA
using this API. The artifact (e.g., its extension) is configured based on the properties of the someZip
task. The name seems to not be taken from the someZip
task in your example because you manually set archiveName
; hence we need to explicitly declare it. If you use archiveBaseName = 'xxx'
in someZip
instead, then you don’t need the closure when adding the artifact.
来源:https://stackoverflow.com/questions/57110795/define-an-artifact-to-be-used-as-a-dependency-in-another-project