Skip to content

Commit b1d3823

Browse files
committed
Windows: portable gcc via WinLibs, PATH g++ fallback, bundled DLL detection
1 parent 4bb6603 commit b1d3823

3 files changed

Lines changed: 74 additions & 3 deletions

File tree

mode/CppMode.jar

1.28 KB
Binary file not shown.

src/java/CppBuild.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,14 +417,18 @@ private void checkGppAvailable(RunnerListener listener) throws Exception {
417417
boolean isMac = os.contains("mac");
418418
if (isWin) {
419419
for (String p : new String[]{
420+
// Portable gcc (downloaded by InstallWizard, no MSYS2 needed)
421+
System.getenv("APPDATA") + "\\CppMode\\gcc\\mingw64\\bin\\g++.exe",
420422
"C:\\msys64\\mingw64\\bin\\g++.exe",
421423
"C:\\msys2\\mingw64\\bin\\g++.exe",
422424
System.getProperty("user.home") + "\\msys64\\mingw64\\bin\\g++.exe",
423425
"C:\\msys64\\ucrt64\\bin\\g++.exe"})
424426
if (new File(p).exists()) return;
425-
// Do NOT fall back to PATH g++ -- it won't have GLFW/GLEW and will
426-
// produce linker errors. Only MSYS2 mingw64 g++ is accepted on Windows.
427-
// Run the wizard unconditionally if MSYS2 g++ not found at known paths.
427+
// Try PATH g++ as final fallback (bundled DLLs cover GLFW/GLEW)
428+
try {
429+
if (Runtime.getRuntime().exec(new String[]{"g++","--version"}).waitFor()==0) return;
430+
} catch (Exception ignored) {}
431+
// No g++ found anywhere -- run the install wizard.
428432
if (InstallWizard.run(listener)) return;
429433

430434
Object[] opts = { "Install Automatically", "Download MSYS2", "Cancel" };
@@ -3340,6 +3344,8 @@ private String preprocessMacros(String code) {
33403344
private String findGpp(boolean win) {
33413345
if (win) {
33423346
for (String p : new String[]{
3347+
// Portable gcc (downloaded by InstallWizard, no MSYS2 needed)
3348+
System.getenv("APPDATA") + "\\CppMode\\gcc\\mingw64\\bin\\g++.exe",
33433349
"C:\\msys64\\mingw64\\bin\\g++.exe",
33443350
"C:\\msys2\\mingw64\\bin\\g++.exe",
33453351
System.getProperty("user.home") + "\\msys64\\mingw64\\bin\\g++.exe"})

src/java/InstallWizard.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,64 @@ private boolean commandExists(String... cmd) {
238238
// ── Windows ────────────────────────────────────────────────────────────
239239

240240
/** Pure detection, no dialog — used by run() before showing anything. */
241+
private static final String WINLIBS_URL =
242+
"https://github.com/brechtsanders/winlibs_mingw/releases/download/" +
243+
"14.2.0posix-19.1.1-12.0.0-ucrt-r2/" +
244+
"winlibs-x86_64-posix-seh-gcc-14.2.0-mingw-w64ucrt-12.0.0-r2.zip";
245+
246+
public static File getPortableGccDir() {
247+
return new File(System.getenv("APPDATA") + "\\CppMode\\gcc\\mingw64\\bin");
248+
}
249+
250+
public static File getPortableGpp() {
251+
return new File(getPortableGccDir(), "g++.exe");
252+
}
253+
254+
private boolean installPortableGcc() {
255+
File gccDir = new File(System.getenv("APPDATA") + "\\CppMode\\gcc");
256+
gccDir.mkdirs();
257+
File zipFile = new File(gccDir, "winlibs-gcc.zip");
258+
try {
259+
setStep("Downloading portable g++ (WinLibs GCC 14.2)...");
260+
appendLog("Source: " + WINLIBS_URL);
261+
appendLog("Destination: " + gccDir.getAbsolutePath());
262+
appendLog("Size: ~130 MB — please wait...");
263+
try (java.io.InputStream in = new java.net.URI(WINLIBS_URL).toURL().openStream();
264+
java.io.OutputStream out = new java.io.FileOutputStream(zipFile)) {
265+
byte[] buf = new byte[64 * 1024];
266+
long total = 0; int n;
267+
while ((n = in.read(buf)) != -1) {
268+
if (cancelled.get()) return false;
269+
out.write(buf, 0, n);
270+
total += n;
271+
if (total % (5 * 1024 * 1024) < buf.length)
272+
appendLog("Downloaded " + (total / (1024 * 1024)) + " MB...");
273+
}
274+
}
275+
setStep("Extracting gcc...");
276+
appendLog("Extracting to " + gccDir.getAbsolutePath());
277+
// Use PowerShell Expand-Archive (available on all modern Windows)
278+
Process extract = new ProcessBuilder(
279+
"powershell", "-NoProfile", "-Command",
280+
"Expand-Archive -Force -Path '" + zipFile.getAbsolutePath() +
281+
"' -DestinationPath '" + gccDir.getAbsolutePath() + "'")
282+
.redirectErrorStream(true).start();
283+
streamToLog(extract);
284+
int code = extract.waitFor();
285+
zipFile.delete(); // clean up zip after extraction
286+
if (code != 0) { appendLog("Extraction failed."); return false; }
287+
if (!getPortableGpp().exists()) {
288+
appendLog("g++.exe not found after extraction -- unexpected zip structure.");
289+
return false;
290+
}
291+
appendLog("Portable g++ installed: " + getPortableGpp().getAbsolutePath());
292+
return true;
293+
} catch (Exception e) {
294+
appendLog("Error: " + e.getMessage());
295+
return false;
296+
}
297+
}
298+
241299
private java.util.List<String> detectWindowsMissing() {
242300
String pacman = findWindowsPacman();
243301
boolean haveGpp = pacman != null ? false : commandExists("g++", "--version");
@@ -321,6 +379,13 @@ private boolean[] windowsLibsPresentDetailed() {
321379
*/
322380
private boolean installWindowsToolchain(String existingPacman) {
323381
try {
382+
// Prefer portable gcc (no MSYS2 needed) unless MSYS2 already installed.
383+
if (existingPacman == null && !getPortableGpp().exists()) {
384+
if (!installPortableGcc()) return false;
385+
if (cancelled.get()) return false;
386+
// Portable gcc bundles everything -- no pacman step needed.
387+
return true;
388+
}
324389
String pacman = existingPacman;
325390
if (pacman == null) {
326391
File installer = File.createTempFile("msys2-installer", ".exe");

0 commit comments

Comments
 (0)