From aa221597bc8a5bf618f9916fcfd4063251965a29 Mon Sep 17 00:00:00 2001 From: Thad House Date: Mon, 20 Jun 2022 11:28:46 -0700 Subject: [PATCH] [build] Add M1 builds, change arm name, update to 2023 deps (#4315) --- .github/workflows/gradle.yml | 12 ++--- README.md | 2 +- build.gradle | 2 +- buildSrc/build.gradle | 2 +- cscore/build.gradle | 8 ++-- datalogtool/build.gradle | 8 ++-- datalogtool/publish.gradle | 12 ++--- fieldImages/build.gradle | 2 +- glass/build.gradle | 8 ++-- glass/publish.gradle | 13 +++--- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 60756 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 6 +++ gradlew.bat | 14 +++--- outlineviewer/build.gradle | 4 +- outlineviewer/publish.gradle | 12 ++--- roborioteamnumbersetter/build.gradle | 8 ++-- roborioteamnumbersetter/publish.gradle | 12 ++--- shared/config.gradle | 14 +++--- shared/java/javacommon.gradle | 2 +- shared/jni/setupBuild.gradle | 8 ++-- shared/plugins/setupBuild.gradle | 4 +- simulation/frc_gazebo_plugins/build.gradle | 2 +- simulation/gz_msgs/build.gradle | 2 +- simulation/halsim_ds_socket/build.gradle | 2 +- simulation/halsim_gazebo/build.gradle | 2 +- simulation/halsim_gui/build.gradle | 4 +- simulation/halsim_ws_server/build.gradle | 2 +- wpigui/build.gradle | 6 +-- wpilibNewCommands/WPILibNewCommands.json | 7 +-- wpilibjExamples/build.gradle | 2 +- .../edu/wpi/first/util/RuntimeDetector.java | 43 ++++++++---------- 32 files changed, 115 insertions(+), 112 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index fa13febb96..356c288bd6 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -16,11 +16,11 @@ jobs: artifact-name: Athena build-options: "-Ponlylinuxathena" - container: wpilib/raspbian-cross-ubuntu:10-20.04 - artifact-name: Raspbian - build-options: "-Ponlylinuxraspbian" + artifact-name: Arm32 + build-options: "-Ponlylinuxarm32" - container: wpilib/aarch64-cross-ubuntu:bionic-20.04 - artifact-name: Aarch64 - build-options: "-Ponlylinuxaarch64bionic" + artifact-name: Arm64 + build-options: "-Ponlylinuxarm64" - container: wpilib/ubuntu-base:20.04 artifact-name: Linux build-options: "-Ponlylinuxx86-64" @@ -64,7 +64,7 @@ jobs: - os: macOS-11 artifact-name: macOS architecture: x64 - build-options: "" + build-options: "-Pbuildalldesktop" task: "build" name: "Build - ${{ matrix.artifact-name }}" runs-on: ${{ matrix.os }} @@ -100,7 +100,7 @@ jobs: ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} - name: Sign Libraries with Developer ID - run: ./gradlew build -PbuildServer -PskipJavaFormat -PdeveloperID=${{ secrets.APPLE_DEVELOPER_ID }} ${{ env.EXTRA_GRADLE_ARGS }} + run: ./gradlew build -PbuildServer -PskipJavaFormat -PdeveloperID=${{ secrets.APPLE_DEVELOPER_ID }} ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }} if: | matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))) diff --git a/README.md b/README.md index a1d82ff293..9f7a7d8c22 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Using Gradle makes building WPILib very straightforward. It only has a few depen - Run `./gradlew installRoboRioToolchain` after cloning this repository - If the WPILib installer was used, this toolchain is already installed - Raspberry Pi toolchain (optional) - - Run `./gradlew installRaspbianToolchain` after cloning this repository + - Run `./gradlew installArm32Toolchain` after cloning this repository ## Setup diff --git a/build.gradle b/build.gradle index 2edfeeca11..620a13b9af 100644 --- a/build.gradle +++ b/build.gradle @@ -156,5 +156,5 @@ ext.getCurrentArch = { } wrapper { - gradleVersion = '7.3.3' + gradleVersion = '7.5-rc-2' } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 41d42c93ca..b90fc771d8 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -5,5 +5,5 @@ repositories { } } dependencies { - implementation "edu.wpi.first:native-utils:2023.0.2" + implementation "edu.wpi.first:native-utils:2023.0.7" } diff --git a/cscore/build.gradle b/cscore/build.gradle index 974adcad07..c1a7243164 100644 --- a/cscore/build.gradle +++ b/cscore/build.gradle @@ -23,8 +23,8 @@ model { enableCheckTask true javaCompileTasks << compileJava jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.roborio) - jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.raspbian) - jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.aarch64bionic) + jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm32) + jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm64) sources { cpp { @@ -180,7 +180,7 @@ model { components { examplesMap.each { key, value -> if (key == "usbviewer") { - if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { "${key}"(NativeExecutableSpec) { targetBuildTypes 'debug' binaries.all { @@ -189,7 +189,7 @@ model { lib project: ':wpigui', library: 'wpigui', linkage: 'static' lib library: 'cscore', linkage: 'shared' nativeUtils.useRequiredLibrary(it, 'imgui_static') - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { it.buildable = false return } diff --git a/datalogtool/build.gradle b/datalogtool/build.gradle index 8c8fc6c7d4..c7f1c158b5 100644 --- a/datalogtool/build.gradle +++ b/datalogtool/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { +if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { description = "roboRIO Team Number Setter" @@ -27,12 +27,12 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra nativeUtils { nativeDependencyContainer { libssh(getNativeDependencyTypeClass('WPIStaticMavenDependency')) { - groupId = "edu.wpi.first.thirdparty.frc2022" + groupId = "edu.wpi.first.thirdparty.frc2023" artifactId = "libssh" headerClassifier = "headers" sourceClassifier = "sources" ext = "zip" - version = '0.95-1' + version = '0.95-3' targetPlatforms.addAll(nativeUtils.wpi.platforms.desktopPlatforms) } } @@ -107,7 +107,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { it.buildable = false return } diff --git a/datalogtool/publish.gradle b/datalogtool/publish.gradle index 2130d0449a..9608bef7b6 100644 --- a/datalogtool/publish.gradle +++ b/datalogtool/publish.gradle @@ -10,7 +10,7 @@ model { tasks { // Create the run task. $.components.datalogtool.binaries.each { bin -> - if (bin.buildable && bin.name.toLowerCase().contains("debug")) { + if (bin.buildable && bin.name.toLowerCase().contains("debug") && nativeUtils.isNativeDesktopPlatform(bin.targetPlatform)) { Task run = project.tasks.create("run", Exec) { commandLine bin.tasks.install.runScriptFile.get().asFile.toString() } @@ -30,10 +30,10 @@ model { def icon = file("$project.projectDir/src/main/native/mac/datalogtool.icns") // Create the macOS bundle. - def bundleTask = project.tasks.create("bundleDataLogToolOsxApp", Copy) { + def bundleTask = project.tasks.create("bundleDataLogToolOsxApp" + binary.targetPlatform.architecture.name, Copy) { description("Creates a macOS application bundle for DataLogTool") from(file("$project.projectDir/Info.plist")) - into(file("$project.buildDir/outputs/bundles/DataLogTool.app/Contents")) + into(file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/DataLogTool.app/Contents")) into("MacOS") { with copySpec { from binary.executable.file } } into("Resources") { with copySpec { from icon } } @@ -48,7 +48,7 @@ model { "codesign --force --strict --deep " + "--timestamp --options=runtime " + "--verbose -s ${project.findProperty("developerID")} " + - "$project.buildDir/outputs/bundles/DataLogTool.app/" + "$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/DataLogTool.app/" ] commandLine args } @@ -58,12 +58,12 @@ model { // Reset the application path if we are creating a bundle. if (binary.targetPlatform.operatingSystem.isMacOsX()) { - applicationPath = file("$project.buildDir/outputs/bundles") + applicationPath = file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name") project.build.dependsOn bundleTask } // Create the ZIP. - def task = project.tasks.create("copyDataLogToolExecutable", Zip) { + def task = project.tasks.create("copyDataLogToolExecutable" + binary.targetPlatform.architecture.name, Zip) { description("Copies the DataLogTool executable to the outputs directory.") destinationDirectory = outputsFolder diff --git a/fieldImages/build.gradle b/fieldImages/build.gradle index 476dd3c309..0d1dbb1cfc 100644 --- a/fieldImages/build.gradle +++ b/fieldImages/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { +if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { apply plugin: 'cpp' apply plugin: 'c' diff --git a/glass/build.gradle b/glass/build.gradle index 9f42d6f182..6c31d17234 100644 --- a/glass/build.gradle +++ b/glass/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { +if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { description = "A different kind of dashboard" @@ -100,7 +100,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { it.buildable = false return } @@ -128,7 +128,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { it.buildable = false return } @@ -169,7 +169,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { it.buildable = false return } diff --git a/glass/publish.gradle b/glass/publish.gradle index 4dce506947..b127c11321 100644 --- a/glass/publish.gradle +++ b/glass/publish.gradle @@ -64,7 +64,8 @@ model { tasks { // Create the run task. $.components.glassApp.binaries.each { bin -> - if (bin.buildable && bin.name.toLowerCase().contains("debug")) { + if (bin.buildable && bin.name.toLowerCase().contains("debug") && nativeUtils.isNativeDesktopPlatform(bin.targetPlatform)) { + Task run = project.tasks.create("run", Exec) { commandLine bin.tasks.install.runScriptFile.get().asFile.toString() } @@ -84,10 +85,10 @@ model { def icon = file("$project.projectDir/src/app/native/mac/glass.icns") // Create the macOS bundle. - def bundleTask = project.tasks.create("bundleGlassOsxApp", Copy) { + def bundleTask = project.tasks.create("bundleGlassOsxApp" + binary.targetPlatform.architecture.name, Copy) { description("Creates a macOS application bundle for Glass") from(file("$project.projectDir/Info.plist")) - into(file("$project.buildDir/outputs/bundles/Glass.app/Contents")) + into(file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/Glass.app/Contents")) into("MacOS") { with copySpec { from binary.executable.file } } into("Resources") { with copySpec { from icon } } @@ -102,7 +103,7 @@ model { "codesign --force --strict --deep " + "--timestamp --options=runtime " + "--verbose -s ${project.findProperty("developerID")} " + - "$project.buildDir/outputs/bundles/Glass.app/" + "$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/Glass.app/" ] commandLine args } @@ -112,12 +113,12 @@ model { // Reset the application path if we are creating a bundle. if (binary.targetPlatform.operatingSystem.isMacOsX()) { - applicationPath = file("$project.buildDir/outputs/bundles") + applicationPath = file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name") project.build.dependsOn bundleTask } // Create the ZIP. - def task = project.tasks.create("copyGlassExecutable", Zip) { + def task = project.tasks.create("copyGlassExecutable" + binary.targetPlatform.architecture.name, Zip) { description("Copies the Glass executable to the outputs directory.") destinationDirectory = outputsFolder diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..249e5832f090a2944b7473328c07c9755baa3196 100644 GIT binary patch delta 10158 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 delta 9041 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e6e5897b5..26e62a13f1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-rc-2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787337..a69d9cb6c2 100755 --- a/gradlew +++ b/gradlew @@ -205,6 +205,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f938..53a6b238d4 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/outlineviewer/build.gradle b/outlineviewer/build.gradle index 17c5baf8b9..cbf0a16c63 100644 --- a/outlineviewer/build.gradle +++ b/outlineviewer/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { +if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { description = "NetworkTables Viewer" @@ -93,7 +93,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { it.buildable = false return } diff --git a/outlineviewer/publish.gradle b/outlineviewer/publish.gradle index 78f044fa6e..85bb26c69a 100644 --- a/outlineviewer/publish.gradle +++ b/outlineviewer/publish.gradle @@ -10,7 +10,7 @@ model { tasks { // Create the run task. $.components.outlineviewer.binaries.each { bin -> - if (bin.buildable && bin.name.toLowerCase().contains("debug")) { + if (bin.buildable && bin.name.toLowerCase().contains("debug") && nativeUtils.isNativeDesktopPlatform(bin.targetPlatform)) { Task run = project.tasks.create("run", Exec) { commandLine bin.tasks.install.runScriptFile.get().asFile.toString() } @@ -30,10 +30,10 @@ model { def icon = file("$project.projectDir/src/main/native/mac/ov.icns") // Create the macOS bundle. - def bundleTask = project.tasks.create("bundleOutlineViewerOsxApp", Copy) { + def bundleTask = project.tasks.create("bundleOutlineViewerOsxApp" + binary.targetPlatform.architecture.name, Copy) { description("Creates a macOS application bundle for OutlineViewer") from(file("$project.projectDir/Info.plist")) - into(file("$project.buildDir/outputs/bundles/OutlineViewer.app/Contents")) + into(file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/OutlineViewer.app/Contents")) into("MacOS") { with copySpec { from binary.executable.file } } into("Resources") { with copySpec { from icon } } @@ -48,7 +48,7 @@ model { "codesign --force --strict --deep " + "--timestamp --options=runtime " + "--verbose -s ${project.findProperty("developerID")} " + - "$project.buildDir/outputs/bundles/OutlineViewer.app/" + "$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/OutlineViewer.app/" ] commandLine args } @@ -58,12 +58,12 @@ model { // Reset the application path if we are creating a bundle. if (binary.targetPlatform.operatingSystem.isMacOsX()) { - applicationPath = file("$project.buildDir/outputs/bundles") + applicationPath = file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name") project.build.dependsOn bundleTask } // Create the ZIP. - def task = project.tasks.create("copyOutlineViewerExecutable", Zip) { + def task = project.tasks.create("copyOutlineViewerExecutable" + binary.targetPlatform.architecture.name, Zip) { description("Copies the OutlineViewer executable to the outputs directory.") destinationDirectory = outputsFolder diff --git a/roborioteamnumbersetter/build.gradle b/roborioteamnumbersetter/build.gradle index 4a08fdcc19..2ca1215b2e 100644 --- a/roborioteamnumbersetter/build.gradle +++ b/roborioteamnumbersetter/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { +if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { description = "roboRIO Team Number Setter" @@ -27,12 +27,12 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra nativeUtils { nativeDependencyContainer { libssh(getNativeDependencyTypeClass('WPIStaticMavenDependency')) { - groupId = "edu.wpi.first.thirdparty.frc2022" + groupId = "edu.wpi.first.thirdparty.frc2023" artifactId = "libssh" headerClassifier = "headers" sourceClassifier = "sources" ext = "zip" - version = '0.95-1' + version = '0.95-3' targetPlatforms.addAll(nativeUtils.wpi.platforms.desktopPlatforms) } } @@ -107,7 +107,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { it.buildable = false return } diff --git a/roborioteamnumbersetter/publish.gradle b/roborioteamnumbersetter/publish.gradle index 478f3d39a0..10b9de1d0f 100644 --- a/roborioteamnumbersetter/publish.gradle +++ b/roborioteamnumbersetter/publish.gradle @@ -10,7 +10,7 @@ model { tasks { // Create the run task. $.components.roborioteamnumbersetter.binaries.each { bin -> - if (bin.buildable && bin.name.toLowerCase().contains("debug")) { + if (bin.buildable && bin.name.toLowerCase().contains("debug") && nativeUtils.isNativeDesktopPlatform(bin.targetPlatform)) { Task run = project.tasks.create("run", Exec) { commandLine bin.tasks.install.runScriptFile.get().asFile.toString() } @@ -30,10 +30,10 @@ model { def icon = file("$project.projectDir/src/main/native/mac/rtns.icns") // Create the macOS bundle. - def bundleTask = project.tasks.create("bundleroboRIOTeamNumberSetterOsxApp", Copy) { + def bundleTask = project.tasks.create("bundleroboRIOTeamNumberSetterOsxApp" + binary.targetPlatform.architecture.name, Copy) { description("Creates a macOS application bundle for roboRIO Team Number Setter") from(file("$project.projectDir/Info.plist")) - into(file("$project.buildDir/outputs/bundles/roboRIOTeamNumberSetter.app/Contents")) + into(file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/roboRIOTeamNumberSetter.app/Contents")) into("MacOS") { with copySpec { from binary.executable.file } } into("Resources") { with copySpec { from icon } } @@ -48,7 +48,7 @@ model { "codesign --force --strict --deep " + "--timestamp --options=runtime " + "--verbose -s ${project.findProperty("developerID")} " + - "$project.buildDir/outputs/bundles/roboRIOTeamNumberSetter.app/" + "$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/roboRIOTeamNumberSetter.app/" ] commandLine args } @@ -58,12 +58,12 @@ model { // Reset the application path if we are creating a bundle. if (binary.targetPlatform.operatingSystem.isMacOsX()) { - applicationPath = file("$project.buildDir/outputs/bundles") + applicationPath = file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name") project.build.dependsOn bundleTask } // Create the ZIP. - def task = project.tasks.create("copyroboRIOTeamNumberSetterExecutable", Zip) { + def task = project.tasks.create("copyroboRIOTeamNumberSetterExecutable" + binary.targetPlatform.architecture.name, Zip) { description("Copies the roboRIOTeamNumberSetter executable to the outputs directory.") destinationDirectory = outputsFolder diff --git a/shared/config.gradle b/shared/config.gradle index fa02c5ee55..a565026cc6 100644 --- a/shared/config.gradle +++ b/shared/config.gradle @@ -7,17 +7,17 @@ if (project.hasProperty('ciDebugOnly')) { } nativeUtils.addWpiNativeUtils() -nativeUtils.withRoboRIO() -nativeUtils.withRaspbian() -nativeUtils.withBionic() +nativeUtils.withCrossRoboRIO() +nativeUtils.withCrossLinuxArm32() +nativeUtils.withCrossLinuxArm64() nativeUtils { wpi { configureDependencies { wpiVersion = "-1" niLibVersion = "2022.4.0" - opencvVersion = "4.5.2-1" - googleTestVersion = "1.9.0-5-437e100-1" - imguiVersion = "1.86-1" + opencvVersion = "4.5.5-3" + googleTestVersion = "1.11.0-2" + imguiVersion = "1.87-2" wpimathVersion = "-1" } } @@ -38,7 +38,7 @@ nativeUtils.platformConfigs.each { return } it.linker.args << '-Wl,-rpath,\'$ORIGIN\'' - if (it.name == 'osxx86-64') { + if (it.name == 'osxx86-64' || it.name == 'osxarm64') { it.linker.args << "-headerpad_max_install_names" } } diff --git a/shared/java/javacommon.gradle b/shared/java/javacommon.gradle index 0065886fe3..4c57f1f49e 100644 --- a/shared/java/javacommon.gradle +++ b/shared/java/javacommon.gradle @@ -81,7 +81,7 @@ test { finalizedBy jacocoTestReport } -if (project.hasProperty('onlylinuxathena') || project.hasProperty('onlylinuxraspbian') || project.hasProperty('onlylinuxaarch64bionic')) { +if (project.hasProperty('onlylinuxathena') || project.hasProperty('onlylinuxarm32') || project.hasProperty('onlylinuxarm64')) { test.enabled = false } diff --git a/shared/jni/setupBuild.gradle b/shared/jni/setupBuild.gradle index f89780647d..10d1740d09 100644 --- a/shared/jni/setupBuild.gradle +++ b/shared/jni/setupBuild.gradle @@ -104,8 +104,8 @@ model { enableCheckTask !project.hasProperty('skipJniCheck') javaCompileTasks << compileJava jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.roborio) - jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.raspbian) - jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.aarch64bionic) + jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm32) + jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm64) sources { cpp { source { @@ -145,8 +145,8 @@ model { enableCheckTask !project.hasProperty('skipJniCheck') javaCompileTasks << compileJava jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.roborio) - jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.raspbian) - jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.aarch64bionic) + jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm32) + jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm64) sources { cpp { source { diff --git a/shared/plugins/setupBuild.gradle b/shared/plugins/setupBuild.gradle index 6b0eb0771f..3caa30a3f7 100644 --- a/shared/plugins/setupBuild.gradle +++ b/shared/plugins/setupBuild.gradle @@ -57,7 +57,7 @@ if (!project.hasProperty('onlylinuxathena')) { } } binaries.all { - if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { project(':hal').addHalDependency(it, 'shared') lib library: pluginName if (project.hasProperty('includeNtCore')) { @@ -84,7 +84,7 @@ if (!project.hasProperty('onlylinuxathena')) { model { tasks { def c = $.components - if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { project.tasks.create('runCpp', Exec) { group = 'WPILib' description = "Run the ${pluginName}Dev executable" diff --git a/simulation/frc_gazebo_plugins/build.gradle b/simulation/frc_gazebo_plugins/build.gradle index f42b70bf88..a7f7a76cac 100644 --- a/simulation/frc_gazebo_plugins/build.gradle +++ b/simulation/frc_gazebo_plugins/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'cpp' apply plugin: "google-test" ext.skiplinuxathena = true -ext.skiplinuxraspbian = true +ext.skiplinuxarm32 = true apply from: "${rootDir}/shared/config.gradle" diff --git a/simulation/gz_msgs/build.gradle b/simulation/gz_msgs/build.gradle index 31f3df4985..c77b24634c 100644 --- a/simulation/gz_msgs/build.gradle +++ b/simulation/gz_msgs/build.gradle @@ -9,7 +9,7 @@ description = "A C++ and Java library to pass FRC Simulation Messages in and out /* The simulation does not run on real hardware; so we always skip Athena */ ext.skiplinuxathena = true -ext.skiplinuxraspbian = true +ext.skiplinuxarm32 = true apply from: "${rootDir}/shared/config.gradle" /* Use a sort of poor man's autoconf to find the protobuf development diff --git a/simulation/halsim_ds_socket/build.gradle b/simulation/halsim_ds_socket/build.gradle index f21fb552b9..186903e8eb 100644 --- a/simulation/halsim_ds_socket/build.gradle +++ b/simulation/halsim_ds_socket/build.gradle @@ -21,7 +21,7 @@ apply from: "${rootDir}/shared/plugins/setupBuild.gradle" model { testSuites { def comps = $.components - if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { "${pluginName}Test"(GoogleTestTestSuiteSpec) { for(NativeComponentSpec c : comps) { if (c.name == pluginName) { diff --git a/simulation/halsim_gazebo/build.gradle b/simulation/halsim_gazebo/build.gradle index 8d340d38c7..3e4eb396ca 100644 --- a/simulation/halsim_gazebo/build.gradle +++ b/simulation/halsim_gazebo/build.gradle @@ -4,7 +4,7 @@ apply plugin: 'edu.wpi.first.NativeUtils' apply plugin: 'cpp' ext.skiplinuxathena = true -ext.skiplinuxraspbian = true +ext.skiplinuxarm32 = true ext.pluginName = 'halsim_gazebo' /* If gz_msgs or gazebo is not available, do not attempt a build */ diff --git a/simulation/halsim_gui/build.gradle b/simulation/halsim_gui/build.gradle index b947733f54..b9dcc316bf 100644 --- a/simulation/halsim_gui/build.gradle +++ b/simulation/halsim_gui/build.gradle @@ -1,4 +1,4 @@ -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { +if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { description = "A plugin that creates a simulation gui" @@ -29,7 +29,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra lib project: ':wpinet', library: 'wpinet', linkage: 'shared' lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared' nativeUtils.useRequiredLibrary(it, 'imgui_static') - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { it.buildable = false return } diff --git a/simulation/halsim_ws_server/build.gradle b/simulation/halsim_ws_server/build.gradle index 94237d426d..e4eb6c2f70 100644 --- a/simulation/halsim_ws_server/build.gradle +++ b/simulation/halsim_ws_server/build.gradle @@ -21,7 +21,7 @@ apply from: "${rootDir}/shared/plugins/setupBuild.gradle" model { testSuites { def comps = $.components - if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { "${pluginName}Test"(GoogleTestTestSuiteSpec) { for(NativeComponentSpec c : comps) { if (c.name == pluginName) { diff --git a/wpigui/build.gradle b/wpigui/build.gradle index c37d9e0cbc..40b0a52243 100644 --- a/wpigui/build.gradle +++ b/wpigui/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) { +if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { apply plugin: 'cpp' if (OperatingSystem.current().isMacOsX()) { @@ -49,7 +49,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra } binaries.all { nativeUtils.useRequiredLibrary(it, 'imgui_static') - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { it.buildable = false return } @@ -111,7 +111,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra } binaries { all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { it.buildable = false return } diff --git a/wpilibNewCommands/WPILibNewCommands.json b/wpilibNewCommands/WPILibNewCommands.json index fb6622786c..22e1c6f395 100644 --- a/wpilibNewCommands/WPILibNewCommands.json +++ b/wpilibNewCommands/WPILibNewCommands.json @@ -25,12 +25,13 @@ "skipInvalidPlatforms": true, "binaryPlatforms": [ "linuxathena", - "linuxraspbian", - "linuxaarch64bionic", + "linuxarm32", + "linuxarm64", "windowsx86-64", "windowsx86", "linuxx86-64", - "osxx86-64" + "osxx86-64", + "osxarm64" ] } ] diff --git a/wpilibjExamples/build.gradle b/wpilibjExamples/build.gradle index 431dbd5ad1..a241925ee1 100644 --- a/wpilibjExamples/build.gradle +++ b/wpilibjExamples/build.gradle @@ -21,7 +21,7 @@ test { finalizedBy jacocoTestReport } -if (project.hasProperty('onlylinuxathena') || project.hasProperty('onlylinuxraspbian') || project.hasProperty('onlylinuxaarch64bionic')) { +if (project.hasProperty('onlylinuxathena') || project.hasProperty('onlylinuxarm32') || project.hasProperty('onlylinuxarm64')) { test.enabled = false } diff --git a/wpiutil/src/main/java/edu/wpi/first/util/RuntimeDetector.java b/wpiutil/src/main/java/edu/wpi/first/util/RuntimeDetector.java index d4ad833042..81a9e21dc7 100644 --- a/wpiutil/src/main/java/edu/wpi/first/util/RuntimeDetector.java +++ b/wpiutil/src/main/java/edu/wpi/first/util/RuntimeDetector.java @@ -4,11 +4,7 @@ package edu.wpi.first.util; -import java.io.BufferedReader; import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; public final class RuntimeDetector { private static String filePrefix; @@ -22,6 +18,7 @@ public final class RuntimeDetector { boolean intel32 = is32BitIntel(); boolean intel64 = is64BitIntel(); + boolean arm64 = isArm64(); if (isWindows()) { filePrefix = ""; @@ -35,7 +32,9 @@ public final class RuntimeDetector { filePrefix = "lib"; fileExtension = ".dylib"; if (intel32) { - filePath = "/osx/x86"; + filePath = "/osx/x86/"; + } else if (arm64) { + filePath = "/osx/arm64/"; } else { filePath = "/osx/x86-64/"; } @@ -48,10 +47,10 @@ public final class RuntimeDetector { filePath = "/linux/x86-64/"; } else if (isAthena()) { filePath = "/linux/athena/"; - } else if (isRaspbian()) { - filePath = "/linux/raspbian/"; - } else if (isAarch64()) { - filePath = "/linux/aarch64bionic/"; + } else if (isArm32()) { + filePath = "/linux/arm32/"; + } else if (arm64) { + filePath = "/linux/arm64/"; } else { filePath = "/linux/nativearm/"; } @@ -128,29 +127,23 @@ public final class RuntimeDetector { } /** - * Check if OS is Raspbian. + * Check if OS is Arm32. * - * @return True if OS is Raspbian. + * @return True if OS is Arm32. */ - public static boolean isRaspbian() { - try (BufferedReader reader = Files.newBufferedReader(Paths.get("/etc/os-release"))) { - String value = reader.readLine(); - if (value == null) { - return false; - } - return value.contains("Raspbian"); - } catch (IOException ex) { - return false; - } + public static boolean isArm32() { + String arch = System.getProperty("os.arch"); + return "arm".equals(arch) || "arm32".equals(arch); } /** - * check if architecture is aarch64. + * check if architecture is Arm64. * - * @return if architecture is aarch64 + * @return if architecture is Arm64 */ - public static boolean isAarch64() { - return "aarch64".equals(System.getProperty("os.arch")); + public static boolean isArm64() { + String arch = System.getProperty("os.arch"); + return "aarch64".equals(arch) || "arm64".equals(arch); } public static boolean isLinux() {