diff --git a/build.gradle b/build.gradle index 4965c9c3..3781a5db 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,14 @@ repositories { mavenLocal() } +configurations { + processstarterDownload +} + +def processstarterToolVersion = "2025.3.2" + dependencies { + api 'com.google.code.gson:gson:2.13.1' api 'edu.wpi.first:native-utils:2025.9.1' @@ -27,6 +34,13 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter-api:5.13.4") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") testImplementation gradleTestKit() + + processstarterDownload "edu.wpi.first.tools:processstarter:$processstarterToolVersion:windowsx86-64@zip" + processstarterDownload "edu.wpi.first.tools:processstarter:$processstarterToolVersion:linuxx86-64@zip" + processstarterDownload "edu.wpi.first.tools:processstarter:$processstarterToolVersion:linuxarm32@zip" + processstarterDownload "edu.wpi.first.tools:processstarter:$processstarterToolVersion:linuxarm64@zip" + processstarterDownload "edu.wpi.first.tools:processstarter:$processstarterToolVersion:osxuniversal@zip" + processstarterDownload "edu.wpi.first.tools:processstarter:$processstarterToolVersion:windowsarm64@zip" } tasks.withType(Test).configureEach { @@ -112,6 +126,46 @@ examplesFolder.eachFile { File file -> jar.finalizedBy zipExamples +task processprocessstarterDownload { + inputs.files configurations.processstarterDownload + doLast { + configurations.processstarterDownload.each { downloadedFile -> + def destinationDir = file("${buildDir}/resources/main") + // Unzip and copy files + copy { + from(zipTree(downloadedFile)) { + include 'processstarter*' + } + into destinationDir + } + + // Rename the extracted file to include the classifier + destinationDir.eachFile { extractedFile -> + + if (extractedFile.name.startsWith('processstarter') && !extractedFile.name.contains('-')) { + def destinationFile = file("${buildDir}/resources/main/processstarter") + if (downloadedFile.name.contains("linuxarm32")) { + destinationFile = file("${buildDir}/resources/main/processstarter-linuxarm32") + } else if (downloadedFile.name.contains("linuxarm64")) { + destinationFile = file("${buildDir}/resources/main/processstarter-linuxarm64") + } else if (downloadedFile.name.contains("linuxx86-64")) { + destinationFile = file("${buildDir}/resources/main/processstarter-linuxx86-64") + } else if (downloadedFile.name.contains("osxuniversal")) { + destinationFile = file("${buildDir}/resources/main/processstarter-osxuniversal") + } else if (downloadedFile.name.contains("windowsx86-64")) { + destinationFile = file("${buildDir}/resources/main/processstarter-windowsx86-64.exe") + } else if (downloadedFile.name.contains("windowsarm64")) { + destinationFile = file("${buildDir}/resources/main/processstarter-windowsarm64.exe") + } + extractedFile.renameTo(destinationFile) + } + } + } + } +} + +jar.dependsOn processprocessstarterDownload + wrapper { gradleVersion = '8.11' distributionType = Wrapper.DistributionType.BIN diff --git a/src/main/java/edu/wpi/first/gradlerio/wpi/WPIVersionsExtension.java b/src/main/java/edu/wpi/first/gradlerio/wpi/WPIVersionsExtension.java index 446500dd..74b6e02f 100644 --- a/src/main/java/edu/wpi/first/gradlerio/wpi/WPIVersionsExtension.java +++ b/src/main/java/edu/wpi/first/gradlerio/wpi/WPIVersionsExtension.java @@ -25,6 +25,7 @@ public abstract class WPIVersionsExtension { private static final String roboRIOTeamNumberSetterVersion = "2025.3.2"; private static final String dataLogToolVersion = "2025.3.2"; private static final String wpicalToolVersion = "2025.3.2"; + private static final String processstarterToolVersion = "2025.3.2"; public abstract Property getWpilibVersion(); @@ -46,6 +47,7 @@ public abstract class WPIVersionsExtension { public abstract Property getRoboRIOTeamNumberSetterVersion(); public abstract Property getDataLogToolVersion(); public abstract Property getwpicalToolVersion(); + public abstract Property getprocessstarterToolVersion(); @Inject public WPIVersionsExtension() { @@ -68,6 +70,7 @@ public WPIVersionsExtension() { getRoboRIOTeamNumberSetterVersion().convention(roboRIOTeamNumberSetterVersion); getDataLogToolVersion().convention(dataLogToolVersion); getwpicalToolVersion().convention(wpicalToolVersion); + getprocessstarterToolVersion().convention(processstarterToolVersion); } } diff --git a/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/CppToolRunTask.java b/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/CppToolRunTask.java index 70958c30..4095f701 100644 --- a/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/CppToolRunTask.java +++ b/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/CppToolRunTask.java @@ -60,8 +60,8 @@ private String getArgumentPath(String toolNameLower) { private void runToolWindows() { Directory toolsFolder = this.toolsFolder.get(); String toolName = this.toolName.get(); - File outputFile = toolsFolder.file(toolName + ".vbs").getAsFile(); - ProcessBuilder builder = new ProcessBuilder("wscript.exe", outputFile.getAbsolutePath(), "silent", + File outputFile = toolsFolder.file(toolName + ".exe").getAsFile(); + ProcessBuilder builder = new ProcessBuilder(outputFile.getAbsolutePath(), getArgumentPath(toolName.toLowerCase())); try { Process proc = builder.start(); @@ -80,7 +80,7 @@ private void runToolWindows() { private void runToolUnix() { Directory toolsFolder = this.toolsFolder.get(); String toolName = this.toolName.get(); - File outputFile = toolsFolder.file(toolName + ".sh").getAsFile(); + File outputFile = toolsFolder.file(toolName).getAsFile(); operations.exec(spec -> { spec.setExecutable(outputFile.getAbsolutePath()); spec.args(getArgumentPath(toolName.toLowerCase())); diff --git a/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/ToolInstallTask.java b/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/ToolInstallTask.java index 16eb09df..e74ad334 100644 --- a/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/ToolInstallTask.java +++ b/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/ToolInstallTask.java @@ -14,6 +14,8 @@ import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; +import edu.wpi.first.toolchain.NativePlatforms; + import org.codehaus.groovy.runtime.IOGroovyMethods; import org.codehaus.groovy.runtime.ResourceGroovyMethods; import org.gradle.api.Action; @@ -138,7 +140,7 @@ private static synchronized void setToolVersion(Directory toolsFolder, ToolConfi } private static File getScriptFile(Directory toolsFolder, String toolName) { - return toolsFolder.file(toolName + ".vbs").getAsFile(); + return toolsFolder.file(toolName + ".exe").getAsFile(); } private static Dependency getDependencyObject(Configuration configuration, String artifactName) { @@ -218,18 +220,25 @@ public void execute(CopySpec cp) { } private static void extractScriptWindows(Directory toolsFolder, String toolName) { - File outputFile = toolsFolder.file(toolName + ".vbs").getAsFile(); - try (InputStream it = ToolInstallTask.class.getResourceAsStream("/ScriptBase.vbs")) { - ResourceGroovyMethods.setText(outputFile, IOGroovyMethods.getText(it)); + File outputFile = toolsFolder.file(toolName + ".exe").getAsFile(); + String inputFileName = "/processstarter-" + NativePlatforms.desktopOS() + NativePlatforms.desktopArchDirect() + ".exe"; + try (InputStream it = ToolInstallTask.class.getResourceAsStream(inputFileName)) { + ResourceGroovyMethods.setBytes(outputFile, IOGroovyMethods.getBytes(it)); } catch (IOException e) { throw new RuntimeException(e); } } private void extractScriptUnix(Project project, Directory toolsFolder, String toolName) { - File outputFile = toolsFolder.file(toolName + ".sh").getAsFile(); - try (InputStream it = ToolInstallTask.class.getResourceAsStream("/ScriptBase.sh")) { - ResourceGroovyMethods.setText(outputFile, IOGroovyMethods.getText(it)); + File outputFile = toolsFolder.file(toolName).getAsFile(); + String inputFileName = "/processstarter-"; + if (OperatingSystem.current().isMacOsX()) + inputFileName += "osxuniversal"; + else + inputFileName += NativePlatforms.desktopOS() + NativePlatforms.desktopArchDirect(); + System.out.println("Extracting Unix: " + inputFileName + " to " + outputFile.getAbsolutePath()); + try (InputStream it = ToolInstallTask.class.getResourceAsStream(inputFileName)) { + ResourceGroovyMethods.setBytes(outputFile, IOGroovyMethods.getBytes(it)); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/ToolRunTask.java b/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/ToolRunTask.java index 055d6af1..79c96b9f 100644 --- a/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/ToolRunTask.java +++ b/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/ToolRunTask.java @@ -59,8 +59,8 @@ public void runTool() { private void runToolWindows() { Directory toolsFolder = this.toolsFolder.get(); String toolName = this.toolName.get(); - File outputFile = toolsFolder.file(toolName + ".vbs").getAsFile(); - ProcessBuilder builder = new ProcessBuilder("wscript.exe", outputFile.getAbsolutePath(), "silent"); + File outputFile = toolsFolder.file(toolName + ".exe").getAsFile(); + ProcessBuilder builder = new ProcessBuilder(outputFile.getAbsolutePath()); Process proc; try { proc = builder.start(); @@ -79,7 +79,7 @@ private void runToolWindows() { private void runToolUnix() { Directory toolsFolder = this.toolsFolder.get(); String toolName = this.toolName.get(); - File outputFile = toolsFolder.file(toolName + ".sh").getAsFile(); + File outputFile = toolsFolder.file(toolName).getAsFile(); operations.exec(spec -> { spec.setExecutable(outputFile.getAbsolutePath()); }); diff --git a/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/WPIToolsPlugin.java b/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/WPIToolsPlugin.java index af7f61ce..5c2702ae 100644 --- a/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/WPIToolsPlugin.java +++ b/src/main/java/edu/wpi/first/gradlerio/wpi/dependencies/tools/WPIToolsPlugin.java @@ -56,6 +56,9 @@ public void apply(Project project) { "edu.wpi.first.tools:wpical", toolsFolder)); } + cppTools.add(new WPICppTool(project, "processstarter", wpi.getVersions().getprocessstarterToolVersion(), + "edu.wpi.first.tools:processstarter", toolsFolder)); + project.getTasks().register("InstallAllTools", task -> { task.setGroup("GradleRIO"); task.setDescription("Install All Tools"); diff --git a/src/main/resources/ScriptBase.py b/src/main/resources/ScriptBase.py deleted file mode 100644 index 68bbe69f..00000000 --- a/src/main/resources/ScriptBase.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import print_function -import sys -import os -import subprocess -import time - -fullScript = os.path.abspath(sys.argv[0]) - -scriptName = os.path.basename(sys.argv[0]) -scriptName = os.path.splitext(scriptName)[0] - -jarName = scriptName + '.jar' - -toolsFolder = os.path.dirname(fullScript) - -fullJarPath = os.path.join(toolsFolder, jarName) - -jdkDir = os.path.dirname(toolsFolder) -jdkDir = os.path.join(jdkDir, 'jdk', 'bin', 'java') - -try: - subProc = subprocess.Popen([jdkDir, '-jar', fullJarPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - # If here, start succeeded -except: - # Start failed, try JAVA_home - try: - javaHome = os.environ['JAVA_HOME'] - jdkDir = os.path.join(javaHome, 'bin', 'java') - except: - # No JAVA_HOME, try just running java from path - jdkDir = 'java' - try: - subProc = subprocess.Popen([jdkDir, '-jar', fullJarPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except Exception as e: - # Really error - print('Error Launching Tool: ') - print(e) - exit(1) - -# wait 3 seconds, if still open good -count = 0 -while subProc.poll() is None: - time.sleep(1) - count = count + 1 - if count > 2: - exit(0) - - -outputStd = subProc.stdout.read() -outputErr = subProc.stderr.read() - -print(outputStd.decode('utf-8')) -print(outputErr.decode('utf-8'), file=sys.stderr) diff --git a/src/main/resources/ScriptBase.sh b/src/main/resources/ScriptBase.sh deleted file mode 100755 index 1799c2ed..00000000 --- a/src/main/resources/ScriptBase.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -SCRIPT_PATH="$(dirname "$(realpath "$0")")" -SCRIPT_NAME="$(basename "$(realpath "$0")")" -SCRIPT_BASE="$(basename -s .sh "$SCRIPT_NAME")" -JAR_NAME="$SCRIPT_BASE.jar" -JDK_DIR="$(realpath "$SCRIPT_PATH/../jdk/bin/java")" - -if ! "$JDK_DIR" -jar "$SCRIPT_PATH/$JAR_NAME"; then - echo "ERROR launching $SCRIPT_PATH/$JAR_NAME using $JDK_DIR" - if ! "$JAVA_HOME/bin/java" -jar "$SCRIPT_PATH/$JAR_NAME"; then - echo "ERROR launching $SCRIPT_PATH/$JAR_NAME using $JAVA_HOME" - if ! java -jar "$SCRIPT_PATH/$JAR_NAME"; then - echo "ERROR launching $SCRIPT_PATH/$JAR_NAME using java from path: $(which java)" - fi - fi -fi diff --git a/src/main/resources/ScriptBase.vbs b/src/main/resources/ScriptBase.vbs deleted file mode 100644 index 126da48d..00000000 --- a/src/main/resources/ScriptBase.vbs +++ /dev/null @@ -1,84 +0,0 @@ -'Create File System Object for working with directories -Set fso = WScript.CreateObject("Scripting.FileSystemObject") - -'Get the script name, and from that the jar name -jarName = fso.GetBaseName(WScript.ScriptName) + ".jar" - -'Get the folder of this script -toolsFolder = fso.GetParentFolderName(WScript.ScriptFullName) - -'Get the full path to the Jar -fullJarPath = fso.BuildPath(toolsFolder, jarName) - -'Get the full path to the JDK -jdkDir = fso.GetParentFolderName(toolsFolder) -jdkDir = fso.BuildPath(jdkDir, "jdk") -jdkDir = fso.BuildPath(jdkDir, "bin") -jdkDir = fso.BuildPath(jdkDir, "javaw.exe") - - -' Get the full shell to run -shellScript = """" + jdkDir + """ -jar """ + fullJarPath + """" - - -'Create Shell Object -Set objShell = WScript.CreateObject( "WScript.Shell" ) -dim runObject -' Allow us to catch a script run failure -On Error Resume Next -Set runObj = objShell.Exec(shellScript) -If Err.Number <> 0 Then - ' If script failed, try getting java home - javaHomeEnv = "%JAVA_HOME%" - javaHome = objShell.ExpandEnvironmentStrings(javaHomeEnv) - If (javaHome = javaHomeEnv) Then - 'Java Home not found - shellScript = "javaw -jar """ + fullJarPath + """" - Else - 'Java Home found - shellScript = """" + javaHome + "\\bin\\javaw.exe"" -jar """ + fullJarPath + """" - End If - Err.Clear - Set runObj = objShell.Exec(shellScript) - If Err.Number <> 0 Then - If WScript.Arguments.Count > 0 Then - If (WScript.Arguments(0) <> "silent") Then - WScript.Echo "Error Launching Tool" + vbCrLf + Err.Description - Else - WScript.StdOut.Write("Error Launching Tool") - WScript.StdOut.Write(Error.Description) - End If - Else - WScript.Echo "Error Launching Tool" + vbCrLf + Err.Description - End If - Set runObj = Nothing - Set objShell = Nothing - Set fso = Nothing - WScript.Quit(1) - End If -End If - -WScript.Sleep 3000 -If (runObj.Status <> 0) Then - outputStd = runObj.StdOut.ReadAll() - outputErr = runObj.StdErr.ReadAll() - If WScript.Arguments.Count > 0 Then - If (WScript.Arguments(0) <> "silent") Then - WScript.Echo "Tool Failed To Start" + vbCrLf + outputStd + vbCrLf + outputErr - Else - WScript.StdOut.Write(output) - WScript.StdErr.Write(outputErr) - End If - Else - WScript.Echo "Tool Failed To Start" + vbCrLf + outputStd + vbCrLf + outputErr - End If - Set runObj = Nothing - Set objShell = Nothing - Set fso = Nothing - WScript.Quit(2) -End If - -Set runObj = Nothing -Set objShell = Nothing -Set fso = Nothing -WScript.Quit(0) diff --git a/versionupdates.gradle b/versionupdates.gradle index 48634c67..33662ceb 100644 --- a/versionupdates.gradle +++ b/versionupdates.gradle @@ -15,6 +15,7 @@ def versionMap = [ imguiVersion: 'edu.wpi.first.thirdparty.frc2024:imgui:+:headers', wpimathVersion: 'edu.wpi.first.wpimath:wpimath-java:+', wpicalToolVersion: 'edu.wpi.first.tools:wpical:+:windowsx86-64@zip', + processstarterToolVersion: 'edu.wpi.first.tools:processstarter:+:windowsx86-64@zip', ] configurations { @@ -39,6 +40,7 @@ dependencies { } String regex = "String\\s+?placeholder\\s+?=\\s+?[\\\"|\\'].+?[\\\"|\\']" +String buildRegex = "def\\s+?placeholder\\s+?=\\s+?[\\\"|\\'].+?[\\\"|\\']" String mavenDevRegex = "this\\.useDevelopment\\s*=\\s*(true|false)" String validVersionsRegex = "validImageVersions = List\\.of\\((.+)\\);" @@ -67,6 +69,19 @@ tasks.register('UpdateVersions') { } extFile.text = extText + def buildFile = file('build.gradle') + def buildText = buildFile.text + configurations.gradleRioVersions.resolvedConfiguration.resolvedArtifacts.each { + versionMap.each { key, value -> + def id = it.moduleVersion.id + if (value.startsWith("${id.group}:${it.name}:+".toString())) { + def localBuildRegex = buildRegex.replace('placeholder', key) + buildText = buildText.replaceAll(localBuildRegex, "def ${key} = \"${id.version}\"".toString()) + } + } + } + buildFile.text = buildText + def allowedVersions = "" def first = true configurations.gradleRioVersions.resolvedConfiguration.resolvedArtifacts.each {