diff a/installers/linux/universal/tar/build.gradle b/installers/linux/universal/tar/build.gradle
--- /dev/null
+++ b/installers/linux/universal/tar/build.gradle
@@ -0,0 +1,201 @@
+/*
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Amazon designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+dependencies {
+    compile project(path: ':openjdksrc', configuration: 'archives')
+    compile project(path: ':prebuild', configuration: 'cacerts')
+}
+
+if (project.correttoArch == 'x86') {
+    project.correttoCommonFlags += '--with-target-bits=32'
+}
+
+def imageDir = "$buildRoot/build/${project.jdkImageName}/images"
+def jdkResultingImage = "${imageDir}/jdk"
+def testResultingImage = "${imageDir}/test"
+
+// deps
+def depsMap = [:]
+project.configurations.compile.getFiles().each { depsMap[it.getName()] = it }
+/**
+ * Create a local copy of the source tree in our
+ * build root -- this is required since OpenJDK's
+ * build wants to occur inside the source tree,
+ * and we don't want to tamper with someone
+ * else's tree.
+ */
+task copySource(type: Exec) {
+    if (!file(buildRoot).exists()) {
+        file(buildRoot).mkdirs()
+    }
+    workingDir '/usr/bin'
+    commandLine 'rsync', '-am',
+            '--exclude=pre-build',
+            '--exclude=installers',
+            '--exclude=corretto-build',
+            "${project.rootDir}/", buildRoot
+}
+
+/**
+ * Scan the patches folder for any .patch that needs
+ * to be applied before start building.
+ */
+task applyPatches() {
+    dependsOn copySource
+    doLast {
+        fileTree('patches').matching {
+            include '*.patch'
+        }.each { f ->
+            ant.patch(patchfile: f, dir: "$buildRoot", strip: 0)
+        }
+    }
+}
+
+task configureBuild(type: Exec) {
+    dependsOn project.configurations.compile
+    dependsOn applyPatches
+    workingDir "$buildRoot"
+
+    // Platform specific flags
+    def command = ['bash', 'configure',
+            "--with-cacerts-file=${depsMap[caCerts]}",
+            "--with-zlib=system"
+    ]
+    // Common flags
+    command += project.correttoCommonFlags
+    commandLine command.flatten()
+
+}
+
+task executeBuild(type: Exec) {
+    dependsOn configureBuild
+    workingDir "$buildRoot"
+    commandLine 'make', 'images'
+    outputs.dir jdkResultingImage
+}
+
+task createTestImage(type: Exec) {
+    dependsOn executeBuild
+    workingDir "$buildRoot"
+    commandLine 'make','test-image'
+}
+
+task bundleThirdPartyBinaries {
+    dependsOn executeBuild
+    doLast {
+        // If property set, copy async profiler binaries to bundle
+        if (project.asyncProfilerBinariesPath != "") {
+            if (!file(project.asyncProfilerBinariesPath).isDirectory()) {
+                throw new GradleException("asyncProfilerBinariesPath is not a valid directory: ${project.asyncProfilerBinariesPath}")
+            }
+            copy {
+                from project.asyncProfilerBinariesPath
+                include 'bin/**', 'lib/**'
+                into jdkResultingImage
+            }
+            copy {
+                from project.asyncProfilerLegal
+                into "${jdkResultingImage}/legal"
+            }
+        }
+    }
+}
+
+task fixCrossCompileLinking(type: Exec) {
+    dependsOn createTestImage
+    /* When cross-compiling for aarch64, gcc incorrectly links against
+     * libz.so, provided by the -devel packages, instead of libz.so.1
+     * This can lead to runtime errors of the form
+     * javac: error while loading shared libraries: libz.so: cannot open shared object file: No such file or directory
+     * As a workaround, use patchelf to update all references to libz.so to the expected libz.so.1
+     *
+     * See also:
+     * - https://github.com/AppImage/AppImageKit/issues/964
+     * - https://github.com/AppImage/AppImageKit/issues/1092
+     * - https://github.com/electron-userland/electron-builder/issues/7835
+     * - https://github.com/CollaboraOnline/richdocumentscode/issues/68
+     * - https://github.com/Sienci-Labs/gsender/issues/420
+     */
+    if (project.hasProperty("corretto.crossCompile")) {
+        commandLine 'bash', '-c', "find ${imageDir} -type f -exec patchelf --replace-needed libz.so libz.so.1 {} \\; 2>/dev/null"
+    } else {
+        commandLine 'bash', '-c', "echo 'Not a cross-compiled build, no linker fixup required'"
+    }
+}
+
+task packageTestImage(type: Tar) {
+    dependsOn fixCrossCompileLinking
+    description = 'Package test results'
+    archiveFileName = "${project.correttoTestImageArchiveName}.tar.gz"
+    compression = Compression.GZIP
+    from(testResultingImage) {
+        include '**'
+    }
+    into project.correttoTestImageArchiveName
+}
+
+task packageDebugSymbols(type: Tar) {
+    description = 'Package debug results'
+    dependsOn packageTestImage
+    archiveFileName = "${project.correttoDebugSymbolsArchiveName}.tar.gz"
+    compression = Compression.GZIP
+    from(jdkResultingImage) {
+        include 'bin/*.diz'
+        include 'lib/*.diz'
+        include 'lib/server/*.diz'
+        into project.correttoDebugSymbolsArchiveName
+    }
+}
+
+task packageBuildResults(type: Tar) {
+    description = 'Compresses the JDK image and puts the results in build/distributions.'
+    dependsOn packageDebugSymbols
+    dependsOn bundleThirdPartyBinaries
+    archiveFileName = "${project.correttoJdkArchiveName}.tar.gz"
+    compression = Compression.GZIP
+    from(buildRoot) {
+        include project.rootFiles
+        into project.correttoJdkArchiveName
+    }
+    from(jdkResultingImage) {
+        include 'bin/**'
+        include 'conf/**'
+        include 'include/**'
+        include 'jmods/**'
+        include 'lib/**'
+        include 'man/man1/**'
+        include 'release'
+        exclude '**/*.diz'
+        into project.correttoJdkArchiveName
+    }
+
+    // Copy legal directory specifically to set permission correctly.
+    // See https://github.com/corretto/corretto-11/issues/129
+    from("${jdkResultingImage}/legal") {
+        include '**'
+        fileMode = 0444
+        into "${project.correttoJdkArchiveName}/legal"
+    }
+}
+
+artifacts {
+    archives packageBuildResults
+}
