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 }