今のところ、src
という名前の単一のソースフォルダーを持つプロジェクト構造があり、3つのモジュールのソースコードが含まれています。私がやりたいことは:
1)ソースコードをコンパイルします。これは、sourceSets定義を使用して簡単に実行できます。
sourceSets {
main {
Java {
srcDir 'src'
}
}
}
2)コンパイル結果を3つのjarに入れます。私は3つの「jar」タイプのタスクを介してこれを行っています:
私は今、3つの個別のタスクを介してこれを行っています。
util.jar
task utilJar(type: Jar) {
from(sourceSets.main.output) {
include "my/util/package/**"
}
}
client.jar
task clientJar(type: Jar) {
from(sourceSets.main.output) {
include "my/client/package/**"
}
}
server.jar
task serverJar(type: Jar) {
from(sourceSets.main.output) {
include "**"
}
excludes.addAll(utilJar.includes)
excludes.addAll(clientJar.includes)
}
問題は、server.jar
にはclient.jar
およびutil.jar
に含まれていないすべてのクラスが含まれている必要があるということです。 antビルドスクリプトでは、difference
antタスクを使用してこの問題を解決します。これをgradleでどのように行うことができますか(私の現在のアプローチは機能しません)?
たぶん私のアプローチは完全に間違っています。ご意見をお聞かせください。
追伸今のところ、プロジェクトのソースコードのフォルダー構造を変更することはできません。
答えとしてここに作業中のソリューションを投稿します(gradleのフォーラムにヒントがあります)。
Gradleのスコープは非常に奇妙です:)すべてのタスク定義は、この特定のケースでは「JarTask」のような「Task」クラスのオブジェクトを作成すると思いました。その後、build.gradleスクリプトのどこからでもクラスのプロパティにアクセスできます。ただし、jarファイルに含まれるパターンを確認できる唯一の場所は、タスクのfrom
ブロック内です。したがって、今のところ私の作業ソリューションは次のとおりです。
1)server.jar
から除外されるパターンを含むプロジェクトレベルのコレクションを定義します
2)from
タスクのserverJar
ブロック内のすべてのパターンを除外します。
以下の最終版をご覧ください
sourceSets {
main {
Java {
srcDir 'src'
}
}
}
// holds classes included into client.jar and util.jar, so they are to be excluded from server.jar
ext.serverExcludes = []
// util.jar
task utilJar(type: Jar) {
from(sourceSets.main.output) {
include "my/util/package/**"
project.ext.serverExcludes.addAll(includes)
}
}
// client.jar
task clientJar(type: Jar) {
from(sourceSets.main.output) {
include "my/client/package/**"
project.ext.serverExcludes.addAll(includes)
}
}
// server.jar
task serverJar(type: Jar) {
from(sourceSets.main.output) {
exclude project.ext.serverExcludes
}
}
アプローチが間違っていると思います。 3つのサブプロジェクトでプロジェクトを作成することをお勧めします。
project
- util
- server (depends on util)
- client (depends on util)
何らかの理由でクラス構造を変更できない場合は、次の種類のビルドファイルを使用します。
settings.gradle
include 'util', 'client', 'server'
build.gradle
subprojects {
apply plugin: 'Java'
}
project(':util') {
sourceSets {
main {
Java {
srcDir '../src'
include 'util/**'
}
}
}
}
project(':server') {
sourceSets {
main {
Java {
srcDir '../src'
include 'server/**'
}
}
}
dependencies {
compile project(':util')
}
}
project(':client') {
sourceSets {
main {
Java {
srcDir '../src'
include 'client/**'
}
}
}
dependencies {
compile project(':util')
}
}
サブプロジェクトにはまだディレクトリが必要ですが、ソースは必要に応じて1か所にあります。
gradle assemble
を実行すると、個別のクラスセットを持つ3つのjarが作成されます。このソリューションの利点は、jarを作成するためのタスクだけでなく、正しい依存関係を持つ適切なGradleマルチモジュールプロジェクトを作成できることです。
Multi-Project Builds をお読みください。
私の会社でも同じ問題があります。 「良い」プロジェクト構造に移行するのが難しいレガシーコード、および同じコードベースから複数のjarを構築する必要性。異なるsourceSetを定義し、標準のGradleを使用して各sourceSetをビルドすることにしました。
次に、イテレータを使用して、各sourceSetのjarタスクとjavadocタスクを追加します。
sourceSets.all { SourceSet sourceSet ->
Task jarTask = tasks.create("jar" + sourceSet.name, Jar.class)
jarTask.from(sourceSet.output)
// Configure other jar task properties: group, description, manifest etc
Task javadocTask = tasks.create("javadoc" + sourceSet.name, Javadoc.class)
javadocTask.setClasspath(sourceSet.output + sourceSet.compileClasspath)
javadocTask.setSource(sourceSet.allJava)
// Extra config for the javadoc task: group, description etc
Task javadocJarTask = tasks.create("javadocJar" + sourceSet.name, Jar.class)
javadocJarTask.setClassifier("javadoc") // adds "-javadoc" to the name of the jar
javadocJarTask.from(javadocTask.outputs)
// Add extra config: group, description, manifest etc
}
私も原則として受け入れられた答えに同意します。マニフェストがClass-Pathキーによってのみ異なることを除き、クライアントが本質的に同じファイルの2つのJARを必要とするプロジェクトを見つけました。
jar {
manifest {
attributes(
"Main-Class": platformMainClass,
"Implementation-Title": platformDisplayName,
"Implementation-Description": platformDescription,
"Platform-Version": platformVersion,
"Implementation-Version": version,
"Build-Assembly-User": System.getProperty("user.name"),
"Build-Assembly-Date": new Java.util.Date().toString(),
"Class-Path": configurations.compile.collect { "lib/"+it.getName() }.join(' ')
)
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
exclude( [ 'log4j*.properties', 'uk/gov/acme/secret/product/server/**' ])
}
同じマニフェストとソースコードは次のとおりです。
task applicationClientJar(type: Jar, description: "Creates the Application Client JAR file.") {
dependsOn compileJava
manifest {
attributes(
"Main-Class": platformMainClass,
"Implementation-Title": platformDisplayName,
"Implementation-Description": platformDescription,
"Platform-Version": platformVersion,
"Implementation-Version": version,
"Assembly-Date": new Java.util.Date().toString()
)
}
archiveName = "acme-client-${platformVersion}.jar"
destinationDir = file("${buildDir}/libs")
from sourceSets.main.output
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
exclude( [ 'log4j*.properties', 'uk/gov/acme/secret/product/server/**' }
Grzegorz表記は正しいです。Gradleは、GAVを持つ2つの異なるJARがあることを知っているはずです。マルチモジュールが推奨されるオプションです。
compile "uk.gov.acme.secret:acme:1.0" // CORE
compile "uk.gov.acme.secret:acme-client:1.0"
これを設定する唯一の方法は、Multi-Module Gradleプロジェクトを使用してから、コア/メインプロジェクトにコンパイルおよび/またはデプロイの依存関係を追加することです。
project(':common:acme-micro-service-webapp') {
dependencies {
compile project(':common:acme-core')
}
}
「acme-micro-service-webapp」プロジェクト内では、これにより、依存する「common:acme-core」が最初にコンパイルされます。
PS:私はまだより良い解決策を見つけようとしています。
PS PS:Mavenも使用している場合は、「インストール」タスクをフックすることができます。