简体   繁体   English

如何在我的文件系统上添加一个 java gradle 项目作为对另一个本地项目的依赖?

[英]How do I add a java gradle project on my file system as a dependency to another local project?

I have project2 that depends on project1.我有依赖于 project1 的 project2。 They are both next to each other on my file system.它们在我的文件系统上彼此相邻。

When I try to build project2 (after successfully building project1) I get the error:当我尝试构建 project2(成功构建 project1 之后)时,出现错误:

Could not determine the dependencies of task ':app:distTar'.
> Could not resolve all task dependencies for configuration ':app:runtimeClasspath'.
   > Could not resolve project :project1.
     Required by:
         project :app
      > No matching configuration of project :project1 was found. The consumer was configured to find a runtime of a library compatible with Java 11, packaged as a jar, preferably optimized for standard JVMs, and its dependencies declared externally but:
          - None of the consumable configurations have attributes.

Project2 adds the dependency to project1 as follows... Project2 将依赖项添加到 project1 如下...

build.gradle build.gradle

/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java application project to get you started.
 * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
 * User Manual available at https://docs.gradle.org/7.2/userguide/building_java_projects.html
 */

plugins {
    // Apply the application plugin to add support for building a CLI application in Java.
    id 'application'
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use JUnit test framework.
    testImplementation 'junit:junit:4.13.2'

    // This dependency is used by the application.
    implementation 'com.google.guava:guava:30.1.1-jre'

    implementation project(':project1')
    implementation files('../../project1/lib/build/libs/lib.jar')
}

application {
    // Define the main class for the application.
    mainClass = 'project2.App'
}

Settings.gradle设置.gradle

rootProject.name = 'project2'
include('app')

include   ':project1'
project(':project1').projectDir = new File(settingsDir, '../project1')

The source for project1... project1 的来源...

/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package project1;

public class Library {
    public boolean someLibraryMethod() {
        return true;
    }
}

The source for project2 project2 的来源

/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package project2;

import project1.*;

public class App {
    public String getGreeting() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        System.out.println(new App().getGreeting());
        bool someBool = Library.someLibraryMethod();
    }
}

the complete folder structure of the two projects.两个项目的完整文件夹结构。 Although it looks like project2 is under project1, that is just how the copy pasted output looks, they are indeed sibling folders.虽然看起来project2 在project1 下,但复制粘贴的output 看起来就是这样,它们确实是兄弟文件夹。

── project1
│   ├── gradle
│   │   └── wrapper
│   │       ├── gradle-wrapper.jar
│   │       └── gradle-wrapper.properties
│   ├── gradlew
│   ├── gradlew.bat
│   ├── lib
│   │   ├── bin
│   │   │   ├── main
│   │   │   │   └── project1
│   │   │   │       └── Library.class
│   │   │   └── test
│   │   │       └── project1
│   │   │           └── LibraryTest.class
│   │   ├── build

│   │   │   ├── libs
│   │   │   │   └── lib.jar

│   │   ├── build.gradle
│   │   └── src
│   │       ├── main
│   │       │   ├── java
│   │       │   │   └── project1
│   │       │   │       └── Library.java
│   │       │   └── resources
│   │       └── test
│   │           ├── java
│   │           │   └── project1
│   │           │       └── LibraryTest.java
│   │           └── resources
│   └── settings.gradle
└── project2
    ├── app
    │   ├── build.gradle
    │   └── src
    │       ├── main
    │       │   ├── java
    │       │   │   └── project2
    │       │   │       └── App.java
    │       │   └── resources
    │       └── test
    │           ├── java
    │           │   └── project2
    │           │       └── AppTest.java
    │           └── resources
    ├── gradle
    │   └── wrapper
    │       ├── gradle-wrapper.jar
    │       └── gradle-wrapper.properties
    ├── gradlew
    ├── gradlew.bat
    └── settings.gradle

69 directories, 37 files 69个目录,37个文件

First, you have to decide if this is a multi-project build or a composite build .首先,您必须确定这是多项目构建还是复合构建

  • If the two projects are highly coupled (ie, two modules of the same conceptual project), then you should be using a multi-project build.如果这两个项目高度耦合(即同一概念项目的两个模块),那么您应该使用多项目构建。

    I do not include an example of a multi-project build in this answer.我没有在此答案中包含多项目构建的示例。

  • If the two projects are relatively independent of each other, but one depends on the other like any other dependency, then you might consider a composite build.如果这两个项目彼此相对独立,但一个项目像任何其他依赖项一样依赖另一个项目,那么您可以考虑复合构建。

    An example of a composite build is below.下面是一个复合构建的示例。


Example Composite Build示例组合构建

There are at least two ways to include a build in another.至少有两种方法可以将一个构建包含在另一个构建中。

  1. Use --include-build on the command line.在命令行上使用--include-build

  2. Use includeBuild in settings.gradle[.kts] ( not include ; that's for multi-project builds).settings.gradle[.kts]中使用includeBuildinclude ;用于多项目构建)。

    • There's a version of this where you create a "pseudo" parent project whose sole purpose is to define a settings.gradle[.kts] file that simply includes the desired "real" builds.有一个这样的版本,您可以在其中创建一个“伪”父项目,其唯一目的是定义一个仅包含所需“真实”构建的settings.gradle[.kts]文件。 That way you don't have to use --include-build or modify the Gradle files of one or more of the "real" projects.这样一来,您就不必使用 --include --include-build或修改一个或多个“真实”项目的 Gradle 文件。 See here .这里

This example uses --include-build .此示例使用--include-build I also used the Kotlin DSL, but translating to the Groovy DSL should not be too difficult if you prefer that.我还使用了 Kotlin DSL,但如果您愿意的话,转换为 Groovy DSL 应该不会太困难。

My example does not declare any repositories , but that does not mean you cannot do so.我的示例没有声明任何repositories ,但这并不意味着您不能这样做。 You may want to if you do not always want to include a build, but still want to use that other build's published binaries (or, of course, if you have other dependencies).如果您并不总是想包含一个构建,但仍想使用该其他构建的已发布二进制文件(或者,当然,如果您有其他依赖项),则可能需要这样做。 Here's a note on how dependencies work in composite builds:这是关于依赖项如何在复合构建中工作的注释:

Included builds interact with other builds via dependency substitution .包含的构建通过依赖替换与其他构建交互。 If any build in the composite has a dependency that can be satisfied by the included build, then that dependency will be replaced by a project dependency on the included build.如果组合中的任何构建具有可以由包含的构建满足的依赖性,那么该依赖性将被包含构建的项目依赖性所取代。 Because of the reliance on dependency substitution, composite builds may force configurations to be resolved earlier, when composing the task execution graph.由于依赖于依赖替换,复合构建可能会强制在组合任务执行图时更早地解析配置。 This can have a negative impact on overall build performance, because these configurations are not resolved in parallel .这会对整体构建性能产生负面影响,因为这些配置不是并行解析的

Project 1项目一

Here's the source for "project 1", which depends on "project 2".这是“项目 1”的来源,它依赖于“项目 2”。

settings.gradle.kts :设置.gradle.kts

rootProject.name = "project1"

build.gradle.kts : build.gradle.kts :

plugins {
    application
}

group = "sample.project1"
version = "1.0"

application {
    mainClass.set("sample.project1.Main")
}

dependencies {
    implementation("sample.project2:project2:1.0")
}

Main.java :主要.java

package sample.project1;

import sample.project2.Greeter;

public class Main {
    
    public static void main(String[] args) {
        Greeter.greet();
    }
}

Project 2项目2

Here's the source for "project 2".这是“项目 2”的来源。

settings.gradle.kts :设置.gradle.kts

rootProject.name = "project2"

build.gradle.kts : build.gradle.kts :

plugins {
    `java-library`
}

group = "sample.project2"
version = "1.0"

Greeter.java :问候语.java

package sample.project2;

public class Greeter {
    
    public static void greet() {
        System.out.println("Hello, this is a composite build!");
    }
}

Project Structure项目结构

This is the layout of the two projects (they are in sibling directories):这是两个项目的布局(它们在同级目录中):

...\DEMO
├───project1
│   │   build.gradle.kts
│   │   gradlew
│   │   gradlew.bat
│   │   settings.gradle.kts
│   │
│   ├───gradle
│   │   └───wrapper
│   │           gradle-wrapper.jar
│   │           gradle-wrapper.properties
│   │
│   └───src
│       └───main
│           └───java
│               └───sample
│                   └───project1
│                           Main.java
│
└───project2
    │   build.gradle.kts
    │   gradlew
    │   gradlew.bat
    │   settings.gradle.kts
    │
    ├───gradle
    │   └───wrapper
    │           gradle-wrapper.jar
    │           gradle-wrapper.properties
    │
    └───src
        └───main
            └───java
                └───sample
                    └───project2
                            Greeter.java

Running Project 1运行项目 1

And here's an example of running project 1 while including project 2:这是在包含项目 2 的同时运行项目 1 的示例:

...\demo\project1> .\gradlew run --include-build ..\project2

> Task :run
Hello, this is a composite build!

How to Modify Your Code如何修改代码

Given you seem to want a composite build, you need to make a few changes.鉴于您似乎想要一个复合构建,您需要进行一些更改。 For instance, declaring a dependency on an included build looks like declaring a dependency on any other external artifact (ie, it uses Maven coordinates):例如,声明对包含构建的依赖看起来就像声明对任何其他外部工件的依赖(即,它使用 Maven 坐标):

dependencies {
    // Use JUnit test framework.
    testImplementation 'junit:junit:4.13.2'

    // This dependency is used by the application.
    implementation 'com.google.guava:guava:30.1.1-jre'

    // REPLACE WITH REAL groupID, artifactID, AND version
    implementation 'com.example:project1:1.0'
}

And then your settings.gradle file for project 2 should simply look like:然后项目 2 的settings.gradle文件应该如下所示:

rootProject.name = 'project2'

Or, if you don't want to use --include-build :或者,如果您不想使用--include-build

rootProject.name = 'project2'

includeBuild '../project1'

Make directories project1 and project2 both modules, one application and one library module.使目录project1project2都是模块,一个应用程序和一个库模块。 Files gradle , gradlew , gradlew.bat , settings.gradle need to be moved one level up.文件gradlegradlewgradlew.batsettings.gradle需要向上移动一级。 The root project needs it's own build.gradle .根项目需要它自己的build.gradle Including the modules in settings.gradle is straightforward:settings.gradle中包含模块很简单:

include ':project1'
include ':project2'

Then one can depend on module :project2 in module :project1 :然后可以依赖模块:project1中的模块:project2

dependencies {
    testImplementation project(':project2')
    api project(':project2')
}

The library could also be published to the default local repository mavenLocal() .该库也可以发布到默认的本地存储库mavenLocal() Unless publishing a sources package to Maven (eg. lib-sources.jar ), it's usually easier to debug with two modules.除非发布源代码 package 到 Maven(例如lib-sources.jar ),否则使用两个模块进行调试通常更容易。 The library module still can be made a Git sub-module.库模块仍然可以做成一个 Git 子模块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM