Function: treesit--install-language-grammar-1
treesit--install-language-grammar-1 is a byte-compiled function
defined in treesit.el.gz.
Signature
(treesit--install-language-grammar-1 OUT-DIR LANG URL &optional REVISION SOURCE-DIR CC C++)
Documentation
Install and compile a tree-sitter language grammar library.
OUT-DIR is the directory to put the compiled library file. If it is nil, the "tree-sitter" directory under user's Emacs configuration directory is used (and automatically created if it does not exist).
For LANG, URL, REVISION, SOURCE-DIR, GRAMMAR-DIR, CC, C++, see
treesit-language-source-alist. If anything goes wrong, this
function signals an error.
Source Code
;; Defined in /usr/src/emacs/lisp/treesit.el.gz
(defun treesit--install-language-grammar-1
(out-dir lang url &optional revision source-dir cc c++)
"Install and compile a tree-sitter language grammar library.
OUT-DIR is the directory to put the compiled library file. If it
is nil, the \"tree-sitter\" directory under user's Emacs
configuration directory is used (and automatically created if it
does not exist).
For LANG, URL, REVISION, SOURCE-DIR, GRAMMAR-DIR, CC, C++, see
`treesit-language-source-alist'. If anything goes wrong, this
function signals an error."
(let* ((lang (symbol-name lang))
(default-directory (make-temp-file "treesit-workdir" t))
(workdir (expand-file-name "repo"))
(source-dir (expand-file-name (or source-dir "src") workdir))
(cc (or cc (seq-find #'executable-find '("cc" "gcc" "c99"))
;; If no C compiler found, just use cc and let
;; `call-process' signal the error.
"cc"))
(c++ (or c++ (seq-find #'executable-find '("c++" "g++"))
"c++"))
(soext (or (car dynamic-library-suffixes)
(signal 'treesit-error '("Emacs cannot figure out the file extension for dynamic libraries for this system, because `dynamic-library-suffixes' is nil"))))
(out-dir (or (and out-dir (expand-file-name out-dir))
(locate-user-emacs-file "tree-sitter")))
(lib-name (concat "libtree-sitter-" lang soext)))
(unwind-protect
(with-temp-buffer
(message "Cloning repository")
;; git clone xxx --depth 1 --quiet [-b yyy] workdir
(if revision
(treesit--call-process-signal
"git" nil t nil "clone" url "--depth" "1" "--quiet"
"-b" revision workdir)
(treesit--call-process-signal
"git" nil t nil "clone" url "--depth" "1" "--quiet"
workdir))
;; We need to go into the source directory because some
;; header files use relative path (#include "../xxx").
;; cd "${sourcedir}"
(setq default-directory source-dir)
(message "Compiling library")
;; cc -fPIC -c -I. parser.c
(treesit--call-process-signal
cc nil t nil "-fPIC" "-c" "-I." "parser.c")
;; cc -fPIC -c -I. scanner.c
(when (file-exists-p "scanner.c")
(treesit--call-process-signal
cc nil t nil "-fPIC" "-c" "-I." "scanner.c"))
;; c++ -fPIC -I. -c scanner.cc
(when (file-exists-p "scanner.cc")
(treesit--call-process-signal
c++ nil t nil "-fPIC" "-c" "-I." "scanner.cc"))
;; cc/c++ -fPIC -shared *.o -o "libtree-sitter-${lang}.${soext}"
(apply #'treesit--call-process-signal
(if (file-exists-p "scanner.cc") c++ cc)
nil t nil
`("-fPIC" "-shared"
,@(directory-files
default-directory nil
(rx bos (+ anychar) ".o" eos))
"-o" ,lib-name))
;; Copy out.
(unless (file-exists-p out-dir)
(make-directory out-dir t))
(let* ((library-fname (expand-file-name lib-name out-dir))
(old-fname (concat library-fname ".old")))
;; Rename the existing shared library, if any, then
;; install the new one, and try deleting the old one.
;; This is for Windows systems, where we cannot simply
;; overwrite a DLL that is being used.
(if (file-exists-p library-fname)
(rename-file library-fname old-fname t))
(copy-file lib-name (file-name-as-directory out-dir) t t)
;; Ignore errors, in case the old version is still used.
(ignore-errors (delete-file old-fname)))
(message "Library installed to %s/%s" out-dir lib-name))
(when (file-exists-p workdir)
(delete-directory workdir t)))))