diff options
author | Blaž Hrastnik | 2020-09-09 05:41:12 +0000 |
---|---|---|
committer | Blaž Hrastnik | 2020-09-09 05:41:12 +0000 |
commit | 7eac12a4bb02aaa96f63de612077a12df1d5fedc (patch) | |
tree | c54b40453427e9f029577d710ebb92325a4d4349 /helix-syntax/build.rs | |
parent | 563e094916b6e0d3ef0fafe8141372116e35ebde (diff) |
Add helix-syntax as a wrapper around tree-sitter parsers.
Diffstat (limited to 'helix-syntax/build.rs')
-rw-r--r-- | helix-syntax/build.rs | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/helix-syntax/build.rs b/helix-syntax/build.rs new file mode 100644 index 00000000..217ba9fa --- /dev/null +++ b/helix-syntax/build.rs @@ -0,0 +1,126 @@ +use cc::Build; + +use std::io::{BufWriter, Read, Write}; +use std::path::{Path, PathBuf}; +use std::{env, fs}; + +fn get_opt_level() -> u32 { + env::var("OPT_LEVEL").unwrap().parse::<u32>().unwrap() +} + +fn get_debug() -> bool { + env::var("DEBUG").unwrap() == "true" +} + +fn collect_tree_sitter_dirs(ignore: Vec<String>) -> Vec<String> { + let mut dirs = Vec::new(); + for entry in fs::read_dir("languages").unwrap() { + if let Ok(entry) = entry { + let path = entry.path(); + let dir = path.file_name().unwrap().to_str().unwrap().to_string(); + if !ignore.contains(&dir) { + dirs.push(dir); + } + } + } + dirs +} + +fn collect_src_files(dir: &str) -> (Vec<String>, Vec<String>) { + eprintln!("Collect files for {}", dir); + + let mut c_files = Vec::new(); + let mut cpp_files = Vec::new(); + let path = PathBuf::from("languages").join(&dir).join("src"); + for entry in fs::read_dir(path).unwrap() { + if let Ok(entry) = entry { + let path = entry.path(); + if path + .file_stem() + .unwrap() + .to_str() + .unwrap() + .starts_with("binding") + { + continue; + } + if let Some(ext) = path.extension() { + if ext == "c" { + c_files.push(path.to_str().unwrap().to_string()); + } else if ext == "cc" || ext == "cpp" || ext == "cxx" { + cpp_files.push(path.to_str().unwrap().to_string()); + } + } + } + } + (c_files, cpp_files) +} + +fn build_c(files: Vec<String>, language: &str) { + let mut build = cc::Build::new(); + for file in files { + build + .file(&file) + .include(PathBuf::from(file).parent().unwrap()) + .pic(true) + .opt_level(get_opt_level()) + .debug(get_debug()) + .warnings(false) + .flag_if_supported("-std=c99"); + } + build.compile(&format!("tree-sitter-{}-c", language)); +} + +fn build_cpp(files: Vec<String>, language: &str) { + let mut build = cc::Build::new(); + for file in files { + build + .file(&file) + .include(PathBuf::from(file).parent().unwrap()) + .pic(true) + .opt_level(get_opt_level()) + .debug(get_debug()) + .warnings(false) + .cpp(true); + } + build.compile(&format!("tree-sitter-{}-cpp", language)); +} + +fn build_dir(dir: &str, language: &str) { + println!("Build language {}", language); + if PathBuf::from("languages") + .join(dir) + .read_dir() + .unwrap() + .next() + .is_none() + { + eprintln!( + "The directory {} is empty, did you use 'git clone --recursive'?", + dir + ); + eprintln!("You can fix in using 'git submodule init && git submodule update --recursive'."); + std::process::exit(1); + } + let (c, cpp) = collect_src_files(&dir); + if !c.is_empty() { + build_c(c, &language); + } + if !cpp.is_empty() { + build_cpp(cpp, &language); + } +} + +fn main() { + let ignore = vec![ + "tree-sitter-typescript".to_string(), + "tree-sitter-cpp".to_string(), + ]; + let dirs = collect_tree_sitter_dirs(ignore); + for dir in dirs { + let language = &dir[12..]; // skip tree-sitter- prefix + build_dir(&dir, &language); + } + build_dir("tree-sitter-typescript/tsx", "tsx"); + build_dir("tree-sitter-typescript/typescript", "typescript"); +} |