Initial push.
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
new file mode 100644
index 0000000..0f172d6
--- /dev/null
+++ b/buildSrc/build.gradle
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+apply plugin: 'java'
+apply plugin: 'idea'
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    compile group: 'com.google.guava', name: 'guava', version: '19.0'
+    compile group: 'org.smali', name: 'smali', version: '2.2b4'
+}
diff --git a/buildSrc/src/main/java/dx/DexMerger.java b/buildSrc/src/main/java/dx/DexMerger.java
new file mode 100644
index 0000000..39a4bfb
--- /dev/null
+++ b/buildSrc/src/main/java/dx/DexMerger.java
@@ -0,0 +1,67 @@
+// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package dx;
+
+import java.io.File;
+import java.io.IOException;
+import org.gradle.api.Action;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.UncheckedIOException;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.process.ExecSpec;
+import utils.Utils;
+
+public class DexMerger extends DefaultTask {
+
+  private FileTree source;
+  private File destination;
+  private File dexMergerExecutable;
+  private boolean debug;
+
+  public FileTree getSource() {
+    return source;
+  }
+
+  public void setSource(FileTree source) {
+    this.source = source;
+    getInputs().file(source);
+  }
+
+  public File getDestination() {
+    return destination;
+  }
+
+  public void setDestination(File destination) {
+    this.destination = destination;
+    getOutputs().file(destination);
+  }
+
+  public File getDexMergerExecutable() {
+    return dexMergerExecutable;
+  }
+
+  public void setDexMergerExecutable(File dexMergerExecutable) {
+    this.dexMergerExecutable = dexMergerExecutable;
+  }
+
+  @TaskAction
+  void exec() {
+    getProject().exec(new Action<ExecSpec>() {
+      @Override
+      public void execute(ExecSpec execSpec) {
+        try {
+          if (dexMergerExecutable == null) {
+            dexMergerExecutable = new File("tools/" + Utils.toolsDir() + "/dx/bin/dexmerger");
+          }
+          execSpec.setExecutable(dexMergerExecutable);
+          execSpec.args(destination.getCanonicalPath());
+          execSpec.args(source.getFiles());
+        } catch (IOException e) {
+          throw new UncheckedIOException(e);
+        }
+      }
+    });
+  }
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/java/dx/Dx.java b/buildSrc/src/main/java/dx/Dx.java
new file mode 100644
index 0000000..e4b89c4
--- /dev/null
+++ b/buildSrc/src/main/java/dx/Dx.java
@@ -0,0 +1,83 @@
+// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package dx;
+
+import java.io.File;
+import java.io.IOException;
+import org.gradle.api.Action;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.UncheckedIOException;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.process.ExecSpec;
+import utils.Utils;
+
+public class Dx extends DefaultTask {
+
+  private FileTree source;
+  private File destination;
+  private File dxExecutable;
+  private boolean debug;
+
+  public FileTree getSource() {
+    return source;
+  }
+
+  public void setSource(FileTree source) {
+    this.source = source;
+    getInputs().file(source);
+  }
+
+  public File getDestination() {
+    return destination;
+  }
+
+  public void setDestination(File destination) {
+    this.destination = destination;
+    File classesFile = destination.toPath().resolve("classes.dex").toFile();
+    // The output from running DX is classes.dex in the destination directory.
+    // TODO(sgjesse): Handle multidex?
+    getOutputs().file(classesFile);
+  }
+
+  public File getDxExecutable() {
+    return dxExecutable;
+  }
+
+  public void setDxExecutable(File dxExecutable) {
+    this.dxExecutable = dxExecutable;
+  }
+
+  public boolean isDebug() {
+    return debug;
+  }
+
+  public void setDebug(boolean debug) {
+    this.debug = debug;
+  }
+
+  @TaskAction
+  void exec() {
+    getProject().exec(new Action<ExecSpec>() {
+      @Override
+      public void execute(ExecSpec execSpec) {
+        try {
+          if (dxExecutable == null) {
+            dxExecutable = new File("tools/" + Utils.toolsDir() + "/dx/bin/dx");
+          }
+          execSpec.setExecutable(dxExecutable);
+          execSpec.args("--dex");
+          execSpec.args("--output");
+          execSpec.args(destination.getCanonicalPath());
+          if (isDebug()) {
+            execSpec.args("--debug");
+          }
+          execSpec.args(source.getFiles());
+        } catch (IOException e) {
+          throw new UncheckedIOException(e);
+        }
+      }
+    });
+  }
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/java/smali/Smali.java b/buildSrc/src/main/java/smali/Smali.java
new file mode 100644
index 0000000..bd217d7
--- /dev/null
+++ b/buildSrc/src/main/java/smali/Smali.java
@@ -0,0 +1,59 @@
+// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package smali;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.UncheckedIOException;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.tasks.TaskAction;
+
+public class Smali extends DefaultTask {
+
+  private FileTree source;
+  private File destination;
+  private File smaliScript;
+
+  public FileTree getSource() {
+    return source;
+  }
+
+  public void setSource(FileTree source) {
+    this.source = source;
+    getInputs().file(source);
+  }
+
+  public File getDestination() {
+    return destination;
+  }
+
+  public void setDestination(File destination) {
+    this.destination = destination;
+    getOutputs().file(destination);
+  }
+
+  public File getSmaliScript() {
+    return smaliScript;
+  }
+
+  public void setSmaliScript(File smaliScript) {
+    this.smaliScript = smaliScript;
+  }
+
+  @TaskAction
+  void exec() {
+    try {
+      List<String> fileNames = source.getFiles().stream().map(file -> file.toString())
+          .collect(Collectors.toList());
+      org.jf.smali.SmaliOptions options = new org.jf.smali.SmaliOptions();
+      options.outputDexFile = destination.getCanonicalPath().toString();
+      org.jf.smali.Smali.assemble(options, fileNames);
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/java/utils/Utils.java b/buildSrc/src/main/java/utils/Utils.java
new file mode 100644
index 0000000..5e5e9d7
--- /dev/null
+++ b/buildSrc/src/main/java/utils/Utils.java
@@ -0,0 +1,10 @@
+// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package utils;
+
+public class Utils {
+  public static String toolsDir() {
+    return System.getProperty("os.name").equals("Mac OS X") ? "mac" : "linux";
+  }
+}