Commit | Line | Data |
---|---|---|
acc33231 CY |
1 | ;;; ede-pmake.el --- EDE Generic Project Makefile code generator. |
2 | ||
3 | ;;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, | |
4 | ;;; 2007, 2008, 2009 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 | ;; Code generator for Makefiles. | |
27 | ;; | |
28 | ;; Here is how it should work: | |
29 | ;; 1) Collect information about the project and targets | |
30 | ;; 2) Insert header into the Makefile | |
31 | ;; 3) Insert basic variables (target/source) | |
32 | ;; 4) Conditional | |
33 | ;; a) Makefile | |
34 | ;; 1) Insert support variables (compiler variables, etc) | |
35 | ;; 2) Insert VERSION and DISTDIR | |
36 | ;; 3) Specify top build dir if necessary | |
37 | ;; 4) Specify compile/link commands (c, etc) | |
38 | ;; 5) Specify dependency files | |
39 | ;; 6) Specify all: target | |
40 | ;; 7) Include dependency files | |
41 | ;; 8) Insert commonized target specify rules | |
42 | ;; 9) Insert clean: and dist: rules | |
43 | ;; b) Automake file | |
44 | ;; 1) Insert distribution source variables for targets | |
45 | ;; 2) Insert user requested rules | |
46 | ||
47 | (require 'ede/proj) | |
48 | (require 'ede/proj-obj) | |
49 | (require 'ede/proj-comp) | |
50 | ||
51 | ;;; Code: | |
52 | (defmethod ede-proj-makefile-create ((this ede-proj-project) mfilename) | |
53 | "Create a Makefile for all Makefile targets in THIS. | |
54 | MFILENAME is the makefile to generate." | |
55 | (let ((mt nil) | |
56 | (isdist (string= mfilename (ede-proj-dist-makefile this))) | |
57 | (depth 0) | |
58 | (orig-buffer nil) | |
59 | (buff-to-kill nil) | |
60 | ) | |
61 | ;; Find out how deep this project is. | |
62 | (let ((tmp this)) | |
63 | (while (setq tmp (ede-parent-project tmp)) | |
64 | (setq depth (1+ depth)))) | |
65 | ;; Collect the targets that belong in a makefile. | |
66 | (mapc | |
67 | (lambda (obj) | |
68 | (if (and (obj-of-class-p obj 'ede-proj-target-makefile) | |
69 | (string= (oref obj makefile) mfilename)) | |
70 | (setq mt (cons obj mt)))) | |
71 | (oref this targets)) | |
72 | ;; Fix the order so things compile in the right direction. | |
73 | (setq mt (nreverse mt)) | |
74 | ;; Add in the header part of the Makefile* | |
75 | (save-excursion | |
76 | (setq orig-buffer (get-file-buffer mfilename)) | |
77 | (set-buffer (setq buff-to-kill (find-file-noselect mfilename))) | |
78 | (goto-char (point-min)) | |
79 | (if (and | |
80 | (not (eobp)) | |
81 | (not (looking-at "# Automatically Generated \\w+ by EDE."))) | |
82 | (if (not (y-or-n-p (format "Really replace %s? " mfilename))) | |
83 | (error "Not replacing Makefile")) | |
84 | (message "Replace EDE Makefile")) | |
85 | (erase-buffer) | |
86 | (ede-srecode-setup) | |
87 | ;; Insert a giant pile of stuff that is common between | |
88 | ;; one of our Makefiles, and a Makefile.in | |
89 | (ede-srecode-insert | |
90 | "file:ede-empty" | |
91 | "MAKETYPE" | |
92 | (with-slots (makefile-type) this | |
93 | (cond ((eq makefile-type 'Makefile) "make") | |
94 | ((eq makefile-type 'Makefile.in) "autoconf") | |
95 | ((eq makefile-type 'Makefile.am) "automake") | |
96 | (t (error ":makefile-type in project invalid"))))) | |
97 | ||
98 | ;; Just this project's variables | |
99 | (ede-proj-makefile-insert-variables this) | |
100 | ||
101 | ;; Space | |
102 | (insert "\n") | |
103 | ||
104 | (cond | |
105 | ((eq (oref this makefile-type) 'Makefile) | |
106 | ;; Make sure the user has the right kind of make | |
107 | (ede-make-check-version) | |
108 | ||
109 | (let* ((targ (if isdist (oref this targets) mt)) | |
110 | (sp (oref this subproj)) | |
111 | (df (apply 'append | |
112 | (mapcar (lambda (tg) | |
113 | (ede-proj-makefile-dependency-files tg)) | |
114 | targ)))) | |
115 | ;; Distribution variables | |
116 | (ede-compiler-begin-unique | |
117 | (mapc 'ede-proj-makefile-insert-variables targ)) | |
118 | ;; Only add the distribution stuff in when depth != 0 | |
119 | (let ((top (ede-toplevel this)) | |
120 | (tmp this) | |
121 | (subdir "")) | |
122 | (insert "VERSION=" (oref top version) "\n" | |
123 | "DISTDIR=$(top)" (oref top name) "-$(VERSION)") | |
124 | (while (ede-parent-project tmp) | |
125 | (setq subdir | |
126 | (concat | |
127 | "/" | |
128 | (file-name-nondirectory | |
129 | (directory-file-name | |
130 | (file-name-directory (oref tmp file)))) | |
131 | subdir) | |
132 | tmp (ede-parent-project tmp))) | |
133 | (insert subdir "\n")) | |
134 | ;; Some built in variables for C code | |
135 | (if df | |
136 | (let ((tc depth)) | |
137 | (insert "top_builddir = ") | |
138 | (while (/= 0 tc) | |
139 | (setq tc (1- tc)) | |
140 | (insert "..") | |
141 | (if (/= tc 0) (insert "/"))) | |
142 | (insert "\n"))) | |
143 | (insert "\n") | |
144 | ;; Create a variable with all the dependency files to include | |
145 | ;; These methods borrowed from automake. | |
146 | (if (and (oref this automatic-dependencies) df) | |
147 | (progn | |
148 | (insert "DEP_FILES=" | |
149 | (mapconcat (lambda (f) | |
150 | (concat ".deps/" | |
151 | (file-name-nondirectory | |
152 | (file-name-sans-extension | |
153 | f)) ".P")) | |
154 | df " ")))) | |
155 | ;; | |
156 | ;; Insert ALL Rule | |
157 | ;; | |
158 | (insert "\n\nall:") | |
159 | (mapc (lambda (c) | |
160 | (if (and (slot-exists-p c 'partofall) (oref c partofall)) | |
161 | ;; Only insert this rule if it is a part of ALL. | |
162 | (insert " " (ede-proj-makefile-target-name c)))) | |
163 | targ) | |
164 | (mapc (lambda (c) | |
165 | (insert " " (ede-name c)) | |
166 | ) | |
167 | sp) | |
168 | (insert "\n\n") | |
169 | ;; | |
170 | ;; Add in the include files | |
171 | ;; | |
172 | (mapc (lambda (c) | |
173 | (insert "include " c "\n\n")) | |
174 | (oref this include-file)) | |
175 | ;; Some C inference rules | |
176 | ;; Dependency rules borrowed from automake. | |
177 | ;; | |
178 | ;; NOTE: This is GNU Make specific. | |
179 | (if (and (oref this automatic-dependencies) df) | |
180 | (insert "DEPS_MAGIC := $(shell mkdir .deps > /dev/null " | |
181 | "2>&1 || :)\n" | |
182 | "-include $(DEP_FILES)\n\n")) | |
183 | ;; | |
184 | ;; General makefile rules stored in the individual targets | |
185 | ;; | |
186 | (ede-compiler-begin-unique | |
187 | (ede-proj-makefile-insert-rules this) | |
188 | (mapc 'ede-proj-makefile-insert-rules targ)) | |
189 | ;; | |
190 | ;; phony targets for sub projects | |
191 | ;; | |
192 | (mapc 'ede-proj-makefile-insert-subproj-rules sp) | |
193 | ;; | |
194 | ;; Distribution rules such as CLEAN and DIST | |
195 | ;; | |
196 | (when isdist | |
197 | (ede-proj-makefile-tags this mt) | |
198 | (ede-proj-makefile-insert-dist-rules this))) | |
199 | (save-buffer)) | |
200 | ((eq (oref this makefile-type) 'Makefile.in) | |
201 | (error "Makefile.in is not supported")) | |
202 | ((eq (oref this makefile-type) 'Makefile.am) | |
203 | (require 'ede-pconf) | |
204 | ;; Distribution variables | |
205 | (let ((targ (if isdist (oref this targets) mt))) | |
206 | (ede-compiler-begin-unique | |
207 | (mapc 'ede-proj-makefile-insert-automake-pre-variables targ)) | |
208 | (ede-compiler-begin-unique | |
209 | (mapc 'ede-proj-makefile-insert-source-variables targ)) | |
210 | (ede-compiler-begin-unique | |
211 | (mapc 'ede-proj-makefile-insert-automake-post-variables targ)) | |
212 | (ede-compiler-begin-unique | |
213 | (ede-proj-makefile-insert-user-rules this)) | |
214 | (insert "\n# End of Makefile.am\n") | |
215 | (save-buffer)) | |
216 | ) | |
217 | (t (error "Unknown makefile type when generating Makefile"))) | |
218 | ;; Put the cursor in a nice place | |
219 | (goto-char (point-min))) | |
220 | ;; If we have an original buffer, then don't kill it. | |
221 | (when (not orig-buffer) | |
222 | (kill-buffer buff-to-kill)) | |
223 | )) | |
224 | ||
225 | ;;; VARIABLE insertion | |
226 | ;; | |
227 | (defun ede-pmake-end-of-variable () | |
228 | "Move to the end of the variable declaration under point." | |
229 | (end-of-line) | |
230 | (while (= (preceding-char) ?\\) | |
231 | (forward-char 1) | |
232 | (end-of-line)) | |
233 | ) | |
234 | ||
235 | (defmacro ede-pmake-insert-variable-shared (varname &rest body) | |
236 | "Add VARNAME into the current Makefile. | |
237 | Execute BODY in a location where a value can be placed." | |
238 | `(let ((addcr t) (v ,varname)) | |
239 | (if (re-search-backward (concat "^" v "\\s-*=") nil t) | |
240 | (progn | |
241 | (ede-pmake-end-of-variable) | |
242 | (if (< (current-column) 40) | |
243 | (if (and (/= (preceding-char) ?=) | |
244 | (/= (preceding-char) ? )) | |
245 | (insert " ")) | |
246 | (insert "\\\n ")) | |
247 | (setq addcr nil)) | |
248 | (insert v "=")) | |
249 | ,@body | |
250 | (if addcr (insert "\n")) | |
251 | (goto-char (point-max)))) | |
252 | (put 'ede-pmake-insert-variable-shared 'lisp-indent-function 1) | |
253 | ||
254 | ;;; SOURCE VARIABLE NAME CONSTRUCTION | |
255 | ||
256 | (defsubst ede-pmake-varname (obj) | |
257 | "Convert OBJ into a variable name name. | |
258 | Change . to _ in the variable name." | |
259 | (let ((name (oref obj name))) | |
260 | (while (string-match "\\." name) | |
261 | (setq name (replace-match "_" nil t name))) | |
262 | name)) | |
263 | ||
264 | (defmethod ede-proj-makefile-sourcevar ((this ede-proj-target)) | |
265 | "Return the variable name for THIS's sources." | |
266 | (concat (ede-pmake-varname this) "_YOU_FOUND_A_BUG")) | |
267 | ||
268 | ;;; DEPENDENCY FILE GENERATOR LISTS | |
269 | ;; | |
270 | (defmethod ede-proj-makefile-dependency-files ((this ede-proj-target)) | |
271 | "Return a list of source files to convert to dependencies. | |
272 | Argument THIS is the target to get sources from." | |
273 | nil) | |
274 | ||
275 | ;;; GENERIC VARIABLES | |
276 | ;; | |
277 | (defmethod ede-proj-makefile-configuration-variables ((this ede-proj-project) | |
278 | configuration) | |
279 | "Return a list of configuration variables from THIS. | |
280 | Use CONFIGURATION as the current configuration to query." | |
281 | (cdr (assoc configuration (oref this configuration-variables)))) | |
282 | ||
283 | (defmethod ede-proj-makefile-insert-variables-new ((this ede-proj-project)) | |
284 | "Insert variables needed by target THIS. | |
285 | ||
286 | NOTE: Not yet in use! This is part of an SRecode conversion of | |
287 | EDE that is in progress." | |
288 | ; (let ((conf-table (ede-proj-makefile-configuration-variables | |
289 | ; this (oref this configuration-default))) | |
290 | ; (conf-done nil)) | |
291 | ; | |
292 | ; (ede-srecode-insert-with-dictionary | |
293 | ; "declaration:ede-vars" | |
294 | ; | |
295 | ; ;; Insert all variables, and augment them with details from | |
296 | ; ;; the current configuration. | |
297 | ; (mapc (lambda (c) | |
298 | ; | |
299 | ; (let ((ldict (srecode-dictionary-add-section-dictionary | |
300 | ; dict "VARIABLE")) | |
301 | ; ) | |
302 | ; (srecode-dictionary-set-value ldict "NAME" (car c)) | |
303 | ; (if (assoc (car c) conf-table) | |
304 | ; (let ((vdict (srecode-dictionary-add-section-dictionary | |
305 | ; ldict "VALUE"))) | |
306 | ; (srecode-dictionary-set-value | |
307 | ; vdict "VAL" (cdr (assoc (car c) conf-table))) | |
308 | ; (setq conf-done (cons (car c) conf-done)))) | |
309 | ; (let ((vdict (srecode-dictionary-add-section-dictionary | |
310 | ; ldict "VALUE"))) | |
311 | ; (srecode-dictionary-set-value vdict "VAL" (cdr c)))) | |
312 | ; ) | |
313 | ; | |
314 | ; (oref this variables)) | |
315 | ; | |
316 | ; ;; Add in all variables from the configuration not allready covered. | |
317 | ; (mapc (lambda (c) | |
318 | ; | |
319 | ; (if (member (car c) conf-done) | |
320 | ; nil | |
321 | ; (let* ((ldict (srecode-dictionary-add-section-dictionary | |
322 | ; dict "VARIABLE")) | |
323 | ; (vdict (srecode-dictionary-add-section-dictionary | |
324 | ; ldict "VALUE")) | |
325 | ; ) | |
326 | ; (srecode-dictionary-set-value ldict "NAME" (car c)) | |
327 | ; (srecode-dictionary-set-value vdict "VAL" (cdr c)))) | |
328 | ; ) | |
329 | ; | |
330 | ; conf-table) | |
331 | ; | |
332 | ||
333 | ;; @TODO - finish off this function, and replace the below fcn | |
334 | ||
335 | ; )) | |
336 | ) | |
337 | ||
338 | (defmethod ede-proj-makefile-insert-variables ((this ede-proj-project)) | |
339 | "Insert variables needed by target THIS." | |
340 | (let ((conf-table (ede-proj-makefile-configuration-variables | |
341 | this (oref this configuration-default))) | |
342 | (conf-done nil)) | |
343 | ;; Insert all variables, and augment them with details from | |
344 | ;; the current configuration. | |
345 | (mapc (lambda (c) | |
346 | (insert (car c) "=") | |
347 | (if (assoc (car c) conf-table) | |
348 | (progn | |
349 | (insert (cdr (assoc (car c) conf-table)) " ") | |
350 | (setq conf-done (cons (car c) conf-done)))) | |
351 | (insert (cdr c) "\n")) | |
352 | (oref this variables)) | |
353 | ;; Add in all variables from the configuration not allready covered. | |
354 | (mapc (lambda (c) | |
355 | (if (member (car c) conf-done) | |
356 | nil | |
357 | (insert (car c) "=" (cdr c) "\n"))) | |
358 | conf-table)) | |
359 | (let* ((top "") | |
360 | (tmp this)) | |
361 | (while (ede-parent-project tmp) | |
362 | (setq tmp (ede-parent-project tmp) | |
363 | top (concat "../" top))) | |
364 | (insert "\ntop=" top)) | |
365 | (insert "\nede_FILES=" (file-name-nondirectory (oref this file)) " " | |
366 | (file-name-nondirectory (ede-proj-dist-makefile this)) "\n")) | |
367 | ||
368 | (defmethod ede-proj-makefile-insert-source-variables ((this ede-proj-target) | |
369 | &optional | |
370 | moresource) | |
371 | "Insert the source variables needed by THIS. | |
372 | Optional argument MORESOURCE is a list of additional sources to add to the | |
373 | sources variable." | |
374 | (let ((sv (ede-proj-makefile-sourcevar this))) | |
375 | ;; This variable may be shared between targets | |
376 | (ede-pmake-insert-variable-shared (cond ((listp sv) (car sv)) | |
377 | (t sv)) | |
378 | (insert (mapconcat (lambda (a) a) (oref this source) " ")) | |
379 | (if moresource | |
380 | (insert " \\\n " (mapconcat (lambda (a) a) moresource " ") ""))))) | |
381 | ||
382 | (defmethod ede-proj-makefile-insert-variables ((this ede-proj-target) &optional | |
383 | moresource) | |
384 | "Insert variables needed by target THIS. | |
385 | Optional argument MORESOURCE is a list of additional sources to add to the | |
386 | sources variable." | |
387 | (ede-proj-makefile-insert-source-variables this moresource) | |
388 | ) | |
389 | ||
390 | (defmethod ede-proj-makefile-configuration-variables ((this ede-proj-target-makefile) | |
391 | configuration) | |
392 | "Return a list of configuration variables from THIS. | |
393 | Use CONFIGURATION as the current configuration to query." | |
394 | (cdr (assoc configuration (oref this configuration-variables)))) | |
395 | ||
396 | (defmethod ede-proj-makefile-insert-variables ((this ede-proj-target-makefile) | |
397 | &optional moresource) | |
398 | "Insert variables needed by target THIS. | |
399 | Optional argument MORESOURCE is a list of additional sources to add to the | |
400 | sources variable." | |
401 | (call-next-method) | |
402 | (let* ((proj (ede-target-parent this)) | |
403 | (conf-table (ede-proj-makefile-configuration-variables | |
404 | this (oref proj configuration-default))) | |
405 | (conf-done nil) | |
406 | ) | |
407 | ;; Add in all variables from the configuration not allready covered. | |
408 | (mapc (lambda (c) | |
409 | (if (member (car c) conf-done) | |
410 | nil | |
411 | (insert (car c) "=" (cdr c) "\n"))) | |
412 | conf-table)) | |
413 | (let ((comp (ede-proj-compilers this)) | |
414 | (link (ede-proj-linkers this)) | |
415 | (name (ede-proj-makefile-target-name this)) | |
416 | (src (oref this source))) | |
417 | (while comp | |
418 | (ede-compiler-only-once (car comp) | |
419 | (ede-proj-makefile-insert-object-variables (car comp) name src) | |
420 | (ede-proj-makefile-insert-variables (car comp))) | |
421 | (setq comp (cdr comp))) | |
422 | (while link | |
423 | (ede-linker-only-once (car link) | |
424 | (ede-proj-makefile-insert-variables (car link))) | |
425 | (setq link (cdr link))))) | |
426 | ||
427 | (defmethod ede-proj-makefile-insert-automake-pre-variables | |
428 | ((this ede-proj-target)) | |
429 | "Insert variables needed by target THIS in Makefile.am before SOURCES." | |
430 | nil) | |
431 | ||
432 | (defmethod ede-proj-makefile-insert-automake-post-variables | |
433 | ((this ede-proj-target)) | |
434 | "Insert variables needed by target THIS in Makefile.am after SOURCES." | |
435 | nil) | |
436 | ||
437 | ;;; GARBAGE PATTERNS | |
438 | ;; | |
439 | (defmethod ede-proj-makefile-garbage-patterns ((this ede-proj-project)) | |
440 | "Return a list of patterns that are considered garbage to THIS. | |
441 | These are removed with make clean." | |
442 | (let ((mc (ede-map-targets | |
443 | this (lambda (c) (ede-proj-makefile-garbage-patterns c)))) | |
444 | (uniq nil)) | |
445 | (setq mc (sort (apply 'append mc) 'string<)) | |
446 | ;; Filter out duplicates from the targets. | |
447 | (while mc | |
448 | (if (and (car uniq) (string= (car uniq) (car mc))) | |
449 | nil | |
450 | (setq uniq (cons (car mc) uniq))) | |
451 | (setq mc (cdr mc))) | |
452 | (nreverse uniq))) | |
453 | ||
454 | (defmethod ede-proj-makefile-garbage-patterns ((this ede-proj-target)) | |
455 | "Return a list of patterns that are considered garbage to THIS. | |
456 | These are removed with make clean." | |
457 | ;; Get the the source object from THIS, and use the specified garbage. | |
458 | (let ((src (ede-target-sourcecode this)) | |
459 | (garb nil)) | |
460 | (while src | |
461 | (setq garb (append (oref (car src) garbagepattern) garb) | |
462 | src (cdr src))) | |
463 | garb)) | |
464 | ||
465 | ||
466 | ;;; RULES | |
467 | ;; | |
468 | (defmethod ede-proj-makefile-insert-subproj-rules ((this ede-proj-project)) | |
469 | "Insert a rule for the project THIS which should be a subproject." | |
470 | (insert ".PHONY:" (ede-name this)) | |
471 | (newline) | |
472 | (insert (ede-name this) ":") | |
473 | (newline) | |
474 | (insert "\t$(MAKE) -C " (directory-file-name (ede-subproject-relative-path this))) | |
475 | (newline) | |
476 | (newline) | |
477 | ) | |
478 | ||
479 | (defmethod ede-proj-makefile-insert-rules ((this ede-proj-project)) | |
480 | "Insert rules needed by THIS target." | |
481 | (mapc 'ede-proj-makefile-insert-rules (oref this inference-rules)) | |
482 | ) | |
483 | ||
484 | (defmethod ede-proj-makefile-insert-dist-dependencies ((this ede-proj-project)) | |
485 | "Insert any symbols that the DIST rule should depend on. | |
486 | Argument THIS is the project that should insert stuff." | |
487 | (mapc 'ede-proj-makefile-insert-dist-dependencies (oref this targets)) | |
488 | ) | |
489 | ||
490 | (defmethod ede-proj-makefile-insert-dist-dependencies ((this ede-proj-target)) | |
491 | "Insert any symbols that the DIST rule should depend on. | |
492 | Argument THIS is the target that should insert stuff." | |
493 | nil) | |
494 | ||
495 | (defmethod ede-proj-makefile-insert-dist-filepatterns ((this ede-proj-target)) | |
496 | "Insert any symbols that the DIST rule should depend on. | |
497 | Argument THIS is the target that should insert stuff." | |
498 | (ede-proj-makefile-insert-dist-dependencies this) | |
499 | ) | |
500 | ||
501 | (defmethod ede-proj-makefile-insert-dist-rules ((this ede-proj-project)) | |
502 | "Insert distribution rules for THIS in a Makefile, such as CLEAN and DIST." | |
503 | (let ((junk (ede-proj-makefile-garbage-patterns this)) | |
504 | tmp) | |
505 | ;; Build CLEAN, DIST, TAG, and other rules here. | |
506 | (if junk | |
507 | (insert "\nclean:\n" | |
508 | "\trm -f " | |
509 | (mapconcat (lambda (c) c) junk " ") | |
510 | "\n\n")) | |
511 | ;; @TODO: ^^^ Clean should also recurse. ^^^ | |
512 | ||
513 | (insert ".PHONY: dist\n") | |
514 | (insert "\ndist:") | |
515 | (ede-proj-makefile-insert-dist-dependencies this) | |
516 | (insert "\n") | |
517 | (unless (or (ede-subproject-p this) | |
518 | (oref this metasubproject)) | |
519 | ;; Only delete if we are the toplevel project. | |
520 | (insert "\trm -rf $(DISTDIR)\n")) | |
521 | (insert "\tmkdir $(DISTDIR)\n") ;We may need a -p, but I think not. | |
522 | (setq tmp (oref this targets)) | |
523 | (insert "\tcp") | |
524 | (while tmp | |
525 | (let ((sv (ede-proj-makefile-sourcevar (car tmp)))) | |
526 | (if (listp sv) | |
527 | ;; Handle special case variables. | |
528 | (cond ((eq (cdr sv) 'share) | |
529 | ;; This variable may be shared between multiple targets. | |
530 | (if (re-search-backward (concat "\\$(" (car sv) ")") | |
531 | (save-excursion | |
532 | (beginning-of-line) | |
533 | (point)) | |
534 | t) | |
535 | ;; If its already in the dist target, then skip it. | |
536 | nil | |
537 | (setq sv (car sv)))) | |
538 | (t (setq sv (car sv))))) | |
539 | (if (stringp sv) | |
540 | (insert " $(" sv ")")) | |
541 | (ede-proj-makefile-insert-dist-filepatterns (car tmp)) | |
542 | (setq tmp (cdr tmp)))) | |
543 | (insert " $(ede_FILES) $(DISTDIR)\n") | |
544 | ||
545 | ;; Call our sub projects. | |
546 | (ede-map-subprojects | |
547 | this (lambda (sproj) | |
548 | (let ((rp (directory-file-name (ede-subproject-relative-path sproj)))) | |
549 | (insert "\t$(MAKE) -C " rp " $(MFLAGS) DISTDIR=$(DISTDIR)/" rp | |
550 | " dist" | |
551 | "\n")))) | |
552 | ||
553 | ;; Tar up the stuff. | |
554 | (unless (or (ede-subproject-p this) | |
555 | (oref this metasubproject)) | |
556 | (insert "\ttar -cvzf $(DISTDIR).tar.gz $(DISTDIR)\n" | |
557 | "\trm -rf $(DISTDIR)\n")) | |
558 | ||
559 | ;; Make sure the Makefile is ok. | |
560 | (insert "\n" | |
561 | (file-name-nondirectory (buffer-file-name)) ": " | |
562 | (file-name-nondirectory (oref this file)) "\n" | |
563 | ;; "$(EMACS) -batch Project.ede -l ede -f ede-proj-regenerate" | |
564 | "\t@echo Makefile is out of date! " | |
565 | "It needs to be regenerated by EDE.\n" | |
566 | "\t@echo If you have not modified Project.ede, you can" | |
567 | " use 'touch' to update the Makefile time stamp.\n" | |
568 | "\t@false\n\n" | |
569 | "\n\n# End of Makefile\n"))) | |
570 | ||
571 | (defmethod ede-proj-makefile-insert-rules ((this ede-proj-target)) | |
572 | "Insert rules needed by THIS target." | |
573 | nil) | |
574 | ||
575 | (defmethod ede-proj-makefile-insert-rules ((this ede-proj-target-makefile)) | |
576 | "Insert rules needed by THIS target." | |
577 | (mapc 'ede-proj-makefile-insert-rules (oref this rules)) | |
578 | (let ((c (ede-proj-compilers this))) | |
579 | (when c | |
580 | (mapc 'ede-proj-makefile-insert-rules c) | |
581 | (if (oref this phony) | |
582 | (insert ".PHONY: " (ede-proj-makefile-target-name this) "\n")) | |
583 | (insert (ede-proj-makefile-target-name this) ": " | |
584 | (ede-proj-makefile-dependencies this) "\n") | |
585 | (ede-proj-makefile-insert-commands this) | |
586 | ))) | |
587 | ||
588 | (defmethod ede-proj-makefile-insert-commands ((this ede-proj-target-makefile)) | |
589 | "Insert the commands needed by target THIS. | |
590 | For targets, insert the commands needed by the chosen compiler." | |
591 | (mapc 'ede-proj-makefile-insert-commands (ede-proj-compilers this)) | |
592 | (when (object-assoc t :uselinker (ede-proj-compilers this)) | |
593 | (mapc 'ede-proj-makefile-insert-commands (ede-proj-linkers this)))) | |
594 | ||
595 | ||
596 | (defmethod ede-proj-makefile-insert-user-rules ((this ede-proj-project)) | |
597 | "Insert user specified rules needed by THIS target. | |
598 | This is different from `ede-proj-makefile-insert-rules' in that this | |
599 | function won't create the building rules which are auto created with | |
600 | automake." | |
601 | (mapc 'ede-proj-makefile-insert-user-rules (oref this inference-rules))) | |
602 | ||
603 | (defmethod ede-proj-makefile-insert-user-rules ((this ede-proj-target)) | |
604 | "Insert user specified rules needed by THIS target." | |
605 | (mapc 'ede-proj-makefile-insert-rules (oref this rules))) | |
606 | ||
607 | (defmethod ede-proj-makefile-dependencies ((this ede-proj-target-makefile)) | |
608 | "Return a string representing the dependencies for THIS. | |
609 | Some compilers only use the first element in the dependencies, others | |
610 | have a list of intermediates (object files), and others don't care. | |
611 | This allows customization of how these elements appear." | |
612 | (let* ((c (ede-proj-compilers this)) | |
613 | (io (ede-or (mapcar 'ede-compiler-intermediate-objects-p c))) | |
614 | (out nil)) | |
615 | (if io | |
616 | (progn | |
617 | (while c | |
618 | (setq out | |
619 | (concat out "$(" (ede-compiler-intermediate-object-variable | |
620 | (car c) | |
621 | (ede-proj-makefile-target-name this)) ")") | |
622 | c (cdr c))) | |
623 | out) | |
624 | (let ((sv (ede-proj-makefile-sourcevar this)) | |
625 | (aux (oref this auxsource))) | |
626 | (setq out | |
627 | (if (and (stringp sv) (not (string= sv ""))) | |
628 | (concat "$(" sv ")") | |
629 | "")) | |
630 | (while aux | |
631 | (setq out (concat out " " (car aux))) | |
632 | (setq aux (cdr aux))) | |
633 | out)))) | |
634 | ||
635 | ;; Tags | |
636 | (defmethod ede-proj-makefile-tags ((this ede-proj-project) targets) | |
637 | "Insert into the current location rules to make recursive TAGS files. | |
638 | Argument THIS is the project to create tags for. | |
639 | Argument TARGETS are the targets we should depend on for TAGS." | |
640 | (insert "tags: ") | |
641 | (let ((tg targets)) | |
642 | ;; Loop over all source variables and insert them | |
643 | (while tg | |
644 | (insert "$(" (ede-proj-makefile-sourcevar (car tg)) ") ") | |
645 | (setq tg (cdr tg))) | |
646 | (insert "\n") | |
647 | (if targets | |
648 | (insert "\tetags $^\n")) | |
649 | ;; Now recurse into all subprojects | |
650 | (setq tg (oref this subproj)) | |
651 | (while tg | |
652 | (insert "\t$(MAKE) -C " (ede-subproject-relative-path (car tg)) " $(MFLAGS) $@\n") | |
653 | (setq tg (cdr tg))) | |
654 | (insert "\n"))) | |
655 | ||
656 | ||
657 | (provide 'ede/pmake) | |
658 | ||
659 | ;;; ede/pmake.el ends here |