Files
PhotonVision/photon-lib/build.gradle
Sam Freund 68fc1e7129 Make 2027 build (#2422)
This PR updates everything for 2027. This includes removing GradleRIO, simplifying our wpilib version defintion, updating APIs, updating to Java 21, and more.

Note that photonlibpy is failing because robotpy has not been fully updated yet. Examples are omitted because they need to be updated for our new PhotonPoseEstimator API and still need some changes from WPILIB. photonlib windows build is failing because we're waiting for some upstream changes. Finally, images are failing since they don't have Java 21 yet.
2026-04-11 12:23:14 -05:00

379 lines
13 KiB
Groovy

apply plugin: 'org.photonvision.tools.WpilibTools'
import java.nio.file.Path
ext {
nativeName = "photonlib"
includePhotonTargeting = true
// Include the generated Version file
generatedHeaders = "src/generate/native/include"
licenseFile = file("LICENSE")
}
apply plugin: 'cpp'
apply plugin: 'google-test-test-suite'
apply plugin: 'org.wpilib.NativeUtils'
apply from: "${rootDir}/shared/config.gradle"
apply from: "${rootDir}/shared/javacommon.gradle"
apply from: "${rootDir}/versioningHelper.gradle"
nativeUtils {
exportsConfigs {
"${nativeName}" {}
}
}
model {
components {
"${nativeName}"(NativeLibrarySpec) {
sources {
cpp {
source {
srcDirs 'src/main/native/cpp', "$buildDir/generated/source/proto/main/cpp", "$buildDir/generated/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'
lib project: ':photon-targeting', library: 'photontargetingJNI', linkage: 'shared'
}
}
nativeUtils.useRequiredLibrary(it, "datalog_shared")
nativeUtils.useRequiredLibrary(it, "cscore_shared")
nativeUtils.useRequiredLibrary(it, "cameraserver_shared")
nativeUtils.useRequiredLibrary(it, "wpilib_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.dependsOn 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 copyVendorJsonToExamples {
outputs.upToDateWhen { false }
jar.finalizedBy it
}
[
"photonlib-cpp-examples",
"photonlib-java-examples"
].each { exampleFolder ->
file("${rootDir}/${exampleFolder}")
.listFiles()
.findAll {
return (it.isDirectory()
&& !it.isHidden()
&& !it.name.startsWith(".")
&& it.toPath().resolve("build.gradle").toFile().exists())
}
.collect { it.name }
.each { exampleVendordepFolder ->
task "copyVendorJsonTo${exampleFolder}-${exampleVendordepFolder}"(type: Copy) {
from photonlibFileOutput
into "${rootDir}/${exampleFolder}/${exampleVendordepFolder}/vendordeps/"
outputs.upToDateWhen { false }
copyVendorJsonToExamples.dependsOn it
}
}
}
clean {
[
"photonlib-cpp-examples",
"photonlib-java-examples"
].each { exampleFolder ->
file("${rootDir}/${exampleFolder}")
.listFiles()
.findAll {
return (it.isDirectory()
&& !it.isHidden()
&& !it.name.startsWith(".")
&& it.toPath().resolve("build.gradle").toFile().exists())
}
.collect { it.name }
.each { exampleVendordepFolder ->
delete "${rootDir}/${exampleFolder}/${exampleVendordepFolder}/vendordeps/"
}
}
}
task writeCurrentVersion {
doLast {
def versionFileIn = file("${rootDir}/shared/PhotonVersion.java.in")
writePhotonVersionFile(versionFileIn, Path.of("$buildDir", "generated", "java", "org", "photonvision", "PhotonVersion.java"),
versionString)
versionFileIn = file("${rootDir}/shared/PhotonVersion.cpp.in")
writePhotonVersionFile(versionFileIn, Path.of("$buildDir", "generated", "native", "cpp", "PhotonVersion.cpp"),
versionString)
}
}
// https://github.com/wpilibsuite/allwpilib/blob/main/wpilibj/build.gradle#L52
sourceSets.main.java.srcDir "${buildDir}/generated/java/"
compileJava.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 writeCurrentVersion
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("$buildDir/generated/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')
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')
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 = wpilibVersion
def nativeConfigName = 'wpilibNatives'
def nativeConfig = configurations.create(nativeConfigName)
def nativeTasks = wpilibTools.createExtractionTasks {
configurationName = nativeConfigName
}
nativeTasks.addToSourceSetResources(sourceSets.test)
dependencies {
wpilibNatives project(":photon-targeting")
}
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("datalog")
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" + openCVYear, openCVversion)