From ca65d312e715413cd5675cafd599d74534900d3f Mon Sep 17 00:00:00 2001
From: Pascal Kuthe <pascal.kuthe@semimod.de>
Date: Tue, 18 Apr 2023 03:10:19 +0200
Subject: [PATCH] always build grammars with c++14 and c11 (#6792)

---
 Cargo.lock                  |  1 +
 helix-loader/Cargo.toml     |  1 +
 helix-loader/src/grammar.rs | 48 +++++++++++++++++++++++++++++++------
 3 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 470f41b4..38b10fce 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1134,6 +1134,7 @@ dependencies = [
  "log",
  "once_cell",
  "serde",
+ "tempfile",
  "threadpool",
  "toml",
  "tree-sitter",
diff --git a/helix-loader/Cargo.toml b/helix-loader/Cargo.toml
index 31cfbf62..60b1e911 100644
--- a/helix-loader/Cargo.toml
+++ b/helix-loader/Cargo.toml
@@ -27,6 +27,7 @@ log = "0.4"
 # cloning/compiling tree-sitter grammars
 cc = { version = "1" }
 threadpool = { version = "1.0" }
+tempfile = "3.5.0"
 
 [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
 libloading = "0.8"
diff --git a/helix-loader/src/grammar.rs b/helix-loader/src/grammar.rs
index 2eb59a38..3697ec7e 100644
--- a/helix-loader/src/grammar.rs
+++ b/helix-loader/src/grammar.rs
@@ -8,6 +8,7 @@ use std::{
     process::Command,
     sync::mpsc::channel,
 };
+use tempfile::TempPath;
 use tree_sitter::Language;
 
 #[cfg(unix)]
@@ -446,13 +447,17 @@ fn build_tree_sitter_library(
         command.env(key, value);
     }
     command.args(compiler.args());
+    // used to delay dropping the temporary object file until after the compilation is complete
+    let _path_guard;
 
     if cfg!(all(windows, target_env = "msvc")) {
         command
             .args(["/nologo", "/LD", "/I"])
             .arg(header_path)
             .arg("/Od")
-            .arg("/utf-8");
+            .arg("/utf-8")
+            .arg("/std:c++14")
+            .arg("/std:c11");
         if let Some(scanner_path) = scanner_path.as_ref() {
             command.arg(scanner_path);
         }
@@ -466,20 +471,49 @@ fn build_tree_sitter_library(
             .arg("-shared")
             .arg("-fPIC")
             .arg("-fno-exceptions")
-            .arg("-g")
             .arg("-I")
             .arg(header_path)
             .arg("-o")
-            .arg(&library_path)
-            .arg("-O3");
+            .arg(&library_path);
+
         if let Some(scanner_path) = scanner_path.as_ref() {
             if scanner_path.extension() == Some("c".as_ref()) {
-                command.arg("-xc").arg("-std=c99").arg(scanner_path);
+                command.arg("-xc").arg("-std=c11").arg(scanner_path);
             } else {
-                command.arg(scanner_path);
+                let mut cpp_command = Command::new(compiler.path());
+                cpp_command.current_dir(src_path);
+                for (key, value) in compiler.env() {
+                    cpp_command.env(key, value);
+                }
+                cpp_command.args(compiler.args());
+                let object_file =
+                    library_path.with_file_name(format!("{}_scanner.o", &grammar.grammar_id));
+                cpp_command
+                    .arg("-fPIC")
+                    .arg("-fno-exceptions")
+                    .arg("-I")
+                    .arg(header_path)
+                    .arg("-o")
+                    .arg(&object_file)
+                    .arg("-std=c++14")
+                    .arg("-c")
+                    .arg(scanner_path);
+                let output = cpp_command
+                    .output()
+                    .context("Failed to execute C++ compiler")?;
+                if !output.status.success() {
+                    return Err(anyhow!(
+                        "Parser compilation failed.\nStdout: {}\nStderr: {}",
+                        String::from_utf8_lossy(&output.stdout),
+                        String::from_utf8_lossy(&output.stderr)
+                    ));
+                }
+
+                command.arg(&object_file);
+                _path_guard = TempPath::from_path(object_file);
             }
         }
-        command.arg("-xc").arg(parser_path);
+        command.arg("-xc").arg("-std=c11").arg(parser_path);
         if cfg!(all(
             unix,
             not(any(target_os = "macos", target_os = "illumos"))