Files
allwpilib/shared/jni/setupBuild.gradle
Peter Johnson cf54d9ccb7 [wpiutil, ntcore] Add structured data support (#5391)
This adds support for two serialization formats for complex data types:

- Protobuf for complex objects with variable length internals that need forward and backward wire compatibility (lower speed, more flexible)
- Raw struct (ByteBuffer-style) for fixed-length objects (higher speed, less flexible)

Deserialization can be done either by creating a new object (for immutable objects) or overwriting the contents of an existing object (for mutable objects).

Implementing classes should provide inner classes that implement the Protobuf or Struct interface (in Java) or specialize the wpi::Protobuf or wpi::Struct struct (in C++). It is possible for classes to implement both. If the class itself does not implement serialization, it's possible for third parties/users to provide an implementation instead.

Uses the Google protobuf implementation for C++ and the QuickBuffers alternative protobuf implementation for Java.
2023-10-19 21:41:47 -07:00

343 lines
13 KiB
Groovy

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', "$buildDir/generated/source/proto/main/cpp"
if (project.hasProperty('generatedSources')) {
srcDir generatedSources
}
include '**/*.cpp', '**/*.cc'
exclude '**/jni/**/*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', "$buildDir/generated/source/proto/main/cpp"
if (project.hasProperty('generatedHeaders')) {
srcDir generatedHeaders
}
include '**/*.h'
}
}
}
binaries.all {
if (it instanceof SharedLibraryBinarySpec) {
it.buildable = false
return
}
it.cppCompiler.define 'WPILIB_EXPORTS'
it.cCompiler.define 'WPILIB_EXPORTS'
if (!project.hasProperty('noWpiutil')) {
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
}
it.tasks.withType(CppCompile) {
it.dependsOn generateProto
}
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'
}
if (project.hasProperty('skipJniSymbols')) {
checkSkipSymbols = skipJniSymbols
}
enableCheckTask !project.hasProperty('skipJniCheck')
javaCompileTasks << compileJava
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.roborio)
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm32)
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm64)
sources {
cpp {
source {
srcDirs 'src/main/native/cpp'
if (project.hasProperty('generatedSources')) {
srcDir generatedSources
}
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'
}
if (project.hasProperty('skipJniSymbols')) {
checkSkipSymbols = skipJniSymbols
}
enableCheckTask !project.hasProperty('skipJniCheck')
javaCompileTasks << compileJava
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.roborio)
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm32)
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm64)
sources {
cpp {
source {
srcDirs 'src/main/native/cpp'
if (project.hasProperty('generatedSources')) {
srcDir generatedSources
}
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'
lib project: ':wpiutil', library: 'wpiutilJNIShared', linkage: 'shared'
if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
nativeUtils.useRequiredLibrary(it, 'ni_link_libraries', 'ni_runtime_libraries')
}
}
if (project.hasProperty('exeSplitSetup')) {
exeSplitSetup(it)
}
}
}
"${nativeName}TestLib"(NativeLibrarySpec) {
sources {
cpp {
source {
srcDirs 'src/testlib/native/cpp'
include '**/*.cpp'
}
exportedHeaders {
srcDirs 'src/test/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'
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'
lib project: ':wpiutil', library: 'wpiutilTestLib', linkage: 'shared'
if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
nativeUtils.useRequiredLibrary(it, 'ni_link_libraries', 'ni_runtime_libraries')
}
}
if (project.hasProperty('exeSplitSetup')) {
exeSplitSetup(it)
}
}
}
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
if (project.hasProperty('buildServer')) {
def folderDir = it.tasks.install.installDirectory.get().toString()
test.doLast {
def folder = file(folderDir)
folder.deleteDir()
}
}
test.systemProperty 'java.library.path', filePath
test.environment 'LD_LIBRARY_PATH', filePath
test.environment 'DYLD_LIBRARY_PATH', filePath
test.workingDir filePath
run.dependsOn it.tasks.install
run.systemProperty 'java.library.path', filePath
run.environment 'LD_LIBRARY_PATH', filePath
run.environment 'DYLD_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"