From a38e3e66788129bbd441f9d28e450dba8a7438d1 Mon Sep 17 00:00:00 2001
From: Pierre Langlois <pierre.langlois@gmx.com>
Date: Wed, 23 Feb 2022 20:38:51 +0000
Subject: [PATCH] wip build-system for tree-sitter grammars.
---
Makefile.am | 2 +
gnu/packages/tree-sitter.scm | 312 ++++++++----------------
guix/build-system/tree-sitter.scm | 109 +++++++++
guix/build/tree-sitter-build-system.scm | 124 ++++++++++
4 files changed, 342 insertions(+), 205 deletions(-)
create mode 100644 guix/build-system/tree-sitter.scm
create mode 100644 guix/build/tree-sitter-build-system.scm
@@ -167,6 +167,7 @@ MODULES = \
guix/build-system/ruby.scm \
guix/build-system/scons.scm \
guix/build-system/texlive.scm \
+ guix/build-system/tree-sitter.scm \
guix/build-system/trivial.scm \
guix/ftp-client.scm \
guix/http-client.scm \
@@ -220,6 +221,7 @@ MODULES = \
guix/build/ruby-build-system.scm \
guix/build/scons-build-system.scm \
guix/build/texlive-build-system.scm \
+ guix/build/tree-sitter-build-system.scm \
guix/build/waf-build-system.scm \
guix/build/haskell-build-system.scm \
guix/build/julia-build-system.scm \
@@ -23,6 +23,7 @@ (define-module (gnu packages tree-sitter)
#:use-module (guix build-system emacs)
#:use-module (guix build-system gnu)
#:use-module (guix build-system node)
+ #:use-module (guix build-system tree-sitter)
#:use-module (guix build-system trivial)
#:use-module (guix download)
#:use-module (guix git-download)
@@ -224,70 +225,7 @@ (define-public tree-sitter-c
"0454jziys33i4kbwnvi9xcck0fzya792ghy32ahgk1hhv96xga9w"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
- (build-system node-build-system)
- (native-inputs
- (list tree-sitter tree-sitter-cli))
- (outputs '("out" "js"))
- (arguments
- (list
- #:phases
- (with-imported-modules '((guix build json))
- #~(modify-phases %standard-phases
- (add-after 'patch-dependencies 'delete-dependencies
- (lambda _
- (delete-dependencies '("tree-sitter-cli"
- "nan"
- "node-gyp"))))
- (replace 'build
- (lambda _
- (invoke "tree-sitter" "generate" "--no-bindings")))
- (replace 'check
- (lambda _
- (invoke "tree-sitter" "test")))
- (replace 'install
- (lambda _
- (use-modules (guix build json)
- (ice-9 regex))
- (let* ((name (assoc-ref
- (call-with-input-file "package.json" read-json)
- "name"))
- (lang (cond
- ((string-match "^(@.*/)?tree-sitter-(.*)$" name)
- => (lambda (m)
- (match:substring m 2)))
- (else #f)))
- (lib (string-append #$output "/lib/tree-sitter")))
- (mkdir-p lib)
- (define (source-file path)
- (if (file-exists? path)
- path
- #f))
- (apply invoke
- `(,#$(cxx-for-target)
- "-shared"
- "-fPIC"
- "-fno-exceptions"
- "-O2"
- "-g"
- "-o" ,(string-append lib "/" lang ".so")
- ,@(cond
- ((source-file "src/scanner.c")
- => (lambda (file) (list "-xc" "-std=c99" file)))
- ((source-file "src/scanner.cc")
- => (lambda (file) (list file)))
- (else '()))
- "-xc" "src/parser.c")))))
- (add-after 'install 'install-js-module
- (lambda* (#:key inputs #:allow-other-keys)
- (invoke (search-input-file inputs "/bin/npm")
- "--prefix" #$output:js
- "--global"
- "--offline"
- "--loglevel" "info"
- "--production"
- ;; Skip scripts to prevent building bindings via GYP.
- "--ignore-scripts"
- "install" "../package.tgz")))))))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-c")
(synopsis "Tree-sitter C grammar")
(description
@@ -296,7 +234,6 @@ (define (source-file path)
(define-public tree-sitter-cpp
(package
- (inherit tree-sitter-c)
(name "tree-sitter-cpp")
(version "0.20.0")
(source (origin
@@ -311,7 +248,8 @@ (define-public tree-sitter-cpp
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
(inputs
- (list `(,tree-sitter-c "js")))
+ (list tree-sitter-c))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-cpp")
(synopsis "Tree-sitter C++ grammar")
(description
@@ -319,7 +257,7 @@ (define-public tree-sitter-cpp
(license license:expat)))
(define-public tree-sitter-c-sharp
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-c-sharp")
(version "0.19.1")
(source (origin
@@ -333,6 +271,7 @@ (define-public tree-sitter-c-sharp
"054fmpf47cwh59gbg00sc0nl237ba4rnxi73miz39yqzcs87055r"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-c-sharp")
(synopsis "Tree-sitter C# grammar")
(description
@@ -340,7 +279,7 @@ (define-public tree-sitter-c-sharp
(license license:expat)))
(define-public tree-sitter-bash
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-bash")
(version "0.19.0")
(source (origin
@@ -354,17 +293,7 @@ (define-public tree-sitter-bash
"18c030bb65r50i6z37iy7jb9z9i8i36y7b08dbc9bchdifqsijs5"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
- (arguments
- (substitute-keyword-arguments (package-arguments tree-sitter-c)
- ((#:phases phases)
- `(modify-phases ,phases
- (replace 'delete-dependencies
- (lambda _
- (delete-dependencies '("tree-sitter-cli"
- "nan"
- "node-gyp"
- "prebuild"
- "prebuild-install"))))))))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-bash")
(synopsis "Tree-sitter Bash grammar")
(description
@@ -372,7 +301,7 @@ (define-public tree-sitter-bash
(license license:expat)))
(define-public tree-sitter-css
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-css")
(version "0.19.0")
(source (origin
@@ -386,6 +315,7 @@ (define-public tree-sitter-css
"014jrlgi7zfza9g38hsr4vlbi8964i5p7iglaih6qmzaiml7bja2"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-css")
(synopsis "Tree-sitter CSS grammar")
(description
@@ -395,7 +325,7 @@ (define-public tree-sitter-css
(define-public tree-sitter-elixir
(let ((commit "de20391afe5cb03ef1e8a8e43167e7b58cc52869")
(revision "1"))
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-elixir")
(version (git-version "0.19.0" revision commit))
(source (origin
@@ -409,16 +339,7 @@ (define-public tree-sitter-elixir
"0zrkrwhw3g1vazsxcwrfd1fk4wvs9hdwmwp6073mfh370bz4140h"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
- (arguments
- (substitute-keyword-arguments (package-arguments tree-sitter-c)
- ((#:phases phases)
- `(modify-phases ,phases
- (replace 'delete-dependencies
- (lambda _
- (delete-dependencies '("tree-sitter-cli"
- "node-gyp"
- "nan"
- "prettier"))))))))
+ (build-system tree-sitter-build-system)
(home-page "https://elixir-lang.org/tree-sitter-elixir/")
(synopsis "Tree-sitter Elixir grammar")
(description
@@ -428,7 +349,7 @@ (define-public tree-sitter-elixir
license:expat)))))
(define-public tree-sitter-elm
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-elm")
(version "5.5.1")
(source (origin
@@ -442,18 +363,7 @@ (define-public tree-sitter-elm
"10hbi4vyj4hjixqswdcbvzl60prldczz29mlp02if61wvwiwvqrw"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
- (arguments
- (substitute-keyword-arguments (package-arguments tree-sitter-c)
- ((#:phases phases)
- `(modify-phases ,phases
- (replace 'delete-dependencies
- (lambda _
- (delete-dependencies '("tree-sitter-cli"
- "nan"
- "node-gyp"
- "@asgerf/dts-tree-sitter"
- "prebuild"
- "prebuild-install"))))))))
+ (build-system tree-sitter-build-system)
(home-page "https://elm-tooling.github.io/tree-sitter-elm/")
(synopsis "Tree-sitter Elm grammar")
(description
@@ -461,7 +371,7 @@ (define-public tree-sitter-elm
(license license:expat)))
(define-public tree-sitter-go
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-go")
(version "0.19.1")
(source (origin
@@ -475,6 +385,7 @@ (define-public tree-sitter-go
"0nxs47vd2fc2fr0qlxq496y852rwg39flhg334s7dlyq7d3lcx4x"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-go")
(synopsis "Tree-sitter Go grammar")
(description
@@ -482,7 +393,7 @@ (define-public tree-sitter-go
(license license:expat)))
(define-public tree-sitter-html
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-html")
(version "0.19.0")
(source (origin
@@ -496,6 +407,7 @@ (define-public tree-sitter-html
"1hg7vbcy7bir6b8x11v0a4x0glvqnsqc3i2ixiarbxmycbgl3axy"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-html")
(synopsis "Tree-sitter HTML grammar")
(description
@@ -503,7 +415,7 @@ (define-public tree-sitter-html
(license license:expat)))
(define-public tree-sitter-java
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-java")
(version "0.19.1")
(source (origin
@@ -517,6 +429,7 @@ (define-public tree-sitter-java
"07zw9ygb45hnvlx9qlz7rlz8hc3byjy03d24v72i5iyhpiiwlhvl"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-java")
(synopsis "Tree-sitter Java grammar")
(description
@@ -524,7 +437,7 @@ (define-public tree-sitter-java
(license license:expat)))
(define-public tree-sitter-javascript
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-javascript")
(version "0.20.0")
(source (origin
@@ -538,6 +451,7 @@ (define-public tree-sitter-javascript
"175yrk382n2di0c2xn4gpv8y4n83x1lg4hqn04vabf0yqynlkq67"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-javascript")
(synopsis "Tree-sitter Javascript grammar")
(description
@@ -546,7 +460,7 @@ (define-public tree-sitter-javascript
(license license:expat)))
(define-public tree-sitter-json
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-json")
(version "0.19.0")
(source (origin
@@ -560,6 +474,7 @@ (define-public tree-sitter-json
"06pjh31bv9ja9hlnykk257a6zh8bsxg2fqa54al7qk1r4n9ksnff"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-json")
(synopsis "Tree-sitter JSON grammar")
(description
@@ -567,7 +482,7 @@ (define-public tree-sitter-json
(license license:expat)))
(define-public tree-sitter-julia
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-julia")
(version "0.19.0")
(source (origin
@@ -581,6 +496,7 @@ (define-public tree-sitter-julia
"1pbnmvhy2gq4vg1b0sjzmjm4s2gsgdjh7h01yj8qrrqbcl29c463"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-julia")
(synopsis "Tree-sitter Julia grammar")
(description
@@ -590,7 +506,7 @@ (define-public tree-sitter-julia
(define-public tree-sitter-ocaml
(let ((commit "0348562f385bc2bd67ecf181425e1afd6d454192")
(revision "1"))
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-ocaml")
(version (git-version "0.19.0" revision commit))
(source (origin
@@ -617,43 +533,44 @@ (define-public tree-sitter-ocaml
'("ocaml" "interface"))
#t))))
(arguments
- (substitute-keyword-arguments (package-arguments tree-sitter-c)
- ((#:phases phases)
- #~(modify-phases #$phases
- (replace 'build
- (lambda _
- (for-each (lambda (dir)
- (with-directory-excursion dir
- (invoke "tree-sitter" "generate" "--no-bindings")))
- '("ocaml" "interface"))))
- (replace 'check
- (lambda _
- (for-each (lambda (dir)
- (with-directory-excursion dir
- (invoke "tree-sitter" "test")))
- '("ocaml" "interface"))))
- (replace 'install
- (lambda _
- (let ((lib (string-append #$output "/lib/tree-sitter/")))
- (mkdir-p lib)
- (invoke #$(cxx-for-target)
- "-shared"
- "-fPIC"
- "-fno-exceptions"
- "-O2"
- "-g"
- "-o" (string-append lib "/ocaml.so")
- "ocaml/src/scanner.cc"
- "-xc" "ocaml/src/parser.c")
- (invoke #$(cxx-for-target)
- "-shared"
- "-fPIC"
- "-fno-exceptions"
- "-O2"
- "-g"
- "-o" (string-append lib "/ocaml-interface.so")
- "interface/src/scanner.cc"
- "-xc" "interface/src/parser.c"))))))))
+ (list
+ #:phases
+ #~(modify-phases %standard-phases
+ (replace 'build
+ (lambda _
+ (for-each (lambda (dir)
+ (with-directory-excursion dir
+ (invoke "tree-sitter" "generate" "--no-bindings")))
+ '("ocaml" "interface"))))
+ (replace 'check
+ (lambda _
+ (for-each (lambda (dir)
+ (with-directory-excursion dir
+ (invoke "tree-sitter" "test")))
+ '("ocaml" "interface"))))
+ (replace 'install
+ (lambda _
+ (let ((lib (string-append #$output "/lib/tree-sitter/")))
+ (mkdir-p lib)
+ (invoke #$(cxx-for-target)
+ "-shared"
+ "-fPIC"
+ "-fno-exceptions"
+ "-O2"
+ "-g"
+ "-o" (string-append lib "/ocaml.so")
+ "ocaml/src/scanner.cc"
+ "-xc" "ocaml/src/parser.c")
+ (invoke #$(cxx-for-target)
+ "-shared"
+ "-fPIC"
+ "-fno-exceptions"
+ "-O2"
+ "-g"
+ "-o" (string-append lib "/ocaml-interface.so")
+ "interface/src/scanner.cc"
+ "-xc" "interface/src/parser.c")))))))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-ocaml")
(synopsis "Tree-sitter OCaml grammar")
(description
@@ -663,7 +580,7 @@ (define-public tree-sitter-ocaml
(define-public tree-sitter-php
(let ((commit "435fa00006c0d1515c37fbb4dd6a9de284af75ab")
(revision "1"))
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-php")
(version (git-version "0.19.0" revision commit))
(source (origin
@@ -683,15 +600,7 @@ (define-public tree-sitter-php
(delete-file "src/parser.c")
(delete-file-recursively "src/tree_sitter")
#t))))
- (arguments
- (substitute-keyword-arguments (package-arguments tree-sitter-c)
- ((#:phases phases)
- `(modify-phases ,phases
- (replace 'delete-dependencies
- (lambda _
- (delete-dependencies '("tree-sitter-cli"
- "nan"
- "shelljs"))))))))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-php")
(synopsis "Tree-sitter PHP grammar")
(description
@@ -701,7 +610,7 @@ (define-public tree-sitter-php
(define-public tree-sitter-python
(let ((commit "ed0fe62e55dc617ed9dec8817ebf771aa7cf3c42")
(revision "1"))
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-python")
(version (git-version "0.19.1" revision commit))
(source (origin
@@ -715,6 +624,7 @@ (define-public tree-sitter-python
"0wrfpg84mc3pzcrdi6n5fqwijkqr1nj5sqfnayb502krvqpjilal"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-python")
(synopsis "Tree-sitter Python grammar")
(description
@@ -722,7 +632,7 @@ (define-public tree-sitter-python
(license license:expat))))
(define-public tree-sitter-ruby
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-ruby")
(version "0.19.0")
(source (origin
@@ -736,17 +646,7 @@ (define-public tree-sitter-ruby
"0m3h4928rbs300wcb6776h9r88hi32rybbhcaf6rdympl5nzi83v"))
(modules '((guix build utils)))
(snippet tree-sitter-delete-generated-files)))
- (arguments
- (substitute-keyword-arguments (package-arguments tree-sitter-c)
- ((#:phases phases)
- `(modify-phases ,phases
- (replace 'delete-dependencies
- (lambda _
- (delete-dependencies '("tree-sitter-cli"
- "nan"
- "node-gyp"
- "prebuild"
- "prebuild-install"))))))))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-ruby")
(synopsis "Tree-sitter Ruby grammar")
(description
@@ -754,7 +654,7 @@ (define-public tree-sitter-ruby
(license license:expat)))
(define-public tree-sitter-rust
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-rust")
(version "0.20.1")
(source (origin
@@ -771,6 +671,7 @@ (define-public tree-sitter-rust
(native-inputs
(modify-inputs (package-native-inputs tree-sitter-c)
(prepend bc)))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-rust")
(synopsis "Tree-sitter Rust grammar")
(description
@@ -780,7 +681,7 @@ (define-public tree-sitter-rust
(define-public tree-sitter-typescript
(let ((commit "111b07762e86efab9a918b7c721f720c37e76b0a")
(revision "1"))
- (package (inherit tree-sitter-c)
+ (package
(name "tree-sitter-typescript")
(version (git-version "0.20.0" revision commit))
(source (origin
@@ -806,39 +707,40 @@ (define-public tree-sitter-typescript
'("typescript" "tsx"))
#t))))
(inputs
- (list `(,tree-sitter-javascript "js")))
+ (list tree-sitter-javascript))
(arguments
- (substitute-keyword-arguments (package-arguments tree-sitter-c)
- ((#:phases phases)
- #~(modify-phases #$phases
- (replace 'build
- (lambda _
- (for-each (lambda (dir)
- (with-directory-excursion dir
- (invoke "tree-sitter" "generate" "--no-bindings")))
- '("typescript" "tsx"))))
- (replace 'check
- (lambda _
- (for-each (lambda (dir)
- (with-directory-excursion dir
- (invoke "tree-sitter" "test")))
- '("typescript" "tsx"))))
- (replace 'install
- (lambda _
- (let ((lib (string-append #$output "/lib/tree-sitter/")))
- (mkdir-p lib)
- (for-each
- (lambda (lang)
- (invoke #$(cxx-for-target)
- "-shared"
- "-fPIC"
- "-fno-exceptions"
- "-O2"
- "-g"
- "-o" (string-append lib "/" lang ".so")
- "-xc" (string-append lang "/src/scanner.c")
- "-xc" (string-append lang "/src/parser.c")))
- '("typescript" "tsx")))))))))
+ (list
+ #:phases
+ #~(modify-phases %standard-phases
+ (replace 'build
+ (lambda _
+ (for-each (lambda (dir)
+ (with-directory-excursion dir
+ (invoke "tree-sitter" "generate" "--no-bindings")))
+ '("typescript" "tsx"))))
+ (replace 'check
+ (lambda _
+ (for-each (lambda (dir)
+ (with-directory-excursion dir
+ (invoke "tree-sitter" "test")))
+ '("typescript" "tsx"))))
+ (replace 'install
+ (lambda _
+ (let ((lib (string-append #$output "/lib/tree-sitter/")))
+ (mkdir-p lib)
+ (for-each
+ (lambda (lang)
+ (invoke #$(cxx-for-target)
+ "-shared"
+ "-fPIC"
+ "-fno-exceptions"
+ "-O2"
+ "-g"
+ "-o" (string-append lib "/" lang ".so")
+ "-xc" (string-append lang "/src/scanner.c")
+ "-xc" (string-append lang "/src/parser.c")))
+ '("typescript" "tsx"))))))))
+ (build-system tree-sitter-build-system)
(home-page "https://github.com/tree-sitter/tree-sitter-typescript")
(synopsis "Tree-sitter Typescript grammar")
(description
new file mode 100644
@@ -0,0 +1,109 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2022 Pierre Langlois <pierre.langlois@gmx.com>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (guix build-system tree-sitter)
+ #:use-module (guix store)
+ #:use-module (guix utils)
+ #:use-module (guix packages)
+ #:use-module (guix gexp)
+ #:use-module (guix monads)
+ #:use-module (guix search-paths)
+ #:use-module (guix build-system)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix build-system node)
+ #:use-module (ice-9 match)
+ #:export (%tree-sitter-build-system-modules
+ tree-sitter-build
+ tree-sitter-build-system))
+
+(define %tree-sitter-build-system-modules
+ ;; Build-side modules imported by default.
+ `((guix build tree-sitter-build-system)
+ ;; (guix build json)
+ ,@%node-build-system-modules))
+
+(define* (lower name
+ #:key source inputs native-inputs outputs system target
+ #:allow-other-keys
+ #:rest arguments)
+ ""
+ (define private-keywords
+ '(#:target #:inputs #:native-inputs #:outputs))
+
+ (and (not target) ;XXX: no cross-compilation
+ (bag
+ (name name)
+ (system system)
+ (host-inputs `(,@(if source
+ `(("source" ,source))
+ '())
+ ,@(map (match-lambda
+ ((name package)
+ `(,name ,package "js")))
+ inputs)
+ ;; Keep the standard inputs of 'gnu-build-system'.
+ ,@(standard-packages)))
+ (build-inputs `(("node" ,(module-ref (resolve-interface '(gnu packages node))
+ 'node-lts))
+ ("tree-sitter" ,(module-ref (resolve-interface '(gnu packages tree-sitter))
+ 'tree-sitter))
+ ("tree-sitter-cli" ,(module-ref (resolve-interface '(gnu packages tree-sitter))
+ 'tree-sitter-cli))
+ ,@native-inputs))
+ (outputs (match outputs
+ (("out") (cons "js" outputs))
+ (_ outputs)))
+ (build tree-sitter-build)
+ (arguments (strip-keyword-arguments private-keywords arguments)))))
+
+(define* (tree-sitter-build name inputs
+ #:key
+ source
+ (phases '%standard-phases)
+ (outputs '("out" "js"))
+ (search-paths '())
+ (system (%current-system))
+ (guile #f)
+ (imported-modules %tree-sitter-build-system-modules)
+ (modules '((guix build utils)
+ (guix build tree-sitter-build-system))))
+ (define builder
+ (with-imported-modules imported-modules
+ #~(begin
+ (use-modules #$@(sexp->gexp modules))
+ (tree-sitter-build #:name #$name
+ #:source #+source
+ #:system #$system
+ #:phases #$phases
+ #:outputs #$(outputs->gexp outputs)
+ #:search-paths '#$(sexp->gexp
+ (map search-path-specification->sexp
+ search-paths))
+ #:inputs #$(input-tuples->gexp inputs)))))
+
+ (mlet %store-monad ((guile (package->derivation (or guile (default-guile))
+ system #:graft? #f)))
+ (gexp->derivation name builder
+ #:system system
+ #:guile-for-build guile)))
+
+(define tree-sitter-build-system
+ (build-system
+ (name 'tree-sitter)
+ (description "")
+ (lower lower)))
new file mode 100644
@@ -0,0 +1,124 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2022 Pierre Langlois <pierre.langlois@gmx.com>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (guix build tree-sitter-build-system)
+ #:use-module ((guix build node-build-system) #:prefix node:)
+ #:use-module (guix build json)
+ #:use-module (guix build utils)
+ #:use-module (ice-9 match)
+ #:use-module (ice-9 regex)
+ #:use-module (srfi srfi-1)
+ #:export (%standard-phases
+ tree-sitter-build))
+
+(define (tree-sitter-node-inputs inputs)
+ ""
+ (alist-delete "node"
+ (alist-delete "source"
+ (filter (match-lambda
+ ((label . directory)
+ (directory-exists? (string-append directory
+ "/lib/node_modules")))
+ (_ #f))
+ inputs))))
+
+;;;
+;;; Phases.
+;;;
+
+(define* (adjust-dependencies #:key inputs #:allow-other-keys)
+ ""
+ (node:with-atomic-json-file-replacement "package.json"
+ (match-lambda
+ (('@ . pkg-meta-alist)
+ (cons '@ (map (match-lambda
+ (("dependencies" @ . deps)
+ '("dependencies" @))
+ (("devDependencies" @ . deps)
+ `("devDependencies" @
+ ,@(map
+ (lambda (input)
+ `(,(car input) . "latest"))
+ (tree-sitter-node-inputs inputs))))
+ (other other))
+ pkg-meta-alist))))))
+
+(define (build . _)
+ (invoke "tree-sitter" "generate" "--no-bindings")
+ #t)
+
+(define (check . _)
+ (invoke "tree-sitter" "test")
+ #t)
+
+(define* (install #:key outputs #:allow-other-keys)
+ (use-modules (guix build json)
+ (ice-9 regex))
+ (let* ((name (assoc-ref
+ (call-with-input-file "package.json" read-json)
+ "name"))
+ (lang (cond
+ ((string-match "^(@.*/)?tree-sitter-(.*)$" name)
+ => (lambda (m)
+ (match:substring m 2)))
+ (else #f)))
+ (lib (string-append (assoc-ref outputs "out")
+ "/lib/tree-sitter")))
+ (mkdir-p lib)
+ (define (source-file path)
+ (if (file-exists? path)
+ path
+ #f))
+ (apply invoke
+ `("g++"
+ "-shared"
+ "-fPIC"
+ "-fno-exceptions"
+ "-O2"
+ "-g"
+ "-o" ,(string-append lib "/" lang ".so")
+ ,@(cond
+ ((source-file "src/scanner.c")
+ => (lambda (file) (list "-xc" "-std=c99" file)))
+ ((source-file "src/scanner.cc")
+ => (lambda (file) (list file)))
+ (else '()))
+ "-xc" "src/parser.c"))))
+
+(define* (install-js #:key inputs outputs #:allow-other-keys)
+ (invoke (search-input-file inputs "/bin/npm")
+ "--prefix" (assoc-ref outputs "js")
+ "--global"
+ "--offline"
+ "--loglevel" "info"
+ "--production"
+ ;; Skip scripts to prevent building bindings via GYP.
+ "--ignore-scripts"
+ "install" "../package.tgz"))
+
+(define %standard-phases
+ (modify-phases node:%standard-phases
+ (add-before 'patch-dependencies 'adjust-dependencies adjust-dependencies)
+ (replace 'build build)
+ (replace 'check check)
+ (replace 'install install)
+ (add-after 'install 'install-js install-js)))
+
+(define* (tree-sitter-build #:key inputs (phases %standard-phases)
+ #:allow-other-keys #:rest args)
+ (apply node:node-build #:inputs inputs #:phases phases args))
--
2.34.0