From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Ergus Newsgroups: gmane.emacs.devel Subject: [PATCH] Project out of sources compilation Date: Wed, 27 Mar 2024 17:38:48 +0100 Message-ID: References: <4wwljrdnra3bsloehioa46y24ozxajajmvf2elvskxxq3mhtg2.ref@pyv2z5snot6h> <4wwljrdnra3bsloehioa46y24ozxajajmvf2elvskxxq3mhtg2@pyv2z5snot6h> <87ttl5w0mr.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="yc4lqifqxgossueh" Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="38023"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org To: Dmitry Gutov Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Wed Mar 27 17:39:59 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1rpWJi-0009gP-Ni for ged-emacs-devel@m.gmane-mx.org; Wed, 27 Mar 2024 17:39:58 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rpWIr-0005yH-1o; Wed, 27 Mar 2024 12:39:05 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rpWIo-0005xz-6K for emacs-devel@gnu.org; Wed, 27 Mar 2024 12:39:02 -0400 Original-Received: from sonic317-26.consmr.mail.bf2.yahoo.com ([74.6.129.81]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rpWIk-0005YI-5y for emacs-devel@gnu.org; Wed, 27 Mar 2024 12:39:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aol.com; s=a2048; t=1711557534; bh=6pQBOCq2ydop0pOgqMSpQr7b6VI1ALrYC91+EaP8+5c=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From:Subject:Reply-To; b=AebpPpanWM4eJNLmHEtlt0VhNH1AAjS4nopOVjfi7Bsl3UG5BPuXbd6rTI4L232+Qv00tSenIbDH8G/j8s7Ap8M5zx/g29Dbrae5dTjofv6NIOWENsz8EqUOdNS8HDGtgM4X4kqXt6pa/poYOuW7gQEgYyLpWi/CFFQoMe/tZrI9Jol+AIy23SdUPtAYj5PnV7T7F5nzJjM+/zRvu3gkb0SG6llFNpQUw7XuuRP6AQ0Rzim3X0f2eZN+d7RfjQeyKp6o5JHhQ14Tvne2I1VfIKO2dyFjM2vgdHDK0iJboVkRABWGFSSncLcyVCw7Uo2l0BdTjMCzMztkDXkDiEntCA== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1711557534; bh=R96CiHCFdoTaEaxauA9rFhUBg8+GzFQZNe72dvTRFG6=; h=X-Sonic-MF:Date:From:To:Subject:From:Subject; b=phEQo/nxbI81/96oMDwb4P7j/bNZPOQ+gp5sOthnohxLx5QlvtLU80ceNSbA55BUvBPJtIdhykcPZMy1hoUFjAAn6i8r6yR+QjKaKOIVl3/UCgYzOzRPp1X5CxwrIWq6aN2uf1mES7pM9C0g+jGCAKCrGNQaSsY78GzlqesG/hj9VRezmS3HtNrWq7F+eswdb7zB0akcQ2xY1YNr4fyul4WQm08imJpyfP2mhyrfN2/6fjmxnqsW3/1XK5O+gY35g02dmPuKhbHwPCkVuFRZSapU1Ie/SAYKsVPAg829PqvO9hK0UVXspkeZRBR61vk1C/VMounZKeNDPsGlCQwAYg== X-YMail-OSG: NA7h_VYVM1n6L7BrmAtMLYfl3VqXZJypCD9YEGfts7K5R69icS7tOnRyeoRMhJN vGW6I_eZTsPzDklHosgICx9f5.W5BRCNh0_7UYZtUXUGmuFn8E4MHHebsVwsCImKZklOdVhT8P_X WiuVOMVdhuarNiPUQNlp5ornB3bY1cRUPA9kgHUMsfRUwVcTnoY_oXfh6DpjQB1jvLvt.DPbqXFw oPgIVF.0nsF.jBBi38NV5FHlLWcDrD8K3.FfHAsczyTKRk1ZUc7HfulroWY9yhuwtVZUEqbVkL36 wpDa55pFn4QYwlfZRgkozqH1quhwiBe68qdz7eMB.ryGVLp4aVJZjoq4Z8_kjbfsNMb5xKJrHVWO nC.I6A2ZxHP1sScAg_h_XVnY1pW0_mq5tHovWRKFLEe7c5UxVKQODmEYe.Num8K3KU4.gbHQBcIV UQQr0eiQIGGBdTkxQ.Y5gj0PWdyzELN2SyxIu2gYMtKJ7OTGfZdnacsMei27s9WUWIyIfofhna31 0INKzsz3aL8_cegA_6pn.rvB2M02JcksNxW1J1372KlRtTz9t2uXJCAM0oectunz.4NbkHoMI79. hidMjoa.oSqJxYTXqFoXCpR1mOiZ3i5..qoPlWg_VyetvVzKRJTbgKADebs11PRLxno6qfnlZ3aK CL.prU9u3kCYttAZDFORzQ.C7AcR2Yrnr365rV.Fve3o5T1mOXWr8hCY7E43A51VZB8ZpPouWJyE r8LYhYLLtggXQN_OtsMpxdq1r1Kwe6CAz4U67WeJZcoD9Ge1o5ABYeily.McVuivJ3kL5aGnWrTn 45X.YzOBOzC4BJEAk_8oHUjB1iDkZCt0j3ZLWhS2sV X-Sonic-MF: X-Sonic-ID: 8f41641c-bd0c-4c3b-ae39-bedca03d166c Original-Received: from sonic.gate.mail.ne1.yahoo.com by sonic317.consmr.mail.bf2.yahoo.com with HTTP; Wed, 27 Mar 2024 16:38:54 +0000 Original-Received: by hermes--production-ir2-7bc88bfc75-2gzvg (Yahoo Inc. Hermes SMTP Server) with ESMTPA ID 93d87135b3a5d3195bc2533b363b0054; Wed, 27 Mar 2024 16:38:50 +0000 (UTC) Content-Disposition: inline In-Reply-To: X-Mailer: WebService/1.1.22205 mail.backend.jedi.jws.acl:role.jedi.acl.token.atz.jws.hermes.aol Received-SPF: pass client-ip=74.6.129.81; envelope-from=spacibba@aol.com; helo=sonic317-26.consmr.mail.bf2.yahoo.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:317345 Archived-At: --yc4lqifqxgossueh Content-Type: text/plain; charset=utf-8; format=flowed Content-Disposition: inline Content-Transfer-Encoding: 8bit Hi: Here I attach a very simple patch to allow project out of sources compilation and project build detection. So far I already implemented a very primitive backend [1] for project.el using these features to detect and compile autotools and cmake projects; and, at some point I will propose it for elpa. But I need to work a bit more on it; and, of course, the functionalities in the attached patch need to go to vanilla this way or some other equivalent. Best, Ergus [1] https://github.com/Ergus/project-multi-mode/blob/master/project-multi-mode.el On Tue, Mar 19, 2024 at 07:36:35PM +0100, Ergus wrote: >Hi Dmitry: > >Here I attach a very simple approach to add support for out of sources >compilation in project.el > >This is just a POC, but to have some starting point to discuss. > >Best, >Ergus > > > >On Sun, Mar 17, 2024 at 06:47:43PM +0100, Ergus wrote: >>On Sun, Mar 17, 2024 at 12:36:44PM +0100, Augusto Stoffel wrote: >>>On Sat, 16 Mar 2024 at 14:12, Ergus wrote: >>> >>>>5. Project local variables (a man can dream, a man can dream) >>>> >>>>There are some situations where we want to have variables shared among a >>>>project. (i.e some output directory, logging option when executing, >>>>flags, environment variables). >>>> >>>>At the moment these options work partially by using directory >>>>variables. If we have the concept of a "project", maybe it is logical to >>>>have some sort of project scope concept, specially for projects sharing >>>>a common root. >>> >>>For Emacs variables, why you think dir-local variables only works >>>“partially”? >>> >>>As to environment variables, they are generally assumed to be global in >>>Emacs and it goes a bit against the grain to make them buffer-local / >>>project dependent. Nonetheless, there are packages for that (one is >>>buffer-env, which I wrote) and they work fine (at least for me). >>> >>They work for one directory, but when the project includes multiple >>roots (project-external-roots) the variables are somehow missing just >>when jumping with xref to a definition. >> >>However, we can ignore this as I mentioned before. >> >>>>For example vs-code adds a subdirectory with project variables that the >>>>user (but also any plugin) can refer to in the project's scope. >>> >>>Is this meant to store editor configuration or environment variables? I >>>guess turning VSCode configuration variables into Emacs alternatives >>>would be tricky. >> >>No please. No interaction-importing from other editors will be >>maintainable in the long path. >> >>>But if this is about env vars and the directory >>>organization is sensible, then one could configure buffer-env to >>>interoperate. >> >>This is it. The idea is to extend project.el in order to bring more >>project-oriented features. >> >>Lets say: >> >>The user (or project.el backend) could specify the `build` directory and >>the environment that needs to be set to execute the program from the >>build or bin directory. >> >>So with a simple modification of dir-locals.el the user may be capable >>to run M-x compile (or project-compile), M-x gud-gdb... or being more >>ambitious M-x project-generate (to call autogen.sh and ./configure or >>cmake depending of the project-backend) >> >>For sure we wont cover the 100% of the projects, but wuth automake and >>autotools we will be very close (and in the future someone could add >>other backends for it) >> >> >> >> >> >commit cfa10dfeac01ae25a7acd6857fae0b377b625779 >Author: Jimmy Aguilar Mena >Date: Tue Mar 19 17:57:25 2024 +0100 > > Add basic project-build-dir implementation > > This is just a dummy prototype to discuss about alternatives. > >diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el >index ac18aceadcf..0ca4ca85566 100644 >--- a/lisp/progmodes/project.el >+++ b/lisp/progmodes/project.el >@@ -51,6 +51,9 @@ > ;; files inside the root must not be considered a part of it). It > ;; should be consistent with `project-files'. > ;; >+;; `project-build-dir' can be overridden if the project backend has some >+;; extra information about the project build directory. >+;; > ;; This list can change in future versions. > ;; > ;; Transient project: >@@ -208,6 +211,12 @@ project-prompter > :group 'project > :version "30.1") > >+(defcustom project-build-dir nil >+ "Build directory for current project." >+ :type 'directory >+ :safe t >+ :version "30.1") >+ > ;;;###autoload > (defun project-current (&optional maybe-prompt directory) > "Return the project instance in DIRECTORY, defaulting to `default-directory'. >@@ -289,8 +298,30 @@ project-external-roots > headers search path, load path, class path, and so on." > nil) > >+(cl-defgeneric project-build-dir (_project) >+ "Return build directory 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 be >+called in the project-root. >+If the user defines the directory-local variable `project-build-dir' it >+will have precedence over the result of this function." >+ nil) >+ >+(defun project-get-build-dir (project) >+ "Return build directory of the current PROJECT. >+If the variable `project-build-dir' is defined, this function returns >+it, otherwise it returns the project root. If the defined path is >+relative, this expands it relatively to the project's root" >+ (let ((dir (or project-build-dir >+ (project-build-dir project) >+ (project-root project)))) ;; I assume project-root is absolute >+ (if (file-name-absolute-p dir) >+ dir >+ (expand-file-name dir (project-root project))))) >+ > (cl-defgeneric project-name (project) >- "A human-readable name for the project. >+ "A human-readable name for the PROJECT. > Nominally unique, but not enforced." > (file-name-nondirectory (directory-file-name (project-root project)))) > >@@ -1391,7 +1422,7 @@ project-compile > "Run `compile' in the project root." > (declare (interactive-only compile)) > (interactive) >- (let ((default-directory (project-root (project-current t))) >+ (let ((default-directory (project-get-build-dir (project-current t))) > (compilation-buffer-name-function > (or project-compilation-buffer-name-function > compilation-buffer-name-function))) --yc4lqifqxgossueh Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="project-compile.patch" diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index ac18aceadcf..5a4274d6f68 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -51,6 +51,9 @@ ;; files inside the root must not be considered a part of it). It ;; should be consistent with `project-files'. ;; +;; `project-build-dir' can be overridden if the project backend has some +;; extra information about the project build directory. +;; ;; This list can change in future versions. ;; ;; Transient project: @@ -208,6 +211,22 @@ project-prompter :group 'project :version "30.1") +(defcustom project-build-dir nil + "Build directory for current project. +This is the custom that the user could specify in dir-locals to override +the option specified by the project's backend." + :type 'directory + :safe t + :version "30.1") + +(defcustom project-compile-command nil + "Build command for current project. +This is the custom that the user could specify in dir-locals to override +the option specified by the project's backend." + :type 'directory + :safe t + :version "30.1") + ;;;###autoload (defun project-current (&optional maybe-prompt directory) "Return the project instance in DIRECTORY, defaulting to `default-directory'. @@ -289,8 +308,42 @@ project-external-roots headers search path, load path, class path, and so on." nil) +(cl-defgeneric project-build-dir (_project) + "Return build directory 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 be +called in the project-root. +If the user defines the directory-local variable `project-build-dir' it +will have precedence over the result of this function." + nil) + +(defun project-get-build-dir (project) + "Return build directory of the current PROJECT. +1. If the variable `project-build-dir' is defined, this function returns +it. 2. Else if the function `project-build-dir' return non-nil. +3. 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-build-dir ;; variable for dir-locals or connection local vars + (project-build-dir project) ;; 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))))) + +(cl-defgeneric project-compile-command (_project) + "Return build command 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 `compile-command' value. If the user defines the +directory-local variable `project-build-command' it will have preference +over this function and this will be never called." + nil) + (cl-defgeneric project-name (project) - "A human-readable name for the project. + "A human-readable name for the PROJECT. Nominally unique, but not enforced." (file-name-nondirectory (directory-file-name (project-root project)))) @@ -1391,10 +1444,16 @@ 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-command + (project-compile-command project) + compile-command)) + (compilation-buffer-name-function + (or project-compilation-buffer-name-function + compilation-buffer-name-function))) (call-interactively #'compile))) (defun project-recompile (&optional edit-command) --yc4lqifqxgossueh--