comparison lisp/cedet/ede/proj-comp.el @ 105260:bbd7017a25d9

CEDET (development tools) package merged. * cedet/*.el: * cedet/ede/*.el: * cedet/semantic/*.el: * cedet/srecode/*.el: New files.
author Chong Yidong <cyd@stupidchicken.com>
date Mon, 28 Sep 2009 15:15:00 +0000
parents 8c4870c15962
children 51ba3b848c03
comparison
equal deleted inserted replaced
105259:5707f7454ab5 105260:bbd7017a25d9
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