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