Skip to content

Commit

Permalink
Automatic detection of system images
Browse files Browse the repository at this point in the history
The compilation process is also streamlined, allowing it to be run directly from
Emacs with `M-x eglot-jl-compile-sysimage`.
  • Loading branch information
ffevotte committed Jul 26, 2020
1 parent 57442dd commit 66a5a8a
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 29 deletions.
45 changes: 16 additions & 29 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -78,32 +78,19 @@ takes some time: around 20 seconds are needed before the server is ready, which
manifests itself by the =[eglot:projectName]= indicator showing up in the
modeline.

The =compile.jl= script that ships with =eglot-jl= allows compiling a system
image, which can greatly speed-up language server start-up times:

#+begin_src sh
julia path/to/eglot-jl/compile.jl
#+end_src

This will take a few minutes to generate a system image in
=path/to/eglot-jl/eglot-jl.X.Y.Z.so= (where =X.Y.Z= is your julia version number,
and the file extension is adapted to your system: =.dylib= for MacOS, =.dll= for
Windows).

You can then instruct =eglot-jl= to use this system image by adding the
following to your Emacs configuration:

#+begin_src emacs-lisp
(setq eglot-jl-julia-flags '("--sysimage=/path/to/eglot-jl/eglot-jl.X.Y.Z.so"))
#+end_src

This should reduce language server startup times to less than 2 seconds.

Be aware that you should update this system image (by running =compile.jl=
again) when julia changes, or if you update =eglot-jl= itself. If anything goes
wrong with this system image, you can always reset your julia flags to stop
using it:

#+begin_src emacs-lisp
(setq eglot-jl-julia-flags nil)
#+end_src
As an additional step after installation, =eglot-jl= can compile a custom julia
system image, which can greatly speed-up language server start-up times: simply
run =M-x eglot-jl-compile-sysimage=.

This will take a few minutes to generate a system image, which =eglot-jl= will
detect and automatically use for subsequent language server runs. This should
reduce language server startup times to 1 or 2 seconds.

Be aware that each system image is specific to a version of julia. If you switch
to a version for which you haven't (yet) generated a system image, =eglot-jl=
won't find any suitable sysimage, and language server startup times will be high
again. In such situations, you can simply generate a new system image for the
new julia version by running =M-x eglot-jl-compile-sysimage= again.

If anything goes wrong with system images, you can deactivate this feature
altogether by customizing =eglot-jl-enable-sysimage=.
41 changes: 41 additions & 0 deletions eglot-jl.el
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ The project should have LanguageServer and SymbolServer packages
available."
:type 'string)

(defcustom eglot-jl-enable-sysimage t
"If t, use a system image if a suitable one is
found. Otherwise, don't even look for a system image."
:type 'boolean)

;; Make project.el aware of Julia projects
(defun eglot-jl--project-try (dir)
"Return project instance if DIR is part of a julia project.
Expand All @@ -71,10 +76,31 @@ Otherwise returns nil"
(cl-defmethod project-roots ((project (head julia)))
(list (cdr project)))

(defun eglot-jl--sysimage-args ()
"Returns a list of command-line switches suitable for sysimage loading.
Return nil if no system image has been found or if system images
have been disabled altogether."
(when eglot-jl-enable-sysimage
(let ((julia-version (with-temp-buffer
(call-process eglot-jl-julia-command nil t nil
"-e" "print(Base.VERSION)")
(buffer-string))))
(car
(remove nil
(mapcar
(lambda (ext)
(let ((path (expand-file-name
(concat "eglot-jl." julia-version ext)
eglot-jl-base)))
(when (file-exists-p path)
(list "--sysimage" path))))
'(".dll" ".dylib" ".so")))))))

(defun eglot-jl--ls-invocation (_interactive)
"Return list of strings to be called to start the Julia language server."
`(,eglot-jl-julia-command
"--startup-file=no"
,@(eglot-jl--sysimage-args)
,(concat "--project=" eglot-jl-language-server-project)
,@eglot-jl-julia-flags
,(expand-file-name "eglot-jl.jl" eglot-jl-base)
Expand All @@ -90,5 +116,20 @@ Otherwise returns nil"
;; function instead of strings to find project dir at runtime
'(julia-mode . eglot-jl--ls-invocation)))

;;;###autoload
(defun eglot-jl-compile-sysimage ()
"Create a compiled system image for the language server.
This reduces subsequent start-up times."
(interactive)
(let ((buffer (get-buffer-create "*eglot-jl sysimage compilation*")))
(with-current-buffer buffer
(setq buffer-read-only nil) (erase-buffer) (setq buffer-read-only t)
(start-process "eglot-jl-compile-sysimage" (current-buffer)
eglot-jl-julia-command
"--startup-file=no" "--color=no" "--quiet"
(concat "--project=" eglot-jl-base)
(expand-file-name "compile.jl" eglot-jl-base)))
(display-buffer buffer)))

(provide 'eglot-jl)
;;; eglot-jl.el ends here

0 comments on commit 66a5a8a

Please sign in to comment.