/* * SwerveIO - A versatile open-source FRC swerve drive library. * * Copyright (C) 2019-2024 Jordan Bancino * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published with this * source code. You should have received a copy of the GNU General Public * License with this program. If you did not, contact the distributors of * this program and view it here: https://bancino.net/licenses/gpl-3.0.txt * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */ /* * SwerveIO core build script. This is the master build script that holds the common * project configuration for all SwerveIO subprojects, as well as the main SwerveIO * core project. */ import org.apache.tools.ant.taskdefs.condition.Os def versions = [ 'SwerveIO': '8.0.3', 'WPILib': '2023.4.3', 'OpenCV': '4.6.0-4', 'Jackson': '2.12.4' ] /* Not all "projects" are actual projects. This filters out the ones that aren't. */ def matchProject = { Project proj -> return file("${proj.getProjectDir()}/build.gradle").exists() } /* * Check if there is an internet connection. This is used to dynamically * disable build functionality that requires a connection, because those * functions will fail when we are at a competition. * * This function checks if the --offline was specified before attempting to * establish a connection. */ def isOnline = { /* If we know we're in offline mode, we already know the answer. */ if (project.getGradle().startParameter.isOffline()) { return false } else { /* There may or may not be an available internet connection. */ try { final URL url = new URL("http://wpilib.org") final URLConnection conn = url.openConnection() conn.connect() conn.getInputStream().close() return true } catch (MalformedURLException e) { throw new RuntimeException(e) } catch (IOException e) { return false } } } /* Add external javadoc links if an internet connection is available. */ def javadocAddLinks = { Project proj, String... urls -> if (isOnline()) { configure (proj) { javadoc { for (String url : urls) { options.getLinks().add(url) } } } } } /* Execute a command on the operating system. */ def osExec = { String command, List arguments -> new ByteArrayOutputStream().withStream { OutputStream os -> exec { executable = command args = arguments standardOutput = os } return os.toString() } } def lsRecursive lsRecursive = {File dir, String matches -> def list = [] dir.listFiles().sort().each { File file -> if (file.isFile()) { if (file.getName().matches(matches)) { list += file } } else { list += lsRecursive(file, matches) } } return list } /* Export methods and variables to subprojects. */ rootProject.ext.versions = versions rootProject.ext.isOnline = isOnline rootProject.ext.javadocAddLinks = javadocAddLinks /* Root project tasks */ task updateHeaders() { doLast { def header = file("${projectDir}/header.txt") def patch = file("${projectDir}/header.patch") patch.text = osExec('git', ['diff', "$header"]) if (!patch.text.isEmpty()) { def patchFiles = lsRecursive(file("${projectDir}"), '^.*\\.(gradle|java)$') for (File file : patchFiles) { println "Patching '$file'..." osExec('patch', ["$file", "$patch"]) } def deleteFiles = lsRecursive(file("${projectDir}"), '^.*\\.orig$') for (File file : deleteFiles) { file.delete() } osExec('git', ['commit', "$header", '-m', 'Update header.']) } else { println "Headers up to date." } patch.delete() } } /* Common configuration for all projects. */ configure(allprojects.findAll { matchProject(it) }) { /* Java plugins */ apply plugin: 'java-library' apply plugin: 'maven-publish' /* Maven metadata */ group = 'net.bancino.robotics' version = versions.SwerveIO java { /* Java 11 */ sourceCompatibility = 11 targetCompatibility = 11 } /* * SwerveIO doesn't need any of this stuff without internet. This * will dramatically speed up the time it takes to build SwerveIO, * which can be helpful at competitions when things need to happen * quickly. */ if (isOnline()) { /* Maven jars - for documentation and IDE support. */ java { withJavadocJar() withSourcesJar() } /* All Javadocs should link to the standard Javadoc, and the WPILib Javadoc */ javadocAddLinks(project, 'https://docs.oracle.com/en/java/javase/11/docs/api/', 'https://github.wpilib.org/allwpilib/docs/release/java/' ) } /* All artifacts go to the root repo. */ def repoUrl = "${rootProject.buildDir}/repo" /* Publish to a local repo that can be published separately. */ publishing { publications { /* Artifact is derived from the project name. */ mavenJava(MavenPublication) { artifactId = project.getName() from project.components.java } } repositories { maven { url = repoUrl } } } /* Common Javadoc configuration. */ javadoc { options.overview = "${projectDir}/src/javadoc/overview.html" options.setWindowTitle("${project.getName()} ${project.version} User Documentation") /* All javadocs go to the root directory. */ options.destinationDirectory(file("${rootProject.docsDir}/${project.getName()}")) } /* * Dependency repositories. All repositories must be shared across all projects so that they can include * each other without duplicating the repository requirements. */ repositories { /* Jackson XML */ mavenCentral() /* WPILib */ maven { url 'https://frcmaven.wpi.edu/artifactory/release' } /* Vendor: CTRE */ maven { url 'https://maven.ctr-electronics.com/release' } /* Vendor: RevRobotics */ maven { url 'https://maven.revrobotics.com/' } /* Vendor: KauaiLabs */ maven { url 'https://dev.studica.com/maven/release/2023/' } } /* Generate GradleRIO vendor Json files that can be dropped into vendordeps/ */ task generateVendorJson() { def jsonFile = "${project.getName()}.json" def repoList = { def str = "" repositories.each { str += "\"${it.url}\", " } return str.substring(0, str.length() - 2) } def outputDir = file(repoUrl) doLast { outputDir.mkdirs() file("${outputDir}/${jsonFile}").text = """{ "cppDependencies": [], "fileName": "${jsonFile}", "javaDependencies": [ { "artifactId": "${project.getName()}", "groupId": "${project.group}", "version": "${version}" } ], "jniDependencies": [], "jsonUrl": "", "mavenUrls": [ ${repoList()} ], "name": "${project.getName()}", "uuid": "${project.group}:${project.getName()}", "version": "${version}" } """ } } /* When publishing Maven artifacts, also generate vendor JSON. */ publish.dependsOn generateVendorJson /* All common dependencies go here. */ dependencies { /* WPILib */ api "edu.wpi.first.wpilibj:wpilibj-java:${versions.WPILib}" api "edu.wpi.first.wpilibNewCommands:wpilibNewCommands-java:${versions.WPILib}" api "edu.wpi.first.wpimath:wpimath-java:${versions.WPILib}" /* * The SwerveIO core itself doesn't use these artifacts, but the vendor dependencies, * included in the subprojects may, so we include them here to ensure that they are the * same version across the board. I noticed, for example, that the NavX library would * pull older versions of these artifacts than what SwerveIO was using, so we do this to * make everything line up. */ api "edu.wpi.first.cscore:cscore-java:${versions.WPILib}" api "edu.wpi.first.cameraserver:cameraserver-java:${versions.WPILib}" api "edu.wpi.first.ntcore:ntcore-java:${versions.WPILib}" api "edu.wpi.first.wpiutil:wpiutil-java:${versions.WPILib}" api "edu.wpi.first.hal:hal-java:${versions.WPILib}" /* Required by WPILib - Make sure this lines up with the version specified by WPILib */ api "edu.wpi.first.thirdparty.frc2023.opencv:opencv-java:${versions.OpenCV}" /* Required by WPILib - Gradle emits warnings if this isn't included. */ implementation "com.fasterxml.jackson.core:jackson-annotations:${versions.Jackson}" /* Unit testing */ testImplementation 'org.junit.jupiter:junit-jupiter-api:+' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:+' /* Convert OS into WPILib platform */ def platform if (Os.isFamily(Os.FAMILY_WINDOWS)) { platform = 'windowsx86-64' } else if (Os.isFamily(Os.FAMILY_MAC)) { platform = 'osxx86-64' } else if (Os.isFamily(Os.FAMILY_UNIX)) { platform = 'linuxx86-64' } else { throw new GradleException("Unrecognized operating system.") } /* JNI stuff so WPILib can run on the desktop. */ testImplementation "edu.wpi.first.thirdparty.frc2023.opencv:opencv-jni:${versions.OpenCV}:${platform}@jar" testImplementation "edu.wpi.first.hal:hal-jni:${versions.WPILib}:${platform}@jar" testImplementation "edu.wpi.first.wpiutil:wpiutil-jni:${versions.WPILib}:${platform}@jar" testImplementation "edu.wpi.first.ntcore:ntcore-jni:${versions.WPILib}:${platform}@jar" testImplementation "edu.wpi.first.cscore:cscore-jni:${versions.WPILib}:${platform}@jar" } test { useJUnitPlatform() testLogging { showStandardStreams = true } } } /* Common configuration for subprojects only. */ configure(subprojects.findAll { matchProject(it) }) { /* All subprojects depend on the core SwerveIO project */ dependencies { api rootProject } }