Files
allwpilib/wpiutil/build.gradle
Redrield 7e95010a29 Add compile-time EJML matrix wrapper to wpiutil (#1804)
This adds a wrapper over EJML's SimpleMatrix that uses generated classes representing numbers to encode the dimensions of each matrix at compile time, and to check operations between matrices for validity at compile time, rather than failing with an exception at runtime. This is required for the Java implementation of state-space control.

Additions to the wpiutil gradle script, and a python script at the wpiutil root are used to generate numeric types from a template at build time for both gradle and cmake. Users will be able to access types through functions on the Nat class.
2019-08-18 15:00:40 -07:00

295 lines
10 KiB
Groovy

apply from: "${rootDir}/shared/resources.gradle"
ext {
baseId = 'wpiutil'
groupId = 'edu.wpi.first.wpiutil'
nativeName = 'wpiutil'
devMain = 'edu.wpi.first.wpiutil.DevMain'
def generateTask = createGenerateResourcesTask('main', 'WPI', 'wpi', project)
extraSetup = {
it.tasks.withType(CppCompile) {
dependsOn generateTask
}
it.sources {
libuvCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/libuv/src'
include '*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/libuv/include', 'src/main/native/libuv/src'
}
}
resourcesCpp(CppSourceSet) {
source {
srcDirs "$buildDir/generated/main/cpp", "$rootDir/shared/singlelib"
include '*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include'
}
}
}
if (!it.targetPlatform.operatingSystem.isWindows()) {
it.cppCompiler.define '_GNU_SOURCE'
it.sources {
libuvUnixCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/libuv/src/unix'
includes = [
'async.cpp',
'core.cpp',
'dl.cpp',
'fs.cpp',
'getaddrinfo.cpp',
'getnameinfo.cpp',
'loop-watcher.cpp',
'loop.cpp',
'pipe.cpp',
'poll.cpp',
'process.cpp',
'signal.cpp',
'stream.cpp',
'tcp.cpp',
'thread.cpp',
'timer.cpp',
'tty.cpp',
'udp.cpp',
]
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/libuv/include', 'src/main/native/libuv/src'
}
}
wpiutilUnixCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/unix'
include '**/*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/cpp'
include '**/*.h'
}
}
}
}
if (it.targetPlatform.operatingSystem.isWindows()) {
if (it in SharedLibraryBinarySpec) {
it.cppCompiler.define 'BUILDING_UV_SHARED'
}
it.sources {
libuvWindowsCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/libuv/src/win'
include '*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/libuv/include', 'src/main/native/libuv/src'
}
}
wpiutilWindowsCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/windows'
include '**/*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/cpp'
include '**/*.h'
}
}
}
} else if (it.targetPlatform.operatingSystem.isMacOsX()) {
it.sources {
libuvMacCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/libuv/src/unix'
includes = [
'bsd-ifaddrs.cpp',
'darwin.cpp',
'darwin-proctitle.cpp',
'fsevents.cpp',
'kqueue.cpp',
'proctitle.cpp'
]
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/libuv/include', 'src/main/native/libuv/src'
}
}
}
} else {
it.sources {
libuvLinuxCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/libuv/src/unix'
includes = [
'linux-core.cpp',
'linux-inotify.cpp',
'linux-syscalls.cpp',
'procfs-exepath.cpp',
'proctitle.cpp',
'sysinfo-loadavg.cpp',
]
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/libuv/include', 'src/main/native/libuv/src'
}
}
}
}
}
}
def examplesMap = [:];
file("$projectDir/examples").list(new FilenameFilter() {
@Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
}).each {
examplesMap.put(it, [])
}
apply from: "${rootDir}/shared/javacpp/setupBuild.gradle"
nativeUtils.exportsConfigs {
wpiutil {
x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
}
}
cppHeadersZip {
from('src/main/native/libuv/include') {
into '/'
}
}
model {
components {
all {
it.sources.each {
it.exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/libuv/include', 'src/main/native/libuv/src'
}
}
}
}
}
model {
components {
examplesMap.each { key, value ->
"${key}"(NativeExecutableSpec) {
targetBuildTypes 'debug'
binaries.all {
lib library: 'wpiutil', linkage: 'shared'
}
sources {
cpp {
source {
srcDirs 'examples/' + "${key}"
include '**/*.cpp'
}
}
}
}
}
netconsoleServer(NativeExecutableSpec) {
targetBuildTypes 'release'
sources {
cpp {
source {
srcDirs = ['src/netconsoleServer/native/cpp']
includes = ['**/*.cpp']
}
}
}
binaries.all { binary ->
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
if (binary.targetPlatform.operatingSystem.isLinux()) {
linker.args "-lutil"
}
}
}
netconsoleTee(NativeExecutableSpec) {
targetBuildTypes 'release'
sources {
cpp {
source {
srcDirs = ['src/netconsoleTee/native/cpp']
includes = ['**/*.cpp']
}
}
}
binaries.all { binary ->
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
}
}
}
}
dependencies {
compile "org.ejml:ejml-simple:0.38"
}
def wpilibNumberFileInput = file("src/generate/GenericNumber.java.in")
def natFileInput = file("src/generate/Nat.java.in")
def natGetterInput = file("src/generate/NatGetter.java.in")
def wpilibNumberFileOutputDir = file("$buildDir/generated/java/edu/wpi/first/wpiutil/math/numbers")
def wpilibNatFileOutput = file("$buildDir/generated/java/edu/wpi/first/wpiutil/math/Nat.java")
def maxNum = 20
task generateNumbers() {
description = "Generates generic number classes from template"
group = "WPILib"
inputs.file wpilibNumberFileInput
doLast {
if(wpilibNumberFileOutputDir.exists()) {
wpilibNumberFileOutputDir.delete()
}
wpilibNumberFileOutputDir.mkdirs()
for(i in 0..maxNum) {
def outputFile = new File(wpilibNumberFileOutputDir, "N${i}.java")
def read = wpilibNumberFileInput.text.replace('${num}', i.toString())
outputFile.write(read)
}
}
}
task generateNat() {
description = "Generates Nat.java"
group = "WPILib"
inputs.files([natFileInput, natGetterInput])
dependsOn generateNumbers
doLast {
if(wpilibNatFileOutput.exists()) {
wpilibNatFileOutput.delete()
}
def template = natFileInput.text + "\n"
for(i in 0..maxNum) {
template += natGetterInput.text.replace('${num}', i.toString()) + "\n"
}
template += "}\n" // Close the class body
wpilibNatFileOutput.write(template)
}
}
sourceSets.main.java.srcDir "${buildDir}/generated/java"
compileJava.dependsOn generateNumbers
compileJava.dependsOn generateNat