feat(bindings): generate in 2 steps via make/cmake (#4646)

This makes it possible to run `make` or `cmake --build` in grammar
repos where `grammar.json` hasn't been included, and still get the parser
compilation to work.
This commit is contained in:
Antonin Delpeuch 2025-08-02 10:57:29 +02:00 committed by GitHub
parent 6850df969d
commit b787f31481
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 52 additions and 2 deletions

View file

@ -487,6 +487,22 @@ pub fn generate_grammar_files(
if !contents.contains("cd '$(DESTDIR)$(LIBDIR)' && ln -sf") {
eprintln!("Replacing Makefile");
generate_file(path, MAKEFILE_TEMPLATE, language_name, &generate_opts)?;
} else {
let contents = contents
.replace(
indoc! {r"
$(PARSER): $(SRC_DIR)/grammar.json
$(TS) generate $^
"},
indoc! {r"
$(SRC_DIR)/grammar.json: grammar.js
$(TS) generate --stage=json $^
$(PARSER): $(SRC_DIR)/grammar.json
$(TS) generate --stage=parser $^
"}
);
write_file(path, contents)?;
}
Ok(())
},
@ -518,6 +534,30 @@ pub fn generate_grammar_files(
INTERFACE $<BUILD_INTERFACE:${{CMAKE_CURRENT_SOURCE_DIR}}/bindings/c>
$<INSTALL_INTERFACE:${{CMAKE_INSTALL_INCLUDEDIR}}>)
"}
).replace(
indoc! {r#"
add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json"
COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json
--abi=${TREE_SITTER_ABI_VERSION}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Generating parser.c")
"#},
indoc! {r#"
add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/grammar.js"
COMMAND "${TREE_SITTER_CLI}" generate grammar.js
--stage=json
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Generating grammar.json")
add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json"
COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json
--stage=parser --abi=${TREE_SITTER_ABI_VERSION}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Generating parser.c")
"#}
);
write_file(path, contents)?;
Ok(())

View file

@ -19,10 +19,17 @@ include(GNUInstallDirs)
find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI")
add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/grammar.js"
COMMAND "${TREE_SITTER_CLI}" generate grammar.js
--stage=json
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Generating grammar.json")
add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json"
COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json
--abi=${TREE_SITTER_ABI_VERSION}
--stage=parser --abi=${TREE_SITTER_ABI_VERSION}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Generating parser.c")

View file

@ -72,8 +72,11 @@ $(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in
-e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \
-e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@
$(SRC_DIR)/grammar.json: grammar.js
$(TS) generate --stage=json $^
$(PARSER): $(SRC_DIR)/grammar.json
$(TS) generate $^
$(TS) generate --stage=parser $^
install: all
install -d '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/KEBAB_PARSER_NAME '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)'