mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-21 01:01:41 +00:00
Initial framework for adding JNI libraries. Auto generated JNI headers and sticks native libraries into the JAR (and adds to class path for testing)
342 lines
12 KiB
Groovy
342 lines
12 KiB
Groovy
plugins {
|
|
id 'edu.wpi.first.WpilibTools' version '1.3.0'
|
|
}
|
|
|
|
import java.nio.file.Path
|
|
|
|
ext {
|
|
nativeName = "photonlib"
|
|
includePhotonTargeting = true
|
|
// Include the generated Version file
|
|
generatedHeaders = "src/generate/native/include"
|
|
}
|
|
|
|
apply plugin: 'cpp'
|
|
apply plugin: 'google-test-test-suite'
|
|
apply plugin: 'edu.wpi.first.NativeUtils'
|
|
|
|
apply from: "${rootDir}/shared/config.gradle"
|
|
apply from: "${rootDir}/shared/javacommon.gradle"
|
|
|
|
apply from: "${rootDir}/versioningHelper.gradle"
|
|
|
|
nativeUtils {
|
|
exportsConfigs {
|
|
"${nativeName}" {
|
|
// From https://github.com/wpilibsuite/allwpilib/blob/a32589831184969939fd3d63f449a2788a0a8542/wpimath/build.gradle#L72
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
// the WPILib BSD license file in the root directory of this project.
|
|
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'
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
model {
|
|
components {
|
|
"${nativeName}"(NativeLibrarySpec) {
|
|
sources {
|
|
cpp {
|
|
source {
|
|
srcDirs 'src/main/native/cpp', "$buildDir/generated/source/proto/main/cpp", "src/generate/native/cpp"
|
|
include '**/*.cpp', '**/*.cc'
|
|
}
|
|
exportedHeaders {
|
|
srcDirs 'src/main/native/include', "$buildDir/generated/source/proto/main/cpp"
|
|
if (project.hasProperty('generatedHeaders')) {
|
|
srcDir generatedHeaders
|
|
}
|
|
include "**/*.h"
|
|
}
|
|
}
|
|
}
|
|
|
|
binaries.all {
|
|
it.tasks.withType(CppCompile) {
|
|
it.dependsOn generateProto
|
|
}
|
|
if(project.hasProperty('includePhotonTargeting')) {
|
|
lib project: ':photon-targeting', library: 'photontargeting', linkage: 'shared'
|
|
}
|
|
}
|
|
|
|
nativeUtils.useRequiredLibrary(it, "wpilib_shared")
|
|
nativeUtils.useRequiredLibrary(it, "apriltag_shared")
|
|
nativeUtils.useRequiredLibrary(it, "opencv_shared")
|
|
nativeUtils.useRequiredLibrary(it, "cscore_shared")
|
|
nativeUtils.useRequiredLibrary(it, "cameraserver_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', "$buildDir/generated/source/proto/main/cpp"
|
|
}
|
|
}
|
|
}
|
|
|
|
binaries.all {
|
|
it.tasks.withType(CppCompile) {
|
|
it.dependsOn generateProto
|
|
}
|
|
if(project.hasProperty('includePhotonTargeting')) {
|
|
lib project: ':photon-targeting', library: 'photontargeting', linkage: 'shared'
|
|
}
|
|
}
|
|
|
|
nativeUtils.useRequiredLibrary(it, "cscore_shared")
|
|
nativeUtils.useRequiredLibrary(it, "cameraserver_shared")
|
|
nativeUtils.useRequiredLibrary(it, "wpilib_executable_shared")
|
|
nativeUtils.useRequiredLibrary(it, "googletest_static")
|
|
nativeUtils.useRequiredLibrary(it, "apriltag_shared")
|
|
nativeUtils.useRequiredLibrary(it, "opencv_shared")
|
|
}
|
|
}
|
|
|
|
tasks {
|
|
def c = $.testSuites
|
|
project.tasks.create('runCpp', Exec) {
|
|
description = "Run the photon-lib executable"
|
|
def found = false
|
|
def systemArch = getCurrentArch()
|
|
c.each {
|
|
if (it in GoogleTestTestSuiteSpec && it.name == "${nativeName}Test") {
|
|
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.environment 'DYLD_LIBRARY_PATH', filePath
|
|
test.workingDir filePath
|
|
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
apply from: "${rootDir}/shared/javacpp/publish.gradle"
|
|
|
|
// Include the version file in the distributed sources
|
|
cppHeadersZip {
|
|
from('src/generate/native/include') {
|
|
into '/'
|
|
}
|
|
}
|
|
|
|
def photonlibFileInput = file("src/generate/photonlib.json.in")
|
|
ext.photonlibFileOutput = file("$buildDir/generated/vendordeps/photonlib.json")
|
|
|
|
task generateVendorJson() {
|
|
description = "Generates the vendor JSON file"
|
|
group = "PhotonVision"
|
|
|
|
outputs.file photonlibFileOutput
|
|
inputs.file photonlibFileInput
|
|
|
|
println "Writing vendor JSON ${pubVersion} to $photonlibFileOutput"
|
|
|
|
if (photonlibFileOutput.exists()) {
|
|
photonlibFileOutput.delete()
|
|
}
|
|
photonlibFileOutput.parentFile.mkdirs()
|
|
|
|
def read = photonlibFileInput.text
|
|
.replace('${photon_version}', pubVersion)
|
|
.replace('${frc_year}', frcYear)
|
|
photonlibFileOutput.text = read
|
|
|
|
outputs.upToDateWhen { false }
|
|
}
|
|
|
|
build.mustRunAfter generateVendorJson
|
|
publish.mustRunAfter generateVendorJson
|
|
|
|
task publishVendorJsonToLocalOutputs(type: Copy) {
|
|
from photonlibFileOutput
|
|
into "$allOutputsFolder/vendordeps/"
|
|
|
|
// Rename to match the name of the JSON we publish to maven to avoid user confusion
|
|
rename { String fileName ->
|
|
fileName.replace(".json", "-json-1.0.json")
|
|
}
|
|
|
|
publish.dependsOn it
|
|
}
|
|
|
|
task writeCurrentVersion {
|
|
def versionFileIn = file("${rootDir}/shared/PhotonVersion.java.in")
|
|
writePhotonVersionFile(versionFileIn, Path.of("$projectDir", "src", "main", "java", "org", "photonvision", "PhotonVersion.java"),
|
|
versionString)
|
|
versionFileIn = file("${rootDir}/shared/PhotonVersion.cpp.in")
|
|
writePhotonVersionFile(versionFileIn, Path.of("$projectDir", "src", "generate", "native", "cpp", "PhotonVersion.cpp"),
|
|
versionString)
|
|
}
|
|
|
|
build.mustRunAfter writeCurrentVersion
|
|
cppHeadersZip.dependsOn writeCurrentVersion
|
|
|
|
// Building photon-lib requires photon-targeting to generate its proto files. This technically shouldn't be required but is needed for it to build.
|
|
model {
|
|
components {
|
|
all {
|
|
it.sources.each {
|
|
it.exportedHeaders {
|
|
srcDirs "src/main/native/include"
|
|
srcDirs "src/generate/native/include"
|
|
}
|
|
}
|
|
it.binaries.all {
|
|
it.tasks.withType(CppCompile) {
|
|
it.dependsOn ":photon-targeting:generateProto"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
testSuites {
|
|
all {
|
|
it.binaries.all {
|
|
it.tasks.withType(CppCompile) {
|
|
it.dependsOn ":photon-targeting:generateProto"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
def vendorJson = artifacts.add('archives', file("$photonlibFileOutput"))
|
|
|
|
if (!project.hasProperty('copyOfflineArtifacts')) {
|
|
// Publish the vendordep json
|
|
publishing {
|
|
publications {
|
|
vendorjson(MavenPublication) {
|
|
artifact vendorJson
|
|
|
|
artifactId = "${nativeName}-json"
|
|
groupId = "org.photonvision"
|
|
version "1.0"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add photonversion to cpp sources zip
|
|
tasks.named('cppSourcesZip') {
|
|
dependsOn writeCurrentVersion
|
|
|
|
from("$projectDir/src/generate/native/cpp") {
|
|
into '/'
|
|
}
|
|
}
|
|
|
|
// Publish an uberzip with photon-lib and photon-targeting. This makes python binding easier to have it in one place
|
|
def zipBaseNameCombined = '_GROUP_org.photonvision_combinedcpp_ID_photonvision-combinedcpp_CLS'
|
|
task combinedCppSourcesZip(type: Zip) {
|
|
dependsOn(':photon-lib:cppSourcesZip', ':photon-targeting:cppSourcesZip')
|
|
mustRunAfter(':photon-lib:cppHeadersZip', ':photon-targeting:cppHeadersZip')
|
|
|
|
destinationDirectory = file("$buildDir/outputs")
|
|
archiveBaseName = zipBaseNameCombined
|
|
archiveClassifier = "sources"
|
|
|
|
// Include the contents of the photon-lib cppSourcesZip. Magic chatgpt nonsense
|
|
from(zipTree(project(':photon-lib').tasks.cppSourcesZip.archiveFile.get().asFile)) {
|
|
into 'photon-lib'
|
|
}
|
|
from(zipTree(project(':photon-targeting').tasks.cppSourcesZip.archiveFile.get().asFile)) {
|
|
into 'photon-targeting'
|
|
}
|
|
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
}
|
|
task combinedHeadersZip(type: Zip) {
|
|
dependsOn(':photon-lib:cppHeadersZip', ':photon-targeting:cppHeadersZip')
|
|
mustRunAfter(':photon-lib:cppHeadersZip', ':photon-targeting:cppHeadersZip')
|
|
|
|
destinationDirectory = file("$buildDir/outputs")
|
|
archiveBaseName = zipBaseNameCombined
|
|
archiveClassifier = "headers"
|
|
|
|
// Include the contents of the photon-lib cppHeadersZip. Magic chatgpt nonsense
|
|
from(zipTree(project(':photon-lib').tasks.cppHeadersZip.archiveFile.get().asFile)) {
|
|
into 'photon-lib'
|
|
}
|
|
from(zipTree(project(':photon-targeting').tasks.cppHeadersZip.archiveFile.get().asFile)) {
|
|
into 'photon-targeting'
|
|
}
|
|
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
}
|
|
|
|
// Add the uberzip to our maven publications
|
|
publishing {
|
|
publications {
|
|
// Don't publish if we're creating an offline zip
|
|
if (!project.hasProperty('copyOfflineArtifacts')) {
|
|
combinedcpp(MavenPublication) {
|
|
artifact combinedCppSourcesZip
|
|
artifact combinedHeadersZip
|
|
|
|
artifactId = "${nativeName}-combinedcpp"
|
|
groupId artifactGroupId
|
|
version pubVersion
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// setup wpilib bundled native libs
|
|
wpilibTools.deps.wpilibVersion = wpi.versions.wpilibVersion.get()
|
|
|
|
def nativeConfigName = 'wpilibNatives'
|
|
def nativeConfig = configurations.create(nativeConfigName)
|
|
|
|
def nativeTasks = wpilibTools.createExtractionTasks {
|
|
configurationName = nativeConfigName
|
|
}
|
|
|
|
nativeTasks.addToSourceSetResources(sourceSets.test)
|
|
|
|
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpimath")
|
|
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpinet")
|
|
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpiutil")
|
|
nativeConfig.dependencies.add wpilibTools.deps.wpilib("ntcore")
|
|
nativeConfig.dependencies.add wpilibTools.deps.wpilib("cscore")
|
|
nativeConfig.dependencies.add wpilibTools.deps.wpilib("apriltag")
|
|
nativeConfig.dependencies.add wpilibTools.deps.wpilib("hal")
|
|
nativeConfig.dependencies.add wpilibTools.deps.wpilibOpenCv("frc" + wpi.frcYear.get(), wpi.versions.opencvVersion.get())
|