tree-sitter/lib/binding_rust/build.rs
James McCoy 889015f03b
build(rust): use $CARGO_PKG_RUST_VERSION when generating bindings (#4512)
Since cargo 1.63, $CARGO_PKG_RUST_VERSION is set in the build
environment to the value of the rust-version Cargo.toml field.

This removes the need to manually invoke cargo from build.rs during a
build of the tree-sitter crate with the bindgen feature enabled.

Removing the cargo invocation also ensures the build doesn't write to
the current directory when the target directory has been redirected
elsewhere. "cargo metadata" will attempt to update Cargo.lock, which
will fail if the source tree is read-only.
2025-06-13 11:11:22 -07:00

100 lines
2.9 KiB
Rust

use std::{env, fs, path::PathBuf};
fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
#[cfg(feature = "bindgen")]
generate_bindings(&out_dir);
fs::copy(
"src/wasm/stdlib-symbols.txt",
out_dir.join("stdlib-symbols.txt"),
)
.unwrap();
let mut config = cc::Build::new();
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_WASM");
if env::var("CARGO_FEATURE_WASM").is_ok() {
config
.define("TREE_SITTER_FEATURE_WASM", "")
.define("static_assert(...)", "")
.include(env::var("DEP_WASMTIME_C_API_INCLUDE").unwrap());
}
let manifest_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let include_path = manifest_path.join("include");
let src_path = manifest_path.join("src");
let wasm_path = src_path.join("wasm");
for entry in fs::read_dir(&src_path).unwrap() {
let entry = entry.unwrap();
let path = src_path.join(entry.file_name());
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
}
config
.flag_if_supported("-std=c11")
.flag_if_supported("-fvisibility=hidden")
.flag_if_supported("-Wshadow")
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-incompatible-pointer-types")
.include(&src_path)
.include(&wasm_path)
.include(&include_path)
.define("_POSIX_C_SOURCE", "200112L")
.define("_DEFAULT_SOURCE", None)
.warnings(false)
.file(src_path.join("lib.c"))
.compile("tree-sitter");
println!("cargo:include={}", include_path.display());
}
#[cfg(feature = "bindgen")]
fn generate_bindings(out_dir: &std::path::Path) {
use std::{process::Command, str::FromStr};
use bindgen::RustTarget;
const HEADER_PATH: &str = "include/tree_sitter/api.h";
println!("cargo:rerun-if-changed={HEADER_PATH}");
let no_copy = [
"TSInput",
"TSLanguage",
"TSLogger",
"TSLookaheadIterator",
"TSParser",
"TSTree",
"TSQuery",
"TSQueryCursor",
"TSQueryCapture",
"TSQueryMatch",
"TSQueryPredicateStep",
];
let rust_version = env!("CARGO_PKG_RUST_VERSION");
let bindings = bindgen::Builder::default()
.header(HEADER_PATH)
.layout_tests(false)
.allowlist_type("^TS.*")
.allowlist_function("^ts_.*")
.allowlist_var("^TREE_SITTER.*")
.no_copy(no_copy.join("|"))
.prepend_enum_name(false)
.use_core()
.clang_arg("-D TREE_SITTER_FEATURE_WASM")
.rust_target(RustTarget::from_str(rust_version).unwrap())
.generate()
.expect("Failed to generate bindings");
let bindings_rs = out_dir.join("bindings.rs");
bindings.write_to_file(&bindings_rs).unwrap_or_else(|_| {
panic!(
"Failed to write bindings into path: {}",
bindings_rs.display()
)
});
}