[JAVA] Erstellen Sie mit Gradle eine ausführbare JAR für mehrere Projekte

Zweck dieses Artikels

Eine Erinnerung an die Schritte zum Verwalten eines Multiprojekts mit dem Build-Tool Gradle und zum Erstellen einer ausführbaren JAR als Ergebnis.

Ist das Hauptthema.

Hintergrund der Artikelerstellung

Ich hatte die Möglichkeit, eine GUI-Anwendung mit JavaFX [^ JavaFX] zu erstellen. Die Anwendung wird schließlich im EXE-Format von einem Tool namens javapackager [^ javapackager] verteilt. Als ersten Schritt musste jedoch eine JAR generiert werden, die durch Doppelklicken gestartet werden kann.

[^ JavaFX]: 1 Übersicht über JavaFX (Release 8) (https://docs.oracle.com/javase/jp/8/javafx/get-started-tutorial/jfx-overview.htm) [^ javapackager]: In sich geschlossenes Anwendungspaket (https://docs.oracle.com/javase/jp/8/docs/technotes/guides/deploy/self-contained-packaging.html)

Darüber hinaus mussten Anwendungen mehrere Typen mit nahezu derselben internen Verarbeitung und unterschiedlichem Detailverhalten erstellen. Ich wollte common.jar als gemeinsamen Teil und app1.jar und app2.jar (jeweils abhängig von common.jar) als Eingangs-JAR verwenden, habe mich jedoch mit Jenkins in der Firma befasst und nach einem Multiprojekt mit einer ähnlichen Konfiguration gesucht. Selbst als ich es versuchte, gab es kein Skript, das nur mit Gradle fertiggestellt wurde. Es gab nur ein Shell-Skript, das das allgemeine build.gradle und dann das app1 build.gradle aufrief.

Ich hätte den Zweck durch Nachahmung des Shell-Skripts erreichen können, aber zum Lernen habe ich beschlossen, ein Skript zu erstellen, das mit Gradle vervollständigt wird.

Überprüfungsumgebung

Erstellen Sie ein Multiprojekt und eine ausführbare JAR

Beginnen wir der Einfachheit halber mit nur einem App-Projekt.

Überprüfen Sie den Betrieb mit einem Minimum an mehreren Projekten

Erstellen Sie zunächst ein minimales Multiprojekt und rufen Sie die Aufgabe "Hallo" auf, um den Vorgang zu überprüfen.

Erstellen Sie eine allgemeine Verzeichnis-App, master direkt unter dem Arbeitsverzeichnis, und erstellen Sie build.gradle und settings.gradle direkt unter master [^ tree command on Mac]:

[^ Tree-Befehl auf Mac]: Tree-Befehl auf Mac --Qiita (http://qiita.com/kanuma1984/items/c158162adfeb6b217973)

master$ tree ../
../
├── app
├── common
└── master
    ├── build.gradle
    └── settings.gradle

Geben Sie in settings.gradle das Verzeichnis an, das Sie als Teilprojekt erkennen möchten. Das Stammprojekt ist nicht angegeben, aber das Verzeichnis mit dem Namen master wird automatisch als Stammprojekt erkannt, sodass es nicht angegeben wird [^ Multi-Projekt mit Gradle]:

[^ Multiprojekt mit Gradle]: Multiprojekt mit Gradle-Qiita (http://qiita.com/shiena/items/371fe817c8fb6be2bb1e)

settings.gradle


includeFlat 'app', 'common'

Definieren Sie in build.gradle eine "Hallo" -Aufgabe im "allprojects" -Block [Warum ^ doLast verwenden]:

[Grund für die Verwendung von ^ doLast]: Die Methode leftShift und der Operator << `sind veraltet. (https://docs.gradle.org/3.2/release-notes#the-left-shift-operator-on-the-task-interface)

build.gradle


allprojects {
    task hello {
        doLast {
            println "I`m ${project.name}."
        }
    }
}

Rufen Sie zu diesem Zeitpunkt die Aufgabe "Hallo" im Hauptverzeichnis auf [Bedeutung ^ q]. Wenn Sie Folgendes sehen, ist es in Ordnung:

[Bedeutung von ^ q]: Die Option -q wird verwendet, um das Ergebnis von println besser sichtbar zu machen.

master$ gradle -q hello
I`m master.
I`m app.
I`m common.

Übrigens, wenn Sie die Aufgabe "Hallo" im allgemeinen Verzeichnis aufrufen, wird nur die allgemeine Aufgabe aufgerufen. Sie können diese Eigenschaft auch verwenden, um nur bestimmte Projekte zu erstellen:

common$ gradle -q hello
I`m common.

Machen Sie App und Common zu einem Eclipse-Projekt

Fügen Sie das Eclipse-Plug-In zu Ihrem Teilprojekt hinzu. Fügen Sie nach dem Block "Alle Projekte" Folgendes hinzu:

build.gradle


…

subprojects {
    apply {
        plugin 'eclipse'
    }
}

Allein damit können Sie die Aufgabe "Eclipse" verwenden und ein Eclipse-Projekt erstellen:

master$ gradle eclipse
:app:eclipseProject
:app:eclipse
:common:eclipseProject
:common:eclipse

BUILD SUCCESSFUL

Total time: 2.067 secs

Da das src-Verzeichnis jedoch tatsächlich benötigt wird, werde ich es mit der gradle-Task generieren [Grund für die Nichtverwendung der ^ init-Task]. Fügen Sie ein Java-Plug-In hinzu und erstellen Sie eine "initSrcDirs" -Aufgabe wie unten gezeigt.

[Warum nicht die ^ init-Aufgabe verwenden]: Gradle wird mit einer init -Aufgabe geliefert, aber ich wollte keine zusätzlichen Dateien erstellen, also habe ich sie selbst definiert.

build.gradle


…

subprojects {
    apply {
        plugin 'eclipse'
        plugin 'java'
    }

    task initSrcDirs {
        doLast {
            sourceSets.all {
                java.srcDirs*.mkdirs()
                resources.srcDirs*.mkdirs()
            }
        }
    }
}

Durch Ausführen der Task initSrcDirs werden Dinge wie src / main / java und src / main / resources erstellt. Selbst wenn die Dateien bereits in diesen Pfaden vorhanden sind, werden sie niemals leer sein. Daher ist die Verwendung sicher:

master$ gradle initSrcDirs
:app:initSrcDirs
:common:initSrcDirs

BUILD SUCCESSFUL

Total time: 0.909 secs

master$ tree ../
../
├── app
│   └── src
│       ├── main
│       │   ├── java
│       │   └── resources
│       └── test
│           ├── java
│           └── resources
├── common
│   └── src
│       ├── main
│       │   ├── java
│       │   └── resources
│       └── test
│           ├── java
│           └── resources
└── master
    ├── build.gradle
    └── settings.gradle

Beschreibt die Variablen, die beim Definieren der Task "initSrcDirs" angezeigt wurden.

--sourceSets ist ein Verzeichnissystem wie src / main / java, das vom Java-Plug-In definiert wird. --mkdirs () ruft die mkdirs-Methode von java.io.File auf, da srcDirs eine Liste von java.io.File ist.

Wenn Sie an einer anderen Syntax interessiert sind (z. B. "*." Der Iteration), überprüfen Sie bitte die Syntax von Groovy.

Wenn Sie die Aufgabe "Eclipse" erneut mit dem erstellten Verzeichnis "src" aufrufen, wird auch der Klassenpfad ordnungsgemäß übergeben (die Aufgabe "eclipseClaspath", die zuvor nicht vorhanden war, wird aufgerufen):

master$ gradle eclipse
:app:eclipseClasspath
:app:eclipseJdt
:app:eclipseProject
:app:eclipse
:common:eclipseClasspath
:common:eclipseJdt
:common:eclipseProject
:common:eclipse

BUILD SUCCESSFUL

Total time: 0.994 secs

Machen Sie das App-Projekt vom gemeinsamen Projekt abhängig

Kommen wir zum Kern dessen, was wir mit dem Multi-Projekt-Management erreichen wollten. Machen Sie die App abhängig von gemeinsam.

Fehlerfall

Um den Fehlerfall zu reproduzieren, erstellen Sie zunächst die folgenden zwei Klassen, ohne build.gradle zu ändern. Constant.java wird unter common und Main.java unter app erstellt. Natürlich erkennt Eclipse nicht einmal die Abhängigkeiten des anderen, daher kann es nicht ergänzt werden und gibt einen Fehler aus:

Constant.java


package com.github.kazuma1989.dec10_2016.common;

public class Constant {
    public static final String NAME = "common";
}

Main.java


package com.github.kazuma1989.dec10_2016.app;

import com.github.kazuma1989.dec10_2016.common.Constant;

public class Main {
    public static void main(String[] args) {
        System.out.println(Constant.NAME);
    }
}

Wenn Sie die Aufgabe "jar" in diesem Zustand ausführen, schlägt der Build wie erwartet fehl. Die Aufgabe "compileJava", die der Aufgabe "jar" vorausgeht, ist fehlgeschlagen:

master$ gradle jar
:app:compileJava
/Users/kazuma/qiita/2016/dec10/app/src/main/java/com/github/kazuma1989/dec10_2016/app/Main.java:3:Error:Paket com.github.kazuma1989.dec10_2016.gemeinsam existiert nicht
import com.github.kazuma1989.dec10_2016.common.Constant;
                                              ^
/Users/kazuma/qiita/2016/dec10/app/src/main/java/com/github/kazuma1989/dec10_2016/app/Main.java:7:Error:Symbol kann nicht gefunden werden
        System.out.println(Constant.NAME);
                           ^
Symbol:Variable Konstante
Ort:Klasse Main
2 Fehler
:app:compileJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileJava'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 0.966 secs

Erfolgreicher Fall

Dann machen Sie den Build erfolgreich. Fügen Sie am Ende des Blocks "Teilprojekte" Folgendes hinzu, um die Abhängigkeit von common zu definieren:

build.gradle


…

subprojects {
    …

    //Andere Einstellungen als üblich
    if (project.name in ['common']) return

    dependencies {
        compile project(':common')
    }
}

Diesmal ist die Aufgabe "jar" erfolgreich und die erstellte JAR funktioniert einwandfrei. Die allgemeine JAR-Konvertierung wird zuerst ausgeführt, nicht in aufsteigender Reihenfolge der Projektnamen:

master$ gradle jar
:common:compileJava
:common:processResources UP-TO-DATE
:common:classes
:common:jar
:app:compileJava
:app:processResources UP-TO-DATE
:app:classes
:app:jar

BUILD SUCCESSFUL

Total time: 1.154 secs

master$ java -cp ../app/build/libs/app.jar com.github.kazuma1989.dec10_2016.app.Main
common

Die jar Aufgabe muss nicht unbedingt vom Master aufgerufen werden, sondern nur die in der App kann aufgerufen werden. Selbst in diesem Fall wird die App nach dem Kompilieren von Common JARisiert, sodass sie ordnungsgemäß erfolgreich ist:

master$ gradle clean :app:jar
:app:clean
:common:clean
:common:compileJava
:common:processResources UP-TO-DATE
:common:classes
:common:jar
:app:compileJava
:app:processResources UP-TO-DATE
:app:classes
:app:jar

BUILD SUCCESSFUL

Total time: 0.938 secs

master$ cd ../app/

app$ gradle clean jar
:app:clean
:common:compileJava UP-TO-DATE
:common:processResources UP-TO-DATE
:common:classes UP-TO-DATE
:common:jar UP-TO-DATE
:app:compileJava
:app:processResources UP-TO-DATE
:app:classes
:app:jar

BUILD SUCCESSFUL

Total time: 0.922 secs

Führen Sie nach dem Festlegen der Abhängigkeiten die Task "Eclipse" erneut aus, um den Fehler in Eclipse zu beseitigen und die Code-Vervollständigung zu verwenden.

Fügen Sie ein Manifest hinzu, um die App JAR-fähig zu machen

Legen Sie das Manifest für die Aufgabe "jar" fest und generieren Sie eine ausführbare JAR.

Manchmal funktioniert es, aber die Grundlagen schlagen fehl

Fügen Sie am Ende von build.gradle einfach eine minimale Anweisung hinzu und versuchen Sie trotzdem, die Aufgabe jar auszuführen:

build.gradle


…

project(':app') {
    jar {
        manifest {
            attributes 'Main-Class': 'com.github.kazuma1989.dec10_2016.app.Main'
        }
    }
}
master$ gradle jar
:common:compileJava
:common:processResources UP-TO-DATE
:common:classes
:common:jar
:app:compileJava
:app:processResources UP-TO-DATE
:app:classes
:app:jar

BUILD SUCCESSFUL

Total time: 3.177 secs

Wenn Sie die erstellte JAR mit dem Befehl java aufrufen, wird die Hauptklasse aufgerufen:

master$ java -jar ../app/build/libs/app.jar 
common

Aber es hat einfach funktioniert. Dies liegt daran, dass die Constant-Klasse nur gefunden werden kann, wenn die Abhängigkeitsinformationen für common.jar im Manifest beschrieben sind. Dieses Mal verweist die Main-Klasse nur auf die Konstante der Konstantenzeichenfolge. Daher ist es wahrscheinlich, dass der Wert zur Kompilierungszeit in der Main-Klasse beibehalten wurde.

Fälle, in denen Sie Abhängigkeiten von common.jar festlegen und dies immer funktioniert

Normalerweise ist es NoClassDefFoundError. Die Kompilierung ist erfolgreich, schlägt jedoch zur Laufzeit fehl.

Im Folgenden wird beispielsweise die Basisklasse "AbstractApplication" gemeinsam erstellt und von der App geerbt.

master$ gradle jar
:common:compileJava
:common:processResources UP-TO-DATE
:common:classes
:common:jar
:app:compileJava
:app:processResources UP-TO-DATE
:app:classes
:app:jar

BUILD SUCCESSFUL

Total time: 1.188 secs

master$ java -jar ../app/build/libs/app.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: com/github/kazuma1989/dec10_2016/common/AbstractApplication
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at com.github.kazuma1989.dec10_2016.app.Main.main(Main.java:9)
Caused by: java.lang.ClassNotFoundException: com.github.kazuma1989.dec10_2016.common.AbstractApplication
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 13 more

master$ tree ../app/build/libs/
../app/build/libs/
└── app.jar

Um dies zu lösen, ändern Sie das Innere des jar-Blocks wie folgt. Das Manifest hat einen "Attribute" -Klassenpfad "und der Aufgabe wurde eine" Kopier "-Operation hinzugefügt:

build.gradle


…

project(':app') {
    jar {
        manifest {
            attributes 'Main-Class': 'com.github.kazuma1989.dec10_2016.app.Main'
            attributes 'Class-Path': configurations.runtime.collect{it.name}.join(' ')
        }

        doLast {
            copy {
                from configurations.runtime
                into destinationDir
            }
        }
    }
}

configures.runtime enthält Informationen zu den Laufzeitabhängigkeiten des App-Projekts. Es enthält auch Informationen zu dem allgemeinen Projekt, das im Block "Abhängigkeiten" als "Kompilieren" angegeben ist. Dies liegt daran, dass Kompilierungsabhängigkeiten auch Laufzeitabhängigkeiten sind.

Bei "Attribute" Class-Path "wird der Inhalt von" configuration.runtime "mit Leerzeichen verkettet. Der Inhalt des Manifests lautet also "Klassenpfad: common.jar" (wenn Sie andere Abhängigkeiten als common hinzugefügt haben, ist dies so etwas wie "Klassenpfad: common.jar another.jar extra.jar". ).

Die JAR mit der Angabe "Class-Path: common.jar" im Manifest sucht nach common.jar im selben Verzeichnis wie sie selbst. Kopieren Sie also common.jar in dasselbe Verzeichnis wie app.jar im Block "copy". Ich bin.

Mit dem Hinzufügen des Manifests und der Kopie der abhängigen JAR ist die JAR-Ausführung nun erfolgreich. Wenn Sie das libs-Verzeichnis führen, ist Ihre Anwendung vollständig:

master$ gradle clean jar
:app:clean
:common:clean
:common:compileJava
:common:processResources UP-TO-DATE
:common:classes
:common:jar
:app:compileJava
:app:processResources UP-TO-DATE
:app:classes
:app:jar

BUILD SUCCESSFUL

Total time: 0.952 secs

master$ java -jar ../app/build/libs/app.jar 
common

master$ tree ../app/build/libs/
../app/build/libs/
├── app.jar
└── common.jar

Trennen Sie die Einstellungen für jedes Projekt vom Stammprojekt, um das Hinzufügen neuer Projekte zu vereinfachen

An diesem Punkt können Sie tun, was Sie vorerst tun wollten. Als nächstes möchte ich ein App2-Projekt hinzufügen, um es einem realen Beispiel näher zu bringen, aber zuerst werde ich das Skript organisieren.

Trennen Sie die Nur-App-Einstellungen in app / build.gradle

Ich wollte es vorerst verschieben, deshalb habe ich die Einstellungen des App-Projekts in build.gradle des Master-Projekts aufgelistet. Wenn jedoch nichts unternommen wird, erhöht sich die Anzahl der Beschreibungen, die master / build.gradle ähneln, mit zunehmender Anzahl von Teilprojekten.

Selbst wenn ich die Anzahl der Teilprojekte erhöhe, möchte ich die Änderungen nur in settings.gradle beibehalten. Daher werden die App-Projekteinstellungen im App-Verzeichnis in build.gradle unterteilt:

master$ tree ../ -L 2
../
├── app
│   ├── build.gradle
│   └── src
├── common
│   └── src
└── master
    ├── build.gradle
    └── settings.gradle

Fehlerfall

Auf den ersten Blick scheint es erfolgreich zu sein, aber es scheitert.

Geben Sie für app / build.gradle nur die Hauptklasse an, die für jedes Projekt unterschiedlich ist. Verschieben Sie in master / build.gradle das, was im Block "project (": app ")" geschrieben wurde, in den Block "subprojects":

app/build.gradle


jar {
    manifest {
        attributes 'Main-Class': 'com.github.kazuma1989.dec10_2016.app.Main'
    }
}

master/build.gradle


…

subprojects {
    …

    jar {
        manifest {
            attributes 'Class-Path': configurations.runtime.collect{it.name}.join(' ')
        }

        doLast {
            copy {
                from configurations.runtime
                into libsDir
            }
        }
    }
}

// project(':app') {
// }

In Zeile 33 tritt ein Fehler auf (wobei Attribute'Class-Path'):

master$ gradle clean jar

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/kazuma/qiita/2016/dec10/master/build.gradle' line: 33

* What went wrong:
A problem occurred evaluating root project 'master'.
> Could not resolve all dependencies for configuration ':app:runtime'.
   > Project :app declares a dependency from configuration 'compile' to configuration 'default' which is not declared in the descriptor for project :common.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 0.837 secs

Es scheint, dass ein Fehler aufgetreten ist, weil die in der App verwendete configuration.runtime nicht behoben werden konnte. Dies liegt daran, dass die Einstellungen des App-Projekts ausgeführt wurden, bevor das Java-Plug-In im allgemeinen Projekt aufgerufen wurde.

groovy:master/build.gradle(app/build.(Vor der Gradle-Trennung)


subprojects {
    // app ->Das Projekt ist in der Reihenfolge der gemeinsamen festgelegt (Fortsetzung unten).
    apply {
        plugin 'java'
        …
    }

    …
}

project(':app') {
    //Dieser Block wurde ausgeführt, nachdem das Java-Plug-In auf common angewendet wurde, sodass kein Problem auftrat.
    jar {
        …
    }
}

groovy:master/build.gradle(app/build.Nach Gradle-Trennung)


subprojects {
    // app ->Das Projekt ist in der Reihenfolge der gemeinsamen festgelegt.
    apply {
        plugin 'java'
        …
    }

    // project(':app')Da die Verarbeitung, die in war, in den Teilprojektblock gebracht wurde, wird sie ausgeführt, bevor das Java-Plug-In auf common angewendet wird, und es tritt ein Fehler auf.
    jar {
        …
    }
}

Erfolgreicher Fall

Es funktioniert einwandfrei, wenn Sie den Block "Teilprojekte" in "alle Teilprojekte einschließlich common und app" und "andere Teilprojekte als common" unterteilen. Die Bedeutung des Blocks ist ebenfalls klar, daher ist dies auch für die Lesbarkeit besser:

master/build.gradle


//Alle Teilprojekte einschließlich Common und App
subprojects {
    apply {
        plugin 'java'
        …
    }

    …
}

//Andere als übliche Teilprojekte
subprojects {
    if (project.name in ['common']) return

    dependencies {
        …
    }

    jar {
        …
    }
}
master$ gradle clean jar
:app:clean
:common:clean
:common:compileJava
:common:processResources UP-TO-DATE
:common:classes
:common:jar
:app:compileJava
:app:processResources UP-TO-DATE
:app:classes
:app:jar

BUILD SUCCESSFUL

Total time: 0.94 secs

master$ java -jar ../app/build/libs/app.jar 
common

Ersetzen Sie app / build.gradle durch gradle.properties

Da sich die Einstellungen für jedes Projekt nur in den Werten unterscheiden, ersetzen wir app / build.gradle durch gradle.properties. Gradle.properties ist wie build.gradle eine Eigenschaftendatei, die automatisch geladen wird, wenn sie direkt unter dem Projektverzeichnis vorhanden ist:

master$ tree ../ -L 2
../
├── app
│   ├── gradle.properties
│   └── src
├── common
│   └── src
└── master
    ├── build.gradle
    └── settings.gradle

app/gradle.properties


jar.manifest.attributes.Main-Class=com.github.kazuma1989.dec10_2016.app.Main

Rufen Sie in build.gradle den Wert mit der Methode "getProperty" ab.

Die Einschränkung ist, dass Sie den Block "afterEvaluate" verwenden müssen. Dies liegt daran, dass die Projekte in der Reihenfolge Master-Projekt und App-Projekt geladen werden, sodass app / gradle.properties zum Zeitpunkt von master / build.gradle noch nicht geladen wurde. Innerhalb des afterEvaluate-Blocks funktioniert, nachdem jedes Projekt ausgewertet wurde (nach Abschluss des Projekt-Setups), also funktioniert es:

master/build.gradle


…

subprojects {
    …

    afterEvaluate {
        jar {
            manifest {
                attributes 'Main-Class': getProperty('jar.manifest.attributes.Main-Class')
                attributes 'Class-Path': configurations.runtime.collect{it.name}.join(' ')
            }

            …
        }
    }
}

Zusammenfassung

Am Ende sieht die Konfiguration für mehrere Projekte folgendermaßen aus:

master$ tree ../ -L 2
../
├── app
│   ├── gradle.properties   //Schreiben Sie die Einstellungen für jedes Projekt
│   └── src                 //Quellcode für jede Anwendung. Kommt auf gemeinsame an
├── common
│   └── src                 //Gemeinsame Teile
└── master
    ├── build.gradle        //Definieren Sie Aufgaben, die in allen Projekten verwendet werden
    └── settings.gradle     //Geben Sie Verzeichnisse an, die in mehrere Projekte aufgenommen werden sollen

Alle JARs werden durch Eingabe von "gradle jar" in das Hauptverzeichnis generiert. Sie können in jedem Projektverzeichnis eine separate JAR mit "gradle jar" oder "gradle: common: jar" erstellen. Die generierte JAR ist als JAR organisiert, die vom libs-Verzeichnis abhängt. Sie können sie also so verwenden, wie sie ist, wenn Sie das gesamte Verzeichnis tragen.

Wenn wir die Anzahl der Projekte in Zukunft erhöhen, wird dies wie folgt sein:

master$ tree ../ -L 2
../
├── app
│   ├── gradle.properties
│   └── src
├── app2
│   ├── gradle.properties
│   └── src
├── app3
│   ├── build.gradle        //Skripte können platziert werden, wenn spezielle Einstellungen erforderlich sind
│   ├── gradle.properties
│   └── src
├── common
│   ├── build.gradle        //Geben Sie die Bibliotheken an, von denen Common abhängt
│   └── src
└── master
    ├── build.gradle
    └── settings.gradle

das ist alles.

Recommended Posts

Erstellen Sie mit Gradle eine ausführbare JAR für mehrere Projekte
Spring Boot 2 Multiprojekt mit Gradle
Richten Sie in IntelliJ ein Gradle-Multiprojekt ein, um eine JAR-Datei zu erstellen
Generieren Sie in Gradle 4.9 eine einzelne ausführbare JAR-Datei mit abhängigen Bibliotheken
Erstellen Sie mit Android Studio eine ausführbare JAR-Datei
Konfigurieren Sie ein Multiprojekt mit Unterverzeichnissen in Gradle
So erstellen Sie ein ausführbares JAR in Maven
Machen Sie einen Blackjack mit Java
Puzzle-Notizen in Gradle
Gradle-Einstellungsnotiz (Multiprojekt für alle in einem) für mich
Erstellen Sie eine JAR-Datei, die auf Gradle ausgeführt werden kann
Erstellen Sie mit Gradle ein Java-Multiprojekt
Gradle + Kotlin-Glas mit DSL generieren
Kopieren Sie abhängige Gläser in Gradle 5
Refactoring: Machen Sie Blackjack in Java
Kontrollaufgaben von Gradle
[Gradle] Die Geschichte, dass die Klassendatei nicht in der JAR-Datei vorhanden war
So erstellen Sie eine JAR-Datei ohne Abhängigkeiten in Maven
So erstellen Sie ein neues Gradle + Java + Jar-Projekt in Intellij 2016.03
Fügen Sie dem JAR-Dateinamen in Gradle einen Zeitstempel hinzu