Home | History | Annotate | Download | only in compiler
      1 apply plugin: "cpp"
      2 apply plugin: "com.google.protobuf"
      3 
      4 description = 'The protoc plugin for gRPC Java'
      5 
      6 buildscript {
      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 
     15 def artifactStagingPath = "$buildDir/artifacts" as File
     16 // Adds space-delimited arguments from the environment variable env to the
     17 // argList.
     18 def 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.
     30 def 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 
     37 def String arch = rootProject.hasProperty('targetArch') ? rootProject.targetArch : osdetector.arch
     38 def boolean vcDisable = rootProject.hasProperty('vcDisable') ? rootProject.vcDisable : false
     39 def boolean usingVisualCpp // Whether VisualCpp is actually available and selected
     40 
     41 model {
     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 
    126 configurations {
    127     testLiteCompile
    128     testNanoCompile
    129 }
    130 
    131 dependencies {
    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 
    140 sourceSets {
    141     testLite {
    142         proto { setSrcDirs(['src/test/proto']) }
    143     }
    144     testNano {
    145         proto { setSrcDirs(['src/test/proto']) }
    146     }
    147 }
    148 
    149 compileTestJava {
    150     options.compilerArgs += [
    151         "-Xlint:-cast",
    152         "-XepExcludedPaths:.*/build/generated/source/proto/.*",
    153     ]
    154 }
    155 
    156 compileTestLiteJava {
    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 
    166 compileTestNanoJava {
    167     options.compilerArgs = compileTestJava.options.compilerArgs
    168 }
    169 
    170 protobuf {
    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 
    211 checkstyleTestNano {
    212     source = fileTree(dir: "src/testNano", include: "**/*.java")
    213 }
    214 
    215 println "*** Building codegen requires Protobuf version ${protocVersion}"
    216 println "*** Please refer to https://github.com/grpc/grpc-java/blob/master/COMPILING.md#how-to-build-code-generation-plugin"
    217 
    218 task 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 
    228 archivesBaseName = "$protocPluginBaseName"
    229 
    230 artifacts {
    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 
    304 def 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 
    319 task testGolden(type: Exec)
    320 task testLiteGolden(type: Exec)
    321 task testNanoGolden(type: Exec)
    322 task testDeprecatedGolden(type: Exec)
    323 task testDeprecatedLiteGolden(type: Exec)
    324 task testDeprecatedNanoGolden(type: Exec)
    325 configureTestTask(testGolden, '', '', 'TestService')
    326 configureTestTask(testLiteGolden, 'Lite', '', 'TestService')
    327 configureTestTask(testNanoGolden, 'Nano', '/nano', 'TestService')
    328 configureTestTask(testDeprecatedGolden, '', '', 'TestDeprecatedService')
    329 configureTestTask(testDeprecatedLiteGolden, 'Lite', '', 'TestDeprecatedService')
    330 configureTestTask(testDeprecatedNanoGolden, 'Nano', '/nano', 'TestDeprecatedService')
    331