-
Notifications
You must be signed in to change notification settings - Fork 924
/
Copy pathbuild.gradle
261 lines (218 loc) · 9.29 KB
/
build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.util.concurrent.TimeUnit
def mrJarVersions = [9,12]
mrJarVersions.each { version->
sourceSets {
"java${version}" {
java {
srcDirs = ["src/main/java${version}"]
}
}
"java${version}Test" {
java {
srcDirs = ["src/test/java${version}"]
}
}
}
def targetJavaVersion = Math.max(version, project.ext.targetJavaVersion)
"compileJava${version}Java" {
sourceCompatibility = targetJavaVersion
targetCompatibility = targetJavaVersion
options.release.set(targetJavaVersion)
}
"compileJava${version}TestJava" {
sourceCompatibility = targetJavaVersion
targetCompatibility = targetJavaVersion
options.release.set(targetJavaVersion)
}
task "testJava${version}"(type: Test, group: 'Verification', description: "Runs unit tests for Java ${version} source set") {
testClassesDirs = sourceSets."java${version}Test".output.classesDirs
classpath = sourceSets."java${version}Test".runtimeClasspath
project.ext.configureCommonTestSettings(it)
enabled = project.ext.testJavaVersion >= targetJavaVersion
}
configurations."java${version}Implementation".extendsFrom configurations.implementation
configurations."java${version}TestImplementation".extendsFrom configurations.testImplementation
configurations."java${version}TestRuntimeClasspath".extendsFrom configurations.testRuntimeClasspath
check.dependsOn "testJava${version}"
}
tasks.withType(Jar) {
mrJarVersions.each { version->
into("META-INF/versions/${version}") {
from sourceSets."java${version}".output
}
}
manifest.attributes(
'Multi-Release': 'true'
)
}
// Proguard can't handle multi-release jars so we recreate it here.
tasks.trimShadedJar.doLast {
// outjars is a file, so only one jar generated for sure
def trimmed = tasks.trimShadedJar.outJarFiles[0].toPath()
ant.jar(destfile: trimmed.toString(), update: true, duplicate: 'fail') {
zipfileset(src: tasks.shadedJar.archivePath) {
include(name: 'META-INF/versions/**')
}
// Do not let Ant put the properties that harm the build reproducibility, such as JDK version.
delegate.manifest {
attribute(name: 'Created-By', value: "Gradle ${gradle.gradleVersion}")
}
}
}
tasks.shadedTest.exclude 'META-INF/versions/**'
dependencies {
mrJarVersions.each { version ->
// Common to reference classes in main sourceset from Java 9 one (e.g., to return a common interface)
"java${version}Implementation" files(sourceSets.main.output.classesDirs) { builtBy compileJava }
"java${version}TestImplementation" files(sourceSets.test.output.classesDirs) { builtBy compileTestJava }
}
// Logging decorators expose slf4j in API
api libs.slf4j.api
// cglib
testImplementation libs.cglib
// Caffeine
implementation libs.caffeine
// Jackson
api libs.jackson.core
api libs.jackson.annotations
api libs.jackson.databind
api libs.jackson.datatype.jdk8
api libs.jackson.datatype.jsr310
// Logback is only used for RequestScopedMdc integration.
compileOnly libs.logback14
// Micrometer and other metric-related stuff
api libs.micrometer.core
optionalApi libs.micrometer.prometheus
optionalApi libs.dropwizard.metrics.core
optionalApi libs.prometheus
// Netty
api libs.netty.transport
api libs.netty.codec.haproxy
api libs.netty.codec.http2
api libs.netty.resolver.dns
implementation libs.netty.handler.proxy
// Netty native libraries
['linux-x86_64', 'linux-aarch_64'].each { arch ->
implementation(variantOf(libs.netty.transport.native.unix.common) { classifier(arch) })
implementation(variantOf(libs.netty.transport.native.epoll) { classifier(arch) })
optionalImplementation(variantOf(libs.netty.io.uring) { classifier(arch) })
}
['osx-x86_64', 'osx-aarch_64'].each { arch ->
implementation(variantOf(libs.netty.transport.native.unix.common) { classifier(arch) })
implementation(variantOf(libs.netty.transport.native.kqueue) { classifier(arch) })
implementation(variantOf(libs.netty.resolver.dns.native.macos) { classifier(arch) })
}
['linux-x86_64', 'linux-aarch_64', 'osx-x86_64', 'osx-aarch_64', 'windows-x86_64'].each { arch ->
implementation(variantOf(libs.netty.tcnative.boringssl) { classifier(arch) })
}
// TestNG
testRuntimeOnly libs.junit.testng.engine
// JUnit Pioneer
testImplementation libs.junit.pioneer
// Reactive Streams
api libs.reactivestreams
testImplementation libs.reactivestreams.tck
// Do not upgrade to Scala 2.13.x that causes 'java.lang.ClassNotFoundException: scala.Serializable'
// See https://github.com/scala/bug/issues/11832#issuecomment-568185023
// If needed, you should consider to add 'armeria-scala' module.
optionalImplementation libs.scala.v212
// Bouncy Castle
implementation libs.bouncycastle.bcpkix
implementation libs.bouncycastle.bcprov
implementation libs.bouncycastle.bcutil
// Jetty, for testing interoperability with other servers.
testImplementation libs.jetty94.webapp
// Brotli
implementation libs.brotli4j
optionalImplementation libs.brotli4j.linux
optionalImplementation libs.brotli4j.linux.aarch64
optionalImplementation libs.brotli4j.osx
optionalImplementation libs.brotli4j.osx.aarch64
optionalImplementation libs.brotli4j.windows
// for testing the observation API with tracing
testImplementation (libs.micrometer.tracing.integration.test) {
exclude group: "org.mockito"
}
testImplementation libs.brave6.context.slf4j
testImplementation libs.brave6.instrumentation.http.tests
}
if (!rootProject.hasProperty('noWeb')) {
sourceSets {
main {
output.dir project(':docs-client').file('build/javaweb'), builtBy: ':docs-client:copyWeb'
}
}
}
// Run HttpServerStreamingTest separately with memory constraint.
tasks.test.exclude '**/HttpServerStreamingTest**'
tasks.shadedTest.exclude '**/HttpServerStreamingTest**'
testing.suites {
testStreaming(JvmTestSuite) {
targets.configureEach {
testTask.configure {
group = 'Verification'
description = 'Runs the streaming tests.'
project.ext.configureCommonTestSettings(it)
dependsOn(tasks.copyShadedTestClasses)
// Use small heap for streaming tests to quickly ensure we can stream the content larger than heap.
maxHeapSize = '64m'
include '**/HttpServerStreamingTest**'
testClassesDirs = tasks.shadedTest.testClassesDirs
classpath = testClassesDirs
// Set the class path as late as possible so that the 'shadedTest' task has the correct classpath.
doFirst {
classpath += project.files(configurations.shadedJarTestRuntime.resolve())
}
}
}
}
}
tasks.check.dependsOn testing.suites.testStreaming
if (tasks.findByName('trimShadedJar')) {
tasks.trimShadedJar.configure {
// Keep all classes under com.linecorp.armeria, except the internal ones.
keep "class !com.linecorp.armeria.internal.shaded.**,com.linecorp.armeria.** { *; }"
// Keep the 'NonBlocking' tag interface.
keep "class reactor.core.scheduler.NonBlocking { *; }"
// Do not optimize the dependencies that access some fields via sun.misc.Unsafe or reflection only.
keep "class com.linecorp.armeria.internal.shaded.caffeine.** { *; }"
keep "class com.linecorp.armeria.internal.shaded.jctools.** { *; }"
dontnote
}
}
class PublicSuffixesTask extends DefaultTask {
// Rebuild up to once in 7 days, unless cleaned.
@Input
final def days = (System.currentTimeMillis() / TimeUnit.DAYS.toMillis(7)).intValue()
@OutputFile
final def publicSuffixesFile = project.file("${project.projectDir}/src/main/resources/com/linecorp/armeria/public_suffixes.txt")
@TaskAction
def run() {
try {
def tempFile = File.createTempFile("public_suffixes", null)
def req = (HttpURLConnection) new URL('https://publicsuffix.org/list/public_suffix_list.dat').openConnection()
def res = req.getInputStream()
if (req.getResponseCode() != 200) {
println "received a non-200 response from publicsuffix.org: ${req.getResponseCode()}"
return
}
def sortedSet = new TreeSet<String>()
res.eachLine('UTF-8') {
if (!it.isEmpty() && !it.startsWith("//")) {
sortedSet.add(IDN.toASCII(it))
}
}
sortedSet.each {
tempFile.append(it)
tempFile.append("\n")
}
Files.move(tempFile.toPath(), publicSuffixesFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
println "public suffixes file is updated"
} catch (Exception e) {
println "an exception was thrown: ${e}"
}
}
}
task publicSuffixes(type: PublicSuffixesTask)