aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuan Fu2024-12-28 14:41:55 -0800
committerYuan Fu2024-12-30 00:20:54 -0800
commite2f791715299d97f401a38c75fa11bb51fdb8292 (patch)
tree5845277130159353f73c654f65e18bd4d2136f9c
parenta22730f4d788d6476d5f3c6717ba8a3d4046e819 (diff)
downloademacs-e2f791715299d97f401a38c75fa11bb51fdb8292.tar.gz
emacs-e2f791715299d97f401a38c75fa11bb51fdb8292.zip
Refactor treesit--install-language-grammar-1
Separate treesit--install-language-grammar-1 into two functions, one clones the repository, the other builds and installs the grammar. * lisp/treesit.el (treesit--install-language-grammar-1): Refactor out treesit--build-grammar. (treesit--build-grammar): New function. (treesit--language-git-revision): Now takes REPO-DIR as an argument.
-rw-r--r--lisp/treesit.el154
1 files changed, 85 insertions, 69 deletions
diff --git a/lisp/treesit.el b/lisp/treesit.el
index 090197d86e3..73e7e5446d4 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -4229,17 +4229,18 @@ Return the git revision of the installed grammar, but it only works when
4229 err))))) 4229 err)))))
4230 version)) 4230 version))
4231 4231
4232(defun treesit--language-git-revision () 4232(defun treesit--language-git-revision (repo-dir)
4233 "Return the Git revision of current directory. 4233 "Return the Git revision of the repo in REPO-DIR.
4234 4234
4235Return the output of \"git describe\". If anything goes wrong, return 4235Return the output of \"git describe\". If anything goes wrong, return
4236nil." 4236nil."
4237 (with-temp-buffer 4237 (with-temp-buffer
4238 (cond 4238 (cond
4239 ((eq 0 (call-process "git" nil t nil "describe" "--tags")) 4239 ((eq 0 (call-process "git" nil t nil "-C" repo-dir "describe" "--tags"))
4240 (string-trim (buffer-string))) 4240 (string-trim (buffer-string)))
4241 ((eq 0 (progn (erase-buffer) 4241 ((eq 0 (progn (erase-buffer)
4242 (call-process "git" nil t nil "rev-parse" "HEAD"))) 4242 (call-process "git" nil t nil
4243 "-C" repo-dir "rev-parse" "HEAD")))
4243 (string-trim (buffer-string))) 4244 (string-trim (buffer-string)))
4244 (t nil)))) 4245 (t nil))))
4245 4246
@@ -4284,7 +4285,7 @@ clone if `treesit--install-language-grammar-blobless' is t."
4284 4285
4285(defun treesit--install-language-grammar-1 4286(defun treesit--install-language-grammar-1
4286 (out-dir lang url &optional revision source-dir cc c++ commit) 4287 (out-dir lang url &optional revision source-dir cc c++ commit)
4287 "Install and compile a tree-sitter language grammar library. 4288 "Compile and install a tree-sitter language grammar library.
4288 4289
4289OUT-DIR is the directory to put the compiled library file. If it 4290OUT-DIR is the directory to put the compiled library file. If it
4290is nil, the \"tree-sitter\" directory under user's Emacs 4291is nil, the \"tree-sitter\" directory under user's Emacs
@@ -4292,31 +4293,19 @@ configuration directory is used (and automatically created if it
4292does not exist). 4293does not exist).
4293 4294
4294For LANG, URL, REVISION, SOURCE-DIR, GRAMMAR-DIR, CC, C++, COMMIT, see 4295For LANG, URL, REVISION, SOURCE-DIR, GRAMMAR-DIR, CC, C++, COMMIT, see
4295`treesit-language-source-alist'. If anything goes wrong, this function 4296`treesit-language-source-alist'.
4296signals an error.
4297 4297
4298Return the git revision of the installed grammar. The revision is 4298Return the git revision of the installed grammar. The revision is
4299generated by \"git describe\". It only works when 4299generated by \"git describe\". It only works when
4300`treesit--install-language-grammar-full-clone' is t." 4300`treesit--install-language-grammar-full-clone' is t.
4301 (let* ((lang (symbol-name lang)) 4301
4302If anything goes wrong, this function signals an `treesit-error'."
4303 (let* ((default-directory (make-temp-file "treesit-workdir" t))
4302 (maybe-repo-dir (expand-file-name url)) 4304 (maybe-repo-dir (expand-file-name url))
4303 (url-is-dir (file-accessible-directory-p maybe-repo-dir)) 4305 (url-is-dir (file-accessible-directory-p maybe-repo-dir))
4304 (default-directory (make-temp-file "treesit-workdir" t))
4305 (workdir (if url-is-dir 4306 (workdir (if url-is-dir
4306 maybe-repo-dir 4307 maybe-repo-dir
4307 (expand-file-name "repo"))) 4308 (expand-file-name "repo")))
4308 (source-dir (expand-file-name (or source-dir "src") workdir))
4309 (cc (or cc (seq-find #'executable-find '("cc" "gcc" "c99"))
4310 ;; If no C compiler found, just use cc and let
4311 ;; `call-process' signal the error.
4312 "cc"))
4313 (c++ (or c++ (seq-find #'executable-find '("c++" "g++"))
4314 "c++"))
4315 (soext (or (car dynamic-library-suffixes)
4316 (signal 'treesit-error '("Emacs cannot figure out the file extension for dynamic libraries for this system, because `dynamic-library-suffixes' is nil"))))
4317 (out-dir (or (and out-dir (expand-file-name out-dir))
4318 (locate-user-emacs-file "tree-sitter")))
4319 (lib-name (concat "libtree-sitter-" lang soext))
4320 version) 4309 version)
4321 (unwind-protect 4310 (unwind-protect
4322 (with-temp-buffer 4311 (with-temp-buffer
@@ -4326,59 +4315,86 @@ generated by \"git describe\". It only works when
4326 (treesit--git-clone-repo url revision workdir)) 4315 (treesit--git-clone-repo url revision workdir))
4327 (when commit 4316 (when commit
4328 (treesit--git-checkout-branch workdir commit)) 4317 (treesit--git-checkout-branch workdir commit))
4329 ;; We need to go into the source directory because some 4318 (setq version (treesit--language-git-revision workdir))
4330 ;; header files use relative path (#include "../xxx"). 4319 (treesit--build-grammar workdir out-dir lang source-dir cc c++))
4331 ;; cd "${sourcedir}"
4332 (setq default-directory source-dir)
4333 (setq version (treesit--language-git-revision))
4334 (message "Compiling library")
4335 ;; cc -fPIC -c -I. parser.c
4336 (treesit--call-process-signal
4337 cc nil t nil "-fPIC" "-c" "-I." "parser.c")
4338 ;; cc -fPIC -c -I. scanner.c
4339 (when (file-exists-p "scanner.c")
4340 (treesit--call-process-signal
4341 cc nil t nil "-fPIC" "-c" "-I." "scanner.c"))
4342 ;; c++ -fPIC -I. -c scanner.cc
4343 (when (file-exists-p "scanner.cc")
4344 (treesit--call-process-signal
4345 c++ nil t nil "-fPIC" "-c" "-I." "scanner.cc"))
4346 ;; cc/c++ -fPIC -shared *.o -o "libtree-sitter-${lang}.${soext}"
4347 (apply #'treesit--call-process-signal
4348 (if (file-exists-p "scanner.cc") c++ cc)
4349 nil t nil
4350 (if (eq system-type 'cygwin)
4351 `("-shared" "-Wl,-dynamicbase"
4352 ,@(directory-files
4353 default-directory nil
4354 (rx bos (+ anychar) ".o" eos))
4355 "-o" ,lib-name)
4356 `("-fPIC" "-shared"
4357 ,@(directory-files
4358 default-directory nil
4359 (rx bos (+ anychar) ".o" eos))
4360 "-o" ,lib-name)))
4361 ;; Copy out.
4362 (unless (file-exists-p out-dir)
4363 (make-directory out-dir t))
4364 (let* ((library-fname (expand-file-name lib-name out-dir))
4365 (old-fname (concat library-fname ".old")))
4366 ;; Rename the existing shared library, if any, then
4367 ;; install the new one, and try deleting the old one.
4368 ;; This is for Windows systems, where we cannot simply
4369 ;; overwrite a DLL that is being used.
4370 (if (file-exists-p library-fname)
4371 (rename-file library-fname old-fname t))
4372 (copy-file lib-name (file-name-as-directory out-dir) t t)
4373 ;; Ignore errors, in case the old version is still used.
4374 (ignore-errors (delete-file old-fname)))
4375 (message "Library installed to %s/%s" out-dir lib-name))
4376 ;; Remove workdir if it's not a repo owned by user and we 4320 ;; Remove workdir if it's not a repo owned by user and we
4377 ;; managed to create it in the first place. 4321 ;; managed to create it in the first place.
4378 (when (and (not url-is-dir) (file-exists-p workdir)) 4322 (when (and (not url-is-dir) (file-exists-p workdir))
4379 (delete-directory workdir t))) 4323 (delete-directory workdir t)))
4380 version)) 4324 version))
4381 4325
4326(defun treesit--build-grammar (workdir out-dir lang source-dir cc c++)
4327 "Compile a tree-sitter language grammar library.
4328
4329WORKDIR is the cloned repo's directory. OUT-DIR is the directory to put
4330the compiled library file. If it is nil, the \"tree-sitter\" directory
4331under user's Emacs configuration directory is used (and automatically
4332created if it does not exist).
4333
4334For LANG, SOURCE-DIR, CC, C++, see `treesit-language-source-alist'.
4335
4336If anything goes wrong, this function signals an `treesit-error'."
4337 (let* ((lang (symbol-name lang))
4338 (source-dir (expand-file-name (or source-dir "src") workdir))
4339 (cc (or cc (seq-find #'executable-find '("cc" "gcc" "c99"))
4340 ;; If no C compiler found, just use cc and let
4341 ;; `call-process' signal the error.
4342 "cc"))
4343 (c++ (or c++ (seq-find #'executable-find '("c++" "g++"))
4344 "c++"))
4345 (soext (or (car dynamic-library-suffixes)
4346 (signal 'treesit-error '("Emacs cannot figure out the file extension for dynamic libraries for this system, because `dynamic-library-suffixes' is nil"))))
4347 (out-dir (or (and out-dir (expand-file-name out-dir))
4348 (locate-user-emacs-file "tree-sitter")))
4349 (lib-name (concat "libtree-sitter-" lang soext)))
4350 (with-temp-buffer
4351 ;; We need to go into the source directory because some
4352 ;; header files use relative path (#include "../xxx").
4353 ;; cd "${sourcedir}"
4354 (setq default-directory source-dir)
4355 (message "Compiling library")
4356 ;; cc -fPIC -c -I. parser.c
4357 (treesit--call-process-signal
4358 cc nil t nil "-fPIC" "-c" "-I." "parser.c")
4359 ;; cc -fPIC -c -I. scanner.c
4360 (when (file-exists-p "scanner.c")
4361 (treesit--call-process-signal
4362 cc nil t nil "-fPIC" "-c" "-I." "scanner.c"))
4363 ;; c++ -fPIC -I. -c scanner.cc
4364 (when (file-exists-p "scanner.cc")
4365 (treesit--call-process-signal
4366 c++ nil t nil "-fPIC" "-c" "-I." "scanner.cc"))
4367 ;; cc/c++ -fPIC -shared *.o -o "libtree-sitter-${lang}.${soext}"
4368 (apply #'treesit--call-process-signal
4369 (if (file-exists-p "scanner.cc") c++ cc)
4370 nil t nil
4371 (if (eq system-type 'cygwin)
4372 `("-shared" "-Wl,-dynamicbase"
4373 ,@(directory-files
4374 default-directory nil
4375 (rx bos (+ anychar) ".o" eos))
4376 "-o" ,lib-name)
4377 `("-fPIC" "-shared"
4378 ,@(directory-files
4379 default-directory nil
4380 (rx bos (+ anychar) ".o" eos))
4381 "-o" ,lib-name)))
4382 ;; Copy out.
4383 (unless (file-exists-p out-dir)
4384 (make-directory out-dir t))
4385 (let* ((library-fname (expand-file-name lib-name out-dir))
4386 (old-fname (concat library-fname ".old")))
4387 ;; Rename the existing shared library, if any, then
4388 ;; install the new one, and try deleting the old one.
4389 ;; This is for Windows systems, where we cannot simply
4390 ;; overwrite a DLL that is being used.
4391 (if (file-exists-p library-fname)
4392 (rename-file library-fname old-fname t))
4393 (copy-file lib-name (file-name-as-directory out-dir) t t)
4394 ;; Ignore errors, in case the old version is still used.
4395 (ignore-errors (delete-file old-fname)))
4396 (message "Library installed to %s/%s" out-dir lib-name))))
4397
4382;;; Shortdocs 4398;;; Shortdocs
4383 4399
4384(defun treesit--generate-shortdoc-examples () 4400(defun treesit--generate-shortdoc-examples ()