-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.gradle.kts
163 lines (135 loc) · 6.03 KB
/
build.gradle.kts
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
plugins {
id("unsafe-sanitizer.java-conventions")
alias(libs.plugins.shadow)
}
val agentJar: Configuration by configurations.creating {
// Prevent projects depending on this one from seeing and using this configuration
isCanBeConsumed = false
isVisible = false
isTransitive = false
}
dependencies {
implementation(libs.bytebuddy)
implementation(libs.bytebuddy.agent)
implementation(libs.errorprone.annotations)
implementation(libs.jetbrains.annotations)
// For convenience add `compileOnly` dependency so that code in this project can directly reference agent classes
// However, they are not part of the public API, and accessing them will only work after agent has been installed
compileOnly(project(":agent-impl"))
testCompileOnly(project(":agent-impl"))
agentJar(project(path = ":agent-impl", configuration = "shadow"))
testImplementation(libs.junit)
testRuntimeOnly(libs.junit.launcher)
}
// Embed the agent JAR as resource, see `marcono1234.unsafe_sanitizer.UnsafeSanitizer#addAgentToBootstrapClasspath`
// for details
val agentJarDir = layout.buildDirectory.dir("generated/agent-impl-jar").get().asFile
val copyAgentImplJar = tasks.register<Copy>("copyAgentImplJar") {
from(agentJar) {
// TODO: Trailing `_` is as workaround for https://github.com/GradleUp/shadow/issues/111 for standalone agent JAR
rename(".*", "agent-impl.jar_")
}
// Add package name prefix
into(agentJarDir.resolve("marcono1234/unsafe_sanitizer"))
}
sourceSets.main.get().output.dir(mutableMapOf<String, Any>("builtBy" to copyAgentImplJar), agentJarDir)
// TODO: Maybe configure this using test suites instead, for consistency
val testJdk21 = tasks.register<Test>("testJdk21") {
javaLauncher.set(javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(21))
})
}
tasks.check {
dependsOn(testJdk21)
}
@Suppress("UnstableApiUsage") // for Test Suites
testing {
suites {
data class TestConfig(val javaVersion: Int, val agentArgs: String? = null)
val testConfigs = arrayOf(
TestConfig(17),
TestConfig(21),
TestConfig(21, "call-debug-logging=true,uninitialized-memory-tracking=false")
)
testConfigs.forEach { testConfig ->
// Create integration test for using agent standalone by running with `-javaagent:...`
var testName = "agentTestJdk${testConfig.javaVersion}";
testConfig.agentArgs?.let { testName += "Args" }
val agentTest by register(testName, JvmTestSuite::class) {
useJUnitJupiter(libs.versions.junit)
// TODO: This causes the warning "Duplicate content roots detected" in IntelliJ; can probably be ignored for now
sources {
java {
setSrcDirs(listOf("src/agentTest/java"))
}
}
targets {
all {
testTask.configure {
// Run regular tests first
shouldRunAfter(tasks.test)
// Requires JAR with dependencies
dependsOn(tasks.shadowJar)
val agentJar = tasks.shadowJar.get().archiveFile
// Define the agent JAR as additional input to prevent Gradle from erroneously assuming
// this task is UP-TO-DATE or can be used FROM-CACHE despite the agent JAR having changed
inputs.file(agentJar)
// Evaluate the arguments lazily to make sure the `shadowJar` task has already been configured
jvmArgumentProviders.add {
val agentPath = agentJar.get().asFile.absolutePath;
val agentArgs = testConfig.agentArgs?.let { "=$it" } ?: ""
listOf("-javaagent:${agentPath}${agentArgs}")
}
javaLauncher.set(javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(testConfig.javaVersion))
})
}
}
}
}
tasks.check {
dependsOn(agentTest)
}
}
}
}
// Create JAR with dependencies variant to allow standalone agent usage
tasks.shadowJar {
isEnableRelocation = false
duplicatesStrategy = DuplicatesStrategy.FAIL
archiveClassifier = "standalone-agent"
manifest {
attributes(
// See https://docs.oracle.com/en/java/javase/17/docs/api/java.instrument/java/lang/instrument/package-summary.html
// section "Manifest Attributes"
"Premain-Class" to "marcono1234.unsafe_sanitizer.AgentMain",
"Can-Retransform-Classes" to "true",
// Main class is used for printing usage help on command line
"Main-Class" to "marcono1234.unsafe_sanitizer.AgentMain",
// Mark as multi-release due to multi-release dependencies, see also https://github.com/GradleUp/shadow/issues/449
"Multi-Release" to "true",
)
}
// Exclude `module-info` from dependencies, see also https://github.com/GradleUp/shadow/issues/729
exclude("META-INF/versions/*/module-info.class")
// Exclude duplicated Byte Buddy classes; Byte Buddy contains the same class files for Java 5 and Java 8, but since
// this project here is using Java > 8 can omit the Java 5 classes, see also https://github.com/raphw/byte-buddy/pull/1719
exclude("net/bytebuddy/**")
}
// Run shadow task by default
tasks.build {
dependsOn(tasks.shadowJar)
}
java {
// Publish sources and javadoc
withSourcesJar()
withJavadocJar()
}
// TODO: Maybe should use `agent` as artifactId (by changing rootProject.name?)
publishing {
publications {
create<MavenPublication>("maven") {
from(components["java"])
}
}
}