Squashed 'third_party/allwpilib_2019/' content from commit bd05dfa1c

Change-Id: I2b1c2250cdb9b055133780c33593292098c375b7
git-subtree-dir: third_party/allwpilib_2019
git-subtree-split: bd05dfa1c7cca74c4fac451e7b9d6a37e7b53447
diff --git a/shared/config.gradle b/shared/config.gradle
new file mode 100644
index 0000000..02c2b68
--- /dev/null
+++ b/shared/config.gradle
@@ -0,0 +1,395 @@
+import edu.wpi.first.nativeutils.*
+import org.gradle.internal.os.OperatingSystem
+
+def windowsCompilerArgs = ['/EHsc', '/DNOMINMAX', '/Zi', '/FS', '/Zc:inline', '/MP4']
+def windowsCCompilerArgs = ['/Zi', '/FS', '/Zc:inline']
+def windowsReleaseCompilerArgs = ['/O2', '/MD']
+def windowsDebugCompilerArgs = ['/Od', '/MDd']
+def windowsLinkerArgs = ['/DEBUG:FULL']
+def windowsReleaseLinkerArgs = ['/OPT:REF', '/OPT:ICF']
+
+def linuxCrossCompilerArgs = ['-std=c++14', '-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g',
+                         '-Wno-unused-parameter', '-Wno-error=deprecated-declarations', '-fPIC', '-rdynamic',
+                         '-pthread']
+def linuxCrossCCompilerArgs = ['-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g',
+                          '-Wno-unused-parameter', '-fPIC', '-rdynamic', '-pthread']
+def linuxCrossLinkerArgs = ['-rdynamic', '-pthread', '-ldl']
+def linuxCrossReleaseCompilerArgs = ['-O2']
+def linuxCrossDebugCompilerArgs = ['-Og']
+
+def linuxCompilerArgs = ['-std=c++14', '-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g',
+                         '-Wno-unused-parameter', '-Wno-error=deprecated-declarations', '-fPIC', '-rdynamic',
+                         '-pthread']
+def linuxCCompilerArgs = ['-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g',
+                          '-Wno-unused-parameter', '-fPIC', '-rdynamic', '-pthread']
+def linuxLinkerArgs = ['-rdynamic', '-pthread', '-ldl']
+def linuxReleaseCompilerArgs = ['-O2']
+def linuxDebugCompilerArgs = ['-O0']
+def linux32BitArg = '-m32'
+
+def macCompilerArgs = ['-std=c++14', '-Wall', '-Wextra', '-Werror', '-pedantic-errors', '-fPIC', '-g',
+                       '-Wno-unused-parameter', '-Wno-error=deprecated-declarations', '-Wno-missing-field-initializers',
+                       '-Wno-unused-private-field', '-Wno-unused-const-variable', '-pthread']
+def macCCompilerArgs = ['-Wall', '-Wextra', '-Werror', '-pedantic-errors', '-fPIC', '-g',
+                        '-Wno-unused-parameter', '-Wno-missing-field-initializers', '-Wno-unused-private-field']
+def macObjCLinkerArgs = ['-std=c++14', '-stdlib=libc++','-fobjc-arc', '-g', '-fPIC', '-Wall', '-Wextra', '-Werror']
+def macReleaseCompilerArgs = ['-O2']
+def macDebugCompilerArgs = ['-O0']
+def macLinkerArgs = ['-framework', 'CoreFoundation', '-framework', 'AVFoundation', '-framework', 'Foundation', '-framework', 'CoreMedia', '-framework', 'CoreVideo']
+def mac32BitArg = '-m32'
+
+def buildAll = project.hasProperty('buildAll')
+
+def windows64PlatformDetect = {
+    def arch = System.getProperty("os.arch")
+    def isWin = OperatingSystem.current().isWindows()
+    if (buildAll) {
+        return isWin
+    } else {
+        return isWin && arch == 'amd64'
+    }
+}
+
+def windows32PlatformDetect = {
+    def arch = System.getProperty("os.arch")
+    def isWin = OperatingSystem.current().isWindows()
+    if (buildAll) {
+        return isWin
+    } else {
+        return isWin && arch == 'x86'
+    }
+}
+
+def linux32IntelPlatformDetect = {
+    def arch = System.getProperty("os.arch")
+    def isLinux = OperatingSystem.current().isLinux()
+    def isIntel = (arch == 'amd64' || arch == 'i386')
+    if (buildAll) {
+        return isLinux && isIntel
+    } else {
+        return isLinux && arch == 'i386'
+    }
+}
+
+def linux64IntelPlatformDetect = {
+    def arch = System.getProperty("os.arch")
+    def isLinux = OperatingSystem.current().isLinux()
+    def isIntel = (arch == 'amd64' || arch == 'i386')
+    if (buildAll) {
+        return isLinux && isIntel
+    } else {
+        return isLinux && arch == 'amd64'
+    }
+}
+
+def linuxArmPlatformDetect = {
+    def arch = System.getProperty("os.arch")
+    def isIntel = (arch == 'amd64' || arch == 'i386')
+    return OperatingSystem.current().isLinux() && !isIntel
+}
+
+def mac64PlatformDetect = {
+    def arch = System.getProperty("os.arch")
+    def isMac = OperatingSystem.current().isMacOsX()
+    if (buildAll) {
+        return isMac
+    } else {
+        return isMac && arch == 'x86_64'
+    }
+}
+
+def mac32PlatformDetect = {
+    def arch = System.getProperty("os.arch")
+    def isMac = OperatingSystem.current().isMacOsX()
+    if (buildAll) {
+        return isMac
+    } else {
+        return isMac && arch == 'x86'
+    }
+}
+
+if (!project.hasProperty('skipAthena') && !project.hasProperty('onlyRaspbian')) {
+    model {
+        buildConfigs {
+            roboRio(CrossBuildConfig) {
+                architecture = 'athena'
+                operatingSystem = 'linux'
+                toolChainPrefix = 'arm-frc2019-linux-gnueabi-'
+                compilerArgs = linuxCrossCompilerArgs
+                CCompilerArgs = linuxCrossCCompilerArgs
+                linkerArgs = linuxCrossLinkerArgs
+                debugCompilerArgs = linuxCrossDebugCompilerArgs
+                releaseCompilerArgs = linuxCrossReleaseCompilerArgs
+                stripBuildTypes = ['debug', 'release']
+                compilerFamily = 'Gcc'
+            }
+        }
+    }
+}
+
+if (!project.hasProperty('skipRaspbian') && !project.hasProperty('onlyAthena')) {
+    model {
+        buildConfigs {
+            raspbian(CrossBuildConfig) {
+                architecture = 'raspbian'
+                operatingSystem = 'linux'
+                toolChainPrefix = 'arm-raspbian9-linux-gnueabihf-'
+                compilerArgs = linuxCrossCompilerArgs
+                CCompilerArgs = linuxCrossCCompilerArgs
+                linkerArgs = linuxCrossLinkerArgs
+                debugCompilerArgs = linuxCrossDebugCompilerArgs
+                releaseCompilerArgs = linuxCrossReleaseCompilerArgs
+                stripBuildTypes = ['debug', 'release']
+                compilerFamily = 'Gcc'
+            }
+        }
+    }
+}
+
+if (!project.hasProperty('onlyAthena') && !hasProperty('onlyRaspbian')) {
+    model {
+        buildConfigs {
+            winX86(BuildConfig) {
+                architecture = 'x86'
+                operatingSystem = 'windows'
+                compilerArgs = windowsCompilerArgs
+                CCompilerArgs = windowsCCompilerArgs
+                linkerArgs = windowsLinkerArgs
+                releaseCompilerArgs = windowsReleaseCompilerArgs
+                releaseLinkerArgs = windowsReleaseLinkerArgs
+                debugCompilerArgs = windowsDebugCompilerArgs
+                compilerFamily = 'VisualCpp'
+                detectPlatform = windows32PlatformDetect
+            }
+            winX64(BuildConfig) {
+                architecture = 'x86-64'
+                operatingSystem = 'windows'
+                compilerArgs = windowsCompilerArgs
+                CCompilerArgs = windowsCCompilerArgs
+                linkerArgs = windowsLinkerArgs
+                releaseCompilerArgs = windowsReleaseCompilerArgs
+                releaseLinkerArgs = windowsReleaseLinkerArgs
+                debugCompilerArgs = windowsDebugCompilerArgs
+                compilerFamily = 'VisualCpp'
+                detectPlatform = windows64PlatformDetect
+            }
+            linuxX64(BuildConfig) {
+                architecture = 'x86-64'
+                operatingSystem = 'linux'
+                compilerArgs = linuxCompilerArgs
+                CCompilerArgs = linuxCCompilerArgs
+                linkerArgs = linuxLinkerArgs
+                debugCompilerArgs = linuxDebugCompilerArgs
+                releaseCompilerArgs = linuxReleaseCompilerArgs
+                stripBuildTypes = ['debug', 'release']
+                compilerFamily = 'Gcc'
+                detectPlatform = linux64IntelPlatformDetect
+            }
+            macX64(BuildConfig) {
+                architecture = 'x86-64'
+                operatingSystem = 'osx'
+                compilerArgs = macCompilerArgs
+                CCompilerArgs = macCCompilerArgs
+                debugCompilerArgs = macDebugCompilerArgs
+                releaseCompilerArgs = macReleaseCompilerArgs
+                objCppCompilerArgs = macObjCLinkerArgs
+                linkerArgs = macLinkerArgs
+                compilerFamily = 'Clang'
+                detectPlatform = mac64PlatformDetect
+            }
+        }
+    }
+}
+
+if (project.hasProperty('linuxCross')) {
+    model {
+        buildConfigs {
+            linuxArm(CrossBuildConfig) {
+                architecture = 'nativearm'
+                operatingSystem = 'linux'
+                toolChainPrefix = 'PLEASE_PROVIDE_A_COMPILER_NAME'
+                compilerArgs = linuxCompilerArgs
+                CCompilerArgs = linuxCCompilerArgs
+                linkerArgs = linuxLinkerArgs
+                debugCompilerArgs = linuxDebugCompilerArgs
+                releaseCompilerArgs = linuxReleaseCompilerArgs
+                stripBuildTypes = ['debug', 'release']
+                skipByDefault = true
+                compilerFamily = 'Gcc'
+            }
+        }
+    }
+} else {
+    model {
+        buildConfigs {
+            linuxArm(BuildConfig) {
+                architecture = 'nativearm'
+                operatingSystem = 'linux'
+                compilerArgs = linuxCompilerArgs
+                CCompilerArgs = linuxCCompilerArgs
+                linkerArgs = linuxLinkerArgs
+                debugCompilerArgs = linuxDebugCompilerArgs
+                releaseCompilerArgs = linuxReleaseCompilerArgs
+                stripBuildTypes = ['debug', 'release']
+                compilerFamily = 'Gcc'
+                detectPlatform = linuxArmPlatformDetect
+            }
+        }
+    }
+}
+
+ext.getPublishClassifier = { binary ->
+    return NativeUtils.getPublishClassifier(binary)
+}
+
+ext.getPlatformPath = { binary ->
+    return NativeUtils.getPlatformPath(binary)
+}
+
+ext.appendDebugPathToBinaries = { binaries->
+    binaries.withType(StaticLibraryBinarySpec) {
+        if (it.buildType.name.contains('debug')) {
+            def staticFileDir = it.staticLibraryFile.parentFile
+            def staticFileName = it.staticLibraryFile.name
+            def staticFileExtension = staticFileName.substring(staticFileName.lastIndexOf('.'))
+            staticFileName = staticFileName.substring(0, staticFileName.lastIndexOf('.'))
+            staticFileName = staticFileName + 'd' + staticFileExtension
+            def newStaticFile = new File(staticFileDir, staticFileName)
+            it.staticLibraryFile = newStaticFile
+        }
+    }
+    binaries.withType(SharedLibraryBinarySpec) {
+        if (it.buildType.name.contains('debug')) {
+            def sharedFileDir = it.sharedLibraryFile.parentFile
+            def sharedFileName = it.sharedLibraryFile.name
+            def sharedFileExtension = sharedFileName.substring(sharedFileName.lastIndexOf('.'))
+            sharedFileName = sharedFileName.substring(0, sharedFileName.lastIndexOf('.'))
+            sharedFileName = sharedFileName + 'd' + sharedFileExtension
+            def newSharedFile = new File(sharedFileDir, sharedFileName)
+
+            def sharedLinkFileDir = it.sharedLibraryLinkFile.parentFile
+            def sharedLinkFileName = it.sharedLibraryLinkFile.name
+            def sharedLinkFileExtension = sharedLinkFileName.substring(sharedLinkFileName.lastIndexOf('.'))
+            sharedLinkFileName = sharedLinkFileName.substring(0, sharedLinkFileName.lastIndexOf('.'))
+            sharedLinkFileName = sharedLinkFileName + 'd' + sharedLinkFileExtension
+            def newLinkFile = new File(sharedLinkFileDir, sharedLinkFileName)
+
+            it.sharedLibraryLinkFile = newLinkFile
+            it.sharedLibraryFile = newSharedFile
+        }
+    }
+}
+
+ext.createComponentZipTasks = { components, names, base, type, project, func ->
+    def stringNames = names.collect {it.toString()}
+    def configMap = [:]
+    components.each {
+        if (it in NativeLibrarySpec && stringNames.contains(it.name)) {
+            it.binaries.each {
+                if (!it.buildable) return
+                def target = getPublishClassifier(it)
+                if (configMap.containsKey(target)) {
+                    configMap.get(target).add(it)
+                } else {
+                    configMap.put(target, [])
+                    configMap.get(target).add(it)
+                }
+            }
+        }
+    }
+    def taskList = []
+    def outputsFolder = file("$project.buildDir/outputs")
+    configMap.each { key, value ->
+        def task = project.tasks.create(base + "-${key}", type) {
+            description = 'Creates component archive for platform ' + key
+            destinationDir = outputsFolder
+            classifier = key
+            baseName = '_M_' + base
+            duplicatesStrategy = 'exclude'
+
+            from(licenseFile) {
+                into '/'
+            }
+
+            func(it, value)
+        }
+        taskList.add(task)
+
+        project.build.dependsOn task
+
+        project.artifacts {
+            task
+        }
+        addTaskToCopyAllOutputs(task)
+    }
+    return taskList
+}
+
+ext.createAllCombined = { list, name, base, type, project ->
+    def outputsFolder = file("$project.buildDir/outputs")
+
+    def task = project.tasks.create(base + "-all", type) {
+        description = "Creates component archive for all classifiers"
+        destinationDir = outputsFolder
+        classifier = "all"
+        baseName = base
+        duplicatesStrategy = 'exclude'
+
+        list.each {
+            if (it.name.endsWith('debug')) return
+            from project.zipTree(it.archivePath)
+            dependsOn it
+        }
+    }
+
+    project.build.dependsOn task
+
+    project.artifacts {
+        task
+    }
+
+    return task
+
+}
+
+ext.includeStandardZipFormat = { task, value ->
+    value.each { binary ->
+        if (binary.buildable) {
+            if (binary instanceof SharedLibraryBinarySpec) {
+                task.dependsOn binary.tasks.link
+                task.from(new File(binary.sharedLibraryFile.absolutePath + ".debug")) {
+                    into getPlatformPath(binary) + '/shared'
+                }
+                def sharedPath = binary.sharedLibraryFile.absolutePath
+                sharedPath = sharedPath.substring(0, sharedPath.length() - 4)
+
+                task.from(new File(sharedPath + '.pdb')) {
+                    into getPlatformPath(binary) + '/shared'
+                }
+                task.from(binary.sharedLibraryFile) {
+                    into getPlatformPath(binary) + '/shared'
+                }
+                task.from(binary.sharedLibraryLinkFile) {
+                    into getPlatformPath(binary) + '/shared'
+                }
+            } else  if (binary instanceof StaticLibraryBinarySpec) {
+                task.dependsOn binary.tasks.createStaticLib
+                task.from(binary.staticLibraryFile) {
+                    into getPlatformPath(binary) + '/static'
+                }
+            }
+        }
+    }
+}
+
+ext.getCurrentArch = {
+    def arch = System.getProperty('os.arch');
+
+    if (arch.equals("x86") || arch.equals("i386")) {
+        return 'x86'
+    } else if (arch.equals("amd64") || arch.equals("x86_64")) {
+        return 'x86-64'
+    } else {
+        return arch
+    }
+}
diff --git a/shared/examplecheck.gradle b/shared/examplecheck.gradle
new file mode 100644
index 0000000..64a83c7
--- /dev/null
+++ b/shared/examplecheck.gradle
@@ -0,0 +1,47 @@
+def fileCheck = { file, folder ->
+    def folderNames = new groovy.json.JsonSlurper().parseText(file.text).collect { it.foldername }
+    def folders = []
+    folder.eachDir {
+        folders << it.name
+    }
+    def disjunct = (folders + folderNames) - folders.intersect(folderNames)
+    def missingFromFolders = folderNames.intersect(disjunct)
+    def missingFromJson = folders.intersect(disjunct)
+
+    if (!missingFromFolders.empty || !missingFromJson.empty) {
+        StringBuilder missingString = new StringBuilder();
+        missingString.append("Missing From Folders\n")
+        for (String symbol : missingFromFolders) {
+            missingString.append(symbol);
+            missingString.append('\n');
+        }
+        missingString.append("\nMissing from JSON\n")
+        for (String symbol : missingFromJson) {
+            missingString.append(symbol);
+            missingString.append('\n');
+        }
+        throw new GradleException("Found missing items\n" + missingString.toString());
+    }
+}
+
+task checkTemplates(type: Task) {
+    doLast {
+        fileCheck(templateFile, templateDirectory)
+    }
+}
+
+task checkExamples(type: Task) {
+    doLast {
+        fileCheck(exampleFile, exampleDirectory)
+    }
+}
+
+task checkCommands(type: Task) {
+    doLast {
+        fileCheck(commandFile, commandDirectory)
+    }
+}
+
+check.dependsOn checkTemplates
+check.dependsOn checkExamples
+check.dependsOn checkCommands
diff --git a/shared/googletest.gradle b/shared/googletest.gradle
new file mode 100644
index 0000000..736d886
--- /dev/null
+++ b/shared/googletest.gradle
@@ -0,0 +1,13 @@
+model {
+    dependencyConfigs {
+        googletest(DependencyConfig) {
+            groupId = 'edu.wpi.first.thirdparty.frc2019'
+            artifactId = 'googletest'
+            headerClassifier = 'headers'
+            ext = 'zip'
+            version = '1.8.0-4-4e4df22'
+            sharedConfigs = [:]
+            staticConfigs = project.staticGtestConfigs
+        }
+    }
+}
diff --git a/shared/java/javacommon.gradle b/shared/java/javacommon.gradle
new file mode 100644
index 0000000..6595223
--- /dev/null
+++ b/shared/java/javacommon.gradle
@@ -0,0 +1,124 @@
+apply plugin: 'maven-publish'
+apply plugin: 'java'
+//apply plugin: 'net.ltgt.errorprone'
+
+def pubVersion
+if (project.hasProperty("publishVersion")) {
+    pubVersion = project.publishVersion
+} else {
+    pubVersion = WPILibVersion.version
+}
+
+def baseArtifactId = project.baseId
+def artifactGroupId = project.groupId
+def javaBaseName = "_GROUP_edu_wpi_first_${project.baseId}_ID_${project.baseId}-java_CLS"
+
+def outputsFolder = file("$project.buildDir/outputs")
+
+task sourcesJar(type: Jar, dependsOn: classes) {
+    classifier = 'sources'
+    from sourceSets.main.allSource
+}
+
+task javadocJar(type: Jar, dependsOn: javadoc) {
+    classifier = 'javadoc'
+    from javadoc.destinationDir
+}
+
+task outputJar(type: Jar, dependsOn: classes) {
+    baseName javaBaseName
+    destinationDir outputsFolder
+    from sourceSets.main.output
+}
+
+task outputSourcesJar(type: Jar, dependsOn: classes) {
+    baseName javaBaseName
+    destinationDir outputsFolder
+    classifier = 'sources'
+    from sourceSets.main.allSource
+}
+
+task outputJavadocJar(type: Jar, dependsOn: javadoc) {
+    baseName javaBaseName
+    destinationDir outputsFolder
+    classifier = 'javadoc'
+    from javadoc.destinationDir
+}
+
+artifacts {
+    archives sourcesJar
+    archives javadocJar
+    archives outputJar
+    archives outputSourcesJar
+    archives outputJavadocJar
+}
+
+addTaskToCopyAllOutputs(outputSourcesJar)
+addTaskToCopyAllOutputs(outputJavadocJar)
+addTaskToCopyAllOutputs(outputJar)
+
+build.dependsOn outputSourcesJar
+build.dependsOn outputJavadocJar
+build.dependsOn outputJar
+
+project(':').libraryBuild.dependsOn build
+
+publishing {
+    publications {
+
+        java(MavenPublication) {
+            artifact jar
+            artifact sourcesJar
+            artifact javadocJar
+
+            artifactId = "${baseArtifactId}-java"
+            groupId artifactGroupId
+            version pubVersion
+        }
+    }
+}
+
+test {
+    useJUnitPlatform()
+    systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true'
+    testLogging {
+        events "failed"
+        exceptionFormat "full"
+    }
+}
+
+if (project.hasProperty('onlyAthena') || project.hasProperty('onlyRaspbian')) {
+    test.enabled = false
+}
+
+repositories {
+    mavenCentral()
+    //maven.url "https://oss.sonatype.org/content/repositories/snapshots/"
+}
+
+sourceSets {
+    dev
+}
+
+tasks.withType(JavaCompile).configureEach {
+    options.compilerArgs = ['--release', '8']
+}
+
+dependencies {
+    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'
+    testImplementation 'org.junit.jupiter:junit-jupiter-params:5.2.0'
+    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
+
+    devCompile sourceSets.main.output
+
+    //errorprone 'com.google.errorprone:error_prone_core:2.3.2-SNAPSHOT'
+    //errorproneJavac 'com.google.errorprone:error_prone_core:2.3.1'
+}
+
+task run(type: JavaExec) {
+    classpath = sourceSets.dev.runtimeClasspath
+
+    main = project.devMain
+}
+
+build.dependsOn devClasses
diff --git a/shared/java/javastyle.gradle b/shared/java/javastyle.gradle
new file mode 100644
index 0000000..e091988
--- /dev/null
+++ b/shared/java/javastyle.gradle
@@ -0,0 +1,17 @@
+
+apply plugin: 'checkstyle'
+apply plugin: 'pmd'
+
+checkstyle {
+    toolVersion = "8.12"
+    configDir = file("${project.rootDir}/styleguide")
+    config = resources.text.fromFile(new File(configDir, "checkstyle.xml"))
+}
+
+pmd {
+    toolVersion = '6.7.0'
+    consoleOutput = true
+    reportsDir = file("$project.buildDir/reports/pmd")
+    ruleSetFiles = files(new File(rootDir, "styleguide/pmd-ruleset.xml"))
+    ruleSets = []
+}
diff --git a/shared/javacpp/publish.gradle b/shared/javacpp/publish.gradle
new file mode 100644
index 0000000..854a996
--- /dev/null
+++ b/shared/javacpp/publish.gradle
@@ -0,0 +1,72 @@
+apply plugin: 'maven-publish'
+
+def pubVersion
+if (project.hasProperty("publishVersion")) {
+    pubVersion = project.publishVersion
+} else {
+    pubVersion = WPILibVersion.version
+}
+
+def outputsFolder = file("$buildDir/outputs")
+
+def baseArtifactId = nativeName
+def artifactGroupId = "edu.wpi.first.${nativeName}"
+def zipBaseName = "_GROUP_edu_wpi_first_${nativeName}_ID_${nativeName}-cpp_CLS"
+
+def licenseFile = file("$rootDir/license.txt")
+
+task cppSourcesZip(type: Zip) {
+    destinationDir = outputsFolder
+    baseName = zipBaseName
+    classifier = "sources"
+
+    from(licenseFile) {
+        into '/'
+    }
+
+    from('src/main/native/cpp') {
+        into '/'
+    }
+}
+
+task cppHeadersZip(type: Zip) {
+    destinationDir = outputsFolder
+    baseName = zipBaseName
+    classifier = "headers"
+
+    from(licenseFile) {
+        into '/'
+    }
+
+    from('src/main/native/include') {
+        into '/'
+    }
+}
+
+artifacts {
+    archives cppHeadersZip
+    archives cppSourcesZip
+}
+
+addTaskToCopyAllOutputs(cppSourcesZip)
+addTaskToCopyAllOutputs(cppHeadersZip)
+
+model {
+    publishing {
+        def taskList = createComponentZipTasks($.components, [nativeName], zipBaseName, Zip, project, includeStandardZipFormat)
+
+        publications {
+            cpp(MavenPublication) {
+                taskList.each {
+                    artifact it
+                }
+                artifact cppHeadersZip
+                artifact cppSourcesZip
+
+                artifactId = "${baseArtifactId}-cpp"
+                groupId artifactGroupId
+                version pubVersion
+            }
+        }
+    }
+}
diff --git a/shared/javacpp/setupBuild.gradle b/shared/javacpp/setupBuild.gradle
new file mode 100644
index 0000000..d2cdd1d
--- /dev/null
+++ b/shared/javacpp/setupBuild.gradle
@@ -0,0 +1,153 @@
+apply plugin: 'cpp'
+apply plugin: 'google-test-test-suite'
+apply plugin: 'visual-studio'
+apply plugin: 'edu.wpi.first.NativeUtils'
+apply plugin: SingleNativeBuild
+apply plugin: ExtraTasks
+
+apply from: "${rootDir}/shared/config.gradle"
+
+ext {
+    baseId = nativeName
+    groupId = "edu.wpi.first.${nativeName}"
+}
+
+apply from: "${rootDir}/shared/java/javacommon.gradle"
+
+project(':').libraryBuild.dependsOn build
+
+ext {
+    staticGtestConfigs = [:]
+}
+
+staticGtestConfigs["${nativeName}Test"] = []
+
+apply from: "${rootDir}/shared/googletest.gradle"
+
+model {
+    components {
+        "${nativeName}Base"(NativeLibrarySpec) {
+            sources {
+                cpp {
+                    source {
+                        srcDirs 'src/main/native/cpp'
+                        include '**/*.cpp'
+                    }
+                    exportedHeaders {
+                        srcDirs 'src/main/native/include'
+                    }
+                }
+            }
+            binaries.all {
+                if (it instanceof SharedLibraryBinarySpec) {
+                    it.buildable = false
+                    return
+                }
+                if (project.hasProperty('extraSetup')) {
+                    extraSetup(it)
+                }
+            }
+        }
+        "${nativeName}"(NativeLibrarySpec) {
+            sources {
+                cpp {
+                    source {
+                        srcDirs "${rootDir}/shared/singlelib"
+                        include '**/*.cpp'
+                    }
+                    exportedHeaders {
+                        srcDirs 'src/main/native/include'
+                    }
+                }
+            }
+            appendDebugPathToBinaries(binaries)
+        }
+        // By default, a development executable will be generated. This is to help the case of
+        // testing specific functionality of the library.
+        "${nativeName}Dev"(NativeExecutableSpec) {
+            targetBuildTypes 'debug'
+            sources {
+                cpp {
+                    source {
+                        srcDirs 'src/dev/native/cpp'
+                        include '**/*.cpp'
+                        lib library: nativeName
+                    }
+                    exportedHeaders {
+                        srcDirs 'src/dev/native/include'
+                    }
+                }
+            }
+        }
+    }
+    testSuites {
+        "${nativeName}Test"(GoogleTestTestSuiteSpec) {
+            for(NativeComponentSpec c : $.components) {
+                if (c.name == nativeName) {
+                    testing c
+                    break
+                }
+            }
+            sources {
+                cpp {
+                    source {
+                        srcDirs 'src/test/native/cpp'
+                        include '**/*.cpp'
+                    }
+                    exportedHeaders {
+                        srcDirs 'src/test/native/include', 'src/main/native/cpp'
+                    }
+                }
+            }
+        }
+    }
+    binaries {
+        withType(GoogleTestTestSuiteBinarySpec) {
+            if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) {
+                lib library: nativeName, linkage: 'shared'
+            } else {
+                it.buildable = false
+            }
+        }
+    }
+    tasks {
+        def c = $.components
+        project.tasks.create('runCpp', Exec) {
+            group = 'WPILib'
+            description = "Run the ${nativeName}Dev executable"
+            def found = false
+            def systemArch = getCurrentArch()
+            c.each {
+                if (it in NativeExecutableSpec && it.name == "${nativeName}Dev") {
+                    it.binaries.each {
+                        if (!found) {
+                            def arch = it.targetPlatform.architecture.name
+                            if (arch == systemArch) {
+                                dependsOn it.tasks.install
+                                commandLine it.tasks.install.runScriptFile.get().asFile.toString()
+                                def filePath = it.tasks.install.installDirectory.get().toString() + File.separatorChar + 'lib'
+                                test.dependsOn it.tasks.install
+                                test.systemProperty 'java.library.path', filePath
+                                test.environment 'LD_LIBRARY_PATH', filePath
+                                test.workingDir filePath
+                                run.dependsOn it.tasks.install
+                                run.systemProperty 'java.library.path', filePath
+                                run.environment 'LD_LIBRARY_PATH', filePath
+                                run.workingDir filePath
+
+                                found = true
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+tasks.withType(RunTestExecutable) {
+    args "--gtest_output=xml:test_detail.xml"
+    outputs.dir outputDir
+}
+
+apply from: "${rootDir}/shared/javacpp/publish.gradle"
diff --git a/shared/jni/publish.gradle b/shared/jni/publish.gradle
new file mode 100644
index 0000000..a6a1abe
--- /dev/null
+++ b/shared/jni/publish.gradle
@@ -0,0 +1,130 @@
+import java.security.MessageDigest
+apply plugin: 'maven-publish'
+
+def pubVersion
+if (project.hasProperty("publishVersion")) {
+    pubVersion = project.publishVersion
+} else {
+    pubVersion = WPILibVersion.version
+}
+
+def outputsFolder = file("$buildDir/outputs")
+
+def baseArtifactId = nativeName
+def artifactGroupId = "edu.wpi.first.${nativeName}"
+def zipBaseName = "_GROUP_edu_wpi_first_${nativeName}_ID_${nativeName}-cpp_CLS"
+def jniBaseName = "_GROUP_edu_wpi_first_${nativeName}_ID_${nativeName}-jni_CLS"
+
+def licenseFile = file("$rootDir/license.txt")
+
+task cppSourcesZip(type: Zip) {
+    destinationDir = outputsFolder
+    baseName = zipBaseName
+    classifier = "sources"
+    duplicatesStrategy = 'exclude'
+
+    from(licenseFile) {
+        into '/'
+    }
+
+    from('src/main/native/cpp') {
+        into '/'
+    }
+
+    model {
+        components {
+            it.all {
+                if (it in getJniSpecClass()) {
+                    it.jniHeaderLocations.each {
+                        dependsOn it.key
+                        from(it.value) {
+                            into '/jni'
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+task cppHeadersZip(type: Zip) {
+    destinationDir = outputsFolder
+    baseName = zipBaseName
+    classifier = "headers"
+
+    from(licenseFile) {
+        into '/'
+    }
+
+    from('src/main/native/include') {
+        into '/'
+    }
+}
+
+artifacts {
+    archives cppHeadersZip
+    archives cppSourcesZip
+}
+
+addTaskToCopyAllOutputs(cppSourcesZip)
+addTaskToCopyAllOutputs(cppHeadersZip)
+
+model {
+    publishing {
+        def taskList = createComponentZipTasks($.components, [nativeName, "${nativeName}JNIShared"], zipBaseName, Zip, project, includeStandardZipFormat)
+
+        def jniTaskList = createComponentZipTasks($.components, ["${nativeName}JNI"], jniBaseName, Jar, project, { task, value ->
+            value.each { binary ->
+                if (binary.buildable) {
+                    if (binary instanceof SharedLibraryBinarySpec) {
+                        task.dependsOn binary.tasks.link
+                        def hashFile = new File(binary.sharedLibraryFile.parentFile.absolutePath, "${binary.component.baseName}.hash")
+                        task.outputs.file(hashFile)
+                        task.inputs.file(binary.sharedLibraryFile)
+                        task.from(hashFile) {
+                            into getPlatformPath(binary)
+                        }
+                        task.doFirst {
+                            hashFile.text = MessageDigest.getInstance("MD5").digest(binary.sharedLibraryFile.bytes).encodeHex().toString()
+                        }
+                        task.from(binary.sharedLibraryFile) {
+                            into getPlatformPath(binary)
+                        }
+                    }
+                }
+            }
+        })
+
+        def allJniTask
+        if (!project.hasProperty('jenkinsBuild')) {
+            allJniTask = createAllCombined(jniTaskList, "${nativeName}JNI", jniBaseName, Jar, project)
+        }
+
+        publications {
+            cpp(MavenPublication) {
+                taskList.each {
+                    artifact it
+                }
+                artifact cppHeadersZip
+                artifact cppSourcesZip
+
+                artifactId = "${baseArtifactId}-cpp"
+                groupId artifactGroupId
+                version pubVersion
+            }
+            jni(MavenPublication) {
+                jniTaskList.each {
+                    artifact it
+                }
+
+                if (!project.hasProperty('jenkinsBuild')) {
+                    artifact allJniTask
+                }
+
+                artifactId = "${baseArtifactId}-jni"
+                groupId artifactGroupId
+                version pubVersion
+            }
+        }
+    }
+}
diff --git a/shared/jni/setupBuild.gradle b/shared/jni/setupBuild.gradle
new file mode 100644
index 0000000..a22a67d
--- /dev/null
+++ b/shared/jni/setupBuild.gradle
@@ -0,0 +1,279 @@
+apply plugin: 'cpp'
+apply plugin: 'google-test-test-suite'
+apply plugin: 'visual-studio'
+apply plugin: 'edu.wpi.first.NativeUtils'
+apply plugin: 'edu.wpi.first.GradleJni'
+apply plugin: SingleNativeBuild
+apply plugin: ExtraTasks
+
+apply from: "${rootDir}/shared/config.gradle"
+
+ext {
+    baseId = nativeName
+    groupId = "edu.wpi.first.${nativeName}"
+}
+
+apply from: "${rootDir}/shared/java/javacommon.gradle"
+
+dependencies {
+    compile project(':wpiutil')
+    devCompile project(':wpiutil')
+}
+
+project(':').libraryBuild.dependsOn build
+
+ext {
+    staticGtestConfigs = [:]
+}
+
+staticGtestConfigs["${nativeName}Test"] = []
+
+apply from: "${rootDir}/shared/googletest.gradle"
+
+if (project.hasProperty('niLibraries')) {
+    ext {
+        chipObjectComponents = ["$nativeName".toString(), "${nativeName}Dev".toString(), "${nativeName}Base".toString(),
+                                "${nativeName}JNI".toString(), "${nativeName}JNIShared".toString(), "${nativeName}Test".toString()]
+        netCommComponents = ["$nativeName".toString(), "${nativeName}Dev".toString(), "${nativeName}Base".toString(),
+                             "${nativeName}JNI".toString(), "${nativeName}JNIShared".toString(), "${nativeName}Test".toString()]
+        useNiJava = true
+    }
+
+    apply from: "${rootDir}/shared/nilibraries.gradle"
+}
+
+model {
+    components {
+        "${nativeName}Base"(NativeLibrarySpec) {
+            if (project.hasProperty('setBaseName')) {
+                baseName = setBaseName
+            }
+            sources {
+                cpp {
+                    source {
+                        srcDirs 'src/main/native/cpp'
+                        include '**/*.cpp'
+                        exclude '**/jni/*.cpp'
+                    }
+                    exportedHeaders {
+                        srcDir 'src/main/native/include'
+                        if (project.hasProperty('generatedHeaders')) {
+                            srcDir generatedHeaders
+                        }
+                        include '**/*.h'
+                    }
+                }
+            }
+            binaries.all {
+                if (it instanceof SharedLibraryBinarySpec) {
+                    it.buildable = false
+                    return
+                }
+                lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
+                if (project.hasProperty('splitSetup')) {
+                    splitSetup(it)
+                }
+            }
+        }
+        "${nativeName}"(NativeLibrarySpec) {
+            if (project.hasProperty('setBaseName')) {
+                baseName = setBaseName
+            }
+            sources {
+                cpp {
+                    source {
+                        srcDirs "${rootDir}/shared/singlelib"
+                        include '**/*.cpp'
+                    }
+                    exportedHeaders {
+                        srcDir 'src/main/native/include'
+                        if (project.hasProperty('generatedHeaders')) {
+                            srcDir generatedHeaders
+                        }
+                    }
+                }
+            }
+            binaries.all {
+                lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
+            }
+            appendDebugPathToBinaries(binaries)
+        }
+        "${nativeName}JNIShared"(JniNativeLibrarySpec) {
+            if (project.hasProperty('setBaseName')) {
+                baseName = setBaseName + 'jni'
+            } else {
+                baseName = nativeName + 'jni'
+            }
+            enableCheckTask true
+            javaCompileTasks << compileJava
+            jniCrossCompileOptions << JniCrossCompileOptions('athena')
+            jniCrossCompileOptions << JniCrossCompileOptions('raspbian')
+            sources {
+                cpp {
+                    source {
+                        srcDirs 'src/main/native/cpp'
+                        include '**/jni/*.cpp'
+                    }
+                    exportedHeaders {
+                        srcDir 'src/main/native/include'
+                        if (project.hasProperty('generatedHeaders')) {
+                            srcDir generatedHeaders
+                        }
+                        include '**/*.h'
+                    }
+
+                }
+            }
+            binaries.all {
+                if (it instanceof StaticLibraryBinarySpec) {
+                    it.buildable = false
+                    return
+                }
+                lib library: "${nativeName}", linkage: 'shared'
+                lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
+                if (project.hasProperty('jniSplitSetup')) {
+                    jniSplitSetup(it)
+                }
+            }
+        }
+        "${nativeName}JNI"(JniNativeLibrarySpec) {
+            if (project.hasProperty('setBaseName')) {
+                baseName = setBaseName + 'jni'
+            } else {
+                baseName = nativeName + 'jni'
+            }
+            enableCheckTask true
+            javaCompileTasks << compileJava
+            jniCrossCompileOptions << JniCrossCompileOptions('athena')
+            jniCrossCompileOptions << JniCrossCompileOptions('raspbian')
+            sources {
+                cpp {
+                    source {
+                        srcDirs 'src/main/native/cpp'
+                        include '**/jni/*.cpp'
+                    }
+                    exportedHeaders {
+                        srcDir 'src/main/native/include'
+                        if (project.hasProperty('generatedHeaders')) {
+                            srcDir generatedHeaders
+                        }
+                        include '**/*.h'
+                    }
+                }
+            }
+            binaries.all {
+                if (it instanceof StaticLibraryBinarySpec) {
+                    it.buildable = false
+                    return
+                }
+                lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
+                if (project.hasProperty('jniSplitSetup')) {
+                    jniSplitSetup(it)
+                }
+            }
+        }
+        // By default, a development executable will be generated. This is to help the case of
+        // testing specific functionality of the library.
+        "${nativeName}Dev"(NativeExecutableSpec) {
+            targetBuildTypes 'debug'
+            sources {
+                cpp {
+
+                    source {
+                        srcDirs 'src/dev/native/cpp'
+                        include '**/*.cpp'
+                    }
+                    exportedHeaders {
+                        srcDir 'src/main/native/include'
+                        if (project.hasProperty('generatedHeaders')) {
+                            srcDir generatedHeaders
+                        }
+                    }
+                }
+            }
+            binaries.all {
+                lib library: nativeName, linkage: 'shared'
+                lib library: "${nativeName}JNIShared", linkage: 'shared'
+                lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
+            }
+        }
+    }
+    testSuites {
+        "${nativeName}Test"(GoogleTestTestSuiteSpec) {
+            for(NativeComponentSpec c : $.components) {
+                if (c.name == nativeName) {
+                    testing c
+                    break
+                }
+            }
+            sources {
+                cpp {
+                    source {
+                        srcDirs 'src/test/native/cpp'
+                        include '**/*.cpp'
+                    }
+                    exportedHeaders {
+                        srcDirs 'src/test/native/include', 'src/main/native/cpp'
+                        if (project.hasProperty('generatedHeaders')) {
+                            srcDir generatedHeaders
+                        }
+                    }
+                }
+            }
+        }
+    }
+    binaries {
+        withType(GoogleTestTestSuiteBinarySpec) {
+            if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) {
+                lib library: nativeName, linkage: 'shared'
+                lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
+            } else {
+                it.buildable = false
+            }
+        }
+    }
+    tasks {
+        def c = $.components
+        project.tasks.create('runCpp', Exec) {
+            group = 'WPILib'
+            description = "Run the ${nativeName}Dev executable"
+            def found = false
+            def systemArch = getCurrentArch()
+            c.each {
+                if (it in NativeExecutableSpec && it.name == "${nativeName}Dev") {
+                    it.binaries.each {
+                        if (!found) {
+                            def arch = it.targetPlatform.architecture.name
+                            if (arch == systemArch) {
+                                dependsOn it.tasks.install
+                                commandLine it.tasks.install.runScriptFile.get().asFile.toString()
+                                def filePath = it.tasks.install.installDirectory.get().toString() + File.separatorChar + 'lib'
+                                test.dependsOn it.tasks.install
+                                test.systemProperty 'java.library.path', filePath
+                                test.environment 'LD_LIBRARY_PATH', filePath
+                                test.workingDir filePath
+                                run.dependsOn it.tasks.install
+                                run.systemProperty 'java.library.path', filePath
+                                run.environment 'LD_LIBRARY_PATH', filePath
+                                run.workingDir filePath
+
+                                found = true
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+ext.getJniSpecClass = {
+    return JniNativeLibrarySpec
+}
+
+tasks.withType(RunTestExecutable) {
+    args "--gtest_output=xml:test_detail.xml"
+    outputs.dir outputDir
+}
+
+apply from: "${rootDir}/shared/jni/publish.gradle"
diff --git a/shared/nilibraries.gradle b/shared/nilibraries.gradle
new file mode 100644
index 0000000..937abbf
--- /dev/null
+++ b/shared/nilibraries.gradle
@@ -0,0 +1,37 @@
+def netCommLibConfigs = [:];

+def chipObjectConfigs = [:];

+

+project.chipObjectComponents.each { String s->

+  chipObjectConfigs[s] = ['linux:athena']

+}

+

+project.netCommComponents.each { String s->

+  netCommLibConfigs[s] = ['linux:athena']

+}

+

+def niLibrariesVersion = '2019.12.1'

+

+model {

+  dependencyConfigs {

+    chipobject(DependencyConfig) {

+      groupId = 'edu.wpi.first.ni-libraries'

+      artifactId = 'chipobject'

+      headerClassifier = 'headers'

+      ext = 'zip'

+      version = niLibrariesVersion

+      sharedConfigs = chipObjectConfigs

+      staticConfigs = [:]

+      compileOnlyShared = true

+    }

+    netcomm(DependencyConfig) {

+      groupId = 'edu.wpi.first.ni-libraries'

+      artifactId = 'netcomm'

+      headerClassifier = 'headers'

+      ext = 'zip'

+      version = niLibrariesVersion

+      sharedConfigs = netCommLibConfigs

+      staticConfigs = [:]

+      compileOnlyShared = true

+    }

+  }

+}

diff --git a/shared/opencv.gradle b/shared/opencv.gradle
new file mode 100644
index 0000000..ee9403c
--- /dev/null
+++ b/shared/opencv.gradle
@@ -0,0 +1,30 @@
+def opencvVersion = '3.4.4-4'
+
+if (project.hasProperty('useCpp') && project.useCpp) {
+    model {
+        dependencyConfigs {
+            opencv(DependencyConfig) {
+                groupId = 'edu.wpi.first.thirdparty.frc2019.opencv'
+                artifactId = 'opencv-cpp'
+                headerClassifier = 'headers'
+                ext = 'zip'
+                version = opencvVersion
+                sharedConfigs = project.sharedCvConfigs
+                staticConfigs = project.staticCvConfigs
+                linkExcludes = ['**/*java*']
+            }
+        }
+    }
+}
+
+if (project.hasProperty('useJava') && project.useJava) {
+    dependencies {
+        compile "edu.wpi.first.thirdparty.frc2019.opencv:opencv-java:${opencvVersion}"
+        if (!project.hasProperty('skipDev') || !project.skipDev) {
+            devCompile "edu.wpi.first.thirdparty.frc2019.opencv:opencv-java:${opencvVersion}"
+        }
+        if (project.hasProperty('useDocumentation') && project.useDocumentation) {
+            javaSource "edu.wpi.first.thirdparty.frc2019.opencv:opencv-java:${opencvVersion}:sources"
+        }
+    }
+}
diff --git a/shared/plugins/publish.gradle b/shared/plugins/publish.gradle
new file mode 100644
index 0000000..a9ba538
--- /dev/null
+++ b/shared/plugins/publish.gradle
@@ -0,0 +1,82 @@
+apply plugin: 'maven-publish'
+
+def pubVersion = ''
+if (project.hasProperty("publishVersion")) {
+    pubVersion = project.publishVersion
+} else {
+    pubVersion = WPILibVersion.version
+}
+
+def baseArtifactId = pluginName
+def artifactGroupId = 'edu.wpi.first.halsim'
+def zipBaseName = "_GROUP_edu_wpi_first_halsim_ID_${pluginName}_CLS"
+
+def outputsFolder = file("$project.buildDir/outputs")
+
+task cppSourcesZip(type: Zip) {
+    destinationDir = outputsFolder
+    baseName = zipBaseName
+    classifier = "sources"
+
+    from(licenseFile) {
+        into '/'
+    }
+
+    from('src/main/native/cpp') {
+        into '/'
+    }
+}
+
+task cppHeadersZip(type: Zip) {
+    destinationDir = outputsFolder
+    baseName = zipBaseName
+    classifier = "headers"
+
+    from(licenseFile) {
+        into '/'
+    }
+
+    from('src/main/native/include') {
+        into '/'
+    }
+}
+
+build.dependsOn cppSourcesZip
+build.dependsOn cppHeadersZip
+
+addTaskToCopyAllOutputs(cppSourcesZip)
+addTaskToCopyAllOutputs(cppHeadersZip)
+
+
+model {
+    publishing {
+        def pluginTaskList = createComponentZipTasks($.components, [pluginName], zipBaseName, Zip, project, { task, value ->
+            value.each { binary ->
+                if (binary.buildable) {
+                    if (binary instanceof SharedLibraryBinarySpec) {
+                        task.dependsOn binary.buildTask
+                        task.from(binary.sharedLibraryFile) {
+                            into getPlatformPath(binary) + '/shared'
+                        }
+                    }
+                }
+            }
+        })
+
+        publications {
+            cpp(MavenPublication) {
+                pluginTaskList.each {
+                    artifact it
+                }
+
+                artifact cppHeadersZip
+                artifact cppSourcesZip
+
+
+                artifactId = baseArtifactId
+                groupId artifactGroupId
+                version pubVersion
+            }
+        }
+    }
+}
diff --git a/shared/plugins/setupBuild.gradle b/shared/plugins/setupBuild.gradle
new file mode 100644
index 0000000..ba4c6f0
--- /dev/null
+++ b/shared/plugins/setupBuild.gradle
@@ -0,0 +1,110 @@
+apply plugin: 'cpp'
+apply plugin: 'edu.wpi.first.NativeUtils'
+apply plugin: ExtraTasks
+
+ext {
+    chipObjectComponents = ["$pluginName".toString(), "${pluginName}Dev".toString(), "${pluginName}Test".toString()]
+    netCommComponents = ["$pluginName".toString(), "${pluginName}Dev".toString(), "${pluginName}Test".toString()]
+    useNiJava = false
+}
+
+apply from: "${rootDir}/shared/nilibraries.gradle"
+
+if (!project.hasProperty('onlyAthena')) {
+    ext.skipAthena = true
+    apply from: "${rootDir}/shared/config.gradle"
+
+    model {
+        components {
+            "${pluginName}"(NativeLibrarySpec) {
+                sources {
+                    cpp {
+                        source {
+                            srcDirs = ['src/main/native/cpp']
+                            includes = ["**/*.cpp"]
+                        }
+                        exportedHeaders {
+                            srcDirs = ["src/main/native/include"]
+                        }
+                    }
+                }
+                binaries.all {
+                    if (it instanceof StaticLibraryBinarySpec) {
+                        it.buildable = false
+                        return
+                    }
+                    project(':hal').addHalDependency(it, 'shared')
+                    if (project.hasProperty('includeNtCore')) {
+                        lib project: ':ntcore', library: 'ntcore', linkage: 'shared'
+                    }
+                    if (project.hasProperty('includeWpiutil')) {
+                        lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
+                    }
+                }
+                appendDebugPathToBinaries(binaries)
+            }
+            "${pluginName}Dev"(NativeExecutableSpec) {
+                targetBuildTypes 'debug'
+                sources {
+                    cpp {
+                        source {
+                            srcDirs = ['src/dev/native/cpp']
+                            includes = ["**/*.cpp"]
+                        }
+                        exportedHeaders {
+                            srcDirs = ["src/dev/native/include"]
+                        }
+                    }
+                }
+                binaries.all {
+                    if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) {
+                        project(':hal').addHalDependency(it, 'shared')
+                        lib library: pluginName
+                        if (project.hasProperty('includeNtCore')) {
+                            lib project: ':ntcore', library: 'ntcore', linkage: 'shared'
+                        }
+                        lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
+                    } else {
+                        it.buildable = false
+                    }
+                }
+            }
+        }
+    }
+
+    apply from: "${rootDir}/shared/plugins/publish.gradle"
+}
+
+model {
+    tasks {
+        def c = $.components
+        if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) {
+            project.tasks.create('runCpp', Exec) {
+                group = 'WPILib'
+                description = "Run the ${pluginName}Dev executable"
+                def found = false
+                def systemArch = getCurrentArch()
+                c.each {
+                    if (it in NativeExecutableSpec && it.name == "${pluginName}Dev") {
+                        it.binaries.each {
+                            if (!found) {
+                                def arch = it.targetPlatform.architecture.name
+                                if (arch == systemArch) {
+                                    dependsOn it.tasks.install
+                                    commandLine it.tasks.install.runScriptFile.get().asFile.toString()
+                                    // it.tasks.install.libs.each { lib ->
+                                    //     if (lib.name.contains(pluginName)) {
+                                    //         def filePath = it.tasks.install.installDirectory.get().toString() + File.separatorChar + 'lib' + File.separatorChar + lib.name
+                                    //         environment('HALSIM_EXTENSIONS', filePath)
+                                    //     }
+                                    // }
+                                    found = true
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/shared/resources.gradle b/shared/resources.gradle
new file mode 100644
index 0000000..21da736
--- /dev/null
+++ b/shared/resources.gradle
@@ -0,0 +1,50 @@
+ext.createGenerateResourcesTask = { name, prefix, namespace, project ->
+    def generatedOutputDir = file("$buildDir/generated/$name/cpp")
+
+    def inputDir = file("$projectDir/src/$name/native/resources")
+
+    if (!prefix.isEmpty()) prefix += '_'
+
+    def task = project.tasks.create("generateResources-$name") {
+        outputs.dir generatedOutputDir
+        inputs.dir inputDir
+
+        doLast {
+            generatedOutputDir.mkdirs()
+            inputDir.eachFile { inputFile ->
+                if (inputFile.name.startsWith('.')) return
+                def fileBytes = inputFile.bytes
+                def outputFile = file("$generatedOutputDir/${inputFile.name}.cpp")
+                def funcName = "GetResource_" + inputFile.name.replaceAll('[^a-zA-Z0-9]', '_')
+                outputFile.withWriter { out ->
+                    def inputBytes = inputFile.bytes
+                    out.print '''#include <stddef.h>
+#include <wpi/StringRef.h>
+extern "C" {
+static const unsigned char contents[] = { '''
+
+                    for (int i = 0; i < fileBytes.size(); i++) {
+                        out.print String.format('0x%02x', (int) fileBytes[i] & 0xff)
+                        out.print ', '
+                    }
+                    out.println """};
+const unsigned char* ${prefix}${funcName}(size_t* len) {
+  *len = ${fileBytes.size()};
+  return contents;
+}
+}"""
+                    if (!namespace.isEmpty()) {
+                        out.println "namespace ${namespace} {"
+                    }
+                    out.println """wpi::StringRef ${funcName}() {
+  return wpi::StringRef(reinterpret_cast<const char*>(contents), ${fileBytes.size()});
+}"""
+                    if (!namespace.isEmpty()) {
+                        out.println '}'
+                    }
+                }
+            }
+        }
+    }
+    return task
+}
diff --git a/shared/singlelib/singlelib.cpp b/shared/singlelib/singlelib.cpp
new file mode 100644
index 0000000..6c9476a
--- /dev/null
+++ b/shared/singlelib/singlelib.cpp
@@ -0,0 +1,6 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/