Function: treesit--build-grammar

treesit--build-grammar is a byte-compiled function defined in treesit.el.gz.

Signature

(treesit--build-grammar WORKDIR OUT-DIR LANG SOURCE-DIR CC C++)

Documentation

Compile a tree-sitter language grammar library.

WORKDIR is the cloned repo's directory. 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, SOURCE-DIR, CC, C++, see treesit-language-source-alist.

If anything goes wrong, this function signals an treesit-error.

Source Code

;; Defined in /usr/src/emacs/lisp/treesit.el.gz
(defun treesit--build-grammar (workdir out-dir lang source-dir cc c++)
  "Compile a tree-sitter language grammar library.

WORKDIR is the cloned repo's directory.  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, SOURCE-DIR, CC, C++, see `treesit-language-source-alist'.

If anything goes wrong, this function signals an `treesit-error'."
  (let* ((lang (symbol-name lang))
         (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)))
    (with-temp-buffer
      ;; 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
             (if (eq system-type 'cygwin)
                 `("-shared" "-Wl,-dynamicbase"
                   ,@(directory-files
                      default-directory nil
                      (rx bos (+ anychar) ".o" eos))
                   "-o" ,lib-name)
               `("-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))))