build(bindings): move header to tree_sitter subdirectory

This patch allows users to include the parser by the same path from
local build as well as installed location. Previously it was not
possible to include the header prior to installing the built parser.
This commit is contained in:
Scorg 2025-01-11 13:05:31 +05:00 committed by Amaan Qureshi
parent a633a06bb4
commit 40eb26e580
5 changed files with 72 additions and 22 deletions

View file

@ -6,7 +6,7 @@ use std::{
use anyhow::{anyhow, Context, Result};
use heck::{ToKebabCase, ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
use indoc::indoc;
use indoc::{formatdoc, indoc};
use semver::Version;
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
@ -288,9 +288,16 @@ pub fn generate_grammar_files(
})?;
// Write .gitattributes file
missing_path(repo_path.join(".gitattributes"), |path| {
generate_file(path, GITATTRIBUTES_TEMPLATE, language_name, &generate_opts)
})?;
missing_path_else(
repo_path.join(".gitattributes"),
allow_update,
|path| generate_file(path, GITATTRIBUTES_TEMPLATE, language_name, &generate_opts),
|path| {
let contents = fs::read_to_string(path)?;
write_file(path, contents.replace("bindings/c/* ", "bindings/c/** "))?;
Ok(())
},
)?;
// Write .editorconfig file
missing_path(repo_path.join(".editorconfig"), |path| {
@ -376,10 +383,19 @@ pub fn generate_grammar_files(
// Generate C bindings
if tree_sitter_config.bindings.c {
missing_path(bindings_dir.join("c"), create_dir)?.apply(|path| {
missing_path(
path.join(format!("tree-sitter-{language_name}.h")),
|path| generate_file(path, PARSER_NAME_H_TEMPLATE, language_name, &generate_opts),
)?;
let old_file = &path.join(format!("tree-sitter-{language_name}.h"));
if allow_update && fs::exists(old_file).unwrap_or(false) {
fs::remove_file(old_file)?;
}
missing_path(path.join("tree_sitter"), create_dir)?.apply(|include_path| {
missing_path(
include_path.join(format!("tree-sitter-{language_name}.h")),
|path| {
generate_file(path, PARSER_NAME_H_TEMPLATE, language_name, &generate_opts)
},
)?;
Ok(())
})?;
missing_path(
path.join(format!("tree-sitter-{language_name}.pc.in")),
@ -393,20 +409,50 @@ pub fn generate_grammar_files(
},
)?;
missing_path(repo_path.join("Makefile"), |path| {
generate_file(path, MAKEFILE_TEMPLATE, language_name, &generate_opts)
})?;
missing_path_else(
repo_path.join("Makefile"),
allow_update,
|path| {
generate_file(path, MAKEFILE_TEMPLATE, language_name, &generate_opts)
},
|path| {
let contents = fs::read_to_string(path)?.replace(
"-m644 bindings/c/$(LANGUAGE_NAME).h",
"-m644 bindings/c/tree_sitter/$(LANGUAGE_NAME).h"
);
write_file(path, contents)?;
Ok(())
},
)?;
missing_path_else(
repo_path.join("CMakeLists.txt"),
allow_update,
|path| generate_file(path, CMAKELISTS_TXT_TEMPLATE, language_name, &generate_opts),
|path| {
let contents = fs::read_to_string(path)?;
let old = "add_custom_target(test";
if contents.contains(old) {
write_file(path, contents.replace(old, "add_custom_target(ts-test"))?;
}
let mut contents = fs::read_to_string(path)?;
contents = contents
.replace("add_custom_target(test", "add_custom_target(ts-test")
.replace(
&formatdoc! {r#"
install(FILES bindings/c/tree-sitter-{language_name}.h
DESTINATION "${{CMAKE_INSTALL_INCLUDEDIR}}/tree_sitter")
"#},
indoc! {r#"
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bindings/c/tree_sitter"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
FILES_MATCHING PATTERN "*.h")
"#}
).replace(
&format!("target_include_directories(tree-sitter-{language_name} PRIVATE src)"),
&formatdoc! {"
target_include_directories(tree-sitter-{language_name}
PRIVATE src
INTERFACE $<BUILD_INTERFACE:${{CMAKE_CURRENT_SOURCE_DIR}}/bindings/c>
$<INSTALL_INTERFACE:${{CMAKE_INSTALL_INCLUDEDIR}}>)
"}
);
write_file(path, contents)?;
Ok(())
},
)?;

View file

@ -28,7 +28,10 @@ add_library(tree-sitter-PARSER_NAME src/parser.c)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c)
target_sources(tree-sitter-PARSER_NAME PRIVATE src/scanner.c)
endif()
target_include_directories(tree-sitter-PARSER_NAME PRIVATE src)
target_include_directories(tree-sitter-PARSER_NAME
PRIVATE src
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/bindings/c>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_compile_definitions(tree-sitter-PARSER_NAME PRIVATE
$<$<BOOL:${TREE_SITTER_REUSE_ALLOCATOR}>:TREE_SITTER_REUSE_ALLOCATOR>
@ -46,8 +49,9 @@ configure_file(bindings/c/tree-sitter-PARSER_NAME.pc.in
include(GNUInstallDirs)
install(FILES bindings/c/tree-sitter-PARSER_NAME.h
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/tree_sitter")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bindings/c/tree_sitter"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
FILES_MATCHING PATTERN "*.h")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-PARSER_NAME.pc"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig")
install(TARGETS tree-sitter-PARSER_NAME

View file

@ -6,7 +6,7 @@ src/parser.c linguist-generated
src/tree_sitter/* linguist-generated
# C bindings
bindings/c/* linguist-generated
bindings/c/** linguist-generated
CMakeLists.txt linguist-generated
Makefile linguist-generated

View file

@ -71,7 +71,7 @@ $(PARSER): $(SRC_DIR)/grammar.json
install: all
install -d '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/PARSER_NAME '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)'
install -m644 bindings/c/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h
install -m644 bindings/c/tree_sitter/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h
install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a
install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER)

View file

@ -126,7 +126,7 @@ to be used from different language. Here is a list of these bindings files that
- `Makefile` — This file tells [`make`][make] how to compile your language.
- `CMakeLists.txt` — This file tells [`cmake`][cmake] how to compile your language.
- `bindings/c/tree-sitter-language.h` — This file provides the C interface of your language.
- `bindings/c/tree_sitter/tree-sitter-language.h` — This file provides the C interface of your language.
- `bindings/c/tree-sitter-language.pc` — This file provides [pkg-config][pkg-config] metadata about your language's C library.
- `src/tree_sitter/parser.h` — This file provides some basic C definitions that are used in your generated `parser.c` file.
- `src/tree_sitter/alloc.h` — This file provides some memory allocation macros that are to be used in your external scanner,