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