• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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