Function: vhdl-generate-makefile-1

vhdl-generate-makefile-1 is a byte-compiled function defined in vhdl-mode.el.gz.

Signature

(vhdl-generate-makefile-1)

Documentation

Generate Makefile for current project or directory.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/vhdl-mode.el.gz
(defun vhdl-generate-makefile-1 ()
  "Generate Makefile for current project or directory."
  ;; scan hierarchy if required
  (if (vhdl-project-p)
      (unless (or (assoc vhdl-project vhdl-file-alist)
		  (vhdl-load-cache vhdl-project))
	(vhdl-scan-project-contents vhdl-project))
    (let ((directory (abbreviate-file-name default-directory)))
      (unless (or (assoc directory vhdl-file-alist)
		  (vhdl-load-cache directory))
	(vhdl-scan-directory-contents directory))))
  (defvar rule-alist) ; we need it to be dynamically bound
  (let* ((directory (abbreviate-file-name (vhdl-default-directory)))
	 (project (vhdl-project-p))
	 (ent-alist (vhdl-aget vhdl-entity-alist (or project directory)))
	 (conf-alist (vhdl-aget vhdl-config-alist (or project directory)))
	 (pack-alist (vhdl-aget vhdl-package-alist (or project directory)))
	 (regexp-list (or (nth 12 (vhdl-aget vhdl-compiler-alist vhdl-compiler))
			  '("\\1.vhd" "\\2_\\1.vhd" "\\1.vhd"
			    "\\1.vhd" "\\1_body.vhd" identity)))
	 (mapping-exist
	  (if (nth 12 (vhdl-aget vhdl-compiler-alist vhdl-compiler)) t nil))
	 (ent-regexp (cons "\\(.*\\) \\(.*\\) \\(.*\\)" (nth 0 regexp-list)))
	 (arch-regexp (cons "\\(.*\\) \\(.*\\) \\(.*\\)" (nth 1 regexp-list)))
	 (conf-regexp (cons "\\(.*\\) \\(.*\\) \\(.*\\)" (nth 2 regexp-list)))
	 (pack-regexp (cons "\\(.*\\) \\(.*\\) \\(.*\\)" (nth 3 regexp-list)))
	 (pack-body-regexp (cons "\\(.*\\) \\(.*\\) \\(.*\\)" (nth 4 regexp-list)))
	 (adjust-case (nth 5 regexp-list))
	 (work-library (downcase (vhdl-work-library)))
	 (compile-directory (expand-file-name (vhdl-compile-directory)
					      default-directory))
	 (makefile-name (vhdl-makefile-name))
	 rule-alist arch-alist inst-alist
	 target-list depend-list unit-list prim-list second-list subcomp-list
	 lib-alist lib-body-alist pack-list all-pack-list
	 ent-key ent-file-name arch-key arch-file-name ent-arch-key
	 conf-key conf-file-name pack-key pack-file-name
	 ent-entry arch-entry conf-entry pack-entry inst-entry
	 pack-body-key pack-body-file-name inst-ent-key inst-conf-key
	 tmp-key tmp-list rule)
    ;; check prerequisites
    (unless (file-exists-p compile-directory)
      (make-directory compile-directory t))
    (unless mapping-exist
      (vhdl-warning
       (format "No unit-to-file name mapping found for compiler \"%s\".\n  Directory of dummy files is created instead (to be used as dependencies).\n  Please contact the VHDL Mode maintainer for full support of \"%s\""
	       vhdl-compiler vhdl-compiler) t))
    (message "Generating makefile \"%s\"..." makefile-name)
    ;; rules for all entities
    (setq tmp-list ent-alist)
    (while ent-alist
      (setq ent-entry (car ent-alist)
	    ent-key (nth 0 ent-entry))
      (when (nth 2 ent-entry)
	(setq ent-file-name (if vhdl-compile-absolute-path
				(nth 2 ent-entry)
			      (file-relative-name (nth 2 ent-entry)
						  compile-directory))
	      arch-alist (nth 4 ent-entry)
	      lib-alist (nth 6 ent-entry)
	      rule (vhdl-aget rule-alist ent-file-name)
	      target-list (nth 0 rule)
	      depend-list (nth 1 rule)
	      second-list nil
	      subcomp-list nil)
	(setq tmp-key (vhdl-replace-string
		       ent-regexp
		       (funcall adjust-case
				(concat ent-key "  " work-library))))
	(push (cons ent-key tmp-key) unit-list)
	;; rule target for this entity
	(push ent-key target-list)
	;; rule dependencies for all used packages
	(setq pack-list (vhdl-get-packages lib-alist work-library))
	(setq depend-list (append depend-list pack-list))
	(setq all-pack-list pack-list)
	;; add rule
	(vhdl-aput 'rule-alist ent-file-name (list target-list depend-list))
	;; rules for all corresponding architectures
	(while arch-alist
	  (setq arch-entry (car arch-alist)
		arch-key (nth 0 arch-entry)
		ent-arch-key (concat ent-key "-" arch-key)
		arch-file-name (if vhdl-compile-absolute-path
				   (nth 2 arch-entry)
				 (file-relative-name (nth 2 arch-entry)
						     compile-directory))
		inst-alist (nth 4 arch-entry)
		lib-alist (nth 5 arch-entry)
		rule (vhdl-aget rule-alist arch-file-name)
		target-list (nth 0 rule)
		depend-list (nth 1 rule))
	  (setq tmp-key (vhdl-replace-string
			 arch-regexp
			 (funcall adjust-case
				  (concat arch-key " " ent-key " "
					  work-library))))
	  (setq unit-list
		(cons (cons ent-arch-key tmp-key) unit-list))
	  (push ent-arch-key second-list)
	  ;; rule target for this architecture
	  (push ent-arch-key target-list)
	  ;; rule dependency for corresponding entity
	  (push ent-key depend-list)
	  ;; rule dependencies for contained component instantiations
	  (while inst-alist
	    (setq inst-entry (car inst-alist))
	    (when (or (null (nth 8 inst-entry))
		      (equal (downcase (nth 8 inst-entry)) work-library))
	      (setq inst-ent-key (or (nth 7 inst-entry)
				     (nth 5 inst-entry)))
	      (setq depend-list (cons inst-ent-key depend-list)
		    subcomp-list (cons inst-ent-key subcomp-list)))
	    (setq inst-alist (cdr inst-alist)))
	  ;; rule dependencies for all used packages
	  (setq pack-list (vhdl-get-packages lib-alist work-library))
	  (setq depend-list (append depend-list pack-list))
	  (setq all-pack-list (append all-pack-list pack-list))
	  ;; add rule
	  (vhdl-aput 'rule-alist arch-file-name (list target-list depend-list))
	  (setq arch-alist (cdr arch-alist)))
	(push (list ent-key second-list (append subcomp-list all-pack-list))
	      prim-list))
      (setq ent-alist (cdr ent-alist)))
    (setq ent-alist tmp-list)
    ;; rules for all configurations
    (setq tmp-list conf-alist)
    (while conf-alist
      (setq conf-entry (car conf-alist)
	    conf-key (nth 0 conf-entry)
	    conf-file-name (if vhdl-compile-absolute-path
			       (nth 2 conf-entry)
			     (file-relative-name (nth 2 conf-entry)
						 compile-directory))
	    ent-key (nth 4 conf-entry)
	    arch-key (nth 5 conf-entry)
	    inst-alist (nth 6 conf-entry)
	    lib-alist (nth 7 conf-entry)
	    rule (vhdl-aget rule-alist conf-file-name)
	    target-list (nth 0 rule)
	    depend-list (nth 1 rule)
	    subcomp-list (list ent-key))
      (setq tmp-key (vhdl-replace-string
		     conf-regexp
		     (funcall adjust-case
			      (concat conf-key "  " work-library))))
      (push (cons conf-key tmp-key) unit-list)
      ;; rule target for this configuration
      (push conf-key target-list)
      ;; rule dependency for corresponding entity and architecture
      (setq depend-list
	    (cons ent-key (cons (concat ent-key "-" arch-key) depend-list)))
      ;; rule dependencies for used packages
      (setq pack-list (vhdl-get-packages lib-alist work-library))
      (setq depend-list (append depend-list pack-list))
      ;; rule dependencies for contained component configurations
      (while inst-alist
	(setq inst-entry (car inst-alist))
	(setq inst-ent-key (nth 2 inst-entry)
	      inst-conf-key (nth 4 inst-entry))
	(when (equal (downcase (nth 5 inst-entry)) work-library)
	  (when inst-ent-key
	    (setq depend-list (cons inst-ent-key depend-list)
		  subcomp-list (cons inst-ent-key subcomp-list)))
	  (when inst-conf-key
	    (setq depend-list (cons inst-conf-key depend-list)
		  subcomp-list (cons inst-conf-key subcomp-list))))
	(setq inst-alist (cdr inst-alist)))
      ;; add rule
      (vhdl-aput 'rule-alist conf-file-name (list target-list depend-list))
      (push (list conf-key nil (append subcomp-list pack-list)) prim-list)
      (setq conf-alist (cdr conf-alist)))
    (setq conf-alist tmp-list)
    ;; rules for all packages
    (setq tmp-list pack-alist)
    (while pack-alist
      (setq pack-entry (car pack-alist)
	    pack-key (nth 0 pack-entry)
	    pack-body-key nil)
      (when (nth 2 pack-entry)
	(setq pack-file-name (if vhdl-compile-absolute-path
				 (nth 2 pack-entry)
			       (file-relative-name (nth 2 pack-entry)
						   compile-directory))
	      lib-alist (nth 6 pack-entry) lib-body-alist (nth 10 pack-entry)
	      rule (vhdl-aget rule-alist pack-file-name)
	      target-list (nth 0 rule) depend-list (nth 1 rule))
	(setq tmp-key (vhdl-replace-string
		       pack-regexp
		       (funcall adjust-case
				(concat pack-key "  " work-library))))
	(push (cons pack-key tmp-key) unit-list)
	;; rule target for this package
	(push pack-key target-list)
	;; rule dependencies for all used packages
	(setq pack-list (vhdl-get-packages lib-alist work-library))
	(setq depend-list (append depend-list pack-list))
	(setq all-pack-list pack-list)
	;; add rule
	(vhdl-aput 'rule-alist pack-file-name (list target-list depend-list))
	;; rules for this package's body
	(when (nth 7 pack-entry)
	  (setq pack-body-key (concat pack-key "-body")
		pack-body-file-name (if vhdl-compile-absolute-path
					(nth 7 pack-entry)
				      (file-relative-name (nth 7 pack-entry)
							  compile-directory))
		rule (vhdl-aget rule-alist pack-body-file-name)
		target-list (nth 0 rule)
		depend-list (nth 1 rule))
	  (setq tmp-key (vhdl-replace-string
			 pack-body-regexp
			 (funcall adjust-case
				  (concat pack-key "  " work-library))))
	  (setq unit-list
		(cons (cons pack-body-key tmp-key) unit-list))
	  ;; rule target for this package's body
	  (push pack-body-key target-list)
	  ;; rule dependency for corresponding package declaration
	  (push pack-key depend-list)
	  ;; rule dependencies for all used packages
	  (setq pack-list (vhdl-get-packages lib-body-alist work-library))
	  (setq depend-list (append depend-list pack-list))
	  (setq all-pack-list (append all-pack-list pack-list))
	  ;; add rule
	  (vhdl-aput 'rule-alist pack-body-file-name
		     (list target-list depend-list)))
	(setq prim-list
	      (cons (list pack-key (when pack-body-key (list pack-body-key))
			  all-pack-list)
		    prim-list)))
      (setq pack-alist (cdr pack-alist)))
    (setq pack-alist tmp-list)
    ;; generate Makefile
    (let* ((project (vhdl-aget vhdl-project-alist project))
	   (compiler (vhdl-aget vhdl-compiler-alist vhdl-compiler))
	   (compiler-id (nth 9 compiler))
	   (library-directory
	    (vhdl-resolve-env-variable
	     (vhdl-replace-string
	      (cons "\\(.*\\)" (or (nth 7 project) (nth 7 compiler)))
	      compiler-id)))
	   (makefile-path-name (expand-file-name
				makefile-name compile-directory))
	   (orig-buffer (current-buffer))
	   cell second-list subcomp-list options unit-key unit-name)
      ;; sort lists
      (setq unit-list (vhdl-sort-alist unit-list))
      (setq prim-list (vhdl-sort-alist prim-list))
      (setq tmp-list rule-alist)
      (while tmp-list			; pre-sort rule targets
	(setq cell (cdar tmp-list))
	(setcar cell (sort (car cell) #'string<))
	(setq tmp-list (cdr tmp-list)))
      (setq rule-alist			; sort by first rule target
	    (sort rule-alist
                  (lambda (a b)
                    (string< (car (cadr a)) (car (cadr b))))))
      ;; open and clear Makefile
      (set-buffer (find-file-noselect makefile-path-name t t))
      (erase-buffer)
      (insert "# -*- Makefile -*-\n"
	      "### " (file-name-nondirectory makefile-name)
	      " - VHDL Makefile generated by Emacs VHDL Mode " vhdl-version
	      "\n")
      (if project
	  (insert "\n# Project   : " (nth 0 project))
	(insert "\n# Directory : \"" directory "\""))
      (insert "\n# Platform  : " vhdl-compiler
	      "\n# Generated : " (format-time-string "%Y-%m-%d %T ")
	      (user-login-name) "\n")
      ;; insert compile and option variable settings
      (insert "\n\n# Define compilation command and options\n"
	      "\nCOMPILE = " (nth 0 compiler)
	      "\nOPTIONS = " (vhdl-get-compile-options project compiler nil)
	      (if (equal vhdl-compile-post-command "") ""
		(concat "\nPOST-COMPILE = " vhdl-compile-post-command))
	      "\n")
      ;; insert library paths
      (setq library-directory
	    (directory-file-name
	     (if (file-name-absolute-p library-directory)
		 library-directory
	       (file-relative-name
		(expand-file-name library-directory directory)
		compile-directory))))
      (insert "\n\n# Define library paths\n"
	      "\nLIBRARY-" work-library " = " library-directory "\n")
      (unless mapping-exist
	(insert "LIBRARY-" work-library "-make = " "$(LIBRARY-" work-library
		")/make" "\n"))
      ;; insert variable definitions for all library unit files
      (insert "\n\n# Define library unit files\n")
      (setq tmp-list unit-list)
      (while unit-list
	(insert "\nUNIT-" work-library "-" (caar unit-list)
		" = \\\n\t$(LIBRARY-" work-library
		(if mapping-exist "" "-make") ")/" (cdar unit-list))
	(setq unit-list (cdr unit-list)))
      ;; insert variable definition for list of all library unit files
      (insert "\n\n\n# Define list of all library unit files\n"
	      "\nALL_UNITS =")
      (setq unit-list tmp-list)
      (while unit-list
	(insert " \\\n\t" "$(UNIT-" work-library "-" (caar unit-list) ")")
	(setq unit-list (cdr unit-list)))
      (insert "\n")
      (setq unit-list tmp-list)
      ;; insert `make all' rule
      (insert "\n\n\n# Rule for compiling entire design\n"
	      "\n" (nth 0 vhdl-makefile-default-targets) " :"
	      " \\\n\t\t" (nth 2 vhdl-makefile-default-targets)
	      " \\\n\t\t$(ALL_UNITS)\n")
      ;; insert `make clean' rule
      (insert "\n\n# Rule for cleaning entire design\n"
	      "\n" (nth 1 vhdl-makefile-default-targets) " : "
	      "\n\t-rm -f $(ALL_UNITS)\n")
      ;; insert `make library' rule
      (insert "\n\n# Rule for creating library directory\n"
	      "\n" (nth 2 vhdl-makefile-default-targets) " :"
	      " \\\n\t\t$(LIBRARY-" work-library ")"
	      (if mapping-exist ""
		(concat " \\\n\t\t$(LIBRARY-" work-library "-make)\n"))
	      "\n"
	      "\n$(LIBRARY-" work-library ") :"
	      "\n\t"
	      (vhdl-replace-string
	       (cons "\\(.*\\)\n\\(.*\\)" (nth 5 compiler))
	       (concat "$(LIBRARY-" work-library ")\n" (vhdl-work-library)))
	      "\n")
      (unless mapping-exist
	(insert "\n$(LIBRARY-" work-library "-make) :"
		"\n\t"
		"mkdir -p $(LIBRARY-" work-library "-make)\n"))
      ;; insert '.PHONY' declaration
      (insert "\n\n.PHONY : "
	      (nth 0 vhdl-makefile-default-targets) " "
	      (nth 1 vhdl-makefile-default-targets) " "
	      (nth 2 vhdl-makefile-default-targets) "\n")
      ;; insert rule for each library unit
      (insert "\n\n# Rules for compiling single library units and their subhierarchy\n")
      (while prim-list
	(setq second-list (sort (nth 1 (car prim-list)) #'string<))
	(setq subcomp-list
	      (sort (vhdl-uniquify (nth 2 (car prim-list))) #'string<))
	(setq unit-key (caar prim-list)
	      unit-name (or (nth 0 (vhdl-aget ent-alist unit-key))
			    (nth 0 (vhdl-aget conf-alist unit-key))
			    (nth 0 (vhdl-aget pack-alist unit-key))))
	(insert "\n" unit-key)
	(unless (equal unit-key unit-name)
	  (insert " \\\n" unit-name))
	(insert " :"
		" \\\n\t\t" (nth 2 vhdl-makefile-default-targets))
	(while subcomp-list
	  (when (and (assoc (car subcomp-list) unit-list)
		     (not (equal unit-key (car subcomp-list))))
	    (insert " \\\n\t\t" (car subcomp-list)))
	  (setq subcomp-list (cdr subcomp-list)))
	(insert " \\\n\t\t$(UNIT-" work-library "-" unit-key ")")
	(while second-list
	  (insert " \\\n\t\t$(UNIT-" work-library "-" (car second-list) ")")
	  (setq second-list (cdr second-list)))
	(insert "\n")
	(setq prim-list (cdr prim-list)))
      ;; insert rule for each library unit file
      (insert "\n\n# Rules for compiling single library unit files\n")
      (while rule-alist
	(setq rule (car rule-alist))
	;; get compiler options for this file
	(setq options
	      (vhdl-get-compile-options project compiler (nth 0 rule) t))
	;; insert rule if file is supposed to be compiled
	(setq target-list (nth 1 rule)
	      depend-list (sort (vhdl-uniquify (nth 2 rule)) #'string<))
	;; insert targets
	(setq tmp-list target-list)
	(while target-list
	  (insert "\n$(UNIT-" work-library "-" (car target-list) ")"
		  (if (cdr target-list) " \\" " :"))
	  (setq target-list (cdr target-list)))
	(setq target-list tmp-list)
	;; insert file name as first dependency
	(insert " \\\n\t\t" (nth 0 rule))
	;; insert dependencies (except if also target or unit does not exist)
	(while depend-list
	  (when (and (not (member (car depend-list) target-list))
		     (assoc (car depend-list) unit-list))
	    (insert " \\\n\t\t"
		    "$(UNIT-" work-library "-" (car depend-list) ")"))
	  (setq depend-list (cdr depend-list)))
	;; insert compile command
	(if options
	    (insert "\n\t$(COMPILE) "
		    (if (eq options 'default) "$(OPTIONS)" options) " "
		    (nth 0 rule)
		    (if (equal vhdl-compile-post-command "") ""
		      " $(POST-COMPILE)")
		    "\n")
	  (insert "\n"))
	(unless (and options mapping-exist)
	  (setq tmp-list target-list)
	  (while target-list
	    (insert "\t@touch $(UNIT-" work-library "-" (car target-list) ")\n")
	    (setq target-list (cdr target-list)))
	  (setq target-list tmp-list))
	(setq rule-alist (cdr rule-alist)))

      (insert "\n\n### " makefile-name " ends here\n")
      ;; run Makefile generation hook
      (run-hooks 'vhdl-makefile-generation-hook)
      (message "Generating makefile \"%s\"...done" makefile-name)
      ;; save and close file
      (if (file-writable-p makefile-path-name)
	  (progn (save-buffer)
		 (kill-buffer (current-buffer))
		 (set-buffer orig-buffer)
		 (when (fboundp 'add-to-history)
		   (add-to-history 'file-name-history makefile-path-name)))
	(vhdl-warning-when-idle
	 (format "File not writable: \"%s\""
		 (abbreviate-file-name makefile-path-name)))
	(switch-to-buffer (current-buffer))))))