Squashed 'third_party/allwpilib/' content from commit b0167e633
Change-Id: I5653017a690eec1917e8fff9017195d8af307926
git-subtree-dir: third_party/allwpilib
git-subtree-split: b0167e6337135545e7053acb89dd5726accc7dec
diff --git a/shared/config.gradle b/shared/config.gradle
new file mode 100644
index 0000000..7952018
--- /dev/null
+++ b/shared/config.gradle
@@ -0,0 +1,144 @@
+import org.gradle.internal.os.OperatingSystem
+
+nativeUtils.addWpiNativeUtils()
+nativeUtils.withRoboRIO()
+nativeUtils.withRaspbian()
+nativeUtils.withBionic()
+nativeUtils {
+ wpi {
+ configureDependencies {
+ wpiVersion = "-1"
+ niLibVersion = "2020.10.1"
+ opencvVersion = "3.4.7-2"
+ googleTestVersion = "1.9.0-4-437e100-1"
+ imguiVersion = "1.72b-2"
+ }
+ }
+}
+
+nativeUtils.wpi.addWarnings()
+nativeUtils.wpi.addWarningsAsErrors()
+
+nativeUtils.setSinglePrintPerPlatform()
+
+model {
+ components {
+ all {
+ nativeUtils.useAllPlatforms(it)
+ }
+ }
+ binaries {
+ withType(NativeBinarySpec).all {
+ nativeUtils.usePlatformArguments(it)
+ }
+ }
+}
+
+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 = nativeUtils.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
+ destinationDirectory = outputsFolder
+ classifier = key
+ archiveBaseName = '_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.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 nativeUtils.getPlatformPath(binary) + '/shared'
+ }
+ def sharedPath = binary.sharedLibraryFile.absolutePath
+ sharedPath = sharedPath.substring(0, sharedPath.length() - 4)
+
+ task.from(new File(sharedPath + '.pdb')) {
+ into nativeUtils.getPlatformPath(binary) + '/shared'
+ }
+ task.from(binary.sharedLibraryFile) {
+ into nativeUtils.getPlatformPath(binary) + '/shared'
+ }
+ task.from(binary.sharedLibraryLinkFile) {
+ into nativeUtils.getPlatformPath(binary) + '/shared'
+ }
+ } else if (binary instanceof StaticLibraryBinarySpec) {
+ task.dependsOn binary.tasks.createStaticLib
+ task.from(binary.staticLibraryFile) {
+ into nativeUtils.getPlatformPath(binary) + '/static'
+ }
+ }
+ }
+ }
+}
diff --git a/shared/cppDesktopTestTask.gradle b/shared/cppDesktopTestTask.gradle
new file mode 100644
index 0000000..04b7224
--- /dev/null
+++ b/shared/cppDesktopTestTask.gradle
@@ -0,0 +1,21 @@
+model {
+ tasks {
+ def ts = $.testSuites
+ project.tasks.register('testDesktopCpp') { testTask->
+ def systemArch = getCurrentArch()
+ def found = false
+ ts.each {
+ if (it in GoogleTestTestSuiteSpec && it.name == "${nativeName}Test") {
+ it.binaries.each {
+ if (found) return
+ def arch = it.targetPlatform.name
+ if (arch == systemArch && it.buildType.name == 'debug') {
+ testTask.dependsOn it.tasks.run
+ found = true
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/shared/examplecheck.gradle b/shared/examplecheck.gradle
new file mode 100644
index 0000000..3d05c67
--- /dev/null
+++ b/shared/examplecheck.gradle
@@ -0,0 +1,86 @@
+def fileCheck = { parsedJson, folder ->
+ def folderNames = parsedJson.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 {
+ def parsedJson = new groovy.json.JsonSlurper().parseText(templateFile.text)
+ fileCheck(parsedJson, templateDirectory)
+ parsedJson.each {
+ assert it.name != null
+ assert it.description != null
+ assert it.tags != null
+ assert it.foldername != null
+ assert it.gradlebase != null
+ assert it.commandversion != null
+ if (it.gradlebase == 'java') {
+ assert it.mainclass != null
+ }
+ }
+ }
+}
+
+task checkExamples(type: Task) {
+ doLast {
+ def parsedJson = new groovy.json.JsonSlurper().parseText(exampleFile.text)
+ fileCheck(parsedJson, exampleDirectory)
+ parsedJson.each {
+ assert it.name != null
+ assert it.description != null
+ assert it.tags != null
+ assert it.foldername != null
+ assert it.gradlebase != null
+ assert it.commandversion != null
+ if (it.gradlebase == 'java') {
+ assert it.mainclass != null
+ }
+ }
+ }
+}
+
+task checkCommands(type: Task) {
+ doLast {
+ def parsedJson = new groovy.json.JsonSlurper().parseText(commandFile.text)
+ fileCheck(parsedJson, commandDirectory)
+ parsedJson.each {
+ assert it.name != null
+ assert it.description != null
+ assert it.tags != null
+ assert it.foldername != null
+ assert it.replacename != null
+ assert it.commandversion != null
+ if (project.isCppCommands) {
+ assert it.headers != null
+ assert !it.headers.isEmpty()
+ assert it.source != null
+ assert !it.source.isEmpty()
+ }
+ }
+ }
+}
+
+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..ab3b51f
--- /dev/null
+++ b/shared/googletest.gradle
@@ -0,0 +1,7 @@
+model {
+ binaries {
+ withType(GoogleTestTestSuiteBinarySpec).all {
+ nativeUtils.useRequiredLibrary(it, 'googletest_static')
+ }
+ }
+}
diff --git a/shared/java/javacommon.gradle b/shared/java/javacommon.gradle
new file mode 100644
index 0000000..d83ead2
--- /dev/null
+++ b/shared/java/javacommon.gradle
@@ -0,0 +1,130 @@
+apply plugin: 'maven-publish'
+apply plugin: 'java-library'
+//apply plugin: 'net.ltgt.errorprone'
+apply plugin: 'jacoco'
+
+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) {
+ archiveBaseName = javaBaseName
+ destinationDirectory = outputsFolder
+ from sourceSets.main.output
+}
+
+task outputSourcesJar(type: Jar, dependsOn: classes) {
+ archiveBaseName = javaBaseName
+ destinationDirectory = outputsFolder
+ classifier = 'sources'
+ from sourceSets.main.allSource
+}
+
+task outputJavadocJar(type: Jar, dependsOn: javadoc) {
+ archiveBaseName = javaBaseName
+ destinationDirectory = 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 wpilibVersioning.version.get()
+ }
+ }
+}
+
+test {
+ useJUnitPlatform()
+ systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true'
+ testLogging {
+ events "failed"
+ exceptionFormat "full"
+ }
+ finalizedBy jacocoTestReport
+}
+
+if (project.hasProperty('onlylinuxathena') || project.hasProperty('onlylinuxraspbian') || project.hasProperty('onlylinuxaarch64bionic')) {
+ test.enabled = false
+}
+
+repositories {
+ mavenCentral()
+ //maven.url "https://oss.sonatype.org/content/repositories/snapshots/"
+}
+
+sourceSets {
+ dev
+}
+
+tasks.withType(JavaCompile).configureEach {
+ options.compilerArgs = ['--release', '11']
+}
+
+dependencies {
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'
+ testImplementation 'org.junit.jupiter:junit-jupiter-params:5.4.2'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'
+
+ devImplementation 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
+
+jacoco {
+ toolVersion = "0.8.4"
+}
+
+jacocoTestReport {
+ reports {
+ xml.enabled true
+ html.enabled true
+ }
+}
diff --git a/shared/java/javastyle.gradle b/shared/java/javastyle.gradle
new file mode 100644
index 0000000..eec3796
--- /dev/null
+++ b/shared/java/javastyle.gradle
@@ -0,0 +1,20 @@
+
+apply plugin: 'checkstyle'
+
+checkstyle {
+ toolVersion = "8.12"
+ configDirectory = file("${project.rootDir}/styleguide")
+ config = resources.text.fromFile(new File(configDirectory.get().getAsFile(), "checkstyle.xml"))
+}
+
+if (!project.hasProperty('skipPMD')) {
+ apply plugin: 'pmd'
+
+ 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/javaDesktopTestTask.gradle b/shared/javaDesktopTestTask.gradle
new file mode 100644
index 0000000..766fa50
--- /dev/null
+++ b/shared/javaDesktopTestTask.gradle
@@ -0,0 +1,3 @@
+tasks.register('testDesktopJava') {
+ dependsOn test
+}
diff --git a/shared/javacpp/publish.gradle b/shared/javacpp/publish.gradle
new file mode 100644
index 0000000..5002def
--- /dev/null
+++ b/shared/javacpp/publish.gradle
@@ -0,0 +1,65 @@
+apply plugin: 'maven-publish'
+
+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) {
+ destinationDirectory = outputsFolder
+ archiveBaseName = zipBaseName
+ classifier = "sources"
+
+ from(licenseFile) {
+ into '/'
+ }
+
+ from('src/main/native/cpp') {
+ into '/'
+ }
+}
+
+task cppHeadersZip(type: Zip) {
+ destinationDirectory = outputsFolder
+ archiveBaseName = 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 wpilibVersioning.version.get()
+ }
+ }
+ }
+}
diff --git a/shared/javacpp/setupBuild.gradle b/shared/javacpp/setupBuild.gradle
new file mode 100644
index 0000000..04086ad
--- /dev/null
+++ b/shared/javacpp/setupBuild.gradle
@@ -0,0 +1,152 @@
+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) {
+ lib library: nativeName, linkage: 'shared'
+ }
+ }
+ 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.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
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+apply from: "${rootDir}/shared/cppDesktopTestTask.gradle"
+apply from: "${rootDir}/shared/javaDesktopTestTask.gradle"
+
+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..765302a
--- /dev/null
+++ b/shared/jni/publish.gradle
@@ -0,0 +1,114 @@
+import java.security.MessageDigest
+apply plugin: 'maven-publish'
+
+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) {
+ destinationDirectory = outputsFolder
+ archiveBaseName = 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) {
+ destinationDirectory = outputsFolder
+ archiveBaseName = 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 nativeUtils.getPlatformPath(binary)
+ }
+ task.doFirst {
+ hashFile.text = MessageDigest.getInstance("MD5").digest(binary.sharedLibraryFile.bytes).encodeHex().toString()
+ }
+ task.from(binary.sharedLibraryFile) {
+ into nativeUtils.getPlatformPath(binary)
+ }
+ }
+ }
+ }
+ })
+
+ publications {
+ cpp(MavenPublication) {
+ taskList.each {
+ artifact it
+ }
+ artifact cppHeadersZip
+ artifact cppSourcesZip
+
+ artifactId = "${baseArtifactId}-cpp"
+ groupId artifactGroupId
+ version wpilibVersioning.version.get()
+ }
+ jni(MavenPublication) {
+ jniTaskList.each {
+ artifact it
+ }
+
+ artifactId = "${baseArtifactId}-jni"
+ groupId artifactGroupId
+ version wpilibVersioning.version.get()
+ }
+ }
+ }
+}
diff --git a/shared/jni/setupBuild.gradle b/shared/jni/setupBuild.gradle
new file mode 100644
index 0000000..6c6148c
--- /dev/null
+++ b/shared/jni/setupBuild.gradle
@@ -0,0 +1,290 @@
+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 {
+ if (!project.hasProperty('noWpiutil')) {
+ implementation project(':wpiutil')
+ devImplementation project(':wpiutil')
+ }
+}
+
+project(':').libraryBuild.dependsOn build
+
+ext {
+ staticGtestConfigs = [:]
+}
+
+staticGtestConfigs["${nativeName}Test"] = []
+
+apply from: "${rootDir}/shared/googletest.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
+ }
+ if (!project.hasProperty('noWpiutil')) {
+ 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
+ }
+ }
+ }
+ }
+ if (!project.hasProperty('noWpiutil')) {
+ 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(nativeUtils.wpi.platforms.roborio)
+ jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.raspbian)
+ jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.aarch64bionic)
+ 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'
+ if (!project.hasProperty('noWpiutil')) {
+ 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(nativeUtils.wpi.platforms.roborio)
+ jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.raspbian)
+ jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.aarch64bionic)
+ 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
+ }
+ if (!project.hasProperty('noWpiutil')) {
+ 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'
+ if (!project.hasProperty('noWpiutil')) {
+ lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
+ }
+ if (nativeName == 'hal' && it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
+ nativeUtils.useRequiredLibrary(it, 'netcomm_shared', 'chipobject_shared', 'visa_shared', 'ni_runtime_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) {
+ lib library: nativeName, linkage: 'shared'
+ if (!project.hasProperty('noWpiutil')) {
+ lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
+ if (nativeName == 'hal' && it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
+ nativeUtils.useRequiredLibrary(it, 'netcomm_shared', 'chipobject_shared', 'visa_shared', 'ni_runtime_shared')
+ }
+ }
+ }
+ }
+ 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.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
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+apply from: "${rootDir}/shared/cppDesktopTestTask.gradle"
+apply from: "${rootDir}/shared/javaDesktopTestTask.gradle"
+
+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/opencv.gradle b/shared/opencv.gradle
new file mode 100644
index 0000000..ca3764d
--- /dev/null
+++ b/shared/opencv.gradle
@@ -0,0 +1,33 @@
+def opencvVersion = '3.4.7-2'
+
+if (project.hasProperty('useCpp') && project.useCpp) {
+ model {
+ binaries {
+ withType(NativeBinarySpec).all {
+ def binary = it
+ project.sharedCvConfigs.each {
+ if (binary.component.name == it.key) {
+ nativeUtils.useRequiredLibrary(binary, 'opencv_shared')
+ }
+ }
+ project.staticCvConfigs.each {
+ if (binary.component.name == it.key) {
+ nativeUtils.useRequiredLibrary(binary, 'opencv_static')
+ }
+ }
+ }
+ }
+ }
+}
+
+if (project.hasProperty('useJava') && project.useJava) {
+ dependencies {
+ implementation "edu.wpi.first.thirdparty.frc2020.opencv:opencv-java:${opencvVersion}"
+ if (!project.hasProperty('skipDev') || !project.skipDev) {
+ devImplementation "edu.wpi.first.thirdparty.frc2020.opencv:opencv-java:${opencvVersion}"
+ }
+ if (project.hasProperty('useDocumentation') && project.useDocumentation) {
+ javaSource "edu.wpi.first.thirdparty.frc2020.opencv:opencv-java:${opencvVersion}:sources"
+ }
+ }
+}
diff --git a/shared/plugins/publish.gradle b/shared/plugins/publish.gradle
new file mode 100644
index 0000000..ec160ed
--- /dev/null
+++ b/shared/plugins/publish.gradle
@@ -0,0 +1,75 @@
+apply plugin: 'maven-publish'
+
+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) {
+ destinationDirectory = outputsFolder
+ archiveBaseName = zipBaseName
+ classifier = "sources"
+
+ from(licenseFile) {
+ into '/'
+ }
+
+ from('src/main/native/cpp') {
+ into '/'
+ }
+}
+
+task cppHeadersZip(type: Zip) {
+ destinationDirectory = outputsFolder
+ archiveBaseName = 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 nativeUtils.getPlatformPath(binary) + '/shared'
+ }
+ }
+ }
+ }
+ })
+
+ publications {
+ cpp(MavenPublication) {
+ pluginTaskList.each {
+ artifact it
+ }
+
+ artifact cppHeadersZip
+ artifact cppSourcesZip
+
+
+ artifactId = baseArtifactId
+ groupId artifactGroupId
+ version wpilibVersioning.version.get()
+ }
+ }
+ }
+}
diff --git a/shared/plugins/setupBuild.gradle b/shared/plugins/setupBuild.gradle
new file mode 100644
index 0000000..af9b4c4
--- /dev/null
+++ b/shared/plugins/setupBuild.gradle
@@ -0,0 +1,105 @@
+apply plugin: 'cpp'
+apply plugin: 'edu.wpi.first.NativeUtils'
+apply plugin: ExtraTasks
+
+if (!project.hasProperty('onlylinuxathena')) {
+ ext.skiplinuxathena = 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('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) {
+ 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'
+ if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
+ nativeUtils.useRequiredLibrary(it, 'netcomm_shared', 'chipobject_shared', 'visa_shared', 'ni_runtime_shared')
+ }
+ } else {
+ it.buildable = false
+ }
+ }
+ }
+ }
+ }
+
+ apply from: "${rootDir}/shared/plugins/publish.gradle"
+}
+
+model {
+ tasks {
+ def c = $.components
+ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) {
+ 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.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. */
+/*----------------------------------------------------------------------------*/