emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Project out of sources compilation


From: Ergus
Subject: Re: [PATCH] Project out of sources compilation
Date: Wed, 3 Apr 2024 21:47:10 +0200

Hi Dmitry:

So far I Think I understood part of your las email about functionality.

On Wed, Apr 03, 2024 at 02:23:03AM +0300, Dmitry Gutov wrote:
On 01/04/2024 16:52, Ergus wrote:
So having direct support for this in project.el would be quite welcome,
so I can use that instead of my private hacks.

Projectile already have support for many backends and the implementation
is pretty clean. I am doing this because I thing that something so basic
must be part of vanilla.

Speaking of Projectile, it has this block of definitions of "project types". Which could maybe better called "build tool types" in the context of this discussion.

It would be nice if we could port them over to a design which would be useable by both Projectile and project.el (and together with other project.el backends), rather than having every project backend re-implement these settings, or re-enumerate the supported types.

Their design is actually fine, but I would prefer to keep things simpler
in the api side because project is intended to be more general.

Their use case adds too many functions in order to register, call, test
and generate the different backends I thing it is actually too much for
vanilla. If we want that complexity maybe is better to retake the last
year discussion you mentioned before:

https://lists.gnu.org/archive/html/emacs-devel/2023-05/msg00509.html

But adding that will require also parallel work and code in order to
integrate with project.el.

That's why the idea of orthogonal APIs seems appealing to me (the current one for file listing and root finding; the new one for build tools, and compiling, and running, I guess).

I would probably insist in a simpler basic feature still in the current
project.el. I can't see the features as a separated thing.

What I would probably propose here is (maybe) to move the vc-backend to
it's own file as a separated package in order to keep the general api
separated from the "plugin". So if a developer wants to create a backend
it is clear whats needed and what the standard implementation example...

Until we've drawn up some design for the latter, though, maybe a customizable function variable will suffice.

What I have in mind as now is to add a variable and a method that can be
both optionally defined.

The method defined by backends and the variable by the user (maybe in
dir-locals).

This way the backends won't be forced to define any of these if
compilation is not supported (i.e vs-backend) or if the project is for a
non-compilable languaje (i.e an hypothetic python project)

project-compile-info accepts a second variable that in this case expects
'dir or 'compile-cmd in any case when not implemented the function gives
null and the caller (compile in this case) falls back to the default
values.

This can accept any other command like 'generate-cmd 'test-cmd and so
on.  In the future we can define any other random command relying on
these

So far the only we need for compilation is more or less this:

```
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index a10e24f3e28..9d77d5452f3 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -290,8 +290,29 @@ project-external-roots
 headers search path, load path, class path, and so on."
   nil)
+(cl-defgeneric project-compile-info (_project _info)
+  "Return build information of the current PROJECT.
+
+This function is intended to be defined by the backend when possible.
+Otherwise this returns nil and the `project-compile' command will use
+the default values.
+The current valid values for INFO are `dir' and `compile-cmd'"
+  nil)
+
+(defun project-get-build-dir (project)
+  "Return absolute build directory for the current PROJECT.
+1. Tries the generic function `project-compile-info' with info='dir.
+2. else it return the project-root.
+If the defined path is relative, this expands it relatively to the
+project's root."
+  (let ((dir (or (project-compile-info project 'dir)   ;; backend function
+                 (project-root project))))        ;; I assume project-root is 
always absolute
+    (if (file-name-absolute-p dir)
+        dir
+      (expand-file-name dir (project-root project)))))


@@ -1392,10 +1413,15 @@ project-compile
   "Run `compile' in the project root."
   (declare (interactive-only compile))
   (interactive)
-  (let ((default-directory (project-root (project-current t)))
-        (compilation-buffer-name-function
-         (or project-compilation-buffer-name-function
-             compilation-buffer-name-function)))
+  ;; I am wondering whenever we need to expand connection local
+  ;; variables at this point... maybe before or inside the let.
+  (let* ((project (project-current t))
+         (default-directory (project-get-build-dir project))
+         (compile-command (or (project-compile-info project 'compile-cmd)
+                              compile-command))
+         (compilation-buffer-name-function
+          (or project-compilation-buffer-name-function
+              compilation-buffer-name-function)))
     (call-interactively #'compile)))

```

Finally the only missing detail is user side configuration... I was
thinking in a plist defconst (similar to the approach in
eglot-workspace-configuration) so the user can set it completelly or
partially and we only need to do:

(or (plist-get project-info-plist 'compile-cmd)
    (project-compile-info project 'compile-cmd)
    compile-command)

In this way the user only has one variable to set in the config with all
the parameters optional as well which stays easy, simple in
implementation and with a predictable behavior.

WDYT??
Best,
Ergus


reply via email to

[Prev in Thread] Current Thread [Next in Thread]