Mercurial > emacs
comparison lisp/cedet/ede/proj.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.el --- EDE Generic Project file driver | |
2 | |
3 ;;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 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 ;; EDE defines a method for managing a project. EDE-PROJ aims to be a | |
27 ;; generic project file format based on the EIEIO object stream | |
28 ;; methods. Changes in the project structure will require Makefile | |
29 ;; rebuild. The targets provided in ede-proj can be augmented with | |
30 ;; additional target types inherited directly from `ede-proj-target'. | |
31 | |
32 ;; (eval-and-compile '(require 'ede)) | |
33 (require 'ede/proj-comp) | |
34 (require 'ede/make) | |
35 | |
36 (declare-function ede-proj-makefile-create "ede/pmake") | |
37 (declare-function ede-proj-configure-synchronize "ede/pconf") | |
38 | |
39 (autoload 'ede-proj-target-aux "ede/proj-aux" | |
40 "Target class for a group of lisp files." nil nil) | |
41 (autoload 'ede-proj-target-elisp "ede/proj-elisp" | |
42 "Target class for a group of lisp files." nil nil) | |
43 (autoload 'ede-proj-target-elisp-autoloads "ede/proj-elisp" | |
44 "Target class for generating autoload files." nil nil) | |
45 (autoload 'ede-proj-target-scheme "ede/proj-scheme" | |
46 "Target class for a group of lisp files." nil nil) | |
47 (autoload 'ede-proj-target-makefile-miscelaneous "ede/proj-misc" | |
48 "Target class for a group of miscelaneous w/ a special makefile." nil nil) | |
49 (autoload 'ede-proj-target-makefile-program "ede/proj-prog" | |
50 "Target class for building a program." nil nil) | |
51 (autoload 'ede-proj-target-makefile-archive "ede/proj-archive" | |
52 "Target class for building an archive of object code." nil nil) | |
53 (autoload 'ede-proj-target-makefile-shared-object "ede/proj-shared" | |
54 "Target class for building a shared object." nil nil) | |
55 (autoload 'ede-proj-target-makefile-info "ede/proj-info" | |
56 "Target class for info files." nil nil) | |
57 | |
58 ;;; Class Definitions: | |
59 (defclass ede-proj-target (ede-target) | |
60 ((auxsource :initarg :auxsource | |
61 :initform nil | |
62 :type list | |
63 :custom (repeat (string :tag "File")) | |
64 :label "Auxiliary Source Files" | |
65 :group (default source) | |
66 :documentation "Auxilliary source files included in this target. | |
67 Each of these is considered equivalent to a source file, but it is not | |
68 distributed, and each should have a corresponding rule to build it.") | |
69 (dirty :initform nil | |
70 :type boolean | |
71 :documentation "Non-nil when generated files needs updating.") | |
72 (compiler :initarg :compiler | |
73 :initform nil | |
74 :type (or null symbol) | |
75 :custom (choice (const :tag "None" nil) | |
76 :slotofchoices availablecompilers) | |
77 :label "Compiler for building sources" | |
78 :group make | |
79 :documentation | |
80 "The compiler to be used to compile this object. | |
81 This should be a symbol, which contains the object defining the compiler. | |
82 This enables save/restore to do so by name, permitting the sharing | |
83 of these compiler resources, and global customization thereof.") | |
84 (linker :initarg :linker | |
85 :initform nil | |
86 :type (or null symbol) | |
87 :custom (choice (const :tag "None" nil) | |
88 :slotofchoices availablelinkers) | |
89 :label "Linker for combining intermediate object files." | |
90 :group make | |
91 :documentation | |
92 "The linker to be used to link compiled sources for this object. | |
93 This should be a symbol, which contains the object defining the linker. | |
94 This enables save/restore to do so by name, permitting the sharing | |
95 of these linker resources, and global customization thereof.") | |
96 ;; Class allocated slots | |
97 (phony :allocation :class | |
98 :initform nil | |
99 :type boolean | |
100 :documentation | |
101 "A phony target is one where the build target does not relate to a file. | |
102 Such targets are always built, but make knows how to deal with them..") | |
103 (availablecompilers :allocation :class | |
104 :initform nil | |
105 :type (or null list) | |
106 :documentation | |
107 "A list of `ede-compiler' objects. | |
108 These are the compilers the user can choose from when setting the | |
109 `compiler' slot.") | |
110 (availablelinkers :allocation :class | |
111 :initform nil | |
112 :type (or null list) | |
113 :documentation | |
114 "A list of `ede-linker' objects. | |
115 These are the linkers the user can choose from when setting the | |
116 `linker' slot.") | |
117 ) | |
118 "Abstract class for ede-proj targets.") | |
119 | |
120 (defclass ede-proj-target-makefile (ede-proj-target) | |
121 ((makefile :initarg :makefile | |
122 :initform "Makefile" | |
123 :type string | |
124 :custom string | |
125 :label "Parent Makefile" | |
126 :group make | |
127 :documentation "File name of generated Makefile.") | |
128 (partofall :initarg :partofall | |
129 :initform t | |
130 :type boolean | |
131 :custom boolean | |
132 :label "Part of `all:' target" | |
133 :group make | |
134 :documentation | |
135 "Non nil means the rule created is part of the all target. | |
136 Setting this to nil creates the rule to build this item, but does not | |
137 include it in the ALL`all:' rule.") | |
138 (configuration-variables | |
139 :initarg :configuration-variables | |
140 :initform nil | |
141 :type list | |
142 :custom (repeat (cons (string :tag "Configuration") | |
143 (repeat | |
144 (cons (string :tag "Name") | |
145 (string :tag "Value"))))) | |
146 :label "Environment Variables for configurations" | |
147 :group make | |
148 :documentation "Makefile variables appended to use in different configurations. | |
149 These variables are used in the makefile when a configuration becomes active. | |
150 Target variables are always renamed such as foo_CFLAGS, then included into | |
151 commands where the variable would usually appear.") | |
152 (rules :initarg :rules | |
153 :initform nil | |
154 :type list | |
155 :custom (repeat (object :objecttype ede-makefile-rule)) | |
156 :label "Additional Rules" | |
157 :group (make) | |
158 :documentation | |
159 "Arbitrary rules and dependencies needed to make this target. | |
160 It is safe to leave this blank.") | |
161 ) | |
162 "Abstract class for Makefile based targets.") | |
163 | |
164 (defvar ede-proj-target-alist | |
165 '(("program" . ede-proj-target-makefile-program) | |
166 ("archive" . ede-proj-target-makefile-archive) | |
167 ("sharedobject" . ede-proj-target-makefile-shared-object) | |
168 ("emacs lisp" . ede-proj-target-elisp) | |
169 ("emacs lisp autoloads" . ede-proj-target-elisp-autoloads) | |
170 ("info" . ede-proj-target-makefile-info) | |
171 ("auxiliary" . ede-proj-target-aux) | |
172 ("scheme" . ede-proj-target-scheme) | |
173 ("miscellaneous" . ede-proj-target-makefile-miscelaneous) | |
174 ) | |
175 "Alist of names to class types for available project target classes.") | |
176 | |
177 (defun ede-proj-register-target (name class) | |
178 "Register a new target class with NAME and class symbol CLASS. | |
179 This enables the creation of your target type." | |
180 (let ((a (assoc name ede-proj-target-alist))) | |
181 (if a | |
182 (setcdr a class) | |
183 (setq ede-proj-target-alist | |
184 (cons (cons name class) ede-proj-target-alist))))) | |
185 | |
186 (defclass ede-proj-project (ede-project) | |
187 ((makefile-type :initarg :makefile-type | |
188 :initform Makefile | |
189 :type symbol | |
190 :custom (choice (const Makefile) | |
191 ;(const Makefile.in) | |
192 (const Makefile.am) | |
193 ;(const cook) | |
194 ) | |
195 :documentation "The type of Makefile to generate. | |
196 Can be one of 'Makefile, 'Makefile.in, or 'Makefile.am. | |
197 If this value is NOT 'Makefile, then that overrides the :makefile slot | |
198 in targets.") | |
199 (variables :initarg :variables | |
200 :initform nil | |
201 :type list | |
202 :custom (repeat (cons (string :tag "Name") | |
203 (string :tag "Value"))) | |
204 :group (settings) | |
205 :documentation "Variables to set in this Makefile.") | |
206 (configuration-variables | |
207 :initarg :configuration-variables | |
208 :initform ("debug" (("DEBUG" . "1"))) | |
209 :type list | |
210 :custom (repeat (cons (string :tag "Configuration") | |
211 (repeat | |
212 (cons (string :tag "Name") | |
213 (string :tag "Value"))))) | |
214 :group (settings) | |
215 :documentation "Makefile variables to use in different configurations. | |
216 These variables are used in the makefile when a configuration becomes active.") | |
217 (inference-rules :initarg :inference-rules | |
218 :initform nil | |
219 :custom (repeat | |
220 (object :objecttype ede-makefile-rule)) | |
221 :documentation "Inference rules to add to the makefile.") | |
222 (include-file :initarg :include-file | |
223 :initform nil | |
224 :custom (repeat | |
225 (string :tag "Include File")) | |
226 :documentation "Additional files to include. | |
227 These files can contain additional rules, variables, and customizations.") | |
228 (automatic-dependencies | |
229 :initarg :automatic-dependencies | |
230 :initform t | |
231 :type boolean | |
232 :custom boolean | |
233 :group (default settings) | |
234 :documentation | |
235 "Non-nil to do implement automatic dependencies in the Makefile.") | |
236 (menu :initform | |
237 ( | |
238 [ "Regenerate Makefiles" ede-proj-regenerate t ] | |
239 [ "Upload Distribution" ede-upload-distribution t ] | |
240 ) | |
241 ) | |
242 (metasubproject | |
243 :initarg :metasubproject | |
244 :initform nil | |
245 :type boolean | |
246 :custom boolean | |
247 :group (default settings) | |
248 :documentation | |
249 "Non-nil if this is a metasubproject. | |
250 Usually, a subproject is determined by a parent project. If multiple top level | |
251 projects are grouped into a large project not maintained by EDE, then you need | |
252 to set this to non-nil. The only effect is that the `dist' rule will then avoid | |
253 making a tar file.") | |
254 ) | |
255 "The EDE-PROJ project definition class.") | |
256 | |
257 ;;; Code: | |
258 (defun ede-proj-load (project &optional rootproj) | |
259 "Load a project file from PROJECT directory. | |
260 If optional ROOTPROJ is provided then ROOTPROJ is the root project | |
261 for the tree being read in. If ROOTPROJ is nil, then assume that | |
262 the PROJECT being read in is the root project." | |
263 (save-excursion | |
264 (let ((ret nil) | |
265 (subdirs (directory-files project nil "[^.].*" nil))) | |
266 (set-buffer (get-buffer-create " *tmp proj read*")) | |
267 (unwind-protect | |
268 (progn | |
269 (insert-file-contents (concat project "Project.ede") | |
270 nil nil nil t) | |
271 (goto-char (point-min)) | |
272 (setq ret (read (current-buffer))) | |
273 (if (not (eq (car ret) 'ede-proj-project)) | |
274 (error "Corrupt project file")) | |
275 (setq ret (eval ret)) | |
276 (oset ret file (concat project "Project.ede")) | |
277 (oset ret directory project) | |
278 (oset ret rootproject rootproj) | |
279 ) | |
280 (kill-buffer " *tmp proj read*")) | |
281 (while subdirs | |
282 (let ((sd (file-name-as-directory | |
283 (expand-file-name (car subdirs) project)))) | |
284 (if (and (file-directory-p sd) | |
285 (ede-directory-project-p sd)) | |
286 (oset ret subproj | |
287 (cons (ede-proj-load sd (or rootproj ret)) | |
288 (oref ret subproj)))) | |
289 (setq subdirs (cdr subdirs)))) | |
290 ret))) | |
291 | |
292 (defun ede-proj-save (&optional project) | |
293 "Write out object PROJECT into its file." | |
294 (save-excursion | |
295 (if (not project) (setq project (ede-current-project))) | |
296 (let ((b (set-buffer (get-buffer-create " *tmp proj write*"))) | |
297 (cfn (oref project file)) | |
298 (cdir (oref project directory))) | |
299 (unwind-protect | |
300 (save-excursion | |
301 (erase-buffer) | |
302 (let ((standard-output (current-buffer))) | |
303 (oset project file (file-name-nondirectory cfn)) | |
304 (slot-makeunbound project :directory) | |
305 (object-write project ";; EDE project file.")) | |
306 (write-file cfn nil) | |
307 ) | |
308 ;; Restore the :file on exit. | |
309 (oset project file cfn) | |
310 (oset project directory cdir) | |
311 (kill-buffer b))))) | |
312 | |
313 (defmethod ede-commit-local-variables ((proj ede-proj-project)) | |
314 "Commit change to local variables in PROJ." | |
315 (ede-proj-save proj)) | |
316 | |
317 (defmethod eieio-done-customizing ((proj ede-proj-project)) | |
318 "Call this when a user finishes customizing this object. | |
319 Argument PROJ is the project to save." | |
320 (call-next-method) | |
321 (ede-proj-save proj)) | |
322 | |
323 (defmethod eieio-done-customizing ((target ede-proj-target)) | |
324 "Call this when a user finishes customizing this object. | |
325 Argument TARGET is the project we are completing customization on." | |
326 (call-next-method) | |
327 (ede-proj-save (ede-current-project))) | |
328 | |
329 (defmethod ede-commit-project ((proj ede-proj-project)) | |
330 "Commit any change to PROJ to its file." | |
331 (ede-proj-save proj)) | |
332 | |
333 (defmethod ede-buffer-mine ((this ede-proj-project) buffer) | |
334 "Return t if object THIS lays claim to the file in BUFFER." | |
335 (let ((f (ede-convert-path this (buffer-file-name buffer)))) | |
336 (or (string= (file-name-nondirectory (oref this file)) f) | |
337 (string= (ede-proj-dist-makefile this) f) | |
338 (string-match "Makefile\\(\\.\\(in\\|am\\)\\)?$" f) | |
339 (string-match "config\\(ure\\.in\\|\\.stutus\\)?$" f) | |
340 ))) | |
341 | |
342 (defmethod ede-buffer-mine ((this ede-proj-target) buffer) | |
343 "Return t if object THIS lays claim to the file in BUFFER." | |
344 (or (call-next-method) | |
345 (ede-target-buffer-in-sourcelist this buffer (oref this auxsource)))) | |
346 | |
347 | |
348 ;;; EDE command functions | |
349 ;; | |
350 (defvar ede-proj-target-history nil | |
351 "History when querying for a target type.") | |
352 | |
353 (defmethod project-new-target ((this ede-proj-project) | |
354 &optional name type autoadd) | |
355 "Create a new target in THIS based on the current buffer." | |
356 (let* ((name (or name (read-string "Name: " ""))) | |
357 (type (or type | |
358 (completing-read "Type: " ede-proj-target-alist | |
359 nil t nil '(ede-proj-target-history . 1)))) | |
360 (ot nil) | |
361 (src (if (and (buffer-file-name) | |
362 (if (and autoadd (stringp autoadd)) | |
363 (string= autoadd "y") | |
364 (y-or-n-p (format "Add %s to %s? " (buffer-name) name)))) | |
365 (buffer-file-name))) | |
366 (fcn (cdr (assoc type ede-proj-target-alist))) | |
367 ) | |
368 | |
369 (when (not fcn) | |
370 (error "Unknown target type %s for EDE Project." type)) | |
371 | |
372 (setq ot (funcall fcn name :name name | |
373 :path (ede-convert-path this default-directory) | |
374 :source (if src | |
375 (list (file-name-nondirectory src)) | |
376 nil))) | |
377 ;; If we added it, set the local buffer's object. | |
378 (if src (progn | |
379 (setq ede-object ot) | |
380 (ede-apply-object-keymap))) | |
381 ;; Add it to the project object | |
382 ;;(oset this targets (cons ot (oref this targets))) | |
383 ;; New form: Add to the end using fancy eieio function. | |
384 ;; @todone - Some targets probably want to be in the front. | |
385 ;; How to do that? | |
386 ;; @ans - See elisp autoloads for answer | |
387 (object-add-to-list this 'targets ot t) | |
388 ;; And save | |
389 (ede-proj-save this))) | |
390 | |
391 (defmethod project-new-target-custom ((this ede-proj-project)) | |
392 "Create a new target in THIS for custom." | |
393 (let* ((name (read-string "Name: " "")) | |
394 (type (completing-read "Type: " ede-proj-target-alist | |
395 nil t nil '(ede-proj-target-history . 1)))) | |
396 (funcall (cdr (assoc type ede-proj-target-alist)) name :name name | |
397 :path (ede-convert-path this default-directory) | |
398 :source nil))) | |
399 | |
400 (defmethod project-delete-target ((this ede-proj-target)) | |
401 "Delete the current target THIS from it's parent project." | |
402 (let ((p (ede-current-project)) | |
403 (ts (oref this source))) | |
404 ;; Loop across all sources. If it exists in a buffer, | |
405 ;; clear it's object. | |
406 (while ts | |
407 (let* ((default-directory (oref this path)) | |
408 (b (get-file-buffer (car ts)))) | |
409 (if b | |
410 (save-excursion | |
411 (set-buffer b) | |
412 (if (eq ede-object this) | |
413 (progn | |
414 (setq ede-object nil) | |
415 (ede-apply-object-keymap)))))) | |
416 (setq ts (cdr ts))) | |
417 ;; Remove THIS from it's parent. | |
418 ;; The two vectors should be pointer equivalent. | |
419 (oset p targets (delq this (oref p targets))) | |
420 (ede-proj-save (ede-current-project)))) | |
421 | |
422 (defmethod project-add-file ((this ede-proj-target) file) | |
423 "Add to target THIS the current buffer represented as FILE." | |
424 (let ((file (ede-convert-path this file)) | |
425 (src (ede-target-sourcecode this))) | |
426 (while (and src (not (ede-want-file-p (car src) file))) | |
427 (setq src (cdr src))) | |
428 (when src | |
429 (setq src (car src)) | |
430 (cond ((ede-want-file-source-p this file) | |
431 (object-add-to-list this 'source file t)) | |
432 ((ede-want-file-auxiliary-p this file) | |
433 (object-add-to-list this 'auxsource file t)) | |
434 (t (error "`project-add-file(ede-target)' source mismatch error"))) | |
435 (ede-proj-save)))) | |
436 | |
437 (defmethod project-remove-file ((target ede-proj-target) file) | |
438 "For TARGET, remove FILE. | |
439 FILE must be massaged by `ede-convert-path'." | |
440 ;; Speedy delete should be safe. | |
441 (object-remove-from-list target 'source (ede-convert-path target file)) | |
442 (object-remove-from-list target 'auxsource (ede-convert-path target file)) | |
443 (ede-proj-save)) | |
444 | |
445 (defmethod project-update-version ((this ede-proj-project)) | |
446 "The :version of project THIS has changed." | |
447 (ede-proj-save)) | |
448 | |
449 (defmethod project-make-dist ((this ede-proj-project)) | |
450 "Build a distribution for the project based on THIS target." | |
451 ;; I'm a lazy bum, so I'll make a makefile for doing this sort | |
452 ;; of thing, and rely only on that small section of code. | |
453 (let ((pm (ede-proj-dist-makefile this)) | |
454 (df (project-dist-files this))) | |
455 (if (and (file-exists-p (car df)) | |
456 (not (y-or-n-p "Dist file already exists. Rebuild? "))) | |
457 (error "Try `ede-update-version' before making a distribution")) | |
458 (ede-proj-setup-buildenvironment this) | |
459 (if (string= pm "Makefile.am") (setq pm "Makefile")) | |
460 (compile (concat ede-make-command " -f " pm " dist")) | |
461 )) | |
462 | |
463 (defmethod project-dist-files ((this ede-proj-project)) | |
464 "Return a list of files that constitutes a distribution of THIS project." | |
465 (list | |
466 ;; Note to self, keep this first for the above fn to check against. | |
467 (concat (oref this name) "-" (oref this version) ".tar.gz") | |
468 )) | |
469 | |
470 (defmethod project-compile-project ((proj ede-proj-project) &optional command) | |
471 "Compile the entire current project PROJ. | |
472 Argument COMMAND is the command to use when compiling." | |
473 (let ((pm (ede-proj-dist-makefile proj)) | |
474 (default-directory (file-name-directory (oref proj file)))) | |
475 (ede-proj-setup-buildenvironment proj) | |
476 (if (string= pm "Makefile.am") (setq pm "Makefile")) | |
477 (compile (concat ede-make-command" -f " pm " all")))) | |
478 | |
479 ;;; Target type specific compilations/debug | |
480 ;; | |
481 (defmethod project-compile-target ((obj ede-proj-target) &optional command) | |
482 "Compile the current target OBJ. | |
483 Argument COMMAND is the command to use for compiling the target." | |
484 (project-compile-project (ede-current-project) command)) | |
485 | |
486 (defmethod project-compile-target ((obj ede-proj-target-makefile) | |
487 &optional command) | |
488 "Compile the current target program OBJ. | |
489 Optional argument COMMAND is the s the alternate command to use." | |
490 (ede-proj-setup-buildenvironment (ede-current-project)) | |
491 (compile (concat ede-make-command " -f " (oref obj makefile) " " | |
492 (ede-proj-makefile-target-name obj)))) | |
493 | |
494 (defmethod project-debug-target ((obj ede-proj-target)) | |
495 "Run the current project target OBJ in a debugger." | |
496 (error "Debug-target not supported by %s" (object-name obj))) | |
497 | |
498 (defmethod ede-proj-makefile-target-name ((this ede-proj-target)) | |
499 "Return the name of the main target for THIS target." | |
500 (ede-name this)) | |
501 | |
502 ;;; Compiler and source code generators | |
503 ;; | |
504 (defmethod ede-want-file-auxiliary-p ((this ede-target) file) | |
505 "Return non-nil if THIS target wants FILE." | |
506 ;; By default, all targets reference the source object, and let it decide. | |
507 (let ((src (ede-target-sourcecode this))) | |
508 (while (and src (not (ede-want-file-auxiliary-p (car src) file))) | |
509 (setq src (cdr src))) | |
510 src)) | |
511 | |
512 (defmethod ede-proj-compilers ((obj ede-proj-target)) | |
513 "List of compilers being used by OBJ. | |
514 If the `compiler' slot is empty, concoct one on a first match found | |
515 basis for any given type from the `availablecompilers' slot. | |
516 Otherwise, return the `compiler' slot. | |
517 Converts all symbols into the objects to be used." | |
518 (when (slot-exists-p obj 'compiler) | |
519 (let ((comp (oref obj compiler))) | |
520 (if comp | |
521 ;; Now that we have a pre-set compilers to use, convert tye symbols | |
522 ;; into objects for ease of use | |
523 (if (listp comp) | |
524 (setq comp (mapcar 'symbol-value comp)) | |
525 (setq comp (list (symbol-value comp)))) | |
526 (let* ((acomp (oref obj availablecompilers)) | |
527 (avail (mapcar 'symbol-value acomp)) | |
528 (st (oref obj sourcetype)) | |
529 (sources (oref obj source))) | |
530 ;; COMP is not specified, so generate a list from the available | |
531 ;; compilers list. | |
532 (while st | |
533 (if (ede-want-any-source-files-p (symbol-value (car st)) sources) | |
534 (let ((c (ede-proj-find-compiler avail (car st)))) | |
535 (if c (setq comp (cons c comp))))) | |
536 (setq st (cdr st))))) | |
537 ;; Return the disovered compilers | |
538 comp))) | |
539 | |
540 (defmethod ede-proj-linkers ((obj ede-proj-target)) | |
541 "List of linkers being used by OBJ. | |
542 If the `linker' slot is empty, concoct one on a first match found | |
543 basis for any given type from the `availablelinkers' slot. | |
544 Otherwise, return the `linker' slot. | |
545 Converts all symbols into the objects to be used." | |
546 (when (slot-exists-p obj 'linker) | |
547 (let ((link (oref obj linker))) | |
548 (if link | |
549 ;; Now that we have a pre-set linkers to use, convert type symbols | |
550 ;; into objects for ease of use | |
551 (if (symbolp link) | |
552 (setq link (list (symbol-value link))) | |
553 (error ":linker is not a symbol. Howd you do that?")) | |
554 (let* ((alink (oref obj availablelinkers)) | |
555 (avail (mapcar 'symbol-value alink)) | |
556 (st (oref obj sourcetype)) | |
557 (sources (oref obj source))) | |
558 ;; LINKER is not specified, so generate a list from the available | |
559 ;; compilers list. | |
560 (while st | |
561 (if (ede-want-any-source-files-p (symbol-value (car st)) sources) | |
562 (let ((c (ede-proj-find-linker avail (car st)))) | |
563 (if c (setq link (cons c link))))) | |
564 (setq st (cdr st))) | |
565 (unless link | |
566 ;; No linker stands out! Loop over our linkers and pull out | |
567 ;; the first that has no source type requirement. | |
568 (while (and avail (not (eieio-instance-inheritor-slot-boundp (car avail) 'sourcetype))) | |
569 (setq avail (cdr avail))) | |
570 (setq link (cdr avail))))) | |
571 ;; Return the disovered linkers | |
572 link))) | |
573 | |
574 | |
575 ;;; Target type specific autogenerating gobbldegook. | |
576 ;; | |
577 | |
578 (defun ede-proj-makefile-type (&optional proj) | |
579 "Makefile type of the current project PROJ." | |
580 (oref (or proj (ede-current-project)) makefile-type)) | |
581 | |
582 (defun ede-proj-automake-p (&optional proj) | |
583 "Return non-nil if the current project PROJ is automake mode." | |
584 (eq (ede-proj-makefile-type proj) 'Makefile.am)) | |
585 | |
586 (defun ede-proj-autoconf-p (&optional proj) | |
587 "Return non-nil if the current project PROJ is automake mode." | |
588 (eq (ede-proj-makefile-type proj) 'Makefile.in)) | |
589 | |
590 (defun ede-proj-make-p (&optional proj) | |
591 "Return non-nil if the current project PROJ is automake mode." | |
592 (eq (ede-proj-makefile-type proj) 'Makefile)) | |
593 | |
594 (defmethod ede-proj-dist-makefile ((this ede-proj-project)) | |
595 "Return the name of the Makefile with the DIST target in it for THIS." | |
596 (cond ((eq (oref this makefile-type) 'Makefile.am) | |
597 (concat (file-name-directory (oref this file)) | |
598 "Makefile.am")) | |
599 ((eq (oref this makefile-type) 'Makefile.in) | |
600 (concat (file-name-directory (oref this file)) | |
601 "Makefile.in")) | |
602 ((object-assoc "Makefile" 'makefile (oref this targets)) | |
603 (concat (file-name-directory (oref this file)) | |
604 "Makefile")) | |
605 (t | |
606 (let ((targets (oref this targets))) | |
607 (while (and targets | |
608 (not (obj-of-class-p | |
609 (car targets) | |
610 'ede-proj-target-makefile))) | |
611 (setq targets (cdr targets))) | |
612 (if targets (oref (car targets) makefile) | |
613 (concat (file-name-directory (oref this file)) | |
614 "Makefile")))))) | |
615 | |
616 (defun ede-proj-regenerate () | |
617 "Regenerate Makefiles for and edeproject project." | |
618 (interactive) | |
619 (ede-proj-setup-buildenvironment (ede-current-project) t)) | |
620 | |
621 (defmethod ede-proj-makefile-create-maybe ((this ede-proj-project) mfilename) | |
622 "Create a Makefile for all Makefile targets in THIS if needed. | |
623 MFILENAME is the makefile to generate." | |
624 ;; For now, pass through until dirty is implemented. | |
625 (require 'ede/pmake) | |
626 (if (or (not (file-exists-p mfilename)) | |
627 (file-newer-than-file-p (oref this file) mfilename)) | |
628 (ede-proj-makefile-create this mfilename))) | |
629 | |
630 (defmethod ede-proj-setup-buildenvironment ((this ede-proj-project) | |
631 &optional force) | |
632 "Setup the build environment for project THIS. | |
633 Handles the Makefile, or a Makefile.am configure.in combination. | |
634 Optional argument FORCE will force items to be regenerated." | |
635 (if (not force) | |
636 (ede-proj-makefile-create-maybe this (ede-proj-dist-makefile this)) | |
637 (require 'ede/pmake) | |
638 (ede-proj-makefile-create this (ede-proj-dist-makefile this))) | |
639 ;; Rebuild all subprojects | |
640 (ede-map-subprojects | |
641 this (lambda (sproj) (ede-proj-setup-buildenvironment sproj force))) | |
642 ;; Autoconf projects need to do other kinds of initializations. | |
643 (when (and (ede-proj-automake-p this) | |
644 (eq this (ede-toplevel this))) | |
645 (require 'ede/pconf) | |
646 ;; If the user wants to force this, do it some other way? | |
647 (ede-proj-configure-synchronize this) | |
648 ;; Now run automake to fill in the blanks, autoconf, and other | |
649 ;; auto thingies so that we can just say "make" when done. | |
650 ) | |
651 ) | |
652 | |
653 | |
654 ;;; Lower level overloads | |
655 ;; | |
656 (defmethod project-rescan ((this ede-proj-project)) | |
657 "Rescan the EDE proj project THIS." | |
658 (let ((root (or (ede-project-root this) this)) | |
659 ) | |
660 (setq ede-projects (delq root ede-projects)) | |
661 (ede-proj-load (ede-project-root-directory root)) | |
662 )) | |
663 | |
664 (defmethod project-rescan ((this ede-proj-target) readstream) | |
665 "Rescan target THIS from the read list READSTREAM." | |
666 (setq readstream (cdr (cdr readstream))) ;; constructor/name | |
667 (while readstream | |
668 (let ((tag (car readstream)) | |
669 (val (car (cdr readstream)))) | |
670 (eieio-oset this tag val)) | |
671 (setq readstream (cdr (cdr readstream))))) | |
672 | |
673 (provide 'ede/proj) | |
674 | |
675 ;;; ede/proj.el ends here |