Solution for GRPC codegen deployment.
diff --git a/compiler/build.gradle b/compiler/build.gradle
index 274f985..365ff0d 100644
--- a/compiler/build.gradle
+++ b/compiler/build.gradle
@@ -1,4 +1,5 @@
apply plugin: "cpp"
+apply plugin: "osdetector"
apply plugin: "protobuf"
import org.apache.tools.ant.taskdefs.condition.Os
@@ -8,15 +9,94 @@
buildscript {
repositories {
mavenCentral()
+ mavenLocal()
}
dependencies {
- classpath libraries.protobuf_plugin
+ classpath libraries.protobuf_plugin,
+ 'com.google.gradle:osdetector-gradle-plugin:1.2.1'
}
}
-executables {
- java_plugin {
- baseName "$protocPluginBaseName"
+// When there is only one platform available, Gradle doesn't create a directory
+// for the sole platform. In order to keep the script simple, we intentionally
+// always build the 'local_arch' even though it's duplicate with one of the
+// targetArchs, so that we always have at least two platforms.
+def targetArchs = ['local_arch'] as HashSet
+
+def artifactStagingPath = "$buildDir/artifacts" as File
+def artifactPath = { arch ->
+ return "$artifactStagingPath/java_pluginExecutable/" + arch + "/${protocPluginBaseName}.exe"
+}
+
+
+if (System.env.TARGET_ARCHS != null) {
+ def archs = System.env.TARGET_ARCHS.split(' +')
+ targetArchs.addAll(archs)
+} else {
+ targetArchs.add(osdetector.arch)
+}
+
+// Adds space-delimited arguments from the environment variable env to the
+// argList.
+def addEnvArgs = { env, argList ->
+ def value = System.getenv(env)
+ if (value != null) {
+ value.split(' +').each() { it -> argList.add(it) }
+ }
+}
+
+model {
+ toolChains {
+ gcc(Gcc) {
+ target("x86_64") {
+ cppCompiler.withArguments { args ->
+ args << "-m64"
+ }
+ linker.withArguments { args ->
+ args << "-m64"
+ }
+ }
+ target("x86_32") {
+ cppCompiler.withArguments { args ->
+ args << "-m32"
+ }
+ linker.withArguments { args ->
+ args << "-m32"
+ }
+ }
+ target('local_arch') { }
+ }
+ clang(Clang) {
+ target("x86_64") {
+ cppCompiler.withArguments { args ->
+ args << "-m64"
+ }
+ linker.withArguments { args ->
+ args << "-m64"
+ }
+ }
+ target('local_arch') { }
+ }
+ }
+ platforms {
+ x86_32 {
+ architecture "x86_32"
+ }
+ x86_64 {
+ architecture "x86_64"
+ }
+ local_arch {
+ architecture 'local_arch'
+ }
+ }
+
+ components {
+ java_plugin(NativeExecutableSpec) {
+ targetArchs.each {
+ targetPlatform it
+ }
+ baseName "$protocPluginBaseName"
+ }
}
}
@@ -27,18 +107,21 @@
binaries.all {
if (toolChain in Gcc || toolChain in Clang) {
- // Support Gcc 4.6 by using c++0x instead of c++11
cppCompiler.args "--std=c++0x"
- if (System.env.CXXFLAGS) {
- cppCompiler.args System.env.CXXFLAGS
+ addEnvArgs("CXXFLAGS", cppCompiler.args)
+ addEnvArgs("CPPFLAGS", cppCompiler.args)
+ if (osdetector.os == "osx") {
+ cppCompiler.args "-mmacosx-version-min=10.7", "-stdlib=libc++"
+ } else if (osdetector.os == "windows") {
+ linker.args "-static", "-lprotoc", "-lprotobuf", "-static-libgcc", "-static-libstdc++", "-s"
+ } else {
+ // Link protoc, protobuf, libgcc and libstdc++ statically.
+ // Link other (system) libraries dynamically.
+ // Clang under OSX doesn't support these options.
+ linker.args "-Wl,-Bstatic", "-lprotoc", "-lprotobuf", "-static-libgcc", "-static-libstdc++",
+ "-Wl,-Bdynamic", "-lpthread", "-s"
}
- if (System.env.CPPFLAGS) {
- cppCompiler.args System.env.CPPFLAGS
- }
- linker.args "-lprotoc", "-lprotobuf"
- if (System.env.LDFLAGS) {
- linker.args System.env.LDFLAGS
- }
+ addEnvArgs("LDFLAGS", linker.args)
} else if (toolChain in VisualCpp) {
cppCompiler.args "/EHsc", "/MD"
if (rootProject.hasProperty('protobuf.include')) {
@@ -51,9 +134,58 @@
}
}
+task buildArtifacts(type: Copy) {
+ targetArchs.each {
+ dependsOn it + 'Java_pluginExecutable'
+ }
+ from("$buildDir/binaries") {
+ if (osdetector.os != 'windows') {
+ rename 'protoc-gen-grpc-java', '$0.exe'
+ }
+ }
+ into artifactStagingPath
+}
+
+archivesBaseName = "$protocPluginBaseName"
+
+artifacts {
+ for (arch in (targetArchs - 'local_arch')) {
+ archives(artifactPath(arch) as File) {
+ classifier osdetector.os + "-" + arch
+ type "exe"
+ extension "exe"
+ builtBy buildArtifacts
+ }
+ }
+}
+
+// Exe files are skipped by Maven by default. Override it.
+// Also skip jar files that is generated by the java plugin.
+[
+ install.repositories.mavenInstaller,
+ uploadArchives.repositories.mavenDeployer,
+]*.addFilter('all') {artifact, file ->
+ ! (file.getName().endsWith('jar') || file.getName().endsWith('jar.asc'))
+}
+
+[
+ install.repositories.mavenInstaller,
+ uploadArchives.repositories.mavenDeployer,
+]*.beforeDeployment {
+ for (arch in (targetArchs - 'local_arch')) {
+ def ret = exec {
+ executable 'bash'
+ args 'check-artifact.sh', osdetector.os, arch
+ }
+ if (ret.exitValue != 0) {
+ throw new GradleException("check-artifact.sh exited with " + ret.exitValue)
+ }
+ }
+}
+
protobufCodeGenPlugins = ["java_plugin:$javaPluginPath"]
-generateTestProto.dependsOn 'java_pluginExecutable'
+generateTestProto.dependsOn 'local_archJava_pluginExecutable'
// Ignore test for the moment on Windows. It will be easier to run once the
// gradle protobuf plugin can support nano.
if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
@@ -72,7 +204,7 @@
"$projectDir/src/test/golden/TestService.java.txt"
}
-task testNanoGolden(type: Exec, dependsOn: 'java_pluginExecutable') {
+task testNanoGolden(type: Exec, dependsOn: 'local_archJava_pluginExecutable') {
doFirst {
temporaryDir.createNewFile();
}
@@ -80,8 +212,3 @@
environment 'TEST_TMP_DIR', temporaryDir
commandLine './src/test/run_nano_test.sh'
}
-
-[
- install.repositories.mavenInstaller,
- uploadArchives.repositories.mavenDeployer,
-]*.addFilter('none') { artifact, file -> false }