diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 92365591b13..2069f36b355 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -16,7 +16,7 @@ gradlePlugin { plugins { create("instrument-plugin") { id = "dd-trace-java.instrument" - implementationClass = "InstrumentPlugin" + implementationClass = "datadog.gradle.plugin.instrument.InstrumentPlugin" } create("muzzle-plugin") { diff --git a/buildSrc/src/main/groovy/InstrumentPlugin.groovy b/buildSrc/src/main/groovy/InstrumentPlugin.groovy deleted file mode 100644 index ebfe47b3c93..00000000000 --- a/buildSrc/src/main/groovy/InstrumentPlugin.groovy +++ /dev/null @@ -1,209 +0,0 @@ -import org.gradle.api.DefaultTask -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.file.Directory -import org.gradle.api.file.DirectoryProperty -import org.gradle.api.invocation.BuildInvocationDetails -import org.gradle.api.provider.ListProperty -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Classpath -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputDirectory -import org.gradle.api.tasks.InputFiles -import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.OutputDirectory -import org.gradle.api.tasks.TaskAction -import org.gradle.api.tasks.compile.AbstractCompile -import org.gradle.jvm.toolchain.JavaLanguageVersion -import org.gradle.jvm.toolchain.JavaToolchainService -import org.gradle.workers.WorkAction -import org.gradle.workers.WorkParameters -import org.gradle.workers.WorkerExecutor - -import javax.inject.Inject -import java.util.concurrent.ConcurrentHashMap -import java.util.regex.Matcher - -/** - * instrument task plugin which performs build-time instrumentation of classes. - */ -@SuppressWarnings('unused') -class InstrumentPlugin implements Plugin { - @Override - void apply(Project project) { - InstrumentExtension extension = project.extensions.create('instrument', InstrumentExtension) - - project.tasks.matching { - it.name in ['compileJava', 'compileScala', 'compileGroovy'] || - it.name =~ /compileMain_.+Java/ - }.all { - AbstractCompile compileTask = it as AbstractCompile - Matcher versionMatcher = it.name =~ /compileMain_(.+)Java/ - project.afterEvaluate { - if (!compileTask.source.empty) { - String sourceSetSuffix = null - String javaVersion = null - if (versionMatcher.matches()) { - sourceSetSuffix = versionMatcher.group(1) - if (sourceSetSuffix ==~ /java\d+/) { - javaVersion = sourceSetSuffix[4..-1] - } - } - - // insert intermediate 'raw' directory for unprocessed classes - Directory classesDir = compileTask.destinationDirectory.get() - Directory rawClassesDir = classesDir.dir("../raw${sourceSetSuffix ? "_$sourceSetSuffix" : ''}/") - compileTask.destinationDirectory.set(rawClassesDir.asFile) - - // insert task between compile and jar, and before test* - String instrumentTaskName = compileTask.name.replace('compile', 'instrument') - def instrumentTask = project.tasks.register(instrumentTaskName, InstrumentTask) { - // Task configuration - it.group = 'Byte Buddy' - it.description = "Instruments the classes compiled by ${compileTask.name}" - it.inputs.dir(compileTask.destinationDirectory) - it.outputs.dir(classesDir) - // Task inputs - it.javaVersion = javaVersion - def instrumenterConfiguration = project.configurations.named('instrumentPluginClasspath') - if (instrumenterConfiguration.present) { - it.pluginClassPath.from(instrumenterConfiguration.get()) - } - it.plugins = extension.plugins - it.instrumentingClassPath.from( - findCompileClassPath(project, it.name) + - rawClassesDir + - findAdditionalClassPath(extension, it.name) - ) - it.sourceDirectory = rawClassesDir - // Task output - it.targetDirectory = classesDir - } - if (javaVersion) { - project.tasks.named(project.sourceSets."main_java${javaVersion}".classesTaskName) { - it.dependsOn(instrumentTask) - } - } else { - project.tasks.named(project.sourceSets.main.classesTaskName) { - it.dependsOn(instrumentTask) - } - } - } - } - } - } - - static findCompileClassPath(Project project, String taskName) { - def matcher = taskName =~ /instrument([A-Z].+)Java/ - def cfgName = matcher.matches() ? "${matcher.group(1).uncapitalize()}CompileClasspath" : 'compileClasspath' - project.configurations.named(cfgName).findAll { - it.name != 'previous-compilation-data.bin' && !it.name.endsWith('.gz') - } - } - - static findAdditionalClassPath(InstrumentExtension extension, String taskName) { - extension.additionalClasspath.getOrDefault(taskName, []).collect { - // insert intermediate 'raw' directory for unprocessed classes - def fileName = it.get().asFile.name - it.get().dir("../${fileName.replaceFirst('^main', 'raw')}") - } - } -} - -abstract class InstrumentExtension { - abstract ListProperty getPlugins() - Map> additionalClasspath = [:] -} - -abstract class InstrumentTask extends DefaultTask { - @Input @Optional - String javaVersion - @InputFiles @Classpath - abstract ConfigurableFileCollection getPluginClassPath() - @Input - ListProperty plugins - @InputFiles @Classpath - abstract ConfigurableFileCollection getInstrumentingClassPath() - @InputDirectory - Directory sourceDirectory - - @OutputDirectory - Directory targetDirectory - - @Inject - abstract JavaToolchainService getJavaToolchainService() - @Inject - abstract BuildInvocationDetails getInvocationDetails() - @Inject - abstract WorkerExecutor getWorkerExecutor() - - @TaskAction - instrument() { - workQueue().submit(InstrumentAction.class, parameters -> { - parameters.buildStartedTime.set(this.invocationDetails.buildStartedTime) - parameters.pluginClassPath.from(this.pluginClassPath) - parameters.plugins.set(this.plugins) - parameters.instrumentingClassPath.setFrom(this.instrumentingClassPath) - parameters.sourceDirectory.set(this.sourceDirectory.asFile) - parameters.targetDirectory.set(this.targetDirectory.asFile) - }) - } - - private workQueue() { - if (!this.javaVersion) { - this.javaVersion = "8" - } - def javaLauncher = this.javaToolchainService.launcherFor { spec -> - spec.languageVersion.set(JavaLanguageVersion.of(this.javaVersion)) - }.get() - return this.workerExecutor.processIsolation { spec -> - spec.forkOptions { fork -> - fork.executable = javaLauncher.executablePath - } - } - } -} - -interface InstrumentWorkParameters extends WorkParameters { - Property getBuildStartedTime() - ConfigurableFileCollection getPluginClassPath() - ListProperty getPlugins() - ConfigurableFileCollection getInstrumentingClassPath() - DirectoryProperty getSourceDirectory() - DirectoryProperty getTargetDirectory() -} - -abstract class InstrumentAction implements WorkAction { - private static final Object lock = new Object() - private static final Map classLoaderCache = new ConcurrentHashMap<>() - private static volatile long lastBuildStamp - - @Override - void execute() { - String[] plugins = parameters.getPlugins().get() as String[] - String classLoaderKey = plugins.join(':') - - // reset shared class-loaders each time a new build starts - long buildStamp = parameters.buildStartedTime.get() - ClassLoader pluginCL = classLoaderCache.get(classLoaderKey) - if (lastBuildStamp < buildStamp || !pluginCL) { - synchronized (lock) { - pluginCL = classLoaderCache.get(classLoaderKey) - if (lastBuildStamp < buildStamp || !pluginCL) { - pluginCL = createClassLoader(parameters.pluginClassPath) - classLoaderCache.put(classLoaderKey, pluginCL) - lastBuildStamp = buildStamp - } - } - } - File sourceDirectory = parameters.getSourceDirectory().get().asFile - File targetDirectory = parameters.getTargetDirectory().get().asFile - ClassLoader instrumentingCL = createClassLoader(parameters.instrumentingClassPath, pluginCL) - InstrumentingPlugin.instrumentClasses(plugins, instrumentingCL, sourceDirectory, targetDirectory) - } - - static ClassLoader createClassLoader(cp, parent = InstrumentAction.classLoader) { - return new URLClassLoader(cp*.toURI()*.toURL() as URL[], parent as ClassLoader) - } -} diff --git a/buildSrc/src/main/groovy/InstrumentingPlugin.groovy b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/ByteBuddyInstrumenter.groovy similarity index 96% rename from buildSrc/src/main/groovy/InstrumentingPlugin.groovy rename to buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/ByteBuddyInstrumenter.groovy index 9a766971487..7b471b8f5dc 100644 --- a/buildSrc/src/main/groovy/InstrumentingPlugin.groovy +++ b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/ByteBuddyInstrumenter.groovy @@ -1,3 +1,5 @@ +package datadog.gradle.plugin.instrument + import net.bytebuddy.ClassFileVersion import net.bytebuddy.build.EntryPoint import net.bytebuddy.build.Plugin @@ -12,8 +14,8 @@ import org.slf4j.LoggerFactory * Performs build-time instrumentation of classes, called indirectly from InstrumentPlugin. * (This is the byte-buddy side of the task; InstrumentPlugin contains the Gradle pieces.) */ -class InstrumentingPlugin { - static final Logger log = LoggerFactory.getLogger(InstrumentingPlugin.class) +class ByteBuddyInstrumenter { + static final Logger log = LoggerFactory.getLogger(ByteBuddyInstrumenter.class) static void instrumentClasses( String[] plugins, ClassLoader instrumentingLoader, File sourceDirectory, File targetDirectory) diff --git a/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentAction.groovy b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentAction.groovy new file mode 100644 index 00000000000..49f3c946412 --- /dev/null +++ b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentAction.groovy @@ -0,0 +1,58 @@ +package datadog.gradle.plugin.instrument + +import java.nio.file.Path +import java.util.concurrent.ConcurrentHashMap +import javax.inject.Inject +import org.gradle.api.file.FileSystemOperations +import org.gradle.api.model.ObjectFactory +import org.gradle.workers.WorkAction + +abstract class InstrumentAction implements WorkAction { + private static final Object lock = new Object() + private static final Map classLoaderCache = new ConcurrentHashMap<>() + private static volatile long lastBuildStamp + + @Inject + public abstract FileSystemOperations getFileSystemOperations(); + + @Inject + public abstract ObjectFactory getObjects(); + + @Override + void execute() { + String[] plugins = parameters.getPlugins().get() as String[] + String classLoaderKey = plugins.join(':') + + // reset shared class-loaders each time a new build starts + long buildStamp = parameters.buildStartedTime.get() + ClassLoader pluginCL = classLoaderCache.get(classLoaderKey) + if (lastBuildStamp < buildStamp || !pluginCL) { + synchronized (lock) { + pluginCL = classLoaderCache.get(classLoaderKey) + if (lastBuildStamp < buildStamp || !pluginCL) { + pluginCL = createClassLoader(parameters.pluginClassPath) + classLoaderCache.put(classLoaderKey, pluginCL) + lastBuildStamp = buildStamp + } + } + } + Path classesDirectory = parameters.compilerOutputDirectory.get().asFile.toPath() + Path tmpUninstrumentedDir = parameters.tmpDirectory.get().asFile.toPath() + + // Original classes will be replaced by post-processed ones + fileSystemOperations.sync { + from(classesDirectory) + into(tmpUninstrumentedDir) + } + fileSystemOperations.delete { + delete(objects.fileTree().from(classesDirectory)) + } + + ClassLoader instrumentingCL = createClassLoader(parameters.instrumentingClassPath, pluginCL) + ByteBuddyInstrumenter.instrumentClasses(plugins, instrumentingCL, tmpUninstrumentedDir.toFile(), classesDirectory.toFile()) + } + + static ClassLoader createClassLoader(cp, parent = InstrumentAction.classLoader) { + return new URLClassLoader(cp*.toURI()*.toURL() as URL[], parent as ClassLoader) + } +} diff --git a/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentExtension.groovy b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentExtension.groovy new file mode 100644 index 00000000000..739f648035d --- /dev/null +++ b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentExtension.groovy @@ -0,0 +1,9 @@ +package datadog.gradle.plugin.instrument + +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.ListProperty + +abstract class InstrumentExtension { + abstract ListProperty getPlugins() + abstract ListProperty getAdditionalClasspath() +} diff --git a/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentPlugin.groovy b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentPlugin.groovy new file mode 100644 index 00000000000..e0fb3c6e273 --- /dev/null +++ b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentPlugin.groovy @@ -0,0 +1,119 @@ +package datadog.gradle.plugin.instrument + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.logging.Logger +import org.gradle.api.logging.Logging +import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.compile.AbstractCompile + +import java.util.regex.Matcher + +/** + * instrument task plugin which performs build-time instrumentation of classes. + */ +@SuppressWarnings('unused') +class InstrumentPlugin implements Plugin { + public static final String DEFAULT_JAVA_VERSION = 'default' + public static final String INSTRUMENT_PLUGIN_CLASSPATH_CONFIGURATION = 'instrumentPluginClasspath' + private final Logger logger = Logging.getLogger(InstrumentPlugin) + + @Override + void apply(Project project) { + InstrumentExtension extension = project.extensions.create('instrument', InstrumentExtension) + project.configurations.register(INSTRUMENT_PLUGIN_CLASSPATH_CONFIGURATION) + + + ['java', 'kotlin', 'scala', 'groovy'].each { langPluginId -> + project.pluginManager.withPlugin(langPluginId) { + configurePostCompilationInstrumentation(langPluginId, project, extension) + } + } + } + + private void configurePostCompilationInstrumentation(String language, Project project, InstrumentExtension extension) { + project.extensions.configure(SourceSetContainer) { SourceSetContainer sourceSets -> + // For any "main" source-set configure its compile task + sourceSets.configureEach { SourceSet sourceSet -> + def sourceSetName = sourceSet.name + logger.info("[InstrumentPlugin] source-set: $sourceSetName, language: $language") + + if (!sourceSetName.startsWith(SourceSet.MAIN_SOURCE_SET_NAME)) { + logger.debug("[InstrumentPlugin] Skipping non-main source set {} for language {}", sourceSetName, language) + return + } + + def compileTaskName = sourceSet.getCompileTaskName(language) + logger.info("[InstrumentPlugin] compile task name: " + compileTaskName) + + // For each compile task, append an instrumenting post-processing step + // Examples of compile tasks: + // - compileJava, + // - compileMain_java17Java, + // - compileMain_jetty904Java, + // - compileMain_play25Java, + // - compileKotlin, + // - compileScala, + // - compileGroovy, + project.tasks.withType(AbstractCompile).matching { + it.name == compileTaskName && !it.source.isEmpty() + }.configureEach { + logger.info('[InstrumentPlugin] Applying instrumentPluginClasspath configuration as compile task input') + it.inputs.files(project.configurations.named(INSTRUMENT_PLUGIN_CLASSPATH_CONFIGURATION)) + + if (it.source.isEmpty()) { + logger.debug("[InstrumentPlugin] Skipping $compileTaskName for source set $sourceSetName as it has no source files") + return + } + + // Compute optional Java version + Matcher versionMatcher = compileTaskName =~ /compileMain_(.+)Java/ + String sourceSetSuffix = null + String javaVersion = null + if (versionMatcher.matches()) { + sourceSetSuffix = versionMatcher.group(1) + if (sourceSetSuffix ==~ /java\d+/) { + javaVersion = sourceSetSuffix[4..-1] + } + } + javaVersion = javaVersion ?: DEFAULT_JAVA_VERSION // null not accepted + it.inputs.property("javaVersion", javaVersion) + + it.inputs.property("plugins", extension.plugins) + + it.inputs.files(extension.additionalClasspath) + + // Temporary location for raw (un-instrumented) classes + DirectoryProperty tmpUninstrumentedClasses = project.objects.directoryProperty().value( + project.layout.buildDirectory.dir("tmp/${it.name}-raw-classes") + ) + + // Class path to use for instrumentation post-processing + ConfigurableFileCollection instrumentingClassPath = project.objects.fileCollection() + instrumentingClassPath.setFrom( + it.classpath, + extension.additionalClasspath, + tmpUninstrumentedClasses + ) + + // This were the post processing happens, i.e. were the instrumentation is applied + it.doLast( + "instrumentClasses", + project.objects.newInstance( + InstrumentPostProcessingAction, + javaVersion, + extension.plugins, + instrumentingClassPath, + it.destinationDirectory, + tmpUninstrumentedClasses + ) + ) + logger.info("[InstrumentPlugin] Configured post-compile instrumentation for $compileTaskName for source-set $sourceSetName") + } + } + } + } +} diff --git a/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.groovy b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.groovy new file mode 100644 index 00000000000..89ef0e9286b --- /dev/null +++ b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.groovy @@ -0,0 +1,86 @@ +package datadog.gradle.plugin.instrument + +import javax.inject.Inject +import org.gradle.api.Action +import org.gradle.api.Project +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.FileCollection +import org.gradle.api.invocation.BuildInvocationDetails +import org.gradle.api.logging.Logger +import org.gradle.api.logging.Logging +import org.gradle.api.provider.ListProperty +import org.gradle.api.tasks.compile.AbstractCompile +import org.gradle.jvm.toolchain.JavaLanguageVersion +import org.gradle.jvm.toolchain.JavaToolchainService +import org.gradle.workers.WorkerExecutor + +abstract class InstrumentPostProcessingAction implements Action { + private final Logger logger = Logging.getLogger(InstrumentPostProcessingAction) + + @Inject + abstract Project getProject() + + @Inject + abstract JavaToolchainService getJavaToolchainService() + + @Inject + abstract BuildInvocationDetails getInvocationDetails() + + @Inject + abstract WorkerExecutor getWorkerExecutor() + + // Those cannot be private other wise Groovy will fail at runtime with a missing property ex + final JavaLanguageVersion javaVersion + final ListProperty plugins + final FileCollection instrumentingClassPath + final DirectoryProperty compilerOutputDirectory + final DirectoryProperty tmpDirectory + + @Inject + InstrumentPostProcessingAction( + String javaVersion, + ListProperty plugins, + FileCollection instrumentingClassPath, + DirectoryProperty compilerOutputDirectory, + DirectoryProperty tmpDirectory + ) { + this.javaVersion = javaVersion == InstrumentPlugin.DEFAULT_JAVA_VERSION ? JavaLanguageVersion.current() : JavaLanguageVersion.of(javaVersion) + this.plugins = plugins + this.instrumentingClassPath = instrumentingClassPath + this.compilerOutputDirectory = compilerOutputDirectory + this.tmpDirectory = tmpDirectory + } + + @Override + void execute(AbstractCompile task) { + logger.info( + "[InstrumentPostProcessingAction] About to instrument classes \n" + + " javaVersion=${javaVersion}, \n" + + " plugins=${plugins.get()}, \n" + + " instrumentingClassPath=${instrumentingClassPath.files}, \n" + + " rawClassesDirectory=${compilerOutputDirectory.get().asFile}" + ) + def postCompileAction = this + workQueue().submit(InstrumentAction.class, parameters -> { + parameters.buildStartedTime.set(invocationDetails.buildStartedTime) + parameters.pluginClassPath.from( + project.configurations.named(InstrumentPlugin.INSTRUMENT_PLUGIN_CLASSPATH_CONFIGURATION) + ) + parameters.plugins.set(postCompileAction.plugins) + parameters.instrumentingClassPath.setFrom(postCompileAction.instrumentingClassPath) + parameters.compilerOutputDirectory.set(postCompileAction.compilerOutputDirectory) + parameters.tmpDirectory.set(postCompileAction.tmpDirectory) + }) + } + + private workQueue() { + def javaLauncher = this.javaToolchainService.launcherFor { spec -> + spec.languageVersion.set(this.javaVersion) + }.get() + return this.workerExecutor.processIsolation { spec -> + spec.forkOptions { fork -> + fork.executable = javaLauncher.executablePath + } + } + } +} diff --git a/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentWorkParameters.groovy b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentWorkParameters.groovy new file mode 100644 index 00000000000..95dfad91916 --- /dev/null +++ b/buildSrc/src/main/groovy/datadog/gradle/plugin/instrument/InstrumentWorkParameters.groovy @@ -0,0 +1,17 @@ +package datadog.gradle.plugin.instrument + + +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.workers.WorkParameters + +interface InstrumentWorkParameters extends WorkParameters { + Property getBuildStartedTime() + ConfigurableFileCollection getPluginClassPath() + ListProperty getPlugins() + ConfigurableFileCollection getInstrumentingClassPath() + DirectoryProperty getCompilerOutputDirectory() + DirectoryProperty getTmpDirectory() +} diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/csi/CallSiteInstrumentationPlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/csi/CallSiteInstrumentationPlugin.kt index a0591294843..9fff60f498f 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/csi/CallSiteInstrumentationPlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/csi/CallSiteInstrumentationPlugin.kt @@ -188,14 +188,7 @@ abstract class CallSiteInstrumentationPlugin : Plugin { dependsOn(mainCompileTask) } - // Workaround for instrument plugin modifying compile tasks - project.pluginManager.withPlugin("dd-trace-java.instrument") { - callSiteGeneratorTask.configure { - dependsOn("instrumentJava") - } - } - - // make all sourcesets' class tasks depend on call site generator + // make all sourceSets class tasks depend on call site generator val sourceSets = project.sourceSets sourceSets.named(MAIN_SOURCE_SET_NAME) { project.tasks.named(classesTaskName) { diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt index d72074676c3..bbddbd3288d 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt @@ -14,7 +14,9 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.artifacts.Configuration +import org.gradle.api.tasks.SourceSetContainer import org.gradle.api.tasks.TaskProvider +import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.exclude import org.gradle.kotlin.dsl.getByType @@ -71,9 +73,8 @@ class MuzzlePlugin : Plugin { // compileMuzzle compiles all projects required to run muzzle validation. // Not adding group and description to keep this task from showing in `gradle tasks`. - @Suppress("UNCHECKED_CAST") val compileMuzzle = project.tasks.register("compileMuzzle") { - dependsOn(project.tasks.withType(Class.forName("InstrumentTask") as Class)) // kotlin can't see groovy code + inputs.files(project.providers.provider { project.allMainSourceSet }) dependsOn(bootstrapProject.tasks.named("compileJava")) dependsOn(bootstrapProject.tasks.named("compileMain_java11Java")) dependsOn(toolingProject.tasks.named("compileJava")) diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/instrument/InstrumentPluginTest.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/instrument/InstrumentPluginTest.kt index 8c7b0b13f0b..69d36a2263d 100644 --- a/buildSrc/src/test/kotlin/datadog/gradle/plugin/instrument/InstrumentPluginTest.kt +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/instrument/InstrumentPluginTest.kt @@ -30,12 +30,6 @@ class InstrumentPluginTest { compileOnly group: 'net.bytebuddy', name: 'byte-buddy', version: '1.18.3' // just to build TestPlugin } - configurations { - instrumentPluginClasspath { - canBeResolved = true - } - } - instrument.plugins = [ 'TestPlugin' ] diff --git a/dd-java-agent/instrumentation/build.gradle b/dd-java-agent/instrumentation/build.gradle index 96479c0f6d2..5dbecbae50f 100644 --- a/dd-java-agent/instrumentation/build.gradle +++ b/dd-java-agent/instrumentation/build.gradle @@ -2,6 +2,7 @@ import static org.gradle.api.plugins.JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAM import static org.gradle.api.tasks.SourceSet.MAIN_SOURCE_SET_NAME import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import datadog.gradle.plugin.instrument.InstrumentExtension plugins { id 'com.gradleup.shadow' @@ -23,12 +24,15 @@ subprojects { Project subProj -> ) } - subProj.configurations.register("instrumentPluginClasspath") { + subProj.configurations.named('instrumentPluginClasspath') { it.visible = false it.canBeConsumed = false it.canBeResolved = true - it.dependencies.add(subProj.dependencies.project(path: ':dd-java-agent:agent-tooling', configuration: 'instrumentPluginClasspath')) + it.dependencies.add(subProj.dependencies.project( + path: ':dd-java-agent:agent-tooling', + configuration: 'instrumentPluginClasspath' + )) } } diff --git a/dd-java-agent/instrumentation/play/play-2.4/build.gradle b/dd-java-agent/instrumentation/play/play-2.4/build.gradle index b67968733ed..67f91bc37bd 100644 --- a/dd-java-agent/instrumentation/play/play-2.4/build.gradle +++ b/dd-java-agent/instrumentation/play/play-2.4/build.gradle @@ -62,15 +62,19 @@ tasks.named("jar", Jar) { from sourceSets.main_play25.output } -project.afterEvaluate { - tasks.named('instrumentJava') { dependsOn 'compileMain_play25Java' } - tasks.named('forbiddenApisMain_play25') { dependsOn 'instrumentMain_play25Java' } +tasks.named('compileMain_play25Java') { + dependsOn(tasks.named('compileJava')) +} +tasks.named('forbiddenApisMain_play25') { + dependsOn(tasks.named('compileMain_play25Java')) } instrument { - additionalClasspath = [ - instrumentJava: compileMain_play25Java.destinationDirectory - ] + additionalClasspath.add( + tasks.named('compileMain_play25Java', AbstractCompile).map { + it.destinationDirectory + } + ) } dependencies { diff --git a/dd-java-agent/instrumentation/play/play-2.6/build.gradle b/dd-java-agent/instrumentation/play/play-2.6/build.gradle index 08c448d2e4f..dfd3b279daa 100644 --- a/dd-java-agent/instrumentation/play/play-2.6/build.gradle +++ b/dd-java-agent/instrumentation/play/play-2.6/build.gradle @@ -77,19 +77,19 @@ tasks.named("jar", Jar) { from sourceSets.main_play27.output } -tasks.named("compileMain_play27Java", JavaCompile) { - dependsOn(compileJava) +tasks.named('compileMain_play27Java') { + dependsOn(tasks.named('compileJava')) } - -project.afterEvaluate { - tasks.named('instrumentJava') { dependsOn 'compileMain_play27Java' } - tasks.named('forbiddenApisMain_play27') { dependsOn 'instrumentMain_play27Java' } +tasks.named('forbiddenApisMain_play27') { + dependsOn(tasks.named('compileMain_play27Java')) } instrument { - additionalClasspath = [ - instrumentJava: compileMain_play27Java.destinationDirectory - ] + additionalClasspath.add( + tasks.named('compileMain_play27Java', AbstractCompile).map { + it.destinationDirectory + } + ) } dependencies {