-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCppRunner.java
More file actions
100 lines (100 loc) · 4.53 KB
/
Copy pathCppRunner.java
File metadata and controls
100 lines (100 loc) · 4.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package processing.mode.cpp;
import java.io.*;
import processing.app.RunnerListener;
public class CppRunner {
private final File binary;
private final File sketchFolder;
private final File runtimeDir;
private final RunnerListener listener;
private Process process;
public CppRunner(File binary, File sketchFolder, File runtimeDir, RunnerListener listener) {
this.binary = binary;
this.sketchFolder = sketchFolder;
this.runtimeDir = runtimeDir;
this.listener = listener;
}
public void launch() {
if (!binary.exists()) {
listener.statusError("Binary not found: " + binary.getAbsolutePath());
return;
}
binary.setExecutable(true);
new Thread(() -> {
try {
// On Windows, copy exe to sketch folder and run from there
// so DLLs copied alongside it are found
File exeToRun = binary;
String osName2 = System.getProperty("os.name","").toLowerCase();
if (osName2.contains("win")) {
File exeCopy = new File(sketchFolder, binary.getName());
try {
java.nio.file.Files.copy(binary.toPath(), exeCopy.toPath(),
java.nio.file.StandardCopyOption.REPLACE_EXISTING);
exeToRun = exeCopy;
} catch (Exception ignored) {}
}
ProcessBuilder pb;
if (System.getProperty("os.name","").toLowerCase().contains("mac")) {
// macOS: launch directly -- the .app bundle approach breaks stdio piping
// Just run the binary directly; modern macOS allows subprocess windows
// as long as the parent process has screen access (Processing does).
pb = new ProcessBuilder(exeToRun.getAbsolutePath());
} else {
pb = new ProcessBuilder(exeToRun.getAbsolutePath());
}
pb.directory(sketchFolder);
pb.redirectErrorStream(false);
// Pass sketch folder so loadImage/loadStrings find data/ assets
// On Windows, add bundled DLL directory to PATH so the exe finds them at runtime
String osName = System.getProperty("os.name", "").toLowerCase();
if (osName.contains("win") && runtimeDir != null) {
String existingPath = pb.environment().getOrDefault("PATH", "");
StringBuilder winPath = new StringBuilder();
// Add sketch folder first (DLLs are copied here)
winPath.append(sketchFolder.getAbsolutePath()).append(";");
// Add WinLibs portable gcc bin (compiler runtime DLLs)
File portableBin = new File(System.getenv("APPDATA") + "\\CppMode\\gcc\\mingw64\\bin");
if (portableBin.exists()) winPath.append(portableBin.getAbsolutePath()).append(";");
// Add bundled libs
File bundledLibs = new File(runtimeDir.getParentFile(), "libs/windows-x64");
if (bundledLibs.exists()) winPath.append(bundledLibs.getAbsolutePath()).append(";");
winPath.append(existingPath);
pb.environment().put("PATH", winPath.toString());
}
pb.environment().put("PROCESSING_SKETCH_NAME", sketchFolder.getName());
pb.environment().put("PROCESSING_SKETCH_PATH",
sketchFolder.getAbsolutePath().replace('\\', '/'));
// Pass mode src/ dir so Processing.cpp can find fonts
if (runtimeDir != null)
// Pass the mode root (parent of src/) so fonts/ subdir is reachable
pb.environment().put("PROCESSING_MODE_PATH",
runtimeDir.getParentFile().getAbsolutePath().replace('\\', '/'));
process = pb.start();
Thread out = new Thread(() -> pipe(process.getInputStream(), System.out));
Thread err = new Thread(() -> pipe(process.getErrorStream(), System.err));
out.start();
err.start();
int code = process.waitFor();
out.join();
err.join();
if (code != 0 && code != 137 && code != 143) listener.statusError("Sketch exited with code " + code);
else listener.statusNotice("Sketch finished.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
listener.statusError("Could not launch: " + e.getMessage());
}
}).start();
}
public void stop() {
if (process != null && process.isAlive())
process.destroyForcibly();
}
private void pipe(InputStream in, PrintStream out) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
String line;
while ((line = br.readLine()) != null)
out.println(line);
} catch (IOException ignored) {}
}
}