java.gradle 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. import java.time.Duration
  2. apply plugin: 'java'
  3. apply plugin: 'groovy'
  4. apply from: "$rootDir/gradle/spotless.gradle"
  5. apply from: "$rootDir/gradle/checkstyle.gradle"
  6. apply from: "$rootDir/gradle/codenarc.gradle"
  7. apply from: "$rootDir/gradle/spotbugs.gradle"
  8. def applyCodeCoverage = !(
  9. project.path.startsWith(":smoke-tests") ||
  10. //TODO why some tests fail on java 11 if jacoco is present?
  11. project.path == ":opentelemetry-auto" ||
  12. project.path == ":load-generator" ||
  13. project.path.startsWith(":benchmark") ||
  14. project.path.startsWith(":instrumentation"))
  15. if (applyCodeCoverage) {
  16. apply from: "$rootDir/gradle/jacoco.gradle"
  17. }
  18. sourceCompatibility = 1.7
  19. targetCompatibility = 1.7
  20. if (project.hasProperty('minJavaVersionForTests') && project.getProperty('minJavaVersionForTests') != JavaVersion.VERSION_1_7) {
  21. def version = JavaVersion.toVersion(project.getProperty('minJavaVersionForTests'))
  22. def name = "java$version.majorVersion"
  23. sourceSets {
  24. "main_$name" {
  25. java.srcDirs "${project.projectDir}/src/main/$name"
  26. }
  27. }
  28. "compileMain_${name}Java" {
  29. sourceCompatibility = version
  30. targetCompatibility = version
  31. }
  32. // Note: ideally lombok plugin would do this for us, but currently it doesn't support custom
  33. // source sets. See https://github.com/franzbecker/gradle-lombok/issues/17.
  34. dependencies {
  35. compileOnly sourceSets."main_$name".compileClasspath
  36. compile sourceSets."main_$name".output
  37. "main_${name}CompileOnly" "org.projectlombok:lombok:${project.lombok.version}" transitive false
  38. "main_${name}AnnotationProcessor" "org.projectlombok:lombok:${project.lombok.version}" transitive false
  39. }
  40. jar {
  41. from sourceSets."main_$name".output
  42. }
  43. // In some cases we would like to avoid setting java version to `minJavaVersionForTests`.
  44. // For example we would like to be able to run profiling tests with ZULU8, but we cannot run it with other JDK8 implementations at the moment
  45. def skipSettingTestJavaVersion = project.hasProperty('skipSettingTestJavaVersion') && project.getProperty('skipSettingTestJavaVersion')
  46. if (!skipSettingTestJavaVersion) {
  47. tasks.withType(JavaCompile).configureEach {
  48. if (it.name.toLowerCase().contains("test")) {
  49. sourceCompatibility = version
  50. targetCompatibility = version
  51. }
  52. }
  53. }
  54. }
  55. java {
  56. // See https://docs.gradle.org/current/userguide/upgrading_version_5.html, Automatic target JVM version
  57. disableAutoTargetJvm()
  58. }
  59. [JavaCompile, ScalaCompile].each { type ->
  60. tasks.withType(type) {
  61. doFirst {
  62. // We do this specifically for Java7 bytecode generation because we would like to be able to compile
  63. // with Java8+ compiler. This likely would require some modifications when we switch to java11 compiler.
  64. // Using proper Java7 bootstrap and extensions allows to be sure our code will run on real Java7.
  65. if (JavaVersion.toVersion(sourceCompatibility) == JavaVersion.VERSION_1_7
  66. && JavaVersion.current() != JavaVersion.VERSION_1_7
  67. && System.env.JAVA_7_HOME != null) {
  68. options.fork = true
  69. options.bootstrapClasspath = fileTree(include: ['*.jar'], dir: "${System.env.JAVA_7_HOME}/jre/lib/")
  70. options.extensionDirs = "${System.env.JAVA_7_HOME}/jre/lib/ext/"
  71. }
  72. }
  73. }
  74. }
  75. apply plugin: "io.franzbecker.gradle-lombok"
  76. lombok { // optional: values below are the defaults
  77. version = versions.lombok
  78. sha256 = ""
  79. }
  80. apply plugin: "eclipse"
  81. eclipse {
  82. classpath {
  83. downloadSources = true
  84. downloadJavadoc = true
  85. }
  86. }
  87. if (configurations.find { it.name == 'jmh' }) {
  88. eclipse.classpath.plusConfigurations += [configurations.jmh]
  89. }
  90. jar {
  91. /*
  92. Make Jar build fail on duplicate files
  93. By default Gradle Jar task can put multiple files with the same name
  94. into a Jar. This may lead to confusion. For example if auto-service
  95. annotation processing creates files with same name in `scala` and
  96. `java` directory this would result in Jar having two files with the
  97. same name in it. Which in turn would result in only one of those
  98. files being actually considered when that Jar is used leading to very
  99. confusing failures.
  100. Instead we should 'fail early' and avoid building such Jars.
  101. */
  102. duplicatesStrategy = 'fail'
  103. }
  104. tasks.register("packageSources", Jar) {
  105. classifier = 'sources'
  106. from sourceSets.main.allSource
  107. }
  108. artifacts.archives packageSources
  109. repositories {
  110. jcenter()
  111. mavenCentral()
  112. maven {
  113. url "https://adoptopenjdk.jfrog.io/adoptopenjdk/jmc-libs-snapshots"
  114. }
  115. maven {
  116. url "https://repo.typesafe.com/typesafe/releases"
  117. }
  118. // this is only needed for the working against unreleased otel-java snapshots
  119. maven {
  120. url "https://oss.jfrog.org/artifactory/oss-snapshot-local"
  121. content {
  122. includeGroup "io.opentelemetry"
  123. }
  124. }
  125. mavenLocal()
  126. }
  127. dependencies {
  128. testCompile deps.spock
  129. testCompile deps.groovy
  130. testCompile deps.testLogging
  131. testCompile group: 'info.solidsoft.spock', name: 'spock-global-unroll', version: '0.5.1'
  132. testCompile group: 'com.anotherchrisberry', name: 'spock-retry', version: '0.6.4'
  133. testCompile group: 'com.github.stefanbirkner', name: 'system-rules', version: '1.19.0'
  134. }
  135. jar {
  136. manifest {
  137. attributes(
  138. "Implementation-Title": project.name,
  139. "Implementation-Version": project.version,
  140. "Implementation-Vendor": "OpenTelemetry",
  141. "Implementation-URL": "https://github.com/open-telemetry/opentelemetry-auto-instr-java",
  142. )
  143. }
  144. }
  145. tasks.withType(Javadoc).configureEach {
  146. options.encoding = "utf-8"
  147. options.docEncoding = "utf-8"
  148. options.charSet = "utf-8"
  149. options.addStringOption('Xdoclint:none', '-quiet')
  150. doFirst {
  151. if (project.ext.has("apiLinks")) {
  152. options.links(*project.apiLinks)
  153. }
  154. }
  155. }
  156. javadoc {
  157. source = sourceSets.main.allJava
  158. classpath = configurations.compileClasspath
  159. options {
  160. setMemberLevel JavadocMemberLevel.PUBLIC
  161. setAuthor true
  162. links "https://docs.oracle.com/javase/8/docs/api/"
  163. source = 8
  164. }
  165. }
  166. tasks.register("sourceJar", Jar) {
  167. from sourceSets.main.allJava
  168. classifier = 'sources'
  169. }
  170. tasks.register("javaDocJar", Jar) {
  171. from javadoc.destinationDir
  172. classifier = 'javadoc'
  173. dependsOn javadoc
  174. }
  175. artifacts {
  176. archives sourceJar
  177. archives javaDocJar
  178. }
  179. project.afterEvaluate {
  180. if (project.plugins.hasPlugin('org.unbroken-dome.test-sets') && configurations.hasProperty("latestDepTestRuntime")) {
  181. tasks.withType(Test).configureEach {
  182. doFirst {
  183. def testArtifacts = configurations.testRuntime.resolvedConfiguration.resolvedArtifacts
  184. def latestTestArtifacts = configurations.latestDepTestRuntime.resolvedConfiguration.resolvedArtifacts
  185. assert testArtifacts != latestTestArtifacts: "latestDepTest dependencies are identical to test"
  186. }
  187. }
  188. }
  189. }
  190. if (project.plugins.hasPlugin('com.github.johnrengelman.shadow')) {
  191. // Remove the no-deps jar from the archives to prevent publication
  192. configurations.archives.with {
  193. artifacts.remove artifacts.find {
  194. if (it.hasProperty("delegate")) {
  195. it.delegate.archiveTask.is jar
  196. } else {
  197. it.archiveTask.is jar
  198. }
  199. }
  200. }
  201. artifacts {
  202. archives shadowJar
  203. }
  204. }
  205. if (project.hasProperty("removeJarVersionNumbers") && removeJarVersionNumbers) {
  206. tasks.withType(AbstractArchiveTask).configureEach {
  207. version = null
  208. }
  209. }
  210. if (!rootProject.ext.has("javaExecutableVersionCache")) {
  211. rootProject.ext.javaExecutableVersionCache = [:]
  212. }
  213. /**
  214. * Returns version of java from a given java home.
  215. */
  216. JavaVersion getJavaHomeVersion(String javaHome) {
  217. def cache = rootProject.ext.javaExecutableVersionCache
  218. if (cache.containsKey(javaHome)) {
  219. return cache.get(javaHome)
  220. }
  221. new ByteArrayOutputStream().withStream { stream ->
  222. exec {
  223. commandLine = [toExecutable(javaHome), "-version"]
  224. errorOutput = stream
  225. }
  226. def output = stream.toString()
  227. for (def line : output.split('\n')) {
  228. line = line.trim()
  229. def matcher = line =~ /^(?:java|openjdk) version "([^"]+)"/
  230. if (matcher) {
  231. def version = JavaVersion.toVersion(matcher.group(1))
  232. cache.put(javaHome, version)
  233. return version
  234. }
  235. }
  236. // Getting here means we didn't find a line matching the version pattern.
  237. throw new GradleScriptException("Cannot determine java version. Executable: ${javaHome}, output: ${output}", null)
  238. }
  239. }
  240. def isJavaVersionAllowed(JavaVersion version) {
  241. if (project.hasProperty('minJavaVersionForTests') && project.getProperty('minJavaVersionForTests').compareTo(version) > 0) {
  242. return false
  243. }
  244. if (project.hasProperty('maxJavaVersionForTests') && project.getProperty('maxJavaVersionForTests').compareTo(version) < 0) {
  245. return false
  246. }
  247. return true
  248. }
  249. /**
  250. * For a given java home return the location of java executable
  251. */
  252. static String toExecutable(String javaHome) {
  253. return Objects.requireNonNull(javaHome) + "/bin/java"
  254. }
  255. /**
  256. * Returns java home for a given version or {@code null} if not found
  257. */
  258. String findJavaHome(JavaVersion version) {
  259. def javaHome = System.getenv("JAVA_${version.majorVersion}_HOME")
  260. if (javaHome == null) {
  261. return null
  262. }
  263. def foundVersion = getJavaHomeVersion(javaHome)
  264. return version == foundVersion ? javaHome : null
  265. }
  266. ext {
  267. findJavaHome = this.&findJavaHome
  268. }
  269. def addTestRule(String testTaskName) {
  270. def prefix = testTaskName + "Java"
  271. tasks.addRule("Pattern: $prefix<Version>: Runs tests using given java version") { String taskName ->
  272. if (taskName.startsWith(prefix)) {
  273. def requestedJavaVersion = JavaVersion.toVersion(taskName - prefix)
  274. def gradleJavaVersion = JavaVersion.current()
  275. if (gradleJavaVersion != requestedJavaVersion) {
  276. def javaHomeForTests = findJavaHome(requestedJavaVersion)
  277. if (javaHomeForTests != null) {
  278. tasks.withType(Test).all {
  279. // minJavaVersionForTests property, which specifies java version requirements for tests,
  280. // currently does not work with custom source sets created by org.unbroken-dome.test-sets plugin.
  281. // Thus we are forced to ignore all of them
  282. // TODO solve this problem. We want to run custom test sets with all java versions as well
  283. if (name != testTaskName) {
  284. return
  285. }
  286. executable = toExecutable(javaHomeForTests)
  287. enabled = isJavaVersionAllowed(requestedJavaVersion)
  288. if (requestedJavaVersion.isJava7()) {
  289. // Disable JIT for this method. Sometimes Java7 JVM crashes trying to compile it.
  290. jvmArgs '-XX:CompileCommand=exclude,net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor::onParameterizedType'
  291. }
  292. }
  293. } else {
  294. throw new BuildCancelledException("Requested java version $requestedJavaVersion not found")
  295. }
  296. }
  297. task(taskName, dependsOn: testTaskName)
  298. }
  299. }
  300. }
  301. addTestRule("test")
  302. addTestRule("latestDepTest")
  303. tasks.withType(Test).configureEach {
  304. if (project.findProperty("enableJunitPlatform") == true) {
  305. useJUnitPlatform()
  306. }
  307. // All tests must complete within 15 minutes.
  308. // This value is quite big because with lower values (3 mins) we were experiencing large number of false positives
  309. timeout = Duration.ofMinutes(15)
  310. // Disable all tests if current JVM doesn't match version requirements
  311. // Disable all tests if skipTests property was specified
  312. enabled = isJavaVersionAllowed(JavaVersion.current()) && !project.rootProject.hasProperty("skipTests")
  313. }
  314. plugins.withType(BasePlugin) {
  315. project.afterEvaluate {
  316. def deleteTasks = tasks.withType(Delete) + project.tasks.findByPath('clean')
  317. def otherTasks = tasks - deleteTasks
  318. otherTasks*.mustRunAfter deleteTasks
  319. }
  320. }