Files
allwpilib/docs/build.gradle

307 lines
9.6 KiB
Groovy
Raw Normal View History

plugins {
id 'java'
id "org.ysb33r.doxygen" version "0.7.0"
}
evaluationDependsOn(':apriltag')
evaluationDependsOn(':cameraserver')
evaluationDependsOn(':cscore')
evaluationDependsOn(':hal')
evaluationDependsOn(':ntcore')
evaluationDependsOn(':wpilibNewCommands')
evaluationDependsOn(':wpilibc')
evaluationDependsOn(':wpilibj')
evaluationDependsOn(':wpimath')
evaluationDependsOn(':wpinet')
[wpiunits] Add subproject for a Java typesafe unit system (#5371) # Background Unit safety has always been a problem in WPILib. Any value corresponding to a physical measurement, such as current draw or distance traveled, is represented by a bare number with no unit tied to it; it's up to the programmer to know what units they're working and take care to remember that while working on their robot program. This leads to bugs when programmers accidentally mix units without knowing, or measure something (such as a wheel diameter) in one unit and program using another. `wpiunits` is intended to eliminate that class of bugs. Another source of friction is the controllers and models in `wpimath` that expect all inputs to be in terms of SI units (meter, kilogram, and so on), while most FRC teams are US-based and most commonly use imperial units. wpimath does a good job of noting unit types in method names and argument names; however, it still relies on users properly converting values (and knowing they even have to do so). # API There are really only two core classes in this library: `Unit` and `Measure`. A `Unit` represents some dimension like distance or time. `Unit` is subclassed to define specific dimensions (eg `Distance` and `Time`) and those subclasses are instantiated to defined particular units in those dimensions, such as `Meters` and `Feet` being instances of the `Distance` class. A `Measure` is a value tied to a particular dimension like distance and knows what unit that value is tied to. `Measure` has two implementations - one immutable and one mutable. The `Measure` interface only defines *read-only* operations; any API working with measurements should use the interface. The default implementation is `ImmutableMeasure`, which only implements those read-only operations and is useful for tracking constants. `MutableMeasure` also adds some methods that will allow for mutation of its internal state; this class is intended for use for things like sensors and controllers that track internal state and don't want to allocate new `Measure` objects every time something like `myEncoder.getDistance()` is called. However, the APIs for those methods should still only expose the read-only `Measure` interface so users can't (without casting or reflection) change the internal values. A `Units` class provides convenient definitions for most of the commonly used unit types, such as `Meters`, `Feet`, and `Milliseconds`. I recommend static importing these units eg `import static edu.wpi.first.units.Units.Meters`) so they can be used like `Meters.of(1.234)` instead of `Units.Meters.of(1.234)` # Examples These examples are admittedly contrived. Users shouldn't be interacting much with measure objects themselves, since wpimath and wpilibj classes will be updated to support working with them; users will often just have to take a `Measure` output from one place (such as an encoder) and feed it as input to something else (such as a PID controller or kinematics model) ```java // Using raw units Encoder encoder = ... int kPulsesPerRev = 2048; double kWheelDiameterMeters = Units.inchesToMeters(6); double kGearRatio = 10.86; // always have to remember this encoder will output in meters! encoder.setDistancePerPulse(kWheelDiameterMeters * Math.PI / (kGearRatio * kPulsesPerRev)); Command driveDistance(double distance) { // have to know the distance argument needs to be in meters! return run(this::driveStraight).until(() -> encoder.getDistance() >= distance); } // Oops! This will go 16 feet, not 5! Command driveFiveFeet = driveDistance(5); Command driveOneMeter = driveDistance(1); ``` ```java // Using wpiunits Encoder encoder = ... int kPulsesPerRev = 2048; Measure<Distance> kWheelDiameter = Inches.of(6); double kGearRatio = 10.86; encoder.setDistancePerPulse(kWheelDiameter.times(Math.PI).divide(kGearRatio * kPulsesPerRev)); Command driveDistance(Measure<Distance> distance) { // Measure#gte automatically handles unit conversions return run(this::driveStraight).until(() -> encoder.getDistance().gte(distance)); } // Users HAVE to be explicit about their units Command driveFiveFeet = driveDistance(Feet.of(5)); Command driveOneMeter = driveDistance(Meters.of(1)); ``` ```java SmartDashboard.putNumber("Temperature (C)", pdp.getTemperature().in(Celsius)); SmartDashboard.putNumber("Temperature (F)", pdp.getTemperature().in(Fahrenheit)); ``` ```java var InchSecond = Inch.mult(Second); // new combined unit types can be user-defined var InchPerSecond = Inch.per(Second); PIDController<Distance, ElectricPotential> heightController = new PIDController<>( /* kP */ Volts.of(0.2).per(Inch), /* kI */ Volts.of(0.002).per(InchSecond), /* kD */ Volts.of(0.008).per(InchPerSecond) ); var elevatorTop = Feet.of(4).plus(Inches.of(6.125)); elevatorMotor.setVoltage(heightController.calculate(encoder.getDistance(), elevatorTop)); ```
2023-07-23 17:18:17 -04:00
evaluationDependsOn(':wpiunits')
evaluationDependsOn(':wpiutil')
def baseArtifactIdCpp = 'documentation'
def artifactGroupIdCpp = 'edu.wpi.first.wpilibc'
def zipBaseNameCpp = '_GROUP_edu_wpi_first_wpilibc_ID_documentation_CLS'
def baseArtifactIdJava = 'documentation'
def artifactGroupIdJava = 'edu.wpi.first.wpilibj'
def zipBaseNameJava = '_GROUP_edu_wpi_first_wpilibj_ID_documentation_CLS'
def outputsFolder = file("$project.buildDir/outputs")
def cppProjectZips = []
def cppIncludeRoots = []
cppProjectZips.add(project(':apriltag').cppHeadersZip)
cppProjectZips.add(project(':cameraserver').cppHeadersZip)
cppProjectZips.add(project(':cscore').cppHeadersZip)
cppProjectZips.add(project(':hal').cppHeadersZip)
cppProjectZips.add(project(':ntcore').cppHeadersZip)
cppProjectZips.add(project(':wpilibNewCommands').cppHeadersZip)
cppProjectZips.add(project(':wpilibc').cppHeadersZip)
cppProjectZips.add(project(':wpimath').cppHeadersZip)
cppProjectZips.add(project(':wpinet').cppHeadersZip)
cppProjectZips.add(project(':wpiutil').cppHeadersZip)
doxygen {
// Doxygen binaries are only provided for x86_64 platforms
// Other platforms will need to provide doxygen via their system
// See below maven and https://doxygen.nl/download.html for provided binaries
String arch = System.getProperty("os.arch");
if (arch.equals("x86_64") || arch.equals("amd64")) {
executables {
doxygen version : '1.9.4',
baseURI : 'https://frcmaven.wpi.edu/artifactory/generic-release-mirror/doxygen'
}
}
}
doxygen {
generate_html true
html_extra_stylesheet 'theme.css'
cppProjectZips.each {
dependsOn it
source it.source
it.ext.includeDirs.each {
cppIncludeRoots.add(it.absolutePath)
}
}
cppIncludeRoots << '../ntcore/build/generated/main/native/include/'
if (project.hasProperty('docWarningsAsErrors')) {
// Eigen
exclude 'Eigen/**'
exclude 'unsupported/**'
// LLVM
exclude 'wpi/AlignOf.h'
exclude 'wpi/Casting.h'
exclude 'wpi/Chrono.h'
exclude 'wpi/Compiler.h'
exclude 'wpi/ConvertUTF.h'
exclude 'wpi/DenseMap.h'
exclude 'wpi/DenseMapInfo.h'
exclude 'wpi/Endian.h'
exclude 'wpi/EpochTracker.h'
exclude 'wpi/Errc.h'
exclude 'wpi/Errno.h'
exclude 'wpi/ErrorHandling.h'
exclude 'wpi/bit.h'
exclude 'wpi/fs.h'
exclude 'wpi/FunctionExtras.h'
exclude 'wpi/function_ref.h'
exclude 'wpi/Hashing.h'
exclude 'wpi/iterator.h'
exclude 'wpi/iterator_range.h'
exclude 'wpi/ManagedStatic.h'
exclude 'wpi/MapVector.h'
exclude 'wpi/MathExtras.h'
exclude 'wpi/MemAlloc.h'
exclude 'wpi/PointerIntPair.h'
exclude 'wpi/PointerLikeTypeTraits.h'
exclude 'wpi/PointerUnion.h'
exclude 'wpi/raw_os_ostream.h'
exclude 'wpi/raw_ostream.h'
exclude 'wpi/SmallPtrSet.h'
exclude 'wpi/SmallSet.h'
exclude 'wpi/SmallString.h'
exclude 'wpi/SmallVector.h'
exclude 'wpi/StringExtras.h'
exclude 'wpi/StringMap.h'
exclude 'wpi/SwapByteOrder.h'
exclude 'wpi/type_traits.h'
exclude 'wpi/VersionTuple.h'
exclude 'wpi/WindowsError.h'
// fmtlib
exclude 'fmt/**'
// libuv
exclude 'uv.h'
exclude 'uv/**'
exclude 'wpinet/uv/**'
// json
exclude 'wpi/adl_serializer.h'
exclude 'wpi/byte_container_with_subtype.h'
exclude 'wpi/detail/**'
exclude 'wpi/json.h'
exclude 'wpi/json_fwd.h'
exclude 'wpi/ordered_map.h'
exclude 'wpi/thirdparty/**'
// memory
exclude 'wpi/memory/**'
// mpack
exclude 'wpi/mpack.h'
// units
exclude 'units/**'
}
//TODO: building memory docs causes search to break
exclude 'wpi/memory/**'
exclude '*.pb.h'
// Save space by excluding protobuf and eigen
exclude 'Eigen/**'
exclude 'google/protobuf/**'
aliases 'effects=\\par <i>Effects:</i>^^',
'notes=\\par <i>Notes:</i>^^',
'requires=\\par <i>Requires:</i>^^',
'requiredbe=\\par <i>Required Behavior:</i>^^',
'concept{2}=<a href=\"md_doc_concepts.html#\1\">\2</a>',
'defaultbe=\\par <i>Default Behavior:</i>^^'
case_sense_names false
extension_mapping 'inc=C++', 'no_extension=C++'
extract_all true
extract_static true
file_patterns '*'
full_path_names true
generate_html true
generate_latex false
generate_treeview true
html_extra_stylesheet 'theme.css'
html_timestamp true
javadoc_autobrief true
project_name 'WPILibC++'
project_logo '../wpiutil/src/main/native/resources/wpilib-128.png'
project_number wpilibVersioning.version.get()
quiet true
recursive true
strip_code_comments false
strip_from_inc_path cppIncludeRoots as String[]
strip_from_path cppIncludeRoots as String[]
use_mathjax true
warnings false
warn_if_incomplete_doc true
warn_if_undocumented false
warn_no_paramdoc true
//enable doxygen preprocessor expansion of WPI_DEPRECATED to fix MotorController docs
enable_preprocessing true
macro_expansion true
expand_only_predef true
predefined "WPI_DEPRECATED(x)=[[deprecated(x)]]\"\\\n" +
"\"__cplusplus\"\\\n" +
"\"HAL_ENUM(name)=enum name : int32_t"
if (project.hasProperty('docWarningsAsErrors')) {
warn_as_error 'FAIL_ON_WARNINGS'
}
}
tasks.register("zipCppDocs", Zip) {
2019-11-12 17:14:04 -08:00
archiveBaseName = zipBaseNameCpp
destinationDirectory = outputsFolder
dependsOn doxygen
from ("$buildDir/docs/doxygen/html")
into '/'
}
// Java
configurations {
javaSource {
transitive false
}
}
ext {
sharedCvConfigs = [:]
staticCvConfigs = [:]
useJava = true
useCpp = false
skipDev = true
useDocumentation = true
}
apply from: "${rootDir}/shared/opencv.gradle"
task generateJavaDocs(type: Javadoc) {
classpath += project(":wpimath").sourceSets.main.compileClasspath
options.links("https://docs.oracle.com/en/java/javase/17/docs/api/")
options.addStringOption("tag", "pre:a:Pre-Condition")
options.addBooleanOption("Xdoclint:html,missing,reference,syntax", true)
options.addBooleanOption('html5', true)
options.linkSource(true)
dependsOn project(':wpilibj').generateJavaVersion
source project(':apriltag').sourceSets.main.java
source project(':cameraserver').sourceSets.main.java
source project(':cscore').sourceSets.main.java
source project(':hal').sourceSets.main.java
source project(':ntcore').sourceSets.main.java
source project(':wpilibNewCommands').sourceSets.main.java
source project(':wpilibj').sourceSets.main.java
source project(':wpimath').sourceSets.main.java
source project(':wpinet').sourceSets.main.java
source project(':wpiunits').sourceSets.main.java
source project(':wpiutil').sourceSets.main.java
source configurations.javaSource.collect { zipTree(it) }
include '**/*.java'
failOnError = true
title = "WPILib API ${wpilibVersioning.version.get()}"
ext.entryPoint = "$destinationDir/index.html"
if (JavaVersion.current().isJava8Compatible() && project.hasProperty('docWarningsAsErrors')) {
// Treat javadoc warnings as errors.
//
2023-02-26 15:06:37 -08:00
// The second argument '-quiet' is a hack. The one parameter
// addStringOption() doesn't work, so we add '-quiet', which is added
// anyway by gradle. See https://github.com/gradle/gradle/issues/2354.
//
// See JDK-8200363 (https://bugs.openjdk.java.net/browse/JDK-8200363)
// for information about the nonstandard -Xwerror option. JDK 15+ has
// -Werror.
options.addStringOption('Xwerror', '-quiet')
}
if (JavaVersion.current().isJava11Compatible()) {
if (!JavaVersion.current().isJava12Compatible()) {
options.addBooleanOption('-no-module-directories', true)
}
doLast {
// This is a work-around for https://bugs.openjdk.java.net/browse/JDK-8211194. Can be removed once that issue is fixed on JDK's side
// Since JDK 11, package-list is missing from javadoc output files and superseded by element-list file, but a lot of external tools still need it
// Here we generate this file manually
new File(destinationDir, 'package-list').text = new File(destinationDir, 'element-list').text
}
}
}
tasks.register("zipJavaDocs", Zip) {
2019-11-12 17:14:04 -08:00
archiveBaseName = zipBaseNameJava
destinationDirectory = outputsFolder
dependsOn generateJavaDocs
from ("$buildDir/docs/javadoc")
into '/'
}
tasks.register("zipDocs") {
dependsOn zipCppDocs
dependsOn zipJavaDocs
}
apply plugin: 'maven-publish'
publishing {
publications {
java(MavenPublication) {
artifact zipJavaDocs
artifactId = "${baseArtifactIdJava}"
groupId artifactGroupIdJava
version wpilibVersioning.version.get()
}
cpp(MavenPublication) {
artifact zipCppDocs
artifactId = "${baseArtifactIdCpp}"
groupId artifactGroupIdCpp
version wpilibVersioning.version.get()
}
}
}