1apply plugin: "cpp" 2apply plugin: "com.google.protobuf" 3 4description = 'The protoc plugin for gRPC Java' 5 6buildscript { 7 repositories { 8 maven { // The google mirror is less flaky than mavenCentral() 9 url "https://maven-central.storage-download.googleapis.com/repos/central/data/" } 10 mavenLocal() 11 } 12 dependencies { classpath libraries.protobuf_plugin } 13} 14 15def artifactStagingPath = "$buildDir/artifacts" as File 16// Adds space-delimited arguments from the environment variable env to the 17// argList. 18def addEnvArgs = { env, argList -> 19 def value = System.getenv(env) 20 if (value != null) { 21 value.split(' +').each() { it -> argList.add(it) } 22 } 23} 24 25// Adds corresponding "-l" option to the argList if libName is not found in 26// LDFLAGS. This is only used for Mac because when building for uploadArchives 27// artifacts, we add the ".a" files directly to LDFLAGS and without "-l" in 28// order to get statically linked, otherwise we add the libraries through "-l" 29// so that they can be searched for in default search paths. 30def addLibraryIfNotLinked = { libName, argList -> 31 def ldflags = System.env.LDFLAGS 32 if (ldflags == null || !ldflags.contains('lib' + libName + '.a')) { 33 argList.add('-l' + libName) 34 } 35} 36 37def String arch = rootProject.hasProperty('targetArch') ? rootProject.targetArch : osdetector.arch 38def boolean vcDisable = rootProject.hasProperty('vcDisable') ? rootProject.vcDisable : false 39def boolean usingVisualCpp // Whether VisualCpp is actually available and selected 40 41model { 42 toolChains { 43 // If you have both VC and Gcc installed, VC will be selected, unless you 44 // set 'vcDisable=true' 45 if (!vcDisable) { 46 visualCpp(VisualCpp) { 47 // Prefer vcvars-provided environment over registry-discovered environment 48 def String vsDir = System.getenv("VSINSTALLDIR") 49 def String winDir = System.getenv("WindowsSdkDir") 50 if (vsDir != null && winDir != null) { 51 installDir = vsDir 52 windowsSdkDir = winDir 53 } 54 } 55 } 56 gcc(Gcc) { 57 target("ppcle_64") 58 target("aarch_64") 59 } 60 clang(Clang) { 61 } 62 } 63 64 platforms { 65 x86_32 { architecture "x86" } 66 x86_64 { architecture "x86_64" } 67 ppcle_64 { architecture "ppcle_64" } 68 aarch_64 { architecture "aarch_64" } 69 } 70 71 components { 72 java_plugin(NativeExecutableSpec) { 73 if (arch in [ 74 'x86_32', 75 'x86_64', 76 'ppcle_64', 77 'aarch_64' 78 ]) { 79 // If arch is not within the defined platforms, we do not specify the 80 // targetPlatform so that Gradle will choose what is appropriate. 81 targetPlatform arch 82 } 83 baseName "$protocPluginBaseName" 84 } 85 } 86 87 binaries { 88 all { 89 if (toolChain in Gcc || toolChain in Clang) { 90 cppCompiler.define("GRPC_VERSION", version) 91 cppCompiler.args "--std=c++0x" 92 addEnvArgs("CXXFLAGS", cppCompiler.args) 93 addEnvArgs("CPPFLAGS", cppCompiler.args) 94 if (osdetector.os == "osx") { 95 cppCompiler.args "-mmacosx-version-min=10.7", "-stdlib=libc++" 96 addLibraryIfNotLinked('protoc', linker.args) 97 addLibraryIfNotLinked('protobuf', linker.args) 98 } else if (osdetector.os == "windows") { 99 linker.args "-static", "-lprotoc", "-lprotobuf", "-static-libgcc", "-static-libstdc++", 100 "-s" 101 } else { 102 // Link protoc, protobuf, libgcc and libstdc++ statically. 103 // Link other (system) libraries dynamically. 104 // Clang under OSX doesn't support these options. 105 linker.args "-Wl,-Bstatic", "-lprotoc", "-lprotobuf", "-static-libgcc", 106 "-static-libstdc++", 107 "-Wl,-Bdynamic", "-lpthread", "-s" 108 } 109 addEnvArgs("LDFLAGS", linker.args) 110 } else if (toolChain in VisualCpp) { 111 usingVisualCpp = true 112 cppCompiler.define("GRPC_VERSION", version) 113 cppCompiler.args "/EHsc", "/MT" 114 if (rootProject.hasProperty('vcProtobufInclude')) { 115 cppCompiler.args "/I${rootProject.vcProtobufInclude}" 116 } 117 linker.args "libprotobuf.lib", "libprotoc.lib" 118 if (rootProject.hasProperty('vcProtobufLibs')) { 119 linker.args "/LIBPATH:${rootProject.vcProtobufLibs}" 120 } 121 } 122 } 123 } 124} 125 126configurations { 127 testLiteCompile 128 testNanoCompile 129} 130 131dependencies { 132 testCompile project(':grpc-protobuf'), 133 project(':grpc-stub') 134 testLiteCompile project(':grpc-protobuf-lite'), 135 project(':grpc-stub') 136 testNanoCompile project(':grpc-protobuf-nano'), 137 project(':grpc-stub') 138} 139 140sourceSets { 141 testLite { 142 proto { setSrcDirs(['src/test/proto']) } 143 } 144 testNano { 145 proto { setSrcDirs(['src/test/proto']) } 146 } 147} 148 149compileTestJava { 150 options.compilerArgs += [ 151 "-Xlint:-cast", 152 "-XepExcludedPaths:.*/build/generated/source/proto/.*", 153 ] 154} 155 156compileTestLiteJava { 157 options.compilerArgs = compileTestJava.options.compilerArgs 158 // Protobuf-generated Lite produces quite a few warnings. 159 options.compilerArgs += [ 160 "-Xlint:-rawtypes", 161 "-Xlint:-unchecked", 162 "-Xlint:-fallthrough" 163 ] 164} 165 166compileTestNanoJava { 167 options.compilerArgs = compileTestJava.options.compilerArgs 168} 169 170protobuf { 171 protoc { 172 if (project.hasProperty('protoc')) { 173 path = project.protoc 174 } else { 175 artifact = "com.google.protobuf:protoc:${protocVersion}" 176 } 177 } 178 plugins { 179 javalite { 180 if (project.hasProperty('protoc-gen-javalite')) { 181 path = project['protoc-gen-javalite'] 182 } else { 183 artifact = libraries.protoc_lite 184 } 185 } 186 grpc { path = javaPluginPath } 187 } 188 generateProtoTasks { 189 all().each { task -> 190 task.dependsOn 'java_pluginExecutable' 191 task.inputs.file javaPluginPath 192 } 193 ofSourceSet('test')*.plugins { grpc {} } 194 ofSourceSet('testLite')*.each { task -> 195 task.builtins { remove java } 196 task.plugins { 197 javalite {} 198 grpc { option 'lite' } 199 } 200 } 201 ofSourceSet('testNano').each { task -> 202 task.builtins { 203 remove java 204 javanano { option 'ignore_services=true' } 205 } 206 task.plugins { grpc { option 'nano' } } 207 } 208 } 209} 210 211checkstyleTestNano { 212 source = fileTree(dir: "src/testNano", include: "**/*.java") 213} 214 215println "*** Building codegen requires Protobuf version ${protocVersion}" 216println "*** Please refer to https://github.com/grpc/grpc-java/blob/master/COMPILING.md#how-to-build-code-generation-plugin" 217 218task buildArtifacts(type: Copy) { 219 dependsOn 'java_pluginExecutable' 220 from("$buildDir/exe") { 221 if (osdetector.os != 'windows') { 222 rename 'protoc-gen-grpc-java', '$0.exe' 223 } 224 } 225 into artifactStagingPath 226} 227 228archivesBaseName = "$protocPluginBaseName" 229 230artifacts { 231 archives("$artifactStagingPath/java_plugin/${protocPluginBaseName}.exe" as File) { 232 classifier osdetector.os + "-" + arch 233 type "exe" 234 extension "exe" 235 builtBy buildArtifacts 236 } 237} 238 239// Exe files are skipped by Maven by default. Override it. 240// Also skip jar files that is generated by the java plugin. 241[ 242 install.repositories.mavenInstaller, 243 uploadArchives.repositories.mavenDeployer, 244]*.setFilter {artifact, file -> 245 ! (file.getName().endsWith('jar') || file.getName().endsWith('jar.asc')) 246} 247 248[ 249 uploadArchives.repositories.mavenDeployer, 250]*.beforeDeployment { it -> 251 if (!usingVisualCpp) { 252 def ret = exec { 253 executable 'bash' 254 args 'check-artifact.sh', osdetector.os, arch 255 } 256 if (ret.exitValue != 0) { 257 throw new GradleException("check-artifact.sh exited with " + ret.exitValue) 258 } 259 } else { 260 def exeName = "$artifactStagingPath/java_plugin/${protocPluginBaseName}.exe" 261 def os = new ByteArrayOutputStream() 262 def ret = exec { 263 executable 'dumpbin' 264 args '/nologo', '/dependents', exeName 265 standardOutput = os 266 } 267 if (ret.exitValue != 0) { 268 throw new GradleException("dumpbin exited with " + ret.exitValue) 269 } 270 def dlls = os.toString() =~ /Image has the following dependencies:\s+(.*)\s+Summary/ 271 if (dlls[0][1] != "KERNEL32.dll") { 272 throw new Exception("unexpected dll deps: " + dlls[0][1]); 273 } 274 os.reset() 275 ret = exec { 276 executable 'dumpbin' 277 args '/nologo', '/headers', exeName 278 standardOutput = os 279 } 280 if (ret.exitValue != 0) { 281 throw new GradleException("dumpbin exited with " + ret.exitValue) 282 } 283 def machine = os.toString() =~ / machine \(([^)]+)\)/ 284 def expectedArch = [x86_32: "x86", x86_64: "x64"][arch] 285 if (machine[0][1] != expectedArch) { 286 throw new Exception("unexpected architecture: " + machine[0][1]); 287 } 288 } 289} 290 291[ 292 install.repositories.mavenInstaller, 293 uploadArchives.repositories.mavenDeployer, 294]*.pom*.whenConfigured { pom -> 295 pom.project { 296 // This isn't any sort of Java archive artifact, and OSSRH doesn't enforce 297 // javadoc for 'pom' packages. 'exe' would be a more appropriate packaging 298 // value, but it isn't clear how that will be interpreted. In addition, 299 // 'pom' is typically the value used when building an exe with Maven. 300 packaging = "pom" 301 } 302} 303 304def configureTestTask(Task task, String dep, String extraPackage, String serviceName) { 305 test.dependsOn task 306 task.dependsOn "generateTest${dep}Proto" 307 if (osdetector.os != 'windows') { 308 task.executable "diff" 309 task.args "-u" 310 } else { 311 task.executable "fc" 312 } 313 // File isn't found on Windows if last slash is forward-slash 314 def slash = System.getProperty("file.separator") 315 task.args "$buildDir/generated/source/proto/test${dep}/grpc/io/grpc/testing/compiler${extraPackage}${slash}${serviceName}Grpc.java", 316 "$projectDir/src/test${dep}/golden/${serviceName}.java.txt" 317} 318 319task testGolden(type: Exec) 320task testLiteGolden(type: Exec) 321task testNanoGolden(type: Exec) 322task testDeprecatedGolden(type: Exec) 323task testDeprecatedLiteGolden(type: Exec) 324task testDeprecatedNanoGolden(type: Exec) 325configureTestTask(testGolden, '', '', 'TestService') 326configureTestTask(testLiteGolden, 'Lite', '', 'TestService') 327configureTestTask(testNanoGolden, 'Nano', '/nano', 'TestService') 328configureTestTask(testDeprecatedGolden, '', '', 'TestDeprecatedService') 329configureTestTask(testDeprecatedLiteGolden, 'Lite', '', 'TestDeprecatedService') 330configureTestTask(testDeprecatedNanoGolden, 'Nano', '/nano', 'TestDeprecatedService') 331