Mercurial > emacs
comparison lisp/cedet/ede/proj-comp.el @ 104496:8c4870c15962
* cedet/ede.el, cedet/ede/*.el: New files.
* cedet/cedet.el: Require ede.
* cedet/semantic/symref/filter.el (semantic-symref-hits-in-region):
Require semantic/idle.
author | Chong Yidong <cyd@stupidchicken.com> |
---|---|
date | Sun, 20 Sep 2009 15:06:05 +0000 |
parents | |
children | bbd7017a25d9 |
comparison
equal
deleted
inserted
replaced
104495:4659ddbe20bf | 104496:8c4870c15962 |
---|---|
1 ;;; ede-proj-comp.el --- EDE Generic Project compiler/rule driver | |
2 | |
3 ;;; Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2009 | |
4 ;;; Free Software Foundation, Inc. | |
5 | |
6 ;; Author: Eric M. Ludlam <zappo@gnu.org> | |
7 ;; Keywords: project, make | |
8 | |
9 ;; This file is part of GNU Emacs. | |
10 | |
11 ;; GNU Emacs is free software: you can redistribute it and/or modify | |
12 ;; it under the terms of the GNU General Public License as published by | |
13 ;; the Free Software Foundation, either version 3 of the License, or | |
14 ;; (at your option) any later version. | |
15 | |
16 ;; GNU Emacs is distributed in the hope that it will be useful, | |
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 ;; GNU General Public License for more details. | |
20 | |
21 ;; You should have received a copy of the GNU General Public License | |
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
23 | |
24 ;;; Commentary: | |
25 ;; | |
26 ;; This software handles the maintenance of compiler and rule definitions | |
27 ;; for different object types. | |
28 ;; | |
29 ;; The `ede-compiler' class lets different types of project objects create | |
30 ;; definitions of compilers that can be swapped in and out for compiling | |
31 ;; source code. Users can also define new compiler types whenever they | |
32 ;; some customized behavior. | |
33 ;; | |
34 ;; The `ede-makefile-rule' class lets users add customized rules into thier | |
35 ;; objects, and also lets different compilers add chaining rules to their | |
36 ;; behaviors. | |
37 ;; | |
38 ;; It is important that all new compiler types be registered once. That | |
39 ;; way the chaining rules and variables are inserted into any given Makefile | |
40 ;; only once. | |
41 ;; | |
42 ;; To insert many compiler elements, wrap them in `ede-compiler-begin-unique' | |
43 ;; before calling their insert methods. | |
44 ;; To write a method that inserts a variable or rule for a compiler | |
45 ;; based object, wrap the body of your call in `ede-compiler-only-once' | |
46 | |
47 (require 'ede) ;source object | |
48 (require 'ede/autoconf-edit) | |
49 | |
50 ;;; Types: | |
51 (defclass ede-compilation-program (eieio-instance-inheritor) | |
52 ((name :initarg :name | |
53 :type string | |
54 :custom string | |
55 :documentation "Name of this type of compiler.") | |
56 (variables :initarg :variables | |
57 :type list | |
58 :custom (repeat (cons (string :tag "Variable") | |
59 (string :tag "Value"))) | |
60 :documentation | |
61 "Variables needed in the Makefile for this compiler. | |
62 An assoc list where each element is (VARNAME . VALUE) where VARNAME | |
63 is a string, and VALUE is either a string, or a list of strings. | |
64 For example, GCC would define CC=gcc, and emacs would define EMACS=emacs.") | |
65 (sourcetype :initarg :sourcetype | |
66 :type list ;; of symbols | |
67 :documentation | |
68 "A list of `ede-sourcecode' objects this class will handle. | |
69 This is used to match target objects with the compilers and linkers | |
70 they can use, and which files this object is interested in." | |
71 :accessor ede-object-sourcecode) | |
72 (rules :initarg :rules | |
73 :initform nil | |
74 :type list | |
75 :custom (repeat (object :objecttype ede-makefile-rule)) | |
76 :documentation | |
77 "Auxiliary rules needed for this compiler to run. | |
78 For example, yacc/lex files need additional chain rules, or inferences.") | |
79 (commands :initarg :commands | |
80 :type list | |
81 :custom (repeat string) | |
82 :documentation | |
83 "The commands used to execute this compiler. | |
84 The object which uses this compiler will place these commands after | |
85 it's rule definition.") | |
86 (autoconf :initarg :autoconf | |
87 :initform nil | |
88 :type list | |
89 :custom (repeat string) | |
90 :documentation | |
91 "Autoconf function to call if this type of compiler is used. | |
92 When a project is in Automake mode, this defines the autoconf function to | |
93 call to initialize automake to use this compiler. | |
94 For example, there may be multiple C compilers, but they all probably | |
95 use the same autoconf form.") | |
96 (objectextention :initarg :objectextention | |
97 :type string | |
98 :documentation | |
99 "A string which is the extention used for object files. | |
100 For example, C code uses .o on unix, and Emacs Lisp uses .elc.") | |
101 ) | |
102 "A program used to compile or link a program via a Makefile. | |
103 Contains everything needed to output code into a Makefile, or autoconf | |
104 file.") | |
105 | |
106 (defclass ede-compiler (ede-compilation-program) | |
107 ((makedepends :initarg :makedepends | |
108 :initform nil | |
109 :type boolean | |
110 :documentation | |
111 "Non-nil if this compiler can make dependencies.") | |
112 (uselinker :initarg :uselinker | |
113 :initform nil | |
114 :type boolean | |
115 :documentation | |
116 "Non-nil if this compiler creates code that can be linked. | |
117 This requires that the containing target also define a list of available | |
118 linkers that can be used.") | |
119 ) | |
120 "Definition for a compiler. | |
121 Different types of objects will provide different compilers for | |
122 different situations.") | |
123 | |
124 (defclass ede-linker (ede-compilation-program) | |
125 () | |
126 "Contains information needed to link many generated object files together.") | |
127 | |
128 (defclass ede-makefile-rule () | |
129 ((target :initarg :target | |
130 :initform "" | |
131 :type string | |
132 :custom string | |
133 :documentation "The target pattern. | |
134 A pattern of \"%.o\" is used for inference rules, and would match object files. | |
135 A target of \"foo.o\" explicitly matches the file foo.o.") | |
136 (dependencies :initarg :dependencies | |
137 :initform "" | |
138 :type string | |
139 :custom string | |
140 :documentation "Dependencies on this target. | |
141 A pattern of \"%.o\" would match a file of the same prefix as the target | |
142 if that target is also an inference rule pattern. | |
143 A dependency of \"foo.c\" explicitly lists foo.c as a dependency. | |
144 A variable such as $(name_SOURCES) will list all the source files | |
145 belonging to the target name.") | |
146 (rules :initarg :rules | |
147 :initform nil | |
148 :type list | |
149 :custom (repeat string) | |
150 :documentation "Scripts to execute. | |
151 These scripst will be executed in sh (Unless the SHELL variable is overriden). | |
152 Do not prefix with TAB. | |
153 Each individual element of this list can be either a string, or | |
154 a lambda function. (The custom element does not yet express that.") | |
155 (phony :initarg :phony | |
156 :initform nil | |
157 :type boolean | |
158 :custom boolean | |
159 :documentation "Is this a phony rule? | |
160 Adds this rule to a .PHONY list.")) | |
161 "A single rule for building some target.") | |
162 | |
163 ;;; Code: | |
164 (defvar ede-compiler-list nil | |
165 "The master list of all EDE compilers.") | |
166 | |
167 (defvar ede-linker-list nil | |
168 "The master list of all EDE compilers.") | |
169 | |
170 (defvar ede-current-build-list nil | |
171 "List of EDE compilers that have already inserted parts of themselves. | |
172 This is used when creating a Makefile to prevend duplicate variables and | |
173 rules from being created.") | |
174 | |
175 (defmethod initialize-instance :AFTER ((this ede-compiler) &rest fields) | |
176 "Make sure that all ede compiler objects are cached in | |
177 `ede-compiler-list'." | |
178 (add-to-list 'ede-compiler-list this)) | |
179 | |
180 (defmethod initialize-instance :AFTER ((this ede-linker) &rest fields) | |
181 "Make sure that all ede compiler objects are cached in | |
182 `ede-linker-list'." | |
183 (add-to-list 'ede-linker-list this)) | |
184 | |
185 (defmacro ede-compiler-begin-unique (&rest body) | |
186 "Execute BODY, making sure that `ede-current-build-list' is maintained. | |
187 This will prevent rules from creating duplicate variables or rules." | |
188 `(let ((ede-current-build-list nil)) | |
189 ,@body)) | |
190 | |
191 (defmacro ede-compiler-only-once (object &rest body) | |
192 "Using OBJECT, execute BODY only once per Makefile generation." | |
193 `(if (not (member ,object ede-current-build-list)) | |
194 (progn | |
195 (add-to-list 'ede-current-build-list ,object) | |
196 ,@body))) | |
197 | |
198 (defmacro ede-linker-begin-unique (&rest body) | |
199 "Execute BODY, making sure that `ede-current-build-list' is maintained. | |
200 This will prevent rules from creating duplicate variables or rules." | |
201 `(let ((ede-current-build-list nil)) | |
202 ,@body)) | |
203 | |
204 (defmacro ede-linker-only-once (object &rest body) | |
205 "Using OBJECT, execute BODY only once per Makefile generation." | |
206 `(if (not (member ,object ede-current-build-list)) | |
207 (progn | |
208 (add-to-list 'ede-current-build-list ,object) | |
209 ,@body))) | |
210 | |
211 (add-hook 'edebug-setup-hook | |
212 (lambda () | |
213 (def-edebug-spec ede-compiler-begin-unique def-body) | |
214 (def-edebug-spec ede-compiler-only-once (form def-body)) | |
215 (def-edebug-spec ede-linker-begin-unique def-body) | |
216 (def-edebug-spec ede-linker-only-once (form def-body)) | |
217 (def-edebug-spec ede-pmake-insert-variable-shared (form def-body)) | |
218 )) | |
219 | |
220 ;;; Querys | |
221 (defun ede-proj-find-compiler (compilers sourcetype) | |
222 "Return a compiler from the list COMPILERS that will compile SOURCETYPE." | |
223 (while (and compilers | |
224 (not (member sourcetype (oref (car compilers) sourcetype)))) | |
225 (setq compilers (cdr compilers))) | |
226 (car-safe compilers)) | |
227 | |
228 (defun ede-proj-find-linker (linkers sourcetype) | |
229 "Return a compiler from the list LINKERS to be used with SOURCETYPE." | |
230 (while (and linkers | |
231 (slot-boundp (car linkers) 'sourcetype) | |
232 (not (member sourcetype (oref (car linkers) sourcetype)))) | |
233 (setq linkers (cdr linkers))) | |
234 (car-safe linkers)) | |
235 | |
236 ;;; Methods: | |
237 (defmethod ede-proj-tweak-autoconf ((this ede-compilation-program)) | |
238 "Tweak the configure file (current buffer) to accomodate THIS." | |
239 (mapcar | |
240 (lambda (obj) | |
241 (cond ((stringp obj) | |
242 (autoconf-insert-new-macro obj)) | |
243 ((consp obj) | |
244 (autoconf-insert-new-macro (car obj) (cdr obj))) | |
245 (t (error "Autoconf directives must be a string, or cons cell"))) | |
246 ) | |
247 (oref this autoconf))) | |
248 | |
249 (defmethod ede-proj-flush-autoconf ((this ede-compilation-program)) | |
250 "Flush the configure file (current buffer) to accomodate THIS." | |
251 nil) | |
252 | |
253 (defmethod ede-proj-makefile-insert-variables ((this ede-compilation-program)) | |
254 "Insert variables needed by the compiler THIS." | |
255 (if (eieio-instance-inheritor-slot-boundp this 'variables) | |
256 (with-slots (variables) this | |
257 (mapcar | |
258 (lambda (var) | |
259 (insert (car var) "=") | |
260 (let ((cd (cdr var))) | |
261 (if (listp cd) | |
262 (mapc (lambda (c) (insert " " c)) cd) | |
263 (insert cd))) | |
264 (insert "\n")) | |
265 variables)))) | |
266 | |
267 (defmethod ede-compiler-intermediate-objects-p ((this ede-compiler)) | |
268 "Return non-nil if THIS has intermediate object files. | |
269 If this compiler creates code that can be linked together, | |
270 then the object files created by the compiler are considered intermediate." | |
271 (oref this uselinker)) | |
272 | |
273 (defmethod ede-compiler-intermediate-object-variable ((this ede-compiler) | |
274 targetname) | |
275 "Return a string based on THIS representing a make object variable. | |
276 TARGETNAME is the name of the target that these objects belong to." | |
277 (concat targetname "_OBJ")) | |
278 | |
279 (defmethod ede-proj-makefile-insert-object-variables ((this ede-compiler) | |
280 targetname sourcefiles) | |
281 "Insert an OBJ variable to specify object code to be generated for THIS. | |
282 The name of the target is TARGETNAME as a string. SOURCEFILES is the list of | |
283 files to be objectified. | |
284 Not all compilers do this." | |
285 (if (ede-compiler-intermediate-objects-p this) | |
286 (progn | |
287 (insert (ede-compiler-intermediate-object-variable this targetname) | |
288 "=") | |
289 (let ((src (oref this sourcetype))) | |
290 (mapc (lambda (s) | |
291 (let ((ts src)) | |
292 (while (and ts (not (ede-want-file-source-p | |
293 (symbol-value (car ts)) s))) | |
294 (setq ts (cdr ts))) | |
295 ;; Only insert the object if the given file is a major | |
296 ;; source-code type. | |
297 (if ts;; a match as a source file. | |
298 (insert " " (file-name-sans-extension s) | |
299 (oref this objectextention))))) | |
300 sourcefiles) | |
301 (insert "\n"))))) | |
302 | |
303 (defmethod ede-proj-makefile-insert-rules ((this ede-compilation-program)) | |
304 "Insert rules needed for THIS compiler object." | |
305 (ede-compiler-only-once this | |
306 (mapc 'ede-proj-makefile-insert-rules (oref this rules)))) | |
307 | |
308 (defmethod ede-proj-makefile-insert-rules ((this ede-makefile-rule)) | |
309 "Insert rules needed for THIS rule object." | |
310 (if (oref this phony) (insert ".PHONY: (oref this target)\n")) | |
311 (insert (oref this target) ": " (oref this dependencies) "\n\t" | |
312 (mapconcat (lambda (c) c) (oref this rules) "\n\t") | |
313 "\n\n")) | |
314 | |
315 (defmethod ede-proj-makefile-insert-commands ((this ede-compilation-program)) | |
316 "Insert the commands needed to use compiler THIS. | |
317 The object creating makefile rules must call this method for the | |
318 compiler it decides to use after inserting in the rule." | |
319 (when (slot-boundp this 'commands) | |
320 (with-slots (commands) this | |
321 (mapc | |
322 (lambda (obj) (insert "\t" | |
323 (cond ((stringp obj) | |
324 obj) | |
325 ((and (listp obj) | |
326 (eq (car obj) 'lambda)) | |
327 (funcall obj)) | |
328 (t | |
329 (format "%S" obj))) | |
330 "\n")) | |
331 commands)) | |
332 (insert "\n"))) | |
333 | |
334 ;;; Some details about our new macro | |
335 ;; | |
336 (add-hook 'edebug-setup-hook | |
337 (lambda () | |
338 (def-edebug-spec ede-compiler-begin-unique def-body))) | |
339 (put 'ede-compiler-begin-unique 'lisp-indent-function 0) | |
340 (put 'ede-compiler-only-once 'lisp-indent-function 1) | |
341 (put 'ede-linker-begin-unique 'lisp-indent-function 0) | |
342 (put 'ede-linker-only-once 'lisp-indent-function 1) | |
343 | |
344 (provide 'ede/proj-comp) | |
345 | |
346 ;;; ede/proj-comp.el ends here |