From a38e3e66788129bbd441f9d28e450dba8a7438d1 Mon Sep 17 00:00:00 2001 From: Pierre Langlois 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 diff --git a/Makefile.am b/Makefile.am index 8850c4562c..c5da931041 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/gnu/packages/tree-sitter.scm b/gnu/packages/tree-sitter.scm index 0186518b23..725ab16910 100644 --- a/gnu/packages/tree-sitter.scm +++ b/gnu/packages/tree-sitter.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 diff --git a/guix/build-system/tree-sitter.scm b/guix/build-system/tree-sitter.scm new file mode 100644 index 0000000000..bfccea4007 --- /dev/null +++ b/guix/build-system/tree-sitter.scm @@ -0,0 +1,109 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 Pierre Langlois +;;; +;;; 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 . + +(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))) diff --git a/guix/build/tree-sitter-build-system.scm b/guix/build/tree-sitter-build-system.scm new file mode 100644 index 0000000000..bf1d2e363d --- /dev/null +++ b/guix/build/tree-sitter-build-system.scm @@ -0,0 +1,124 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 Pierre Langlois +;;; +;;; 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 . + +(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