diff --git a/Cargo.lock b/Cargo.lock index 470f41b44..38b10fce4 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 31cfbf62d..60b1e911b 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 2eb59a38e..3697ec7e1 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"))