1buildscript { 2 repositories { 3 mavenLocal() 4 maven { url "https://plugins.gradle.org/m2/" } 5 } 6 dependencies { 7 classpath "com.diffplug.spotless:spotless-plugin-gradle:3.13.0" 8 classpath 'com.google.gradle:osdetector-gradle-plugin:1.4.0' 9 classpath 'ru.vyarus:gradle-animalsniffer-plugin:1.4.5' 10 classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.13' 11 classpath 'net.ltgt.gradle:gradle-apt-plugin:0.13' 12 classpath "me.champeau.gradle:jmh-gradle-plugin:0.4.5" 13 classpath 'me.champeau.gradle:japicmp-gradle-plugin:0.2.5' 14 } 15} 16 17subprojects { 18 apply plugin: "checkstyle" 19 apply plugin: "java" 20 apply plugin: "maven" 21 apply plugin: "idea" 22 apply plugin: "signing" 23 apply plugin: "jacoco" 24 25 apply plugin: "me.champeau.gradle.jmh" 26 apply plugin: "com.google.osdetector" 27 // The plugin only has an effect if a signature is specified 28 apply plugin: "ru.vyarus.animalsniffer" 29 // jdk10 not supported by errorprone: https://github.com/google/error-prone/issues/860 30 if (!JavaVersion.current().isJava10Compatible() && 31 rootProject.properties.get('errorProne', true)) { 32 apply plugin: "net.ltgt.errorprone" 33 apply plugin: "net.ltgt.apt" 34 35 dependencies { 36 // The ErrorProne plugin defaults to the latest, which would break our 37 // build if error prone releases a new version with a new check 38 errorprone 'com.google.errorprone:error_prone_core:2.2.0' 39 apt 'com.google.guava:guava-beta-checker:1.0' 40 } 41 } else { 42 // Remove per-project error-prone checker config 43 allprojects { 44 afterEvaluate { project -> 45 project.tasks.withType(JavaCompile) { 46 options.compilerArgs.removeAll { it.startsWith("-Xep") } 47 } 48 } 49 } 50 } 51 // TODO(zpencer): remove when intellij 2017.2 is released 52 // https://github.com/gradle/gradle/issues/2315 53 idea.module.inheritOutputDirs = true 54 55 group = "io.grpc" 56 version = "1.16.0-SNAPSHOT" // CURRENT_GRPC_VERSION 57 58 sourceCompatibility = 1.7 59 targetCompatibility = 1.7 60 61 repositories { 62 maven { // The google mirror is less flaky than mavenCentral() 63 url "https://maven-central.storage-download.googleapis.com/repos/central/data/" } 64 mavenLocal() 65 } 66 67 [ 68 compileJava, 69 compileTestJava, 70 compileJmhJava 71 ].each() { 72 it.options.compilerArgs += [ 73 "-Xlint:all", 74 "-Xlint:-options", 75 "-Xlint:-path", 76 "-Xlint:-try" 77 ] 78 it.options.encoding = "UTF-8" 79 if (rootProject.hasProperty('failOnWarnings') && rootProject.failOnWarnings.toBoolean()) { 80 it.options.compilerArgs += ["-Werror"] 81 } 82 } 83 84 compileTestJava { 85 // serialVersionUID is basically guaranteed to be useless in our tests 86 // LinkedList doesn't hurt much in tests and has lots of usages 87 options.compilerArgs += [ 88 "-Xlint:-serial", 89 "-Xep:JdkObsolete:OFF" 90 ] 91 } 92 93 jar.manifest { 94 attributes('Implementation-Title': name, 95 'Implementation-Version': version, 96 'Built-By': System.getProperty('user.name'), 97 'Built-JDK': System.getProperty('java.version'), 98 'Source-Compatibility': sourceCompatibility, 99 'Target-Compatibility': targetCompatibility) 100 } 101 102 javadoc.options { 103 encoding = 'UTF-8' 104 use = true 105 links 'https://docs.oracle.com/javase/8/docs/api/' 106 } 107 108 ext { 109 def exeSuffix = osdetector.os == 'windows' ? ".exe" : "" 110 protocPluginBaseName = 'protoc-gen-grpc-java' 111 javaPluginPath = "$rootDir/compiler/build/exe/java_plugin/$protocPluginBaseName$exeSuffix" 112 113 nettyVersion = '4.1.27.Final' 114 guavaVersion = '20.0' 115 protobufVersion = '3.5.1' 116 protocVersion = '3.5.1-1' 117 protobufNanoVersion = '3.0.0-alpha-5' 118 opencensusVersion = '0.12.3' 119 120 configureProtoCompilation = { 121 String generatedSourcePath = "${projectDir}/src/generated" 122 if (rootProject.childProjects.containsKey('grpc-compiler')) { 123 // Only when the codegen is built along with the project, will we be able to recompile 124 // the proto files. 125 project.apply plugin: 'com.google.protobuf' 126 project.protobuf { 127 protoc { 128 if (project.hasProperty('protoc')) { 129 path = project.protoc 130 } else { 131 artifact = "com.google.protobuf:protoc:${protocVersion}" 132 } 133 } 134 plugins { grpc { path = javaPluginPath } } 135 generateProtoTasks { 136 all().each { task -> 137 task.dependsOn ':grpc-compiler:java_pluginExecutable' 138 // Delete the generated sources first, so that we can be alerted if they are not re-compiled. 139 task.dependsOn 'deleteGeneratedSource' + task.sourceSet.name 140 // Recompile protos when the codegen has been changed 141 task.inputs.file javaPluginPath 142 // Recompile protos when build.gradle has been changed, because 143 // it's possible the version of protoc has been changed. 144 task.inputs.file "${rootProject.projectDir}/build.gradle" 145 task.plugins { grpc { option 'noversion' } } 146 } 147 } 148 generatedFilesBaseDir = generatedSourcePath 149 } 150 151 sourceSets.each { sourceSet -> 152 task "deleteGeneratedSource${sourceSet.name}" { 153 doLast { 154 project.delete project.fileTree(dir: generatedSourcePath + '/' + sourceSet.name) 155 } 156 } 157 } 158 } else { 159 // Otherwise, we just use the checked-in generated code. 160 project.sourceSets { 161 main { 162 java { 163 srcDir "${generatedSourcePath}/main/java" 164 srcDir "${generatedSourcePath}/main/javanano" 165 srcDir "${generatedSourcePath}/main/grpc" 166 } 167 } 168 test { 169 java { 170 srcDir "${generatedSourcePath}/test/java" 171 srcDir "${generatedSourcePath}/test/javanano" 172 srcDir "${generatedSourcePath}/test/grpc" 173 } 174 } 175 } 176 } 177 178 [ 179 compileJava, 180 compileTestJava, 181 compileJmhJava 182 ].each() { 183 // Protobuf-generated code produces some warnings. 184 // https://github.com/google/protobuf/issues/2718 185 it.options.compilerArgs += [ 186 "-Xlint:-cast", 187 "-XepExcludedPaths:.*/src/generated/[^/]+/java/.*", 188 ] 189 } 190 } 191 192 def epoll_suffix = ""; 193 if (osdetector.classifier in ["linux-x86_64"]) { 194 // The native code is only pre-compiled on certain platforms. 195 epoll_suffix = ":" + osdetector.classifier 196 } 197 libraries = [ 198 animalsniffer_annotations: "org.codehaus.mojo:animal-sniffer-annotations:1.17", 199 errorprone: "com.google.errorprone:error_prone_annotations:2.2.0", 200 gson: "com.google.code.gson:gson:2.7", 201 guava: "com.google.guava:guava:${guavaVersion}", 202 hpack: 'com.twitter:hpack:0.10.1', 203 javax_annotation: 'javax.annotation:javax.annotation-api:1.2', 204 jsr305: 'com.google.code.findbugs:jsr305:3.0.0', 205 oauth_client: 'com.google.auth:google-auth-library-oauth2-http:0.9.0', 206 google_api_protos: 'com.google.api.grpc:proto-google-common-protos:1.0.0', 207 google_auth_credentials: 'com.google.auth:google-auth-library-credentials:0.9.0', 208 google_auth_oauth2_http: 'com.google.auth:google-auth-library-oauth2-http:0.9.0', 209 okhttp: 'com.squareup.okhttp:okhttp:2.5.0', 210 okio: 'com.squareup.okio:okio:1.13.0', 211 opencensus_api: "io.opencensus:opencensus-api:${opencensusVersion}", 212 opencensus_contrib_grpc_metrics: "io.opencensus:opencensus-contrib-grpc-metrics:${opencensusVersion}", 213 opencensus_impl: "io.opencensus:opencensus-impl:${opencensusVersion}", 214 opencensus_impl_lite: "io.opencensus:opencensus-impl-lite:${opencensusVersion}", 215 instrumentation_api: 'com.google.instrumentation:instrumentation-api:0.4.3', 216 protobuf: "com.google.protobuf:protobuf-java:${protobufVersion}", 217 protobuf_lite: "com.google.protobuf:protobuf-lite:3.0.1", 218 protoc_lite: "com.google.protobuf:protoc-gen-javalite:3.0.0", 219 protobuf_nano: "com.google.protobuf.nano:protobuf-javanano:${protobufNanoVersion}", 220 protobuf_plugin: 'com.google.protobuf:protobuf-gradle-plugin:0.8.5', 221 protobuf_util: "com.google.protobuf:protobuf-java-util:${protobufVersion}", 222 lang: "org.apache.commons:commons-lang3:3.5", 223 224 netty: "io.netty:netty-codec-http2:[${nettyVersion}]", 225 netty_epoll: "io.netty:netty-transport-native-epoll:${nettyVersion}" + epoll_suffix, 226 netty_proxy_handler: "io.netty:netty-handler-proxy:${nettyVersion}", 227 netty_tcnative: 'io.netty:netty-tcnative-boringssl-static:2.0.12.Final', 228 229 conscrypt: 'org.conscrypt:conscrypt-openjdk-uber:1.0.1', 230 re2j: 'com.google.re2j:re2j:1.2', 231 232 // Test dependencies. 233 junit: 'junit:junit:4.12', 234 mockito: 'org.mockito:mockito-core:1.9.5', 235 truth: 'com.google.truth:truth:0.42', 236 guava_testlib: 'com.google.guava:guava-testlib:20.0', 237 238 // Benchmark dependencies 239 hdrhistogram: 'org.hdrhistogram:HdrHistogram:2.1.10', 240 math: 'org.apache.commons:commons-math3:3.6', 241 242 // Jetty ALPN dependencies 243 jetty_alpn_agent: 'org.mortbay.jetty.alpn:jetty-alpn-agent:2.0.7' 244 ] 245 } 246 247 // Define a separate configuration for managing the dependency on Jetty ALPN agent. 248 configurations { 249 alpnagent 250 251 compile { 252 // Detect Maven Enforcer's dependencyConvergence failures. We only 253 // care for artifacts used as libraries by others. 254 if (!(project.name in [ 255 'grpc-benchmarks', 256 'grpc-interop-testing', 257 'grpc-gae-interop-testing-jdk7', 258 'grpc-gae-interop-testing-jdk8', 259 ])) { 260 resolutionStrategy.failOnVersionConflict() 261 } 262 } 263 } 264 265 dependencies { 266 testCompile libraries.junit, 267 libraries.mockito, 268 libraries.truth 269 270 // Configuration for modules that use Jetty ALPN agent 271 alpnagent libraries.jetty_alpn_agent 272 273 jmh 'org.openjdk.jmh:jmh-core:1.19', 274 'org.openjdk.jmh:jmh-generator-bytecode:1.19' 275 } 276 277 signing { 278 required false 279 sign configurations.archives 280 } 281 282 // Disable JavaDoc doclint on Java 8. It's annoying. 283 if (JavaVersion.current().isJava8Compatible()) { 284 allprojects { 285 tasks.withType(Javadoc) { 286 options.addStringOption('Xdoclint:none', '-quiet') 287 } 288 } 289 } 290 291 // For jdk10 we must explicitly choose between html4 and html5, otherwise we get a warning 292 if (JavaVersion.current().isJava10Compatible()) { 293 allprojects { 294 tasks.withType(Javadoc) { 295 options.addBooleanOption('html4', true) 296 } 297 } 298 } 299 300 checkstyle { 301 configDir = file("$rootDir/buildscripts") 302 toolVersion = "6.17" 303 ignoreFailures = false 304 if (rootProject.hasProperty("checkstyle.ignoreFailures")) { 305 ignoreFailures = rootProject.properties["checkstyle.ignoreFailures"].toBoolean() 306 } 307 } 308 309 checkstyleMain { 310 source = fileTree(dir: "src/main", include: "**/*.java") 311 } 312 313 checkstyleTest { 314 source = fileTree(dir: "src/test", include: "**/*.java") 315 } 316 317 // invoke jmh on a single benchmark class like so: 318 // ./gradlew -PjmhIncludeSingleClass=StatsTraceContextBenchmark clean :grpc-core:jmh 319 jmh { 320 warmupIterations = 10 321 iterations = 10 322 fork = 1 323 // None of our benchmarks need the tests, and we have pseudo-circular 324 // dependencies that break when including them. (context's testCompile 325 // depends on core; core's testCompile depends on testing) 326 includeTests = false 327 if (project.hasProperty('jmhIncludeSingleClass')) { 328 include = [ 329 project.property('jmhIncludeSingleClass') 330 ] 331 } 332 } 333 334 task javadocJar(type: Jar) { 335 classifier = 'javadoc' 336 from javadoc 337 } 338 339 task sourcesJar(type: Jar) { 340 classifier = 'sources' 341 from sourceSets.main.allSource 342 } 343 344 artifacts { archives javadocJar, sourcesJar } 345 346 uploadArchives.repositories.mavenDeployer { 347 beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 348 if (rootProject.hasProperty('repositoryDir')) { 349 repository(url: new File(rootProject.repositoryDir).toURI()) 350 } else { 351 String stagingUrl 352 if (rootProject.hasProperty('repositoryId')) { 353 stagingUrl = 'https://oss.sonatype.org/service/local/staging/deployByRepositoryId/' + 354 rootProject.repositoryId 355 } else { 356 stagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' 357 } 358 def configureAuth = { 359 if (rootProject.hasProperty('ossrhUsername') && rootProject.hasProperty('ossrhPassword')) { 360 authentication(userName: rootProject.ossrhUsername, password: rootProject.ossrhPassword) 361 } 362 } 363 repository(url: stagingUrl, configureAuth) 364 snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/', configureAuth) 365 } 366 } 367 uploadArchives.onlyIf { !name.contains("grpc-gae-interop-testing") } 368 369 [ 370 install.repositories.mavenInstaller, 371 uploadArchives.repositories.mavenDeployer, 372 ]*.pom*.whenConfigured { pom -> 373 pom.project { 374 name "$project.group:$project.name" 375 description project.description 376 url 'https://github.com/grpc/grpc-java' 377 378 scm { 379 connection 'scm:git:https://github.com/grpc/grpc-java.git' 380 developerConnection 'scm:git:git@github.com:grpc/grpc-java.git' 381 url 'https://github.com/grpc/grpc-java' 382 } 383 384 licenses { 385 license { 386 name 'Apache 2.0' 387 url 'https://opensource.org/licenses/Apache-2.0' 388 } 389 } 390 391 developers { 392 developer { 393 id "grpc.io" 394 name "gRPC Contributors" 395 email "grpc-io@googlegroups.com" 396 url "https://grpc.io/" 397 // https://issues.gradle.org/browse/GRADLE-2719 398 organization = "gRPC Authors" 399 organizationUrl "https://www.google.com" 400 } 401 } 402 } 403 if (!(project.name in 404 [ 405 "grpc-stub", 406 "grpc-protobuf", 407 "grpc-protobuf-lite", 408 "grpc-protobuf-nano" 409 ])) { 410 def core = pom.dependencies.find {dep -> dep.artifactId == 'grpc-core'} 411 if (core != null) { 412 // Depend on specific version of grpc-core because internal package is unstable 413 core.version = "[" + core.version + "]" 414 } 415 } 416 } 417 // At a test failure, log the stack trace to the console so that we don't 418 // have to open the HTML in a browser. 419 test { 420 testLogging { 421 exceptionFormat = 'full' 422 showExceptions true 423 showCauses true 424 showStackTraces true 425 } 426 maxHeapSize = '1500m' 427 } 428} 429 430// Run with: ./gradlew japicmp --continue 431def baselineGrpcVersion = '1.6.1' 432def publicApiSubprojects = [ 433 // TODO: uncomment after grpc-alts artifact is published. 434 // ':grpc-alts', 435 ':grpc-auth', 436 ':grpc-context', 437 ':grpc-core', 438 ':grpc-grpclb', 439 ':grpc-netty', 440 ':grpc-okhttp', 441 ':grpc-protobuf', 442 ':grpc-protobuf-lite', 443 ':grpc-protobuf-nano', 444 ':grpc-stub', 445 ':grpc-testing', 446] 447 448publicApiSubprojects.each { name -> 449 project(":$name") { 450 apply plugin: 'me.champeau.gradle.japicmp' 451 452 // Get the baseline version's jar for this subproject 453 File baselineArtifact = null 454 // Use a detached configuration, otherwise the current version's jar will take precedence 455 // over the baseline jar. 456 // A necessary hack, the intuitive thing does NOT work: 457 // https://discuss.gradle.org/t/is-the-default-configuration-leaking-into-independent-configurations/2088/6 458 def oldGroup = project.group 459 try { 460 project.group = 'virtual_group_for_japicmp' 461 String depModule = "io.grpc:${project.name}:${baselineGrpcVersion}@jar" 462 String depJar = "${project.name}-${baselineGrpcVersion}.jar" 463 Configuration configuration = configurations.detachedConfiguration( 464 dependencies.create(depModule) 465 ) 466 baselineArtifact = files(configuration.files).filter { 467 it.name.equals(depJar) 468 }.singleFile 469 } finally { 470 project.group = oldGroup 471 } 472 473 // Add a japicmp task that compares the current .jar with baseline .jar 474 task japicmp(type: me.champeau.gradle.japicmp.JapicmpTask, dependsOn: jar) { 475 oldClasspath = files(baselineArtifact) 476 newClasspath = files(jar.archivePath) 477 onlyBinaryIncompatibleModified = false 478 // Be quiet about things that did not change 479 onlyModified = true 480 // This task should fail if there are incompatible changes 481 failOnModification = true 482 ignoreMissingClasses = true 483 htmlOutputFile = file("$buildDir/reports/japi.html") 484 485 packageExcludes = ['io.grpc.internal'] 486 487 // Also break on source incompatible changes, not just binary. 488 // Eg adding abstract method to public class. 489 // TODO(zpencer): enable after japicmp-gradle-plugin/pull/14 490 // breakOnSourceIncompatibility = true 491 492 // Ignore any classes or methods marked @ExperimentalApi 493 // TODO(zpencer): enable after japicmp-gradle-plugin/pull/15 494 // annotationExcludes = ['@io.grpc.ExperimentalApi'] 495 } 496 } 497} 498 499// format checkers 500apply plugin: "com.diffplug.gradle.spotless" 501apply plugin: 'groovy' 502spotless { 503 groovyGradle { 504 target '**/*.gradle' 505 greclipse() 506 indentWithSpaces() 507 paddedCell() 508 } 509} 510