diff --git a/cli/loader/build.rs b/cli/loader/build.rs index 714a662b..b01f01bb 100644 --- a/cli/loader/build.rs +++ b/cli/loader/build.rs @@ -3,6 +3,10 @@ fn main() { "cargo:rustc-env=BUILD_TARGET={}", std::env::var("TARGET").unwrap() ); + println!( + "cargo:rustc-env=BUILD_HOST={}", + std::env::var("HOST").unwrap() + ); let emscripten_version = std::fs::read_to_string("emscripten-version").unwrap(); println!("cargo:rustc-env=EMSCRIPTEN_VERSION={emscripten_version}"); diff --git a/cli/loader/src/lib.rs b/cli/loader/src/lib.rs index a2f770ac..9dd6e5c4 100644 --- a/cli/loader/src/lib.rs +++ b/cli/loader/src/lib.rs @@ -83,6 +83,7 @@ impl Config { } const BUILD_TARGET: &str = env!("BUILD_TARGET"); +const BUILD_HOST: &str = env!("BUILD_HOST"); pub struct LanguageConfiguration<'a> { pub scope: Option, @@ -143,7 +144,7 @@ impl<'a> CompileConfig<'a> { scanner_path: None, external_files: externals, output_path, - flags: &["TREE_SITTER_REUSE_ALLOCATOR", "TREE_SITTER_INTERNAL_BUILD"], + flags: &[], name: String::new(), } } @@ -561,16 +562,38 @@ impl Loader { lock_file: &fs::File, lock_path: &Path, ) -> Result<(), Error> { - let mut cc = cc::Build::new(); - cc.cpp(true) - .opt_level(2) + let mut cc_config = cc::Build::new(); + cc_config .cargo_metadata(false) .cargo_warnings(false) .target(BUILD_TARGET) - .host(BUILD_TARGET) - .flag_if_supported("-Werror=implicit-function-declaration"); - let compiler = cc.get_compiler(); + .host(BUILD_HOST) + .file(&config.parser_path) + .includes(&config.header_paths); + + if let Some(scanner_path) = config.scanner_path.as_ref() { + if scanner_path.extension() != Some("c".as_ref()) { + cc_config.cpp(true); + eprintln!("Warning: Using a C++ scanner is now deprecated. Please migrate your scanner code to C, as C++ support will be removed in the near future."); + } else { + cc_config.std("c11"); + } + cc_config.file(scanner_path); + } + + if self.debug_build { + cc_config.opt_level(0).extra_warnings(true); + } else { + cc_config.opt_level(2).extra_warnings(false); + } + + for flag in config.flags { + cc_config.define(flag, None); + } + + let compiler = cc_config.get_compiler(); let mut command = Command::new(compiler.path()); + command.args(compiler.args()); for (key, value) in compiler.env() { command.env(key, value); } @@ -578,72 +601,24 @@ impl Loader { let output_path = config.output_path.as_ref().unwrap(); if compiler.is_like_msvc() { - command.args(["/nologo", "/LD"]); - - for path in &config.header_paths { - command.arg(format!("/I{}", path.to_string_lossy())); - } - - if self.debug_build { - command.arg("/Od"); - } else { - command.arg("/O2"); - } - command.arg(&config.parser_path); - - if let Some(scanner_path) = config.scanner_path.as_ref() { - if scanner_path.extension() != Some("c".as_ref()) { - eprintln!("Warning: Using a C++ scanner is now deprecated. Please migrate your scanner code to C, as C++ support will be removed in the near future."); - } - - command.arg(scanner_path); - } - command - .arg("/utf-8") - .arg("/link") - .arg(format!("/out:{}", output_path.to_str().unwrap())); + let out = format!("-out:{}", output_path.to_str().unwrap()); + command.arg(if self.debug_build { "-LDd" } else { "-LD" }); + command.arg("-utf-8"); + command.args(cc_config.get_files()); + command.arg("-link").arg(out); } else { - command - .arg("-shared") - .arg("-fno-exceptions") - .arg("-g") - .arg("-o") - .arg(output_path); - - for path in &config.header_paths { - command.arg(format!("-I{}", path.to_string_lossy())); - } - - if !cfg!(windows) { - command.arg("-fPIC"); - } - - if self.debug_build { - command.arg("-O0"); + command.args(["-Werror=implicit-function-declaration", "-g"]); + if cfg!(any(target_os = "macos", target_os = "ios")) { + command.arg("-dynamiclib"); + // TODO: remove when supported + command.arg("-UTREE_SITTER_REUSE_ALLOCATOR"); } else { - command.arg("-O2"); + command.arg("-shared"); } - - if let Some(scanner_path) = config.scanner_path.as_ref() { - if scanner_path.extension() == Some("c".as_ref()) { - command.arg("-xc").arg("-std=c11").arg(scanner_path); - } else { - eprintln!("Warning: Using a C++ scanner is now deprecated. Please migrate your scanner code to C, as C++ support will be removed in the near future."); - command.arg(scanner_path); - } - } - command.arg("-xc").arg(&config.parser_path); + command.args(cc_config.get_files()); + command.arg("-o").arg(output_path); } - // For conditional compilation of external scanner code when - // used internally by `tree-sitter parse` and other sub commands. - command.arg("-DTREE_SITTER_INTERNAL_BUILD"); - - // Always use the same allocator in the CLI as any scanner, useful for debugging and - // tracking memory leaks in tests. - #[cfg(not(any(target_os = "macos", target_os = "ios")))] - command.arg("-DTREE_SITTER_REUSE_ALLOCATOR"); - let output = command.output().with_context(|| { format!("Failed to execute the C compiler with the following command:\n{command:?}") })?; @@ -651,20 +626,24 @@ impl Loader { lock_file.unlock()?; fs::remove_file(lock_path)?; - if !output.status.success() { - return Err(anyhow!( + if output.status.success() { + Ok(()) + } else { + Err(anyhow!( "Parser compilation failed.\nStdout: {}\nStderr: {}", String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr) - )); + )) } - - Ok(()) } #[cfg(unix)] fn check_external_scanner(&self, name: &str, library_path: &Path) -> Result<()> { - let prefix = if cfg!(target_os = "macos") { "_" } else { "" }; + let prefix = if cfg!(any(target_os = "macos", target_os = "ios")) { + "_" + } else { + "" + }; let mut must_have = vec![ format!("{prefix}tree_sitter_{name}_external_scanner_create"), format!("{prefix}tree_sitter_{name}_external_scanner_destroy"), diff --git a/cli/src/generate/render.rs b/cli/src/generate/render.rs index 12e0c457..8bf72c3a 100644 --- a/cli/src/generate/render.rs +++ b/cli/src/generate/render.rs @@ -256,7 +256,7 @@ impl Generator { .count() + 1; let constant_name = if let Some(symbol) = symbol { - format!("{}_character_set_{}", self.symbol_ids[&symbol], count) + format!("{}_character_set_{}", self.symbol_ids[symbol], count) } else { format!("extras_character_set_{}", count) }; diff --git a/cli/src/main.rs b/cli/src/main.rs index b5d9c9ac..0c3b2f4d 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -500,7 +500,7 @@ fn run() -> Result<()> { } (true, false) => &["TREE_SITTER_REUSE_ALLOCATOR"], (false, true) => &["TREE_SITTER_INTERNAL_BUILD"], - (false, false) => &[""], + (false, false) => &[], }; let config = Config::load(None)?;