1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-27 10:54:40 +00:00

Synch EDE to CEDET 1.0.

* cedet-idutils.el (cedet-idutils-make-command): New option.
(cedet-idutils-mkid-call):
(cedet-idutils-create/update-database): New functions.

* cedet-cscope.el (cedet-cscope-create):
(cedet-cscope-create/update-database): New functions.
(cedet-cscope-support-for-directory): Make interactive.

* cedet-global.el (cedet-global-gtags-command): New option.
(cedet-gnu-global-gtags-call)
(cedet-gnu-global-create/update-database): New functions.

* ede.el (ede-save-cache): Fix recentf-exclude expression.
(ede-make-dist): Always use toplevel project.
(ede-buffer-object): If we fail to find an object in the current
project, loop upward looking for a match.  If no target is found,
use most local project.
(ede-buffer-belongs-to-target-p)
(ede-buffer-belongs-to-project-p): New functions.
(ede-initialize-state-current-buffer): New function.
(ede-target-forms-menu, ede-project-buffers): Use them.
(ede-minor-mode, ede-reset-all-buffers): Use it.
(project-interactive-select-target, project-add-file): Don't use
ede-project-force-load.
(ede-buffer-object): New arg PROJSYM.
(ede-minor-mode): Remove ede-directory-project-p test.
(ede-initialize-state-current-buffer): Don't test for
ede-directory-project-p if there is a matching open project.
(ede-customize-forms-menu): Prevent error if there is no project.
(ede-load-project-file): Set ede-constructing to the thing being
constructed, instead of t.
(ede-project-force-load): Deleted.

* ede/base.el:
* ede/auto.el:
* ede/custom.el: New files.

* ede/autoconf-edit.el (autoconf-find-last-macro)
(autoconf-parameters-for-macro): Parse multiline parameters of
macros.  Optionally ignore case and at bol for macro.
(autoconf-parameter-strip): Use greedy match for newlines.
(autoconf-new-automake-string): Deleted.
(autoconf-new-program): Use SRecode to fill an empty file.

* ede/cpp-root.el (ede-create-lots-of-projects-under-dir): New
function.

* ede/files.el (ede-flush-project-hash): New command.
(ede-convert-path): Add optional PROJECT arg.
(ede-directory-project-p): Obey ".ede-ignore".
(ede-expand-filename-local)
(ede-expand-filename-impl-via-subproj): New methods.
(ede-expand-filename-impl): Use them.
(ede-project-root, ede-project-root-directory): Move to
ede/auto.el.

* ede/locate.el (ede-locate-flush-hash):
(ede-locate-create/update-root-database): New methods.
(initialize-instance): Use ede-locate-flush-hash.

* ede/pmake.el (ede-proj-makefile-insert-variables): If this is
the top project and not a metasubproject, set TOP to CURDIR.
(ede-proj-makefile-insert-variables): Output a target's object
list whether or not the vars are already in the Makefile.
(ede-pmake-insert-variable-once): New macro.

* ede/project-am.el (project-am-with-makefile-current): Add
recentf-exclude.
(project-am-load-makefile): Obey an optional suggested name.
(project-am-expand-subdirlist): New function.
(project-am-makefile::project-rescan): Use it.  Combine SUBDIRS
and DIST_SUBDIRS.
(project-am-meta-type-alist): A list to scan better Makefile.am
(project-am-scan-for-targets): Scan also over
project-am-meta-type-alist.
(ede-system-include-path): Simple implementation.
(ede-find-target): Deleted.  EDE core takes care of this.
(ede-buffer-mine): Create the searched filename as relative.
(project-am-load): Simplify, using autoconf-edit.
(project-am-extract-package-info): Fix separators.

* ede/proj.el (project-run-target): New method.
(project-make-dist, project-compile-project): Use
ede-proj-automake-p to determine which kind of compile to use.
(project-rescan): Call ede-load-project-file.
(ede-buffer-mine): Add more file names that belong to the project.
(ede-proj-compilers): Improve error message.

* ede/proj-obj.el (ede-ld-linker): Use the LDDEPS variable.
(ede-source-c++): Add more C++ extensions.
(ede-proj-target-makefile-objectcode): Quote initforms.  Support
lex and yacc.

* ede/proj-prog.el (ede-proj-makefile-insert-rules): Removed.
(ede-proj-makefile-insert-variables): New, add LDDEPS.
(ede-proj-makefile-insert-automake-post-variables): Add LDADD
variable.  Use ldlibs-local slot.  Add a -l to ldlibs strings.
(ede-proj-target-makefile-program): Swap order of two slots so
they show up in the same order as in the command line.
(ede-proj-target-makefile-program): Add ldlibs-local slot.

* ede/proj-shared.el (ede-g++-libtool-shared-compiler): Fix
inference rule to use cpp files.
(ede-proj-target-makefile-shared-object): Quote initforms.

* ede/proj-misc.el (ede-proj-target-makefile-miscelaneous):
* ede/proj-info.el (ede-proj-target-makefile-info):
* ede/proj-aux.el (ede-proj-target-aux):
* ede/proj-archive.el (ede-proj-target-makefile-archive):
* ede/proj-elisp.el (ede-proj-target-elisp)
(ede-proj-target-elisp-autoloads): Quote initforms.

* ede/srecode.el (ede-srecode-setup): Load autoconf templates.

* ede/shell.el (ede-shell-buffer): Fix buffer name.

* ede/pconf.el (ede-proj-configure-synchronize): If user events
occur while waiting for the compile process to finish, pull them
in and discard those events.
This commit is contained in:
Eric M. Ludlam 2010-09-20 22:42:53 -04:00 committed by Chong Yidong
parent 9e0d4f9ef1
commit cb85c0d8be
32 changed files with 2318 additions and 1272 deletions

View File

@ -1,3 +1,127 @@
2010-09-21 Eric Ludlam <zappo@gnu.org>
Synch EDE to CEDET 1.0.
* cedet-idutils.el (cedet-idutils-make-command): New option.
(cedet-idutils-mkid-call):
(cedet-idutils-create/update-database): New functions.
* cedet-cscope.el (cedet-cscope-create):
(cedet-cscope-create/update-database): New functions.
(cedet-cscope-support-for-directory): Make interactive.
* cedet-global.el (cedet-global-gtags-command): New option.
(cedet-gnu-global-gtags-call)
(cedet-gnu-global-create/update-database): New functions.
* ede.el (ede-save-cache): Fix recentf-exclude expression.
(ede-make-dist): Always use toplevel project.
(ede-buffer-object): If we fail to find an object in the current
project, loop upward looking for a match. If no target is found,
use most local project.
(ede-buffer-belongs-to-target-p)
(ede-buffer-belongs-to-project-p): New functions.
(ede-initialize-state-current-buffer): New function.
(ede-target-forms-menu, ede-project-buffers): Use them.
(ede-minor-mode, ede-reset-all-buffers): Use it.
(project-interactive-select-target, project-add-file): Don't use
ede-project-force-load.
(ede-buffer-object): New arg PROJSYM.
(ede-minor-mode): Remove ede-directory-project-p test.
(ede-initialize-state-current-buffer): Don't test for
ede-directory-project-p if there is a matching open project.
(ede-customize-forms-menu): Prevent error if there is no project.
(ede-load-project-file): Set ede-constructing to the thing being
constructed, instead of t.
(ede-project-force-load): Deleted.
* ede/base.el:
* ede/auto.el:
* ede/custom.el: New files.
* ede/autoconf-edit.el (autoconf-find-last-macro)
(autoconf-parameters-for-macro): Parse multiline parameters of
macros. Optionally ignore case and at bol for macro.
(autoconf-parameter-strip): Use greedy match for newlines.
(autoconf-new-automake-string): Deleted.
(autoconf-new-program): Use SRecode to fill an empty file.
* ede/cpp-root.el (ede-create-lots-of-projects-under-dir): New
function.
* ede/files.el (ede-flush-project-hash): New command.
(ede-convert-path): Add optional PROJECT arg.
(ede-directory-project-p): Obey ".ede-ignore".
(ede-expand-filename-local)
(ede-expand-filename-impl-via-subproj): New methods.
(ede-expand-filename-impl): Use them.
(ede-project-root, ede-project-root-directory): Move to
ede/auto.el.
* ede/locate.el (ede-locate-flush-hash):
(ede-locate-create/update-root-database): New methods.
(initialize-instance): Use ede-locate-flush-hash.
* ede/pmake.el (ede-proj-makefile-insert-variables): If this is
the top project and not a metasubproject, set TOP to CURDIR.
(ede-proj-makefile-insert-variables): Output a target's object
list whether or not the vars are already in the Makefile.
(ede-pmake-insert-variable-once): New macro.
* ede/project-am.el (project-am-with-makefile-current): Add
recentf-exclude.
(project-am-load-makefile): Obey an optional suggested name.
(project-am-expand-subdirlist): New function.
(project-am-makefile::project-rescan): Use it. Combine SUBDIRS
and DIST_SUBDIRS.
(project-am-meta-type-alist): A list to scan better Makefile.am
(project-am-scan-for-targets): Scan also over
project-am-meta-type-alist.
(ede-system-include-path): Simple implementation.
(ede-find-target): Deleted. EDE core takes care of this.
(ede-buffer-mine): Create the searched filename as relative.
(project-am-load): Simplify, using autoconf-edit.
(project-am-extract-package-info): Fix separators.
* ede/proj.el (project-run-target): New method.
(project-make-dist, project-compile-project): Use
ede-proj-automake-p to determine which kind of compile to use.
(project-rescan): Call ede-load-project-file.
(ede-buffer-mine): Add more file names that belong to the project.
(ede-proj-compilers): Improve error message.
* ede/proj-obj.el (ede-ld-linker): Use the LDDEPS variable.
(ede-source-c++): Add more C++ extensions.
(ede-proj-target-makefile-objectcode): Quote initforms. Support
lex and yacc.
* ede/proj-prog.el (ede-proj-makefile-insert-rules): Removed.
(ede-proj-makefile-insert-variables): New, add LDDEPS.
(ede-proj-makefile-insert-automake-post-variables): Add LDADD
variable. Use ldlibs-local slot. Add a -l to ldlibs strings.
(ede-proj-target-makefile-program): Swap order of two slots so
they show up in the same order as in the command line.
(ede-proj-target-makefile-program): Add ldlibs-local slot.
* ede/proj-shared.el (ede-g++-libtool-shared-compiler): Fix
inference rule to use cpp files.
(ede-proj-target-makefile-shared-object): Quote initforms.
* ede/proj-misc.el (ede-proj-target-makefile-miscelaneous):
* ede/proj-info.el (ede-proj-target-makefile-info):
* ede/proj-aux.el (ede-proj-target-aux):
* ede/proj-archive.el (ede-proj-target-makefile-archive):
* ede/proj-elisp.el (ede-proj-target-elisp)
(ede-proj-target-elisp-autoloads): Quote initforms.
* ede/srecode.el (ede-srecode-setup): Load autoconf templates.
* ede/shell.el (ede-shell-buffer): Fix buffer name.
* ede/pconf.el (ede-proj-configure-synchronize): If user events
occur while waiting for the compile process to finish, pull them
in and discard those events.
2010-09-19 Eric Ludlam <zappo@gnu.org>
Synch Semantic to CEDET 1.0.

View File

@ -72,6 +72,12 @@ SCOPE is the scope of the search, such as 'project or 'subdirs."
)
(cedet-cscope-call (list "-d" "-L" idx searchtext))))
(defun cedet-cscope-create (flags)
"Create a CScope database at the current directory.
FLAGS are additional flags to pass to cscope beyond the
options -cR."
(cedet-cscope-call (append (list "-cR") flags)))
(defun cedet-cscope-call (flags)
"Call CScope with the list of FLAGS."
(let ((b (get-buffer-create "*CEDET CScope*"))
@ -112,13 +118,19 @@ Return a fully qualified filename."
If DIR is not supplied, use the current default directory.
This works by running cscope on a bogus symbol, and looking for
the error code."
(interactive "DDirectory: ")
(save-excursion
(let ((default-directory (or dir default-directory)))
(set-buffer (cedet-cscope-call (list "-d" "-L" "-7" "moose")))
(goto-char (point-min))
(if (looking-at "[^ \n]*cscope: ")
nil
t))))
(let ((ans (looking-at "[^ \n]*cscope: ")))
(if (called-interactively-p 'interactive)
(if ans
(message "No support for CScope in %s" default-directory)
(message "CScope is supported in %s" default-directory))
(if ans
nil
t))))))
(defun cedet-cscope-version-check (&optional noerror)
"Check the version of the installed CScope command.
@ -150,6 +162,14 @@ return nil."
(message "CScope %s - Good enough for CEDET." rev))
t)))))
(defun cedet-cscope-create/update-database (&optional dir)
"Create a CScope database in DIR.
CScope will automatically choose incremental rebuild if
there is already a database in DIR."
(interactive "DDirectory: ")
(let ((default-directory dir))
(cedet-cscope-create nil)))
(provide 'cedet-cscope)
;; arch-tag: 9973f1ad-f13b-4399-bc67-7f488478d78d

View File

@ -33,6 +33,12 @@
:type 'string
:group 'cedet)
(defcustom cedet-global-gtags-command "gtags"
"Command name for the GNU Global gtags executable.
GTAGS is used to create the tags table queried by the 'global' command."
:type 'string
:group 'cedet)
;;; Code:
(defun cedet-gnu-global-search (searchtext texttype type scope)
"Perform a search with GNU Global, return the created buffer.
@ -75,6 +81,19 @@ SCOPE is the scope of the search, such as 'project or 'subdirs."
flags)
b))
(defun cedet-gnu-global-gtags-call (flags)
"Create GNU Global TAGS using gtags with FLAGS."
(let ((b (get-buffer-create "*CEDET Global gtags*"))
(cd default-directory)
)
(with-current-buffer b
(setq default-directory cd)
(erase-buffer))
(apply 'call-process cedet-global-gtags-command
nil b nil
flags)
b))
(defun cedet-gnu-global-expand-filename (filename)
"Expand the FILENAME with GNU Global.
Return a fully qualified filename."
@ -152,6 +171,18 @@ return nil."
;; Return the results
(nreverse hits))))
(defun cedet-gnu-global-create/update-database (&optional dir)
"Create a GNU Global database in DIR.
If a database already exists, then just update it."
(interactive "DDirectory: ")
(let ((root (cedet-gnu-global-root dir)))
(if root (setq dir root))
(let ((default-directory dir))
(cedet-gnu-global-gtags-call
(when root
'("-i");; Incremental update flag.
)))))
(provide 'cedet-global)
;; arch-tag: 0d0d3ac2-91ef-4820-bb2b-1d59ccf38392

View File

@ -43,6 +43,11 @@
:type 'string
:group 'cedet)
(defcustom cedet-idutils-make-command "mkid"
"Command name for the ID Utils executable for creating token databases."
:type 'string
:group 'cedet)
(defun cedet-idutils-search (searchtext texttype type scope)
"Perform a search with ID Utils, return the created buffer.
SEARCHTEXT is text to find.
@ -104,6 +109,20 @@ Return the created buffer with with program output."
flags)
b))
(defun cedet-idutils-mkid-call (flags)
"Call ID Utils mkid with the list of FLAGS.
Return the created buffer with with program output."
(let ((b (get-buffer-create "*CEDET mkid*"))
(cd default-directory)
)
(with-current-buffer b
(setq default-directory cd)
(erase-buffer))
(apply 'call-process cedet-idutils-make-command
nil b nil
flags)
b))
;;; UTIL CALLS
;;
(defun cedet-idutils-expand-filename (filename)
@ -171,6 +190,12 @@ return nil."
(message "ID Utils %s - Good enough for CEDET." rev))
t)))))
(defun cedet-idutils-create/update-database (&optional dir)
"Create an IDUtils database in DIR.
IDUtils must start from scratch when updating a database."
(interactive "DDirectory: ")
(let ((default-directory dir))
(cedet-idutils-mkid-call nil)))
(provide 'cedet-idutils)

File diff suppressed because it is too large Load Diff

128
lisp/cedet/ede/auto.el Normal file
View File

@ -0,0 +1,128 @@
;;; ede/auto.el --- Autoload features for EDE
;; Copyright (C) 2010 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; EDE Autoloads are a way to refer to different project types without
;; loading those projects into Emacs.
;;
;; These routines are used to detect a project in a filesystem before
;; handing over control to the usual EDE project system.
;;; Code:
(require 'eieio)
(defclass ede-project-autoload ()
((name :initarg :name
:documentation "Name of this project type")
(file :initarg :file
:documentation "The lisp file belonging to this class.")
(proj-file :initarg :proj-file
:documentation "Name of a project file of this type.")
(proj-root :initarg :proj-root
:type function
:documentation "A function symbol to call for the project root.
This function takes no arguments, and returns the current directories
root, if available. Leave blank to use the EDE directory walking
routine instead.")
(initializers :initarg :initializers
:initform nil
:documentation
"Initializers passed to the project object.
These are used so there can be multiple types of projects
associated with a single object class, based on the initilizeres used.")
(load-type :initarg :load-type
:documentation "Fn symbol used to load this project file.")
(class-sym :initarg :class-sym
:documentation "Symbol representing the project class to use.")
(new-p :initarg :new-p
:initform t
:documentation
"Non-nil if this is an option when a user creates a project.")
)
"Class representing minimal knowledge set to run preliminary EDE functions.
When more advanced functionality is needed from a project type, that projects
type is required and the load function used.")
(defvar ede-project-class-files
(list
(ede-project-autoload "edeproject-makefile"
:name "Make" :file 'ede/proj
:proj-file "Project.ede"
:load-type 'ede-proj-load
:class-sym 'ede-proj-project)
(ede-project-autoload "edeproject-automake"
:name "Automake" :file 'ede/proj
:proj-file "Project.ede"
:initializers '(:makefile-type Makefile.am)
:load-type 'ede-proj-load
:class-sym 'ede-proj-project)
(ede-project-autoload "automake"
:name "automake" :file 'ede/project-am
:proj-file "Makefile.am"
:load-type 'project-am-load
:class-sym 'project-am-makefile
:new-p nil))
"List of vectors defining how to determine what type of projects exist.")
;;; EDE project-autoload methods
;;
(defmethod ede-project-root ((this ede-project-autoload))
"If a project knows its root, return it here.
Allows for one-project-object-for-a-tree type systems."
nil)
(defmethod ede-project-root-directory ((this ede-project-autoload)
&optional file)
"If a project knows its root, return it here.
Allows for one-project-object-for-a-tree type systems.
Optional FILE is the file to test. If there is no FILE, use
the current buffer."
(when (not file)
(setq file default-directory))
(when (slot-boundp this :proj-root)
(let ((rootfcn (oref this proj-root)))
(when rootfcn
(condition-case nil
(funcall rootfcn file)
(error
(funcall rootfcn)))
))))
(defmethod ede-dir-to-projectfile ((this ede-project-autoload) dir)
"Return a full file name of project THIS found in DIR.
Return nil if the project file does not exist."
(let* ((d (file-name-as-directory dir))
(root (ede-project-root-directory this d))
(pf (oref this proj-file))
(f (cond ((stringp pf)
(expand-file-name pf (or root d)))
((and (symbolp pf) (fboundp pf))
(funcall pf (or root d)))))
)
(when (and f (file-exists-p f))
f)))
(provide 'ede/auto)
;;; ede/auto.el ends here

View File

@ -27,20 +27,8 @@
;;; Code:
(require 'autoconf)
(defvar autoconf-new-automake-string
"dnl Process this file with autoconf to produce a configure script
AC_INIT(%s)
AM_INIT_AUTOMAKE([%s], 0)
AM_CONFIG_HEADER(config.h)
dnl End the configure script.
AC_OUTPUT(Makefile, [date > stamp-h] )\n"
"This string is used to initialize a new configure.in.
The default is designed to be used with automake.
The first %s will be filled with the test file.
The second %s will be filled with the program name.")
(declare-function ede-srecode-setup "ede/srecode")
(declare-function ede-srecode-insert "ede/srecode")
(defun autoconf-new-program (rootdir program testfile)
"Initialize a new configure.in in ROOTDIR for PROGRAM using TESTFILE.
@ -49,6 +37,7 @@ PROGRAM is the program to be configured.
TESTFILE is the file used with AC_INIT.
configure the initial configure script using `autoconf-new-automake-string'"
(interactive "DRoot Dir: \nsProgram: \nsTest File: ")
(require 'ede/srecode)
(if (bufferp rootdir)
(set-buffer rootdir)
(let ((cf1 (expand-file-name "configure.in" rootdir))
@ -62,7 +51,12 @@ configure the initial configure script using `autoconf-new-automake-string'"
(find-file cf2)))
;; Note, we only ask about overwrite if a string/path is specified.
(erase-buffer)
(insert (format autoconf-new-automake-string testfile program)))
(ede-srecode-setup)
(ede-srecode-insert
"file:ede-empty"
"TEST_FILE" testfile
"PROGRAM" program)
)
(defvar autoconf-preferred-macro-order
'("AC_INIT"
@ -151,42 +145,44 @@ From the autoconf manual:
(beginning-of-line)
(looking-at (concat "\\(A[CM]_" macro "\\|" macro "\\)"))))
(defun autoconf-find-last-macro (macro)
(defun autoconf-find-last-macro (macro &optional ignore-bol)
"Move to the last occurrence of MACRO in FILE, and return that point.
The last macro is usually the one in which we would like to insert more
items such as CHECK_HEADERS."
(let ((op (point)))
(let ((op (point)) (atbol (if ignore-bol "" "^")))
(goto-char (point-max))
(if (re-search-backward (concat "^" (regexp-quote macro) "\\s-*\\((\\|$\\)") nil t)
(if (re-search-backward (concat atbol (regexp-quote macro) "\\s-*\\((\\|$\\)") nil t)
(progn
(beginning-of-line)
(unless ignore-bol (beginning-of-line))
(point))
(goto-char op)
nil)))
(defun autoconf-parameter-strip (param)
"Strip the parameter PARAM of whitespace and miscellaneous characters."
(when (string-match "^\\s-*\\[?\\s-*" param)
;; force greedy match for \n.
(when (string-match "\\`\n*\\s-*\\[?\\s-*" param)
(setq param (substring param (match-end 0))))
(when (string-match "\\s-*\\]?\\s-*$" param)
(when (string-match "\\s-*\\]?\\s-*\\'" param)
(setq param (substring param 0 (match-beginning 0))))
param)
(defun autoconf-parameters-for-macro (macro)
(defun autoconf-parameters-for-macro (macro &optional ignore-bol ignore-case)
"Retrieve the parameters to MACRO.
Returns a list of the arguments passed into MACRO as strings."
(save-excursion
(when (autoconf-find-last-macro macro)
(forward-sexp 1)
(mapcar
#'autoconf-parameter-strip
(when (looking-at "(")
(let* ((start (+ (point) 1))
(end (save-excursion
(forward-sexp 1)
(- (point) 1)))
(ans (buffer-substring-no-properties start end)))
(split-string ans "," t)))))))
(let ((case-fold-search ignore-case))
(save-excursion
(when (autoconf-find-last-macro macro ignore-bol)
(forward-sexp 1)
(mapcar
#'autoconf-parameter-strip
(when (looking-at "(")
(let* ((start (+ (point) 1))
(end (save-excursion
(forward-sexp 1)
(- (point) 1)))
(ans (buffer-substring-no-properties start end)))
(split-string ans "," t))))))))
(defun autoconf-position-for-macro (macro)
"Position the cursor where a new MACRO could be inserted.

636
lisp/cedet/ede/base.el Normal file
View File

@ -0,0 +1,636 @@
;;; ede/base.el --- Baseclasses for EDE.
;; Copyright (C) 2010 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; Baseclasses for EDE.
;;
;; Contains all the base structures needed by EDE.
;;; Code:
(require 'eieio)
(require 'eieio-speedbar)
(require 'ede/auto)
;; Defined in ede.el:
(defvar ede-projects)
(defvar ede-object)
(defvar ede-object-root-project)
(declare-function data-debug-new-buffer "data-debug")
(declare-function data-debug-insert-object-slots "eieio-datadebug")
(declare-function ede-parent-project "ede" (&optional obj))
(declare-function ede-current-project "ede" (&optional dir))
;;; TARGET
;;
;; The TARGET is an entity in a project that knows about files
;; and features of those files.
(defclass ede-target (eieio-speedbar-directory-button)
((buttonface :initform speedbar-file-face) ;override for superclass
(name :initarg :name
:type string
:custom string
:label "Name"
:group (default name)
:documentation "Name of this target.")
;; @todo - I think this should be "dir", and not "path".
(path :initarg :path
:type string
;:custom string
;:label "Path to target"
;:group (default name)
:documentation "The path to the sources of this target.
Relative to the path of the project it belongs to.")
(source :initarg :source
:initform nil
;; I'd prefer a list of strings.
:type list
:custom (repeat (string :tag "File"))
:label "Source Files"
:group (default source)
:documentation "Source files in this target.")
(versionsource :initarg :versionsource
:initform nil
:type list
:custom (repeat (string :tag "File"))
:label "Source Files with Version String"
:group (source)
:documentation
"Source files with a version string in them.
These files are checked for a version string whenever the EDE version
of the master project is changed. When strings are found, the version
previously there is updated.")
;; Class level slots
;;
(sourcetype :allocation :class
:type list ;; list of symbols
:documentation
"A list of `ede-sourcecode' objects this class will handle.
This is used to match target objects with the compilers they can use, and
which files this object is interested in."
:accessor ede-object-sourcecode)
(keybindings :allocation :class
:initform (("D" . ede-debug-target))
:documentation
"Keybindings specialized to this type of target."
:accessor ede-object-keybindings)
(menu :allocation :class
:initform ( [ "Debug target" ede-debug-target
(ede-buffer-belongs-to-target-p) ]
[ "Run target" ede-run-target
(ede-buffer-belongs-to-target-p) ]
)
:documentation "Menu specialized to this type of target."
:accessor ede-object-menu)
)
"A target is a structure that describes a file set that produces something.
Targets, as with 'Make', is an entity that will manage a file set
and knows how to compile or otherwise transform those files into some
other desired outcome.")
;;; PROJECT/PLACEHOLDER
;;
;; Project placeholders are minimum parts of a project used
;; by the project cache. The project cache can refer to these placeholders,
;; and swap them out with the real-deal when that project is loaded.
;;
(defclass ede-project-placeholder (eieio-speedbar-directory-button)
((name :initarg :name
:initform "Untitled"
:type string
:custom string
:label "Name"
:group (default name)
:documentation "The name used when generating distribution files.")
(version :initarg :version
:initform "1.0"
:type string
:custom string
:label "Version"
:group (default name)
:documentation "The version number used when distributing files.")
(directory :type string
:initarg :directory
:documentation "Directory this project is associated with.")
(dirinode :documentation "The inode id for :directory.")
(file :type string
:initarg :file
:documentation "File name where this project is stored.")
(rootproject ; :initarg - no initarg, don't save this slot!
:initform nil
:type (or null ede-project-placeholder-child)
:documentation "Pointer to our root project.")
)
"Placeholder object for projects not loaded into memory.
Projects placeholders will be stored in a user specific location
and querying them will cause the actual project to get loaded.")
;;; PROJECT
;;
;; An EDE project controls a set of TARGETS, and can also contain
;; multiple SUBPROJECTS.
;;
;; The project defines a set of features that need to be built from
;; files, in addition as to controlling what to do with the file set,
;; such as creating distributions, compilation, and web sites.
;;
;; Projects can also affect how EDE works, by changing what appears in
;; the EDE menu, or how some keys are bound.
;;
(defclass ede-project (ede-project-placeholder)
((subproj :initform nil
:type list
:documentation "Sub projects controlled by this project.
For Automake based projects, each directory is treated as a project.")
(targets :initarg :targets
:type list
:custom (repeat (object :objectcreatefcn ede-new-target-custom))
:label "Local Targets"
:group (targets)
:documentation "List of top level targets in this project.")
(locate-obj :type (or null ede-locate-base-child)
:documentation
"A locate object to use as a backup to `ede-expand-filename'.")
(tool-cache :initarg :tool-cache
:type list
:custom (repeat object)
:label "Tool: "
:group tools
:documentation "List of tool cache configurations in this project.
This allows any tool to create, manage, and persist project-specific settings.")
(mailinglist :initarg :mailinglist
:initform ""
:type string
:custom string
:label "Mailing List Address"
:group name
:documentation
"An email address where users might send email for help.")
(web-site-url :initarg :web-site-url
:initform ""
:type string
:custom string
:label "Web Site URL"
:group name
:documentation "URL to this projects web site.
This is a URL to be sent to a web site for documentation.")
(web-site-directory :initarg :web-site-directory
:initform ""
:custom string
:label "Web Page Directory"
:group name
:documentation
"A directory where web pages can be found by Emacs.
For remote locations use a path compatible with ange-ftp or EFS.
You can also use TRAMP for use with rcp & scp.")
(web-site-file :initarg :web-site-file
:initform ""
:custom string
:label "Web Page File"
:group name
:documentation
"A file which contains the home page for this project.
This file can be relative to slot `web-site-directory'.
This can be a local file, use ange-ftp, EFS, or TRAMP.")
(ftp-site :initarg :ftp-site
:initform ""
:type string
:custom string
:label "FTP site"
:group name
:documentation
"FTP site where this project's distribution can be found.
This FTP site should be in Emacs form, as needed by `ange-ftp', but can
also be of a form used by TRAMP for use with scp, or rcp.")
(ftp-upload-site :initarg :ftp-upload-site
:initform ""
:type string
:custom string
:label "FTP Upload site"
:group name
:documentation
"FTP Site to upload new distributions to.
This FTP site should be in Emacs form as needed by `ange-ftp'.
If this slot is nil, then use `ftp-site' instead.")
(configurations :initarg :configurations
:initform ("debug" "release")
:type list
:custom (repeat string)
:label "Configuration Options"
:group (settings)
:documentation "List of available configuration types.
Individual target/project types can form associations between a configuration,
and target specific elements such as build variables.")
(configuration-default :initarg :configuration-default
:initform "debug"
:custom string
:label "Current Configuration"
:group (settings)
:documentation "The default configuration.")
(local-variables :initarg :local-variables
:initform nil
:custom (repeat (cons (sexp :tag "Variable")
(sexp :tag "Value")))
:label "Project Local Variables"
:group (settings)
:documentation "Project local variables")
(keybindings :allocation :class
:initform (("D" . ede-debug-target)
("R" . ede-run-target))
:documentation "Keybindings specialized to this type of target."
:accessor ede-object-keybindings)
(menu :allocation :class
:initform
(
[ "Update Version" ede-update-version ede-object ]
[ "Version Control Status" ede-vc-project-directory ede-object ]
[ "Edit Project Homepage" ede-edit-web-page
(and ede-object (oref (ede-toplevel) web-site-file)) ]
[ "Browse Project URL" ede-web-browse-home
(and ede-object
(not (string= "" (oref (ede-toplevel) web-site-url)))) ]
"--"
[ "Rescan Project Files" ede-rescan-toplevel t ]
[ "Edit Projectfile" ede-edit-file-target
(ede-buffer-belongs-to-project-p) ]
)
:documentation "Menu specialized to this type of target."
:accessor ede-object-menu)
)
"Top level EDE project specification.
All specific project types must derive from this project."
:method-invocation-order :depth-first)
;;; Important macros for doing commands.
;;
(defmacro ede-with-projectfile (obj &rest forms)
"For the project in which OBJ resides, execute FORMS."
(list 'save-window-excursion
(list 'let* (list
(list 'pf
(list 'if (list 'obj-of-class-p
obj 'ede-target)
;; @todo -I think I can change
;; this to not need ede-load-project-file
;; but I'm not sure how to test well.
(list 'ede-load-project-file
(list 'oref obj 'path))
obj))
'(dbka (get-file-buffer (oref pf file))))
'(if (not dbka) (find-file (oref pf file))
(switch-to-buffer dbka))
(cons 'progn forms)
'(if (not dbka) (kill-buffer (current-buffer))))))
(put 'ede-with-projectfile 'lisp-indent-function 1)
;;; The EDE persistent cache.
;;
;; The cache is a way to mark where all known projects live without
;; loading those projects into memory, or scanning for them each time
;; emacs starts.
;;
(defcustom ede-project-placeholder-cache-file
(locate-user-emacs-file "ede-projects.el" ".projects.ede")
"File containing the list of projects EDE has viewed."
:group 'ede
:type 'file)
(defvar ede-project-cache-files nil
"List of project files EDE has seen before.")
(defun ede-save-cache ()
"Save a cache of EDE objects that Emacs has seen before."
(interactive)
(let ((p ede-projects)
(c ede-project-cache-files)
(recentf-exclude '( (lambda (f) t) ))
)
(condition-case nil
(progn
(set-buffer (find-file-noselect ede-project-placeholder-cache-file t))
(erase-buffer)
(insert ";; EDE project cache file.
;; This contains a list of projects you have visited.\n(")
(while p
(when (and (car p) (ede-project-p p))
(let ((f (oref (car p) file)))
(when (file-exists-p f)
(insert "\n \"" f "\""))))
(setq p (cdr p)))
(while c
(insert "\n \"" (car c) "\"")
(setq c (cdr c)))
(insert "\n)\n")
(condition-case nil
(save-buffer 0)
(error
(message "File %s could not be saved."
ede-project-placeholder-cache-file)))
(kill-buffer (current-buffer))
)
(error
(message "File %s could not be read."
ede-project-placeholder-cache-file))
)))
(defun ede-load-cache ()
"Load the cache of EDE projects."
(save-excursion
(let ((cachebuffer nil))
(condition-case nil
(progn
(setq cachebuffer
(find-file-noselect ede-project-placeholder-cache-file t))
(set-buffer cachebuffer)
(goto-char (point-min))
(let ((c (read (current-buffer)))
(new nil)
(p ede-projects))
;; Remove loaded projects from the cache.
(while p
(setq c (delete (oref (car p) file) c))
(setq p (cdr p)))
;; Remove projects that aren't on the filesystem
;; anymore.
(while c
(when (file-exists-p (car c))
(setq new (cons (car c) new)))
(setq c (cdr c)))
;; Save it
(setq ede-project-cache-files (nreverse new))))
(error nil))
(when cachebuffer (kill-buffer cachebuffer))
)))
;;; Get the cache usable.
;; @TODO - Remove this cache setup, or use this for something helpful.
;;(add-hook 'kill-emacs-hook 'ede-save-cache)
;;(when (not noninteractive)
;; ;; No need to load the EDE cache if we aren't interactive.
;; ;; This occurs during batch byte-compiling of other tools.
;; (ede-load-cache))
;;; METHODS
;;
;; The methods in ede-base handle project related behavior, and DO NOT
;; related to EDE mode commands directory, such as keybindings.
;;
;; Mode related methods are in ede.el. These methods are related
;; project specific activities not directly tied to a keybinding.
(defmethod ede-subproject-relative-path ((proj ede-project) &optional parent-in)
"Get a path name for PROJ which is relative to the parent project.
If PARENT is specified, then be relative to the PARENT project.
Specifying PARENT is useful for sub-sub projects relative to the root project."
(let* ((parent (or parent-in (ede-parent-project proj)))
(dir (file-name-directory (oref proj file))))
(if (and parent (not (eq parent proj)))
(file-relative-name dir (file-name-directory (oref parent file)))
"")))
(defmethod ede-subproject-p ((proj ede-project))
"Return non-nil if PROJ is a sub project."
;; @TODO - Use this in more places, and also pay attention to
;; metasubproject in ede-proj.el
(ede-parent-project proj))
;;; Default descriptive methods for EDE classes
;;
;; These are methods which you might want to override, but there is
;; no need to in most situations because they are either a) simple, or
;; b) cosmetic.
(defmethod ede-name ((this ede-target))
"Return the name of THIS target."
(oref this name))
(defmethod ede-target-name ((this ede-target))
"Return the name of THIS target, suitable for make or debug style commands."
(oref this name))
(defmethod ede-name ((this ede-project))
"Return a short-name for THIS project file.
Do this by extracting the lowest directory name."
(oref this name))
(defmethod ede-description ((this ede-project))
"Return a description suitable for the minibuffer about THIS."
(format "Project %s: %d subprojects, %d targets."
(ede-name this) (length (oref this subproj))
(length (oref this targets))))
(defmethod ede-description ((this ede-target))
"Return a description suitable for the minibuffer about THIS."
(format "Target %s: with %d source files."
(ede-name this) (length (oref this source))))
;;; HEADERS/DOC
;;
;; Targets and projects are often associated with other files, such as
;; header files, documentation files and the like. Have strong
;; associations can make useful user commands to quickly navigate
;; between the files base on their assocaitions.
;;
(defun ede-header-file ()
"Return the header file for the current buffer.
Not all buffers need headers, so return nil if no applicable."
(if ede-object
(ede-buffer-header-file ede-object (current-buffer))
nil))
(defmethod ede-buffer-header-file ((this ede-project) buffer)
"Return nil, projects don't have header files."
nil)
(defmethod ede-buffer-header-file ((this ede-target) buffer)
"There are no default header files in EDE.
Do a quick check to see if there is a Header tag in this buffer."
(with-current-buffer buffer
(if (re-search-forward "::Header:: \\([a-zA-Z0-9.]+\\)" nil t)
(buffer-substring-no-properties (match-beginning 1)
(match-end 1))
(let ((src (ede-target-sourcecode this))
(found nil))
(while (and src (not found))
(setq found (ede-buffer-header-file (car src) (buffer-file-name))
src (cdr src)))
found))))
(defun ede-documentation-files ()
"Return the documentation files for the current buffer.
Not all buffers need documentations, so return nil if no applicable.
Some projects may have multiple documentation files, so return a list."
(if ede-object
(ede-buffer-documentation-files ede-object (current-buffer))
nil))
(defmethod ede-buffer-documentation-files ((this ede-project) buffer)
"Return all documentation in project THIS based on BUFFER."
;; Find the info node.
(ede-documentation this))
(defmethod ede-buffer-documentation-files ((this ede-target) buffer)
"Check for some documentation files for THIS.
Also do a quick check to see if there is a Documentation tag in this BUFFER."
(with-current-buffer buffer
(if (re-search-forward "::Documentation:: \\([a-zA-Z0-9.]+\\)" nil t)
(buffer-substring-no-properties (match-beginning 1)
(match-end 1))
;; Check the master project
(let ((cp (ede-toplevel)))
(ede-buffer-documentation-files cp (current-buffer))))))
(defmethod ede-documentation ((this ede-project))
"Return a list of files that provide documentation.
Documentation is not for object THIS, but is provided by THIS for other
files in the project."
(let ((targ (oref this targets))
(proj (oref this subproj))
(found nil))
(while targ
(setq found (append (ede-documentation (car targ)) found)
targ (cdr targ)))
(while proj
(setq found (append (ede-documentation (car proj)) found)
proj (cdr proj)))
found))
(defmethod ede-documentation ((this ede-target))
"Return a list of files that provide documentation.
Documentation is not for object THIS, but is provided by THIS for other
files in the project."
nil)
(defun ede-html-documentation-files ()
"Return a list of HTML documentation files associated with this project."
(ede-html-documentation (ede-toplevel))
)
(defmethod ede-html-documentation ((this ede-project))
"Return a list of HTML files provided by project THIS."
)
;;; Default "WANT" methods.
;;
;; These methods are used to determine if a target "wants", or could
;; somehow handle a file, or some source type.
;;
(defmethod ede-want-file-p ((this ede-target) file)
"Return non-nil if THIS target wants FILE."
;; By default, all targets reference the source object, and let it decide.
(let ((src (ede-target-sourcecode this)))
(while (and src (not (ede-want-file-p (car src) file)))
(setq src (cdr src)))
src))
(defmethod ede-want-file-source-p ((this ede-target) file)
"Return non-nil if THIS target wants FILE."
;; By default, all targets reference the source object, and let it decide.
(let ((src (ede-target-sourcecode this)))
(while (and src (not (ede-want-file-source-p (car src) file)))
(setq src (cdr src)))
src))
(defmethod ede-target-sourcecode ((this ede-target))
"Return the sourcecode objects which THIS permits."
(let ((sc (oref this sourcetype))
(rs nil))
(while (and (listp sc) sc)
(setq rs (cons (symbol-value (car sc)) rs)
sc (cdr sc)))
rs))
;;; Debugging.
;;
(defun ede-adebug-project ()
"Run adebug against the current EDE project.
Display the results as a debug list."
(interactive)
(require 'data-debug)
(when (ede-current-project)
(data-debug-new-buffer "*Analyzer ADEBUG*")
(data-debug-insert-object-slots (ede-current-project) "")
))
(defun ede-adebug-project-parent ()
"Run adebug against the current EDE parent project.
Display the results as a debug list."
(interactive)
(require 'data-debug)
(when (ede-parent-project)
(data-debug-new-buffer "*Analyzer ADEBUG*")
(data-debug-insert-object-slots (ede-parent-project) "")
))
(defun ede-adebug-project-root ()
"Run adebug against the current EDE parent project.
Display the results as a debug list."
(interactive)
(require 'data-debug)
(when (ede-toplevel)
(data-debug-new-buffer "*Analyzer ADEBUG*")
(data-debug-insert-object-slots (ede-toplevel) "")
))
;;; TOPLEVEL PROJECT
;;
;; The toplevel project is a way to identify the EDE structure that belongs
;; to the top of a project.
(defun ede-toplevel (&optional subproj)
"Return the ede project which is the root of the current project.
Optional argument SUBPROJ indicates a subproject to start from
instead of the current project."
(or ede-object-root-project
(let* ((cp (or subproj (ede-current-project))))
(or (and cp (ede-project-root cp))
(progn
(while (ede-parent-project cp)
(setq cp (ede-parent-project cp)))
cp)))))
;;; Hooks & Autoloads
;;
;; These let us watch various activities, and respond appropriately.
;; (add-hook 'edebug-setup-hook
;; (lambda ()
;; (def-edebug-spec ede-with-projectfile
;; (form def-body))))
(provide 'ede/base)
;; Local variables:
;; generated-autoload-file: "loaddefs.el"
;; generated-autoload-load-name: "ede/base"
;; End:
;;; ede/base.el ends here

View File

@ -237,6 +237,18 @@ ROOTPROJ is nil, since there is only one project."
;; Snoop through our master list.
(ede-cpp-root-file-existing dir))
;;;###autoload
(add-to-list 'ede-project-class-files
(ede-project-autoload "cpp-root"
:name "CPP ROOT"
:file 'ede-cpp-root
:proj-file 'ede-cpp-root-project-file-for-dir
:proj-root 'ede-cpp-root-project-root
:load-type 'ede-cpp-root-load
:class-sym 'ede-cpp-root
:new-p nil)
t)
;;; CLASSES
;;
;; EDE sets up projects with two kinds of objects.
@ -504,6 +516,21 @@ Also set up the lexical preprocessor map."
"Get the pre-processor map for project THIS."
(ede-preprocessor-map (ede-target-parent this)))
;;; Quick Hack
(defun ede-create-lots-of-projects-under-dir (dir projfile &rest attributes)
"Create a bunch of projects under directory DIR.
PROJFILE is a file name sans directory that indicates a subdirectory
is a project directory.
Generic ATTRIBUTES, such as :include-path can be added.
Note: This needs some work."
(let ((files (directory-files dir t)))
(dolist (F files)
(if (file-exists-p (expand-file-name projfile F))
`(ede-cpp-root-project (file-name-nondirectory F)
:name (file-name-nondirectory F)
:file (expand-file-name projfile F)
attributes)))))
(provide 'ede/cpp-root)
;; Local variables:

215
lisp/cedet/ede/custom.el Normal file
View File

@ -0,0 +1,215 @@
;;; ede.el --- customization of EDE projects.
;; Copyright (C) 2010 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; Customization commands/hooks for EDE.
;;
;; EIEIO supports customizing objects, and EDE uses this to allow
;; users to change basic settings in their projects.
;;
;;; Code:
;;; Customization
;;
;; Routines for customizing projects and targets.
(require 'ede)
(eval-when-compile (require 'eieio-custom))
(defvar eieio-ede-old-variables nil
"The old variables for a project.")
;;; Customization Commands
;;
;; These commands initialize custoization of EDE control objects.
;;;###autoload
(defun ede-customize-project ()
"Edit fields of the current project through EIEIO & Custom."
(interactive)
(require 'eieio-custom)
(let* ((ov (oref (ede-current-project) local-variables))
(cp (ede-current-project)))
(ede-customize cp)
(make-local-variable 'eieio-ede-old-variables)
(setq eieio-ede-old-variables ov)))
;;;###autoload
(defalias 'customize-project 'ede-customize-project)
;;;###autoload
(defun ede-customize-current-target()
"Edit fields of the current target through EIEIO & Custom."
(interactive)
(require 'eieio-custom)
(if (not (obj-of-class-p ede-object ede-target))
(error "Current file is not part of a target"))
(ede-customize-target ede-object))
;;;###autoload
(defalias 'customize-target 'ede-customize-current-target)
(defun ede-customize-target (obj)
"Edit fields of the current target through EIEIO & Custom.
OBJ is the target object to customize."
(require 'eieio-custom)
(if (and obj (not (obj-of-class-p obj ede-target)))
(error "No logical target to customize"))
(ede-customize obj))
(defmethod ede-customize ((proj ede-project))
"Customize the EDE project PROJ."
(eieio-customize-object proj 'default))
(defmethod ede-customize ((target ede-target))
"Customize the EDE TARGET."
(eieio-customize-object target 'default))
;;; Target Sorting
;;
;; Target order can be important, but custom doesn't support a way
;; to resort items in a list. This function by David Engster allows
;; targets to be re-arranged.
(defvar ede-project-sort-targets-order nil
"Variable for tracking target order in `ede-project-sort-targets'.")
;;;###autoload
(defun ede-project-sort-targets ()
"Create a custom-like buffer for sorting targets of current project."
(interactive)
(let ((proj (ede-current-project))
(count 1)
current order)
(switch-to-buffer (get-buffer-create "*EDE sort targets*"))
(erase-buffer)
(setq ede-object-project proj)
(widget-create 'push-button
:notify (lambda (&rest ignore)
(let ((targets (oref ede-object-project targets))
cur newtargets)
(while (setq cur (pop ede-project-sort-targets-order))
(setq newtargets (append newtargets
(list (nth cur targets)))))
(oset ede-object-project targets newtargets))
(ede-commit-project ede-object-project)
(kill-buffer))
" Accept ")
(widget-insert " ")
(widget-create 'push-button
:notify (lambda (&rest ignore)
(kill-buffer))
" Cancel ")
(widget-insert "\n\n")
(setq ede-project-sort-targets-order nil)
(mapc (lambda (x)
(add-to-ordered-list
'ede-project-sort-targets-order
x x))
(number-sequence 0 (1- (length (oref proj targets)))))
(ede-project-sort-targets-list)
(use-local-map widget-keymap)
(widget-setup)
(goto-char (point-min))))
(defun ede-project-sort-targets-list ()
"Sort the target list while using `ede-project-sort-targets'."
(save-excursion
(let ((count 0)
(targets (oref ede-object-project targets))
(inhibit-read-only t)
(inhibit-modification-hooks t))
(goto-char (point-min))
(forward-line 2)
(delete-region (point) (point-max))
(while (< count (length targets))
(if (> count 0)
(widget-create 'push-button
:notify `(lambda (&rest ignore)
(let ((cur ede-project-sort-targets-order))
(add-to-ordered-list
'ede-project-sort-targets-order
(nth ,count cur)
(1- ,count))
(add-to-ordered-list
'ede-project-sort-targets-order
(nth (1- ,count) cur) ,count))
(ede-project-sort-targets-list))
" Up ")
(widget-insert " "))
(if (< count (1- (length targets)))
(widget-create 'push-button
:notify `(lambda (&rest ignore)
(let ((cur ede-project-sort-targets-order))
(add-to-ordered-list
'ede-project-sort-targets-order
(nth ,count cur) (1+ ,count))
(add-to-ordered-list
'ede-project-sort-targets-order
(nth (1+ ,count) cur) ,count))
(ede-project-sort-targets-list))
" Down ")
(widget-insert " "))
(widget-insert (concat " " (number-to-string (1+ count)) ".: "
(oref (nth (nth count ede-project-sort-targets-order)
targets) name) "\n"))
(setq count (1+ count))))))
;;; Customization hooks
;;
;; These hooks are used when finishing up a customization.
(defmethod eieio-done-customizing ((proj ede-project))
"Call this when a user finishes customizing PROJ."
(let ((ov eieio-ede-old-variables)
(nv (oref proj local-variables)))
(setq eieio-ede-old-variables nil)
(while ov
(if (not (assoc (car (car ov)) nv))
(save-excursion
(mapc (lambda (b)
(set-buffer b)
(kill-local-variable (car (car ov))))
(ede-project-buffers proj))))
(setq ov (cdr ov)))
(mapc (lambda (b) (ede-set-project-variables proj b))
(ede-project-buffers proj))))
;; These two methods should be implemented by subclasses of
;; project and targets in order to account for user specified
;; changes.
(defmethod eieio-done-customizing ((target ede-target))
"Call this when a user finishes customizing TARGET."
nil)
(defmethod ede-commit-project ((proj ede-project))
"Commit any change to PROJ to its file."
nil
)
(provide 'ede/custom)
;; Local variables:
;; generated-autoload-file: "loaddefs.el"
;; generated-autoload-load-name: "ede/custom"
;; End:
;;; ede/custom.el ends here

View File

@ -88,7 +88,7 @@ negative, force off."
(let ((files (dired-get-marked-files t)))
(while files
(project-add-file target (car files))
;; Find the buffer for this files, and set it's ede-object
;; Find the buffer for this files, and set its ede-object
(if (get-file-buffer (car files))
(with-current-buffer (get-file-buffer (car files))
(setq ede-object nil)

View File

@ -133,6 +133,18 @@ ROOTPROJ is nil, since there is only one project."
)
)
;;;###autoload
(add-to-list 'ede-project-class-files
(ede-project-autoload "emacs"
:name "EMACS ROOT"
:file 'ede-emacs
:proj-file "src/emacs.c"
:proj-root 'ede-emacs-project-root
:load-type 'ede-emacs-load
:class-sym 'ede-emacs-project
:new-p nil)
t)
(defclass ede-emacs-target-c (ede-target)
()
"EDE Emacs Project target for C code.
@ -150,7 +162,7 @@ All directories need at least one target.")
(defmethod initialize-instance ((this ede-emacs-project)
&rest fields)
"Make sure the :file is fully expanded."
"Make sure the targets slot is bound."
(call-next-method)
(unless (slot-boundp this 'targets)
(oset this :targets nil)))

View File

@ -38,6 +38,7 @@
(declare-function ede-locate-file-in-hash "ede/locate")
(declare-function ede-locate-add-file-to-hash "ede/locate")
(declare-function ede-locate-file-in-project "ede/locate")
(declare-function ede-locate-flush-hash "ede/locate")
(defvar ede--disable-inode nil
"Set to 't' to simulate systems w/out inode support.")
@ -57,44 +58,29 @@ the current EDE project."
(ede-project-root-directory (ede-current-project))))
(find-file fname)))
(defun ede-flush-project-hash ()
"Flush the file locate hash for the current project."
(interactive)
(require 'ede/locate)
(let* ((loc (ede-get-locator-object (ede-current-project))))
(ede-locate-flush-hash loc)))
;;; Placeholders for ROOT directory scanning on base objects
;;
(defmethod ede-project-root ((this ede-project-placeholder))
"If a project knows it's root, return it here.
"If a project knows its root, return it here.
Allows for one-project-object-for-a-tree type systems."
(oref this rootproject))
(defmethod ede-project-root-directory ((this ede-project-placeholder)
&optional file)
"If a project knows it's root, return it here.
"If a project knows its root, return it here.
Allows for one-project-object-for-a-tree type systems.
Optional FILE is the file to test. It is ignored in preference
of the anchor file for the project."
(file-name-directory (expand-file-name (oref this file))))
(defmethod ede-project-root ((this ede-project-autoload))
"If a project knows it's root, return it here.
Allows for one-project-object-for-a-tree type systems."
nil)
(defmethod ede-project-root-directory ((this ede-project-autoload)
&optional file)
"If a project knows it's root, return it here.
Allows for one-project-object-for-a-tree type systems.
Optional FILE is the file to test. If there is no FILE, use
the current buffer."
(when (not file)
(setq file default-directory))
(when (slot-boundp this :proj-root)
(let ((rootfcn (oref this proj-root)))
(when rootfcn
(condition-case nil
(funcall rootfcn file)
(error
(funcall rootfcn)))
))))
(defmethod ede--project-inode ((proj ede-project-placeholder))
"Get the inode of the directory project PROJ is in."
(if (slot-boundp proj 'dirinode)
@ -262,27 +248,30 @@ Do this whenever a new project is created, as opposed to loaded."
(defun ede-directory-project-p (dir &optional force)
"Return a project description object if DIR has a project.
Optional argument FORCE means to ignore a hash-hit of 'nomatch.
This depends on an up to date `ede-project-class-files' variable."
(let* ((dirtest (expand-file-name dir))
(match (ede-directory-project-from-hash dirtest)))
(cond
((and (eq match 'nomatch) (not force))
nil)
((and match (not (eq match 'nomatch)))
match)
(t
(let ((types ede-project-class-files)
(ret nil))
;; Loop over all types, loading in the first type that we find.
(while (and types (not ret))
(if (ede-dir-to-projectfile (car types) dirtest)
(progn
;; We found one! Require it now since we will need it.
(require (oref (car types) file))
(setq ret (car types))))
(setq types (cdr types)))
(ede-directory-project-add-description-to-hash dirtest (or ret 'nomatch))
ret)))))
This depends on an up to date `ede-project-class-files' variable.
Any directory that contains the file .ede-ignore will allways
return nil."
(when (not (file-exists-p (expand-file-name ".ede-ignore" dir)))
(let* ((dirtest (expand-file-name dir))
(match (ede-directory-project-from-hash dirtest)))
(cond
((and (eq match 'nomatch) (not force))
nil)
((and match (not (eq match 'nomatch)))
match)
(t
(let ((types ede-project-class-files)
(ret nil))
;; Loop over all types, loading in the first type that we find.
(while (and types (not ret))
(if (ede-dir-to-projectfile (car types) dirtest)
(progn
;; We found one! Require it now since we will need it.
(require (oref (car types) file))
(setq ret (car types))))
(setq types (cdr types)))
(ede-directory-project-add-description-to-hash dirtest (or ret 'nomatch))
ret))))))
;;; TOPLEVEL
;;
@ -324,7 +313,7 @@ nil is returned if the current directory is not a part of a project."
;; If PROJ didn't know, or there is no PROJ, then
;; Loop up to the topmost project, and then load that single
;; project, and it's sub projects. When we are done, identify the
;; project, and its sub projects. When we are done, identify the
;; sub-project object belonging to file.
(while (and (not ans) newpath proj)
(setq toppath newpath
@ -338,24 +327,6 @@ nil is returned if the current directory is not a part of a project."
)
(or ans toppath))))))
;;; TOPLEVEL PROJECT
;;
;; The toplevel project is a way to identify the EDE structure that belongs
;; to the top of a project.
(defun ede-toplevel (&optional subproj)
"Return the ede project which is the root of the current project.
Optional argument SUBPROJ indicates a subproject to start from
instead of the current project."
(or ede-object-root-project
(let* ((cp (or subproj (ede-current-project)))
)
(or (and cp (ede-project-root cp))
(progn
(while (ede-parent-project cp)
(setq cp (ede-parent-project cp)))
cp)))))
;;; DIRECTORY CONVERSION STUFF
;;
(defmethod ede-convert-path ((this ede-project) path)
@ -372,11 +343,13 @@ Argument THIS is the project to convert PATH to."
(substring fptf (match-end 0))
(error "Cannot convert relativize path %s" fp))))))
(defmethod ede-convert-path ((this ede-target) path)
(defmethod ede-convert-path ((this ede-target) path &optional project)
"Convert path in a standard way for a given project.
Default to making it project relative.
Argument THIS is the project to convert PATH to."
(let ((proj (ede-target-parent this)))
Argument THIS is the project to convert PATH to.
Optional PROJECT is the project that THIS belongs to. Associating
a target to a project is expensive, so using this can speed things up."
(let ((proj (or project (ede-target-parent this))))
(if proj
(let ((p (ede-convert-path proj path))
(lp (or (oref this path) "")))
@ -406,7 +379,8 @@ FILENAME should be just a filename which occurs in a directory controlled
by this project.
Optional argument FORCE forces the default filename to be provided even if it
doesn't exist.
If FORCE equals 'newfile, then the cache is ignored."
If FORCE equals 'newfile, then the cache is ignored and a new file in THIS
is returned."
(require 'ede/locate)
(let* ((loc (ede-get-locator-object this))
(ha (ede-locate-file-in-hash loc filename))
@ -467,17 +441,8 @@ doesn't exist."
(proj (oref this subproj))
(found nil))
;; find it Locally.
(setq found
(cond ((file-exists-p (expand-file-name filename path))
(expand-file-name filename path))
((file-exists-p (expand-file-name (concat "include/" filename) path))
(expand-file-name (concat "include/" filename) path))
(t
(while (and (not found) proj)
(setq found (when (car proj)
(ede-expand-filename (car proj) filename))
proj (cdr proj)))
found)))
(setq found (or (ede-expand-filename-local this filename)
(ede-expand-filename-impl-via-subproj this filename)))
;; Use an external locate tool.
(when (not found)
(require 'ede/locate)
@ -485,6 +450,30 @@ doesn't exist."
;; Return it
found))
(defmethod ede-expand-filename-local ((this ede-project) filename)
"Expand filename locally to project THIS with filesystem tests."
(let ((path (ede-project-root-directory this)))
(cond ((file-exists-p (expand-file-name filename path))
(expand-file-name filename path))
((file-exists-p (expand-file-name (concat "include/" filename) path))
(expand-file-name (concat "include/" filename) path)))))
(defmethod ede-expand-filename-impl-via-subproj ((this ede-project) filename)
"Return a fully qualified file name based on project THIS.
FILENAME should be just a filename which occurs in a directory controlled
by this project."
(let ((proj (list (ede-toplevel this)))
(found nil))
;; find it Locally.
(while (and (not found) proj)
(let ((thisproj (car proj)))
(setq proj (append (cdr proj) (oref thisproj subproj)))
(setq found (when thisproj
(ede-expand-filename-local thisproj filename)))
))
;; Return it
found))
(defmethod ede-expand-filename ((this ede-target) filename &optional force)
"Return a fully qualified file name based on target THIS.
FILENAME should be a filename which occurs in a directory in which THIS works.

442
lisp/cedet/ede/generic.el Normal file
View File

@ -0,0 +1,442 @@
;;; ede/generic.el --- Base Support for generic build systems
;; Copyright (C) 2010 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <eric@siege-engine.com>
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; There are a lot of build systems out there, and EDE can't support
;; them all fully. The ede-generic.el system is the base for
;; supporting alternate build systems in a simple way, automatically.
;;
;; The structure is for the ede-generic baseclass, which is augmented
;; by simple sub-classes that can be created by users on an as needed
;; basis. The generic system will have targets for many language
;; types, and create the targets on an as needed basis. All
;; sub-project types will recycle the same generic target types.
;;
;; The generic target types will only be implemented for languages
;; where having EDE support actually matters, with a single MISC to
;; represent anything else.
;;
;; TOO MANY PROJECTS DETECTED:
;;
;; If enabling ede-generic support starts identifying too many
;; projects, drop a file called `.ede-ignore' into any directory where
;; you do not want a project to be.
;;
;; Customization:
;;
;; Since these projects are all so increadibly generic, a user will
;; need to configure some aspects of the project by hand. In order to
;; enable this without configuring the project objects directly (which
;; are auto-generated) a special ede-generic-confg object is defined to
;; hold the basics. Generic projects will identify and use these
;; config files.
;;
;; Adding support for new projects:
;;
;; To add support to EDE Generic for new project types is very quick.
;; See the end of this file for examples such as CMake and SCons.
;;
;; Support consists of one class for your project, specifying the file
;; name used by the project system you want to support. It also
;; should implement th method `ede-generic-setup-configuration' to
;; prepopulate the configurable portion of the generic project with
;; build details.
;;
;; Lastly, call `ede-generic-new-autoloader' to setup your project so
;; EDE can use it.
;;
;; Adding support for new types of source code:
;;
;; Sources of different types are supported with a simple class which
;; subclasses `ede-generic-target'. The slots `shortname' and
;; `extension' should be given new initial values.
;;
;; Optionally, any target method used by EDE can then be overriden.
;; The ede-generic-target-c-cpp has some example methods setting up
;; the pre-processor map and system include path.
;;
;; NOTE: It is not necessary to modify ede-generic.el to add any of
;; the above described support features.
(require 'eieio-opt)
(require 'ede)
(require 'semantic/db)
;;; Code:
;;
;; Start with the configuration system
(defclass ede-generic-config (eieio-persistent)
((extension :initform ".ede")
(file-header-line :initform ";; EDE Generic Project Configuration")
(project :initform nil
:documentation
"The project this config is bound to.")
;; Generic customizations
(build-command :initarg :build-command
:initform "make -k"
:type string
:custom string
:group (default build)
:documentation
"Command used for building this project.")
(debug-command :initarg :debug-command
:initform "gdb "
:type string
:custom string
:group (default build)
:documentation
"Command used for debugging this project.")
;; C target customixations
(c-include-path :initarg :c-include-path
:initform nil
:type list
:custom (repeat (string :tag "Path"))
:group c
:documentation
"The include path used by C/C++ projects.")
(c-preprocessor-table :initarg :c-preprocessor-table
:initform nil
:type list
:custom (repeat (cons (string :tag "Macro")
(string :tag "Value")))
:group c
:documentation
"Preprocessor Symbols for this project.")
(c-preprocessor-files :initarg :c-preprocessor-files
:initform nil
:type list
:custom (repeat (string :tag "Include File")))
)
"User Configuration object for a generic project.")
(defun ede-generic-load (dir &optional rootproj)
"Return a Generic Project object if there is a match.
Return nil if there isn't one.
Argument DIR is the directory it is created for.
ROOTPROJ is nil, since there is only one project."
;; Doesn't already exist, so lets make one.
(let* ((alobj ede-constructing)
(this nil))
(when (not alobj) (error "Cannot load generic project without the autoload instance"))
(setq this
(funcall (oref alobj class-sym)
(symbol-name (oref alobj class-sym))
:name (file-name-nondirectory
(directory-file-name dir))
:version "1.0"
:directory (file-name-as-directory dir)
:file (expand-file-name (oref alobj :proj-file)) ))
(ede-add-project-to-global-list this)
))
;;; Base Classes for the system
(defclass ede-generic-target (ede-target)
((shortname :initform ""
:type string
:allocation :class
:documentation
"Something prepended to the target name.")
(extension :initform ""
:type string
:allocation :class
:documentation
"Regular expression representing the extension used for this target.
subclasses of this base target will override the default value.")
)
"Baseclass for all targets belonging to the generic ede system."
:abstract t)
(defclass ede-generic-project (ede-project)
((buildfile :initform ""
:type string
:allocation :class
:documentation "The file name that identifies a project of this type.
The class allocated value is replace by different sub classes.")
(config :initform nil
:type (or null ede-generic-config)
:documentation
"The configuration object for this project.")
)
"The baseclass for all generic EDE project types."
:abstract t)
(defmethod initialize-instance ((this ede-generic-project)
&rest fields)
"Make sure the targets slot is bound."
(call-next-method)
(unless (slot-boundp this 'targets)
(oset this :targets nil))
)
(defmethod ede-generic-get-configuration ((proj ede-generic-project))
"Return the configuration for the project PROJ."
(let ((config (oref proj config)))
(when (not config)
(let ((fname (expand-file-name "EDEConfig.el"
(oref proj :directory))))
(if (file-exists-p fname)
;; Load in the configuration
(setq config (eieio-persistent-read fname))
;; Create a new one.
(setq config (ede-generic-config
"Configuration"
:file fname))
;; Set initial values based on project.
(ede-generic-setup-configuration proj config))
;; Link things together.
(oset proj config config)
(oset config project proj)))
config))
(defmethod ede-generic-setup-configuration ((proj ede-generic-project) config)
"Default configuration setup method."
nil)
(defmethod ede-commit-project ((proj ede-generic-project))
"Commit any change to PROJ to its file."
(let ((config (ede-generic-get-configuration proj)))
(ede-commit config)))
;;; A list of different targets
(defclass ede-generic-target-c-cpp (ede-generic-target)
((shortname :initform "C/C++")
(extension :initform "\\([ch]\\(pp\\|xx\\|\\+\\+\\)?\\|cc\\|hh\\|CC?\\)"))
"EDE Generic Project target for C and C++ code.
All directories need at least one target.")
(defclass ede-generic-target-el (ede-generic-target)
((shortname :initform "ELisp")
(extension :initform "el"))
"EDE Generic Project target for Emacs Lisp code.
All directories need at least one target.")
(defclass ede-generic-target-fortran (ede-generic-target)
((shortname :initform "Fortran")
(extension :initform "[fF]9[05]\\|[fF]\\|for"))
"EDE Generic Project target for Fortran code.
All directories need at least one target.")
(defclass ede-generic-target-texi (ede-generic-target)
((shortname :initform "Texinfo")
(extension :initform "texi"))
"EDE Generic Project target for texinfo code.
All directories need at least one target.")
;; MISC must always be last since it will always match the file.
(defclass ede-generic-target-misc (ede-generic-target)
((shortname :initform "Misc")
(extension :initform ""))
"EDE Generic Project target for Misc files.
All directories need at least one target.")
;;; Automatic target aquisition.
(defun ede-generic-find-matching-target (class dir targets)
"Find a target that is a CLASS and is in DIR in the list of TARGETS."
(let ((match nil))
(dolist (T targets)
(when (and (object-of-class-p T class)
(string= (oref T :path) dir))
(setq match T)
))
match))
(defmethod ede-find-target ((proj ede-generic-project) buffer)
"Find an EDE target in PROJ for BUFFER.
If one doesn't exist, create a new one for this directory."
(let* ((ext (file-name-extension (buffer-file-name buffer)))
(classes (eieio-build-class-alist 'ede-generic-target t))
(cls nil)
(targets (oref proj targets))
(dir default-directory)
(ans nil)
)
;; Pick a matching class type.
(when ext
(dolist (C classes)
(let* ((classsym (intern (car C)))
(extreg (oref classsym extension)))
(when (and (not (string= extreg ""))
(string-match (concat "^" extreg "$") ext))
(setq cls classsym)))))
(when (not cls) (setq cls 'ede-generic-target-misc))
;; find a pre-existing matching target
(setq ans (ede-generic-find-matching-target cls dir targets))
;; Create a new instance if there wasn't one
(when (not ans)
(setq ans (make-instance
cls
:name (oref cls shortname)
:path dir
:source nil))
(object-add-to-list proj :targets ans)
)
ans))
;;; C/C++ support
(defmethod ede-preprocessor-map ((this ede-generic-target-c-cpp))
"Get the pre-processor map for some generic C code."
(let* ((proj (ede-target-parent this))
(root (ede-project-root proj))
(config (ede-generic-get-configuration proj))
filemap
)
;; Preprocessor files
(dolist (G (oref config :c-preprocessor-files))
(let ((table (semanticdb-file-table-object
(ede-expand-filename root G))))
(when table
(when (semanticdb-needs-refresh-p table)
(semanticdb-refresh-table table))
(setq filemap (append filemap (oref table lexical-table)))
)))
;; The core table
(setq filemap (append filemap (oref config :c-preprocessor-table)))
filemap
))
(defmethod ede-system-include-path ((this ede-generic-target-c-cpp))
"Get the system include path used by project THIS."
(let* ((proj (ede-target-parent this))
(config (ede-generic-get-configuration proj)))
(oref config c-include-path)))
;;; Customization
;;
(defmethod ede-customize ((proj ede-generic-project))
"Customize the EDE project PROJ."
(let ((config (ede-generic-get-configuration proj)))
(eieio-customize-object config)))
(defmethod ede-customize ((target ede-generic-target))
"Customize the EDE TARGET."
;; Nothing unique for the targets, use the project.
(ede-customize-project))
(defmethod eieio-done-customizing ((config ede-generic-config))
"Called when EIEIO is done customizing the configuration object.
We need to go back through the old buffers, and update them with
the new configuration."
(ede-commit config)
;; Loop over all the open buffers, and re-apply.
(ede-map-targets
(oref config project)
(lambda (target)
(ede-map-target-buffers
target
(lambda (b)
(with-current-buffer b
(ede-apply-target-options)))))))
(defmethod ede-commit ((config ede-generic-config))
"Commit all changes to the configuration to disk."
(eieio-persistent-save config))
;;; Creating Derived Projects:
;;
;; Derived projects need an autoloader so that EDE can find the
;; different projects on disk.
(defun ede-generic-new-autoloader (internal-name external-name
projectfile class)
"Add a new EDE Autoload instance for identifying a generic project.
INTERNAL-NAME is a long name that identifies thsi project type.
EXTERNAL-NAME is a shorter human readable name to describe the project.
PROJECTFILE is a file name that identifies a project of this type to EDE, such as
a Makefile, or SConstruct file.
CLASS is the EIEIO class that is used to track this project. It should subclass
the class `ede-generic-project' project."
(add-to-list 'ede-project-class-files
(ede-project-autoload internal-name
:name external-name
:file 'ede-generic
:proj-file projectfile
:load-type 'ede-generic-load
:class-sym class
:new-p nil)
;; Generics must go at the end, since more specific types
;; can create Makefiles also.
t))
;;;###autoload
(defun ede-enable-generic-projects ()
"Enable generic project loaders."
(interactive)
(ede-generic-new-autoloader "edeproject-makefile" "Make"
"Makefile" 'ede-generic-makefile-project)
(ede-generic-new-autoloader "edeproject-scons" "SCons"
"SConstruct" 'ede-generic-scons-project)
(ede-generic-new-autoloader "edeproject-cmake" "CMake"
"CMakeLists" 'ede-generic-cmake-project)
)
;;; SPECIFIC TYPES OF GENERIC BUILDS
;;
;;; MAKEFILE
(defclass ede-generic-makefile-project (ede-generic-project)
((buildfile :initform "Makefile")
)
"Generic Project for makefiles.")
(defmethod ede-generic-setup-configuration ((proj ede-generic-makefile-project) config)
"Setup a configuration for Make."
(oset config build-command "make -k")
(oset config debug-command "gdb ")
)
;;; SCONS
(defclass ede-generic-scons-project (ede-generic-project)
((buildfile :initform "SConstruct")
)
"Generic Project for scons.")
(defmethod ede-generic-setup-configuration ((proj ede-generic-scons-project) config)
"Setup a configuration for SCONS."
(oset config build-command "scons")
(oset config debug-command "gdb ")
)
;;; CMAKE
(defclass ede-generic-cmake-project (ede-generic-project)
((buildfile :initform "CMakeLists")
)
"Generic Project for cmake.")
(defmethod ede-generic-setup-configuration ((proj ede-generic-cmake-project) config)
"Setup a configuration for CMake."
(oset config build-command "cmake")
(oset config debug-command "gdb ")
)
(provide 'ede/generic)
;; Local variables:
;; generated-autoload-file: "loaddefs.el"
;; generated-autoload-load-name: "ede/generic"
;; End:
;;; ede/generic.el ends here

View File

@ -112,6 +112,18 @@ ROOTPROJ is nil, since there is only one project."
)
)
;;;###autoload
(add-to-list 'ede-project-class-files
(ede-project-autoload "linux"
:name "LINUX ROOT"
:file 'ede-linux
:proj-file "scripts/ver_linux"
:proj-root 'ede-linux-project-root
:load-type 'ede-linux-load
:class-sym 'ede-linux-project
:new-p nil)
t)
(defclass ede-linux-target-c (ede-target)
()
"EDE Linux Project target for C code.
@ -124,7 +136,7 @@ All directories need at least one target.")
(defmethod initialize-instance ((this ede-linux-project)
&rest fields)
"Make sure the :file is fully expanded."
"Make sure the targets slot is bound."
(call-next-method)
(unless (slot-boundp this 'targets)
(oset this :targets nil)))

View File

@ -121,7 +121,7 @@ based on `ede-locate-setup-options'."
;; Basic setup.
(call-next-method)
;; Make sure we have a hash table.
(oset loc hash (make-hash-table :test 'equal))
(ede-locate-flush-hash loc)
)
(defmethod ede-locate-ok-in-project :static ((loc ede-locate-base)
@ -129,6 +129,10 @@ based on `ede-locate-setup-options'."
"Is it ok to use this project type under ROOT."
t)
(defmethod ede-locate-flush-hash ((loc ede-locate-base))
"For LOC, flush hashtable and start from scratch."
(oset loc hash (make-hash-table :test 'equal)))
(defmethod ede-locate-file-in-hash ((loc ede-locate-base)
filestring)
"For LOC, is the file FILESTRING in our hashtable?"
@ -160,6 +164,13 @@ that created this EDE locate object."
nil
)
(defmethod ede-locate-create/update-root-database :STATIC
((loc ede-locate-base) root)
"Create or update the database for the current project.
You cannot create projects for the baseclass."
(error "Cannot create/update a database of type %S"
(object-name loc)))
;;; LOCATE
;;
;; Using the standard unix "locate" command.
@ -242,6 +253,11 @@ that created this EDE locate object."
(let ((default-directory (oref loc root)))
(cedet-gnu-global-expand-filename filesubstring)))
(defmethod ede-locate-create/update-root-database :STATIC
((loc ede-locate-global) root)
"Create or update the GNU Global database for the current project."
(cedet-gnu-global-create/update-database root))
;;; IDUTILS
;;
(defclass ede-locate-idutils (ede-locate-base)
@ -280,6 +296,11 @@ that created this EDE locate object."
(let ((default-directory (oref loc root)))
(cedet-idutils-expand-filename filesubstring)))
(defmethod ede-locate-create/update-root-database :STATIC
((loc ede-locate-idutils) root)
"Create or update the GNU Global database for the current project."
(cedet-idutils-create/update-database root))
;;; CSCOPE
;;
(defclass ede-locate-cscope (ede-locate-base)
@ -315,6 +336,11 @@ that created this EDE locate object."
(let ((default-directory (oref loc root)))
(cedet-cscope-expand-filename filesubstring)))
(defmethod ede-locate-create/update-root-database :STATIC
((loc ede-locate-cscope) root)
"Create or update the GNU Global database for the current project."
(cedet-cscope-create/update-database root))
(provide 'ede/locate)
;; Local variables:

View File

@ -126,7 +126,11 @@ don't do it. A value of nil means to just do it.")
(while compilation-in-progress
(accept-process-output)
(sit-for 1))
;; If sit for indicates that input is waiting, then
;; read and discard whatever it is that is going on.
(when (not (sit-for 1))
(read-event nil nil .1)
))
(with-current-buffer "*compilation*"
(goto-char (point-max))

View File

@ -262,6 +262,18 @@ Execute BODY in a location where a value can be placed."
(goto-char (point-max))))
(put 'ede-pmake-insert-variable-shared 'lisp-indent-function 1)
(defmacro ede-pmake-insert-variable-once (varname &rest body)
"Add VARNAME into the current Makefile if it doesn't exist.
Execute BODY in a location where a value can be placed."
`(let ((addcr t) (v ,varname))
(unless (re-search-backward (concat "^" v "\\s-*=") nil t)
(insert v "=")
,@body
(if addcr (insert "\n"))
(goto-char (point-max)))
))
(put 'ede-pmake-insert-variable-once 'lisp-indent-function 1)
;;; SOURCE VARIABLE NAME CONSTRUCTION
(defsubst ede-pmake-varname (obj)
@ -369,10 +381,14 @@ NOTE: Not yet in use! This is part of an SRecode conversion of
conf-table))
(let* ((top "")
(tmp this))
;; Use relative paths for subdirs.
(while (ede-parent-project tmp)
(setq tmp (ede-parent-project tmp)
top (concat "../" top)))
(insert "\ntop=" top))
;; If this is the top, then use CURDIR.
(if (and (not (oref this metasubproject)) (string= top ""))
(insert "\ntop=\"$(CURDIR)\"/")
(insert "\ntop=" top)))
(insert "\nede_FILES=" (file-name-nondirectory (oref this file)) " "
(file-name-nondirectory (ede-proj-dist-makefile this)) "\n"))
@ -425,14 +441,13 @@ sources variable."
(link (ede-proj-linkers this))
(name (ede-proj-makefile-target-name this))
(src (oref this source)))
(ede-proj-makefile-insert-object-variables (car comp) name src)
(dolist (obj comp)
(ede-compiler-only-once obj
(ede-proj-makefile-insert-variables obj)))
(ede-proj-makefile-insert-object-variables (car comp) name src)
(while link
(ede-linker-only-once (car link)
(ede-proj-makefile-insert-variables (car link)))
(setq link (cdr link)))))
(dolist (linker link)
(ede-linker-only-once linker
(ede-proj-makefile-insert-variables linker)))))
(defmethod ede-proj-makefile-insert-automake-pre-variables
((this ede-proj-target))

View File

@ -29,7 +29,7 @@
(defclass ede-proj-target-makefile-archive
(ede-proj-target-makefile-objectcode)
((availablelinkers :initform (ede-archive-linker)))
((availablelinkers :initform '(ede-archive-linker)))
"This target generates an object code archive.")
(defvar ede-archive-linker

View File

@ -29,7 +29,7 @@
;;; Code:
(defclass ede-proj-target-aux (ede-proj-target)
((sourcetype :initform (ede-aux-source)))
((sourcetype :initform '(ede-aux-source)))
"This target consists of aux files such as READMEs and COPYING.")
(defvar ede-aux-source

View File

@ -36,8 +36,8 @@
((menu :initform nil)
(keybindings :initform nil)
(phony :initform t)
(sourcetype :initform (ede-source-emacs))
(availablecompilers :initform (ede-emacs-compiler ede-xemacs-compiler))
(sourcetype :initform '(ede-source-emacs))
(availablecompilers :initform '(ede-emacs-compiler ede-xemacs-compiler))
(aux-packages :initarg :aux-packages
:initform nil
:type list
@ -259,7 +259,7 @@ is found, such as a `-version' variable, or the standard header."
;; Autoload generators
;;
(defclass ede-proj-target-elisp-autoloads (ede-proj-target-elisp)
((availablecompilers :initform (ede-emacs-cedet-autogen-compiler))
((availablecompilers :initform '(ede-emacs-cedet-autogen-compiler))
(aux-packages :initform ("cedet-autogen"))
(phony :initform t)
(autoload-file :initarg :autoload-file

View File

@ -31,9 +31,9 @@
(defclass ede-proj-target-makefile-info (ede-proj-target-makefile)
((menu :initform nil)
(keybindings :initform nil)
(availablecompilers :initform (ede-makeinfo-compiler
ede-texi2html-compiler))
(sourcetype :initform (ede-makeinfo-source))
(availablecompilers :initform '(ede-makeinfo-compiler
ede-texi2html-compiler))
(sourcetype :initform '(ede-makeinfo-source))
(mainmenu :initarg :mainmenu
:initform ""
:type string

View File

@ -35,8 +35,8 @@
;; FIXME this isn't how you spell "miscellaneous". :(
(defclass ede-proj-target-makefile-miscelaneous (ede-proj-target-makefile)
((sourcetype :initform (ede-misc-source))
(availablecompilers :initform (ede-misc-compile))
((sourcetype :initform '(ede-misc-source))
(availablecompilers :initform '(ede-misc-compile))
(submakefile :initarg :submakefile
:initform ""
:type string

View File

@ -39,28 +39,32 @@
(configuration-variables :initform ("debug" . (("CFLAGS" . "-g")
("LDFLAGS" . "-g"))))
;; @TODO - add an include path.
(availablecompilers :initform (ede-gcc-compiler
ede-g++-compiler
ede-gfortran-compiler
ede-gfortran-module-compiler
;; More C and C++ compilers, plus
;; fortran or pascal can be added here
))
(availablelinkers :initform (ede-g++-linker
ede-cc-linker
ede-gfortran-linker
ede-ld-linker
;; Add more linker thingies here.
))
(sourcetype :initform (ede-source-c
ede-source-c++
ede-source-f77
ede-source-f90
;; ede-source-other
;; This object should take everything that
;; gets compiled into objects like fortran
;; and pascal.
))
(availablecompilers :initform '(ede-gcc-compiler
ede-g++-compiler
ede-gfortran-compiler
ede-gfortran-module-compiler
ede-lex-compiler
ede-yacc-compiler
;; More C and C++ compilers, plus
;; fortran or pascal can be added here
))
(availablelinkers :initform '(ede-g++-linker
ede-cc-linker
ede-ld-linker
ede-gfortran-linker
;; Add more linker thingies here.
))
(sourcetype :initform '(ede-source-c
ede-source-c++
ede-source-f77
ede-source-f90
ede-source-lex
ede-source-yacc
;; ede-source-other
;; This object should take everything that
;; gets compiled into objects like fortran
;; and pascal.
))
)
"Abstract class for Makefile based object code generating targets.
Belonging to this group assumes you could make a .o from an element source
@ -115,15 +119,15 @@ file.")
:name "cc"
:sourcetype '(ede-source-c)
:variables '(("C_LINK" . "$(CC) $(CFLAGS) $(LDFLAGS) -L."))
:commands '("$(C_LINK) -o $@ $^")
:commands '("$(C_LINK) -o $@ $^ $(LDDEPS)")
:objectextention "")
"Linker for C sourcecode.")
(defvar ede-source-c++
(ede-sourcecode "ede-source-c++"
:name "C++"
:sourcepattern "\\.\\(cpp\\|cc\\|cxx\\)$"
:auxsourcepattern "\\.\\(hpp\\|hh?\\|hxx\\)$"
:sourcepattern "\\.\\(c\\(pp?\\|c\\|xx\\|++\\)\\|C\\\(PP\\)?\\)$"
:auxsourcepattern "\\.\\(hpp?\\|hh?\\|hxx\\|H\\)$"
:garbagepattern '("*.o" "*.obj" ".deps/*.P" ".lo"))
"C++ source code definition.")
@ -158,11 +162,43 @@ file.")
;; Only use this linker when c++ exists.
:sourcetype '(ede-source-c++)
:variables '(("CXX_LINK" . "$(CXX) $(CFLAGS) $(LDFLAGS) -L."))
:commands '("$(CXX_LINK) -o $@ $^")
:commands '("$(CXX_LINK) -o $@ $^ $(LDDEPS)")
:autoconf '("AC_PROG_CXX")
:objectextention "")
"Linker needed for c++ programs.")
;;; LEX
(defvar ede-source-lex
(ede-sourcecode "ede-source-lex"
:name "lex"
:sourcepattern "\\.l\\(l\\|pp\\|++\\)")
"Lex source code definition.
No garbage pattern since it creates C or C++ code.")
(defvar ede-lex-compiler
(ede-object-compiler
"ede-lex-compiler"
;; Can we support regular makefiles too??
:autoconf '("AC_PROG_LEX")
:sourcetype '(ede-source-lex))
"Compiler used for Lexical source.")
;;; YACC
(defvar ede-source-yacc
(ede-sourcecode "ede-source-yacc"
:name "yacc"
:sourcepattern "\\.y\\(y\\|pp\\|++\\)")
"Yacc source code definition.
No garbage pattern since it creates C or C++ code.")
(defvar ede-yacc-compiler
(ede-object-compiler
"ede-yacc-compiler"
;; Can we support regular makefiles too??
:autoconf '("AC_PROG_YACC")
:sourcetype '(ede-source-yacc))
"Compiler used for yacc/bison grammar files source.")
;;; Fortran Compiler/Linker
;;
;; Contributed by David Engster
@ -233,7 +269,7 @@ file.")
:name "ld"
:variables '(("LD" . "ld")
("LD_LINK" . "$(LD) $(LDFLAGS) -L."))
:commands '("$(LD_LINK) -o $@ $^")
:commands '("$(LD_LINK) -o $@ $^ $(LDDEPS)")
:objectextention "")
"Linker needed for c++ programs.")

View File

@ -34,14 +34,14 @@
;;; Code:
(defclass ede-proj-target-makefile-program
(ede-proj-target-makefile-objectcode)
((ldlibs :initarg :ldlibs
:initform nil
:type list
:custom (repeat (string :tag "Library"))
:documentation
"Libraries, such as \"m\" or \"Xt\" which this program depends on.
The linker flag \"-l\" is automatically prepended. Do not include a \"lib\"
prefix, or a \".so\" suffix.
((ldlibs-local :initarg :ldlibs-local
:initform nil
:type list
:custom (repeat (string :tag "Local Library"))
:documentation
"Libraries that are part of this project.
The full path to these libraries should be specified, such as:
../lib/libMylib.la or ../ar/myArchive.a
Note: Currently only used for Automake projects."
)
@ -51,10 +51,21 @@ Note: Currently only used for Automake projects."
:custom (repeat (string :tag "Link Flag"))
:documentation
"Additional flags to add when linking this target.
Use ldlibs to add addition libraries. Use this to specify specific
options to the linker.
Use this to specify specific options to the linker.
A Common use may be to add -L to specify in-project locations of libraries
specified with ldlibs.")
(ldlibs :initarg :ldlibs
:initform nil
:type list
:custom (repeat (string :tag "Library"))
:documentation
"Libraries, such as \"m\" or \"Xt\" which this program depends on.
The linker flag \"-l\" is automatically prepended. Do not include a \"lib\"
prefix, or a \".so\" suffix.
Use the 'ldflags' slot to specify where in-project libraries might be.
Note: Not currently used. This bug needs to be fixed.")
Note: Currently only used for Automake projects."
)
)
"This target is an executable program.")
@ -70,27 +81,24 @@ Note: Not currently used. This bug needs to be fixed.")
"Insert bin_PROGRAMS variables needed by target THIS."
(ede-pmake-insert-variable-shared
(concat (ede-name this) "_LDADD")
(mapc (lambda (c) (insert " -l" c)) (oref this ldlibs)))
;; For other targets THIS depends on
;;
;; NOTE: FIX THIS
;;
;;(ede-pmake-insert-variable-shared
;; (concat (ede-name this) "_DEPENDENCIES")
;; (mapcar (lambda (d) (insert d)) (oref this FOOOOOOOO)))
(mapc (lambda (l) (insert " " l)) (oref this ldlibs-local))
(mapc (lambda (c) (insert " " c)) (oref this ldflags))
(when (oref this ldlibs)
(mapc (lambda (d) (insert " -l" d)) (oref this ldlibs)))
)
(call-next-method))
(defmethod ede-proj-makefile-insert-rules ((this ede-proj-target-makefile-program))
"Insert rules needed by THIS target."
(let ((ede-proj-compiler-object-linkflags
(mapconcat 'identity (oref this ldflags) " ")))
(defmethod ede-proj-makefile-insert-variables ((this ede-proj-target-makefile-program))
"Insert variables needed by the compiler THIS."
(call-next-method)
(let ((lf (mapconcat 'identity (oref this ldflags) " ")))
(with-slots (ldlibs) this
(if ldlibs
(setq ede-proj-compiler-object-linkflags
(concat ede-proj-compiler-object-linkflags
" -l"
(mapconcat 'identity ldlibs " -l")))))
(call-next-method)))
(setq lf
(concat lf " -l" (mapconcat 'identity ldlibs " -l")))))
;; LDFLAGS as needed.
(when (and lf (not (string= "" lf)))
(ede-pmake-insert-variable-once "LDDEPS" (insert lf)))))
(defmethod project-debug-target ((obj ede-proj-target-makefile-program))
"Debug a program target OBJ."

View File

@ -34,15 +34,15 @@
;;; Code:
(defclass ede-proj-target-makefile-shared-object
(ede-proj-target-makefile-program)
((availablecompilers :initform (ede-gcc-libtool-shared-compiler
;;ede-gcc-shared-compiler
ede-g++-libtool-shared-compiler
;;ede-g++-shared-compiler
))
(availablelinkers :initform (ede-cc-linker-libtool
ede-g++-linker-libtool
;; Add more linker thingies here.
))
((availablecompilers :initform '(ede-gcc-libtool-shared-compiler
;;ede-gcc-shared-compiler
ede-g++-libtool-shared-compiler
;;ede-g++-shared-compiler
))
(availablelinkers :initform '(ede-cc-linker-libtool
ede-g++-linker-libtool
;; Add more linker thingies here.
))
(ldflags :custom (repeat (string :tag "Libtool flag"))
:documentation
"Additional flags to add when linking this shared library.
@ -124,7 +124,7 @@ Use ldlibs to add addition libraries.")
:rules (list (ede-makefile-rule
"c++-inference-rule-libtool"
:target "%.o"
:dependencies "%.c"
:dependencies "%.cpp"
:rules '("@echo '$(LTCOMPILE) -o $@ $<'; \\"
"$(LTCOMPILE) -o $@ $<"
)

View File

@ -29,7 +29,6 @@
;; rebuild. The targets provided in ede-proj can be augmented with
;; additional target types inherited directly from `ede-proj-target'.
;; (eval-and-compile '(require 'ede))
(require 'ede/proj-comp)
(require 'ede/make)
@ -336,7 +335,9 @@ Argument TARGET is the project we are completing customization on."
(or (string= (file-name-nondirectory (oref this file)) f)
(string= (ede-proj-dist-makefile this) f)
(string-match "Makefile\\(\\.\\(in\\|am\\)\\)?$" f)
(string-match "config\\(ure\\.in\\|\\.stutus\\)?$" f)
(string-match "config\\(ure\\.\\(in\\|ac\\)\\|\\.status\\)?$" f)
(string-match "config.h\\(\\.in\\)?" f)
(member f '("AUTHORS" "NEWS" "COPYING" "INSTALL" "README"))
)))
(defmethod ede-buffer-mine ((this ede-proj-target) buffer)
@ -398,11 +399,11 @@ Argument TARGET is the project we are completing customization on."
:source nil)))
(defmethod project-delete-target ((this ede-proj-target))
"Delete the current target THIS from it's parent project."
"Delete the current target THIS from its parent project."
(let ((p (ede-current-project))
(ts (oref this source)))
;; Loop across all sources. If it exists in a buffer,
;; clear it's object.
;; clear its object.
(while ts
(let* ((default-directory (oref this path))
(b (get-file-buffer (car ts))))
@ -413,7 +414,7 @@ Argument TARGET is the project we are completing customization on."
(setq ede-object nil)
(ede-apply-object-keymap))))))
(setq ts (cdr ts)))
;; Remove THIS from it's parent.
;; Remove THIS from its parent.
;; The two vectors should be pointer equivalent.
(oset p targets (delq this (oref p targets)))
(ede-proj-save (ede-current-project))))
@ -447,15 +448,13 @@ FILE must be massaged by `ede-convert-path'."
(defmethod project-make-dist ((this ede-proj-project))
"Build a distribution for the project based on THIS target."
;; I'm a lazy bum, so I'll make a makefile for doing this sort
;; of thing, and rely only on that small section of code.
(let ((pm (ede-proj-dist-makefile this))
(df (project-dist-files this)))
(if (and (file-exists-p (car df))
(not (y-or-n-p "Dist file already exists. Rebuild? ")))
(error "Try `ede-update-version' before making a distribution"))
(ede-proj-setup-buildenvironment this)
(if (string= (file-name-nondirectory pm) "Makefile.am")
(if (ede-proj-automake-p this)
(setq pm (expand-file-name "Makefile"
(file-name-directory pm))))
(compile (concat ede-make-command " -f " pm " dist"))))
@ -473,7 +472,7 @@ Argument COMMAND is the command to use when compiling."
(let ((pm (ede-proj-dist-makefile proj))
(default-directory (file-name-directory (oref proj file))))
(ede-proj-setup-buildenvironment proj)
(if (string= (file-name-nondirectory pm) "Makefile.am")
(if (ede-proj-automake-p proj)
(setq pm (expand-file-name "Makefile"
(file-name-directory pm))))
(compile (concat ede-make-command" -f " pm " all"))))
@ -539,7 +538,15 @@ Converts all symbols into the objects to be used."
(if (ede-want-any-source-files-p (symbol-value (car st)) sources)
(let ((c (ede-proj-find-compiler avail (car st))))
(if c (setq comp (cons c comp)))))
(setq st (cdr st)))))
(setq st (cdr st)))
;; Provide a good error msg.
(unless comp
(error "Could not find compiler match for source code extension \"%s\".
You may need to add support for this type of file."
(if sources
(file-name-extension (car sources))
"")))
))
;; Return the disovered compilers
comp)))
@ -664,18 +671,9 @@ Optional argument FORCE will force items to be regenerated."
(let ((root (or (ede-project-root this) this))
)
(setq ede-projects (delq root ede-projects))
(ede-proj-load (ede-project-root-directory root))
(ede-load-project-file (ede-project-root-directory root))
))
(defmethod project-rescan ((this ede-proj-target) readstream)
"Rescan target THIS from the read list READSTREAM."
(setq readstream (cdr (cdr readstream))) ;; constructor/name
(while readstream
(let ((tag (car readstream))
(val (car (cdr readstream))))
(eieio-oset this tag val))
(setq readstream (cdr (cdr readstream)))))
(provide 'ede/proj)
;; arch-tag: eb8a40f8-0d2c-41c4-b273-af04101d1cdf

View File

@ -30,27 +30,19 @@
;; fashion.
;;
;; project-am uses the structure defined in all good GNU projects with
;; the Automake file as it's base template, and then maintains that
;; the Automake file as its base template, and then maintains that
;; information during edits, automatically updating the automake file
;; where appropriate.
;; (eval-and-compile
;; ;; Compatibility for makefile mode.
;; (condition-case nil
;; (require 'makefile "make-mode")
;; (error (require 'make-mode "make-mode")))
;; ;; Requiring the .el files prevents incomplete builds.
;; (require 'eieio "eieio.el")
;; (require 'ede "ede.el"))
(require 'make-mode)
(require 'ede)
(require 'ede/make)
(require 'ede/makefile-edit)
(require 'semantic/find) ;; for semantic-find-tags-by-...
(require 'ede/autoconf-edit)
(declare-function autoconf-parameters-for-macro "ede/autoconf-edit")
(declare-function ede-shell-run-something "ede/shell")
(eval-when-compile (require 'compile))
;;; Code:
@ -104,7 +96,7 @@
;; ("ltlibcustom" project-am-lib ".*?_LTLIBRARIES" t)
)
"Alist of type names and the type of object to create for them.
Each entry is of th form:
Each entry is of the form:
(EMACSNAME CLASS AUTOMAKEVAR INDIRECT)
where EMACSNAME is a name for Emacs to use.
CLASS is the EDE target class to represent the target.
@ -113,6 +105,23 @@ AUTOMAKEVAR is the Automake variable to identify. This cannot be a
INDIRECT is optional. If it is non-nil, then the variable in
question lists other variables that need to be looked up.")
(defconst project-am-meta-type-alist
'((project-am-program "_PROGRAMS$" t)
(project-am-lib "_\\(LIBS\\|LIBRARIES\\|LTLIBRARIES\\)$" t)
;; direct primary target use a dummy object (man target)
;; update to: * 3.3 Uniform in automake-1.11 info node.
(project-am-man "_\\(DATA\\|HEADERS\\|PYTHON\\|JAVA\\|SCRIPTS\\|MANS\\|TEXINFOS\\)$" nil)
)
"Alist of meta-target type, each entry has form:
(CLASS REGEXPVAR INDIRECT)
where CLASS is the EDE target class for target.
REGEXPVAR is the regexp used in `semantic-find-tags-by-name-regexp'.
INDIRECT is optional. If it is non-nil, then the variable in it have
other meta-variable based on this name.")
(defclass project-am-target (ede-target)
nil
"Base target class for everything in project-am.")
@ -291,16 +300,6 @@ buffer being in order to provide a smart default target type."
;; Rescan the object in this makefile.
(project-rescan ede-object))))
;(defun project-am-rescan-toplevel ()
; "Rescan all projects in which the current buffer resides."
; (interactive)
; (let* ((tlof (project-am-find-topmost-level default-directory))
; (tlo (project-am-load tlof))
; (ede-deep-rescan t)) ; scan deep in this case.
; ;; tlo is the top level object for whatever file we are in
; ;; or nil. If we have an object, call the rescan method.
; (if tlo (project-am-rescan tlo))))
;;
;; NOTE TO SELF
;;
@ -404,6 +403,7 @@ Argument COMMAND is the command to use for compiling the target."
(defmethod project-run-target ((obj project-am-objectcode))
"Run the current project target in comint buffer."
(require 'ede/shell)
(let ((tb (get-buffer-create " *padt*"))
(dd (oref obj path))
(cmd nil))
@ -427,45 +427,17 @@ Argument COMMAND is the command to use for compiling the target."
;;; Project loading and saving
;;
(defun project-am-load (project &optional rootproj)
"Read an automakefile PROJECT into our data structure.
Make sure that the tree down to our makefile is complete so that there
is cohesion in the project. Return the project file (or sub-project).
(defun project-am-load (directory &optional rootproj)
"Read an automakefile DIRECTORY into our data structure.
If a given set of projects has already been loaded, then do nothing
but return the project for the directory given.
Optional ROOTPROJ is the root EDE project."
;; @TODO - rationalize this to the newer EDE way of doing things.
(setq project (expand-file-name project))
(let* ((ede-constructing t)
(fn (project-am-find-topmost-level (file-name-as-directory project)))
(amo nil)
(trimmed (if (string-match (regexp-quote fn)
project)
(replace-match "" t t project)
""))
(subdir nil))
(setq amo (object-assoc (expand-file-name "Makefile.am" fn)
'file ede-projects))
(if amo
(error "Synchronous error in ede/project-am objects")
(let ((project-am-constructing t))
(setq amo (project-am-load-makefile fn))))
(if (not amo)
nil
;; Now scan down from amo, and find the current directory
;; from the PROJECT file.
(while (< 0 (length trimmed))
(if (string-match "\\([a-zA-Z0-9.-]+\\)/" trimmed)
(setq subdir (match-string 0 trimmed)
trimmed (replace-match "" t t trimmed))
(error "Error scanning down path for project"))
(setq amo (project-am-subtree
amo
(expand-file-name "Makefile.am"
(expand-file-name subdir fn)))
fn (expand-file-name subdir fn)))
amo)
))
(let* ((ede-constructiong t)
(amo (object-assoc (expand-file-name "Makefile.am" directory)
'file ede-projects)))
(when (not amo)
(setq amo (project-am-load-makefile directory)))
amo))
(defun project-am-find-topmost-level (dir)
"Find the topmost automakefile starting with DIR."
@ -486,17 +458,19 @@ Kill the makefile if it was not loaded before the load."
(fb nil)
(kb (get-file-buffer fn)))
(if (not (file-exists-p fn))
nil
(save-excursion
(if kb (setq fb kb)
;; We need to find-file this thing, but don't use
;; any semantic features.
(let ((semantic-init-hook nil))
(setq fb (find-file-noselect fn)))
)
(set-buffer fb)
(prog1 ,@forms
(if (not kb) (kill-buffer (current-buffer))))))))
nil
(save-excursion
(if kb (setq fb kb)
;; We need to find-file this thing, but don't use
;; any semantic features.
(let ((semantic-init-hook nil)
(recentf-exclude '( (lambda (f) t) ))
)
(setq fb (find-file-noselect fn)))
)
(set-buffer fb)
(prog1 ,@forms
(if (not kb) (kill-buffer (current-buffer))))))))
(put 'project-am-with-makefile-current 'lisp-indent-function 1)
(add-hook 'edebug-setup-hook
@ -505,14 +479,18 @@ Kill the makefile if it was not loaded before the load."
(form def-body))))
(defun project-am-load-makefile (path)
(defun project-am-load-makefile (path &optional suggestedname)
"Convert PATH into a project Makefile, and return its project object.
It does not check for existing project objects. Use `project-am-load'."
It does not check for existing project objects. Use `project-am-load'.
Optional argument SUGGESTEDNAME will be the project name.
This is used when subprojects are made in named subdirectories."
(project-am-with-makefile-current path
(if (and ede-object (project-am-makefile-p ede-object))
ede-object
(let* ((pi (project-am-package-info path))
(pn (or (nth 0 pi) (project-am-last-dir fn)))
(sfn (when suggestedname
(project-am-last-dir suggestedname)))
(pn (or sfn (nth 0 pi) (project-am-last-dir fn)))
(ver (or (nth 1 pi) "0.0"))
(bug (nth 2 pi))
(cof (nth 3 pi))
@ -530,21 +508,6 @@ It does not check for existing project objects. Use `project-am-load'."
ampf))))
;;; Methods:
(defmethod ede-find-target ((amf project-am-makefile) buffer)
"Fetch the target belonging to BUFFER."
(or (call-next-method)
(let ((targ (oref amf targets))
(sobj (oref amf subproj))
(obj nil))
(while (and targ (not obj))
(if (ede-buffer-mine (car targ) buffer)
(setq obj (car targ)))
(setq targ (cdr targ)))
(while (and sobj (not obj))
(setq obj (project-am-buffer-object (car sobj) buffer)
sobj (cdr sobj)))
obj)))
(defmethod project-targets-for-file ((proj project-am-makefile))
"Return a list of targets the project PROJ."
(oref proj targets))
@ -554,44 +517,110 @@ It does not check for existing project objects. Use `project-am-load'."
CURRPROJ is the current project being scanned.
DIR is the directory to apply to new targets."
(let* ((otargets (oref currproj targets))
;; `ntargets' results in complete targets list
;; not only the new targets by diffing.
(ntargets nil)
(tmp nil)
)
(mapc
;; Map all the different types
(lambda (typecar)
(let ((macro (nth 2 typecar))
(class (nth 1 typecar))
(indirect (nth 3 typecar))
;(name (car typecar))
)
(if indirect
;; Map all the found objects
(mapc (lambda (lstcar)
(setq tmp (object-assoc lstcar 'name otargets))
(when (not tmp)
(setq tmp (apply class lstcar :name lstcar
:path dir nil)))
(project-rescan tmp)
(setq ntargets (cons tmp ntargets)))
(makefile-macro-file-list macro))
;; Non-indirect will have a target whos sources
;; are actual files, not names of other targets.
(let ((files (makefile-macro-file-list macro)))
(when files
(setq tmp (object-assoc macro 'name otargets))
(when (not tmp)
(setq tmp (apply class macro :name macro
:path dir nil)))
(project-rescan tmp)
(setq ntargets (cons tmp ntargets))
))
)
))
project-am-type-alist)
ntargets))
(defmethod project-rescan ((this project-am-makefile))
(mapc
;; Map all the different types
(lambda (typecar)
(let ((macro (nth 2 typecar))
(class (nth 1 typecar))
(indirect (nth 3 typecar))
)
(if indirect
;; Map all the found objects
(mapc (lambda (lstcar)
(setq tmp (object-assoc lstcar 'name otargets))
(when (not tmp)
(setq tmp (apply class lstcar :name lstcar
:path dir nil)))
(project-rescan tmp)
(setq ntargets (cons tmp ntargets)))
(makefile-macro-file-list macro))
;; Non-indirect will have a target whos sources
;; are actual files, not names of other targets.
(let ((files (makefile-macro-file-list macro)))
(when files
(setq tmp (object-assoc macro 'name otargets))
(when (not tmp)
(setq tmp (apply class macro :name macro
:path dir nil)))
(project-rescan tmp)
(setq ntargets (cons tmp ntargets))
))
)
))
project-am-type-alist)
;; At now check variables for meta-target regexp
;; We have to check ntargets to avoid useless rescan.
;; Also we have check otargets to prevent duplication.
(mapc
(lambda (typecar)
(let ((class (nth 0 typecar))
(metaregex (nth 1 typecar))
(indirect (nth 2 typecar)))
(if indirect
;; Map all the found objects
(mapc
(lambda (lstcar)
(unless (object-assoc lstcar 'name ntargets)
(or
(setq tmp (object-assoc lstcar 'name otargets))
(setq tmp (apply class lstcar :name lstcar
:path dir nil)))
(project-rescan tmp)
(setq ntargets (cons tmp ntargets))))
;; build a target list to map over
(let (atargets)
(dolist (TAG
(semantic-find-tags-by-name-regexp
metaregex (semantic-find-tags-by-class
'variable (semantic-fetch-tags))))
;; default-value have to be a list
(when (cadr (assoc ':default-value TAG))
(setq atargets
(append
(nreverse (cadr (assoc ':default-value TAG)))
atargets))))
(nreverse atargets)))
;; else not indirect, TODO: FIX various direct meta type in a sane way.
(dolist (T (semantic-find-tags-by-name-regexp
metaregex (semantic-find-tags-by-class
'variable (semantic-fetch-tags))))
(unless (setq tmp (object-assoc (car T) 'name ntargets))
(or (setq tmp (object-assoc (car T) 'name otargets))
;; we are really new
(setq tmp (apply class (car T) :name (car T)
:path dir nil)))
(project-rescan tmp)
(setq ntargets (cons tmp ntargets))))
)))
project-am-meta-type-alist)
ntargets))
(defun project-am-expand-subdirlist (place subdirs)
"Store in PLACE the SUBDIRS expanded from variables.
Strip out duplicates, and recurse on variables."
(mapc (lambda (sp)
(let ((var (makefile-extract-varname-from-text sp)))
(if var
;; If it is a variable, expand that variable, and keep going.
(project-am-expand-subdirlist
place (makefile-macro-file-list var))
;; Else, add SP in if it isn't a dup.
(if (member sp (symbol-value place))
nil ; don't do it twice.
(set place (cons sp (symbol-value place))) ;; add
))))
subdirs)
)
(defmethod project-rescan ((this project-am-makefile) &optional suggestedname)
"Rescan the makefile for all targets and sub targets."
(project-am-with-makefile-current (file-name-directory (oref this file))
;;(message "Scanning %s..." (oref this file))
@ -601,10 +630,10 @@ DIR is the directory to apply to new targets."
(bug (nth 2 pi))
(cof (nth 3 pi))
(osubproj (oref this subproj))
(csubproj (or
;; If DIST_SUBDIRS doesn't exist, then go for the
;; static list of SUBDIRS. The DIST version should
;; contain SUBDIRS plus extra stuff.
;; 1/30/10 - We need to append these two lists together,
;; then strip out duplicates. Expanding this list (via
;; references to other variables should also strip out dups
(csubproj (append
(makefile-macro-file-list "DIST_SUBDIRS")
(makefile-macro-file-list "SUBDIRS")))
(csubprojexpanded nil)
@ -615,79 +644,57 @@ DIR is the directory to apply to new targets."
(tmp nil)
(ntargets (project-am-scan-for-targets this dir))
)
(and pn (string= (directory-file-name
(oref this directory))
(directory-file-name
(project-am-find-topmost-level
(oref this directory))))
(oset this name pn)
(and pv (oset this version pv))
(and bug (oset this mailinglist bug))
(oset this configureoutputfiles cof))
; ;; LISP is different. Here there is only one kind of lisp (that I know of
; ;; anyway) so it doesn't get mapped when it is found.
; (if (makefile-move-to-macro "lisp_LISP")
; (let ((tmp (project-am-lisp "lisp"
; :name "lisp"
; :path dir)))
; (project-rescan tmp)
; (setq ntargets (cons tmp ntargets))))
;
(if suggestedname
(oset this name (project-am-last-dir suggestedname))
;; Else, setup toplevel project info.
(and pn (string= (directory-file-name
(oref this directory))
(directory-file-name
(project-am-find-topmost-level
(oref this directory))))
(oset this name pn)
(and pv (oset this version pv))
(and bug (oset this mailinglist bug))
(oset this configureoutputfiles cof)))
;; Now that we have this new list, chuck the old targets
;; and replace it with the new list of targets I just created.
(oset this targets (nreverse ntargets))
;; We still have a list of targets. For all buffers, make sure
;; their object still exists!
;; FIGURE THIS OUT
(mapc (lambda (sp)
(let ((var (makefile-extract-varname-from-text sp))
)
(if (not var)
(setq csubprojexpanded (cons sp csubprojexpanded))
;; If it is a variable, expand that variable, and keep going.
(let ((varexp (makefile-macro-file-list var)))
(dolist (V varexp)
(setq csubprojexpanded (cons V csubprojexpanded)))))
))
csubproj)
(project-am-expand-subdirlist 'csubprojexpanded csubproj)
;; Ok, now lets look at all our sub-projects.
(mapc (lambda (sp)
(let* ((subdir (file-name-as-directory
(expand-file-name
sp (file-name-directory (oref this :file)))))
(submake (expand-file-name
"Makefile.am"
subdir)))
(if (string= submake (oref this :file))
nil ;; don't recurse.. please!
;; For each project id found, see if we need to recycle,
;; and if we do not, then make a new one. Check the deep
;; rescan value for behavior patterns.
(setq tmp (object-assoc
submake
'file osubproj))
(if (not tmp)
(setq tmp
(condition-case nil
;; In case of problem, ignore it.
(project-am-load-makefile subdir)
(error nil)))
;; If we have tmp, then rescan it only if deep mode.
(if ede-deep-rescan
(project-rescan tmp)))
;; Tac tmp onto our list of things to keep, but only
;; if tmp was found.
(when tmp
;;(message "Adding %S" (object-print tmp))
(setq nsubproj (cons tmp nsubproj)))))
)
(nreverse csubprojexpanded))
(let* ((subdir (file-name-as-directory
(expand-file-name
sp (file-name-directory (oref this :file)))))
(submake (expand-file-name
"Makefile.am"
subdir)))
(if (string= submake (oref this :file))
nil ;; don't recurse.. please!
;; For each project id found, see if we need to recycle,
;; and if we do not, then make a new one. Check the deep
;; rescan value for behavior patterns.
(setq tmp (object-assoc
submake
'file osubproj))
(if (not tmp)
(setq tmp
(condition-case nil
;; In case of problem, ignore it.
(project-am-load-makefile subdir subdir)
(error nil)))
;; If we have tmp, then rescan it only if deep mode.
(if ede-deep-rescan
(project-rescan tmp subdir)))
;; Tac tmp onto our list of things to keep, but only
;; if tmp was found.
(when tmp
;;(message "Adding %S" (object-print tmp))
(setq nsubproj (cons tmp nsubproj)))))
)
(nreverse csubprojexpanded))
(oset this subproj nsubproj)
;; All elements should be updated now.
)))
@ -696,12 +703,16 @@ DIR is the directory to apply to new targets."
(defmethod project-rescan ((this project-am-program))
"Rescan object THIS."
(oset this :source (makefile-macro-file-list (project-am-macro this)))
(unless (oref this :source)
(oset this :source (list (concat (oref this :name) ".c"))))
(oset this :ldadd (makefile-macro-file-list
(concat (oref this :name) "_LDADD"))))
(defmethod project-rescan ((this project-am-lib))
"Rescan object THIS."
(oset this :source (makefile-macro-file-list (project-am-macro this))))
(oset this :source (makefile-macro-file-list (project-am-macro this)))
(unless (oref this :source)
(oset this :source (list (concat (file-name-sans-extension (oref this :name)) ".c")))))
(defmethod project-rescan ((this project-am-texinfo))
"Rescan object THIS."
@ -726,19 +737,6 @@ DIR is the directory to apply to new targets."
(defmethod project-rescan ((this project-am-extra-dist))
"Rescan object THIS."
(oset this :source (makefile-macro-file-list "EXTRA_DIST")))
;; NOTE: The below calls 'file' then checks that it is some sort of
;; text file. The file command may not be available on all platforms
;; and some files may not exist yet. (ie - auto-generated)
;;(mapc
;; (lambda (f)
;; ;; prevent garbage to be parsed, could we use :aux ?
;; (if (and (not (member f (oref this :source)))
;; (string-match-p "ASCII\\|text"
;; (shell-command-to-string
;; (concat "file " f))))
;; (oset this :source (cons f (oref this :source)))))
;; (makefile-macro-file-list "EXTRA_DIST")))
(defmethod project-am-macro ((this project-am-objectcode))
"Return the default macro to 'edit' for this object type."
@ -808,22 +806,24 @@ nil means that this buffer belongs to no-one."
(defmethod ede-buffer-mine ((this project-am-objectcode) buffer)
"Return t if object THIS lays claim to the file in BUFFER."
(member (file-name-nondirectory (buffer-file-name buffer))
(member (file-relative-name (buffer-file-name buffer) (oref this :path))
(oref this :source)))
(defmethod ede-buffer-mine ((this project-am-texinfo) buffer)
"Return t if object THIS lays claim to the file in BUFFER."
(let ((bfn (buffer-file-name buffer)))
(or (string= (oref this :name) (file-name-nondirectory bfn))
(member (file-name-nondirectory bfn) (oref this :include)))))
(let ((bfn (file-relative-name (buffer-file-name buffer)
(oref this :path))))
(or (string= (oref this :name) bfn)
(member bfn (oref this :include)))))
(defmethod ede-buffer-mine ((this project-am-man) buffer)
"Return t if object THIS lays claim to the file in BUFFER."
(string= (oref this :name) (buffer-file-name buffer)))
(string= (oref this :name)
(file-relative-name (buffer-file-name buffer) (oref this :path))))
(defmethod ede-buffer-mine ((this project-am-lisp) buffer)
"Return t if object THIS lays claim to the file in BUFFER."
(member (file-name-nondirectory (buffer-file-name buffer))
(member (file-relative-name (buffer-file-name buffer) (oref this :path))
(oref this :source)))
(defmethod project-am-subtree ((ampf project-am-makefile) subdir)
@ -954,7 +954,6 @@ Kill the Configure buffer if it was not already in a buffer."
(cond
;; Try configure.in or configure.ac
(conf-in
(require 'ede/autoconf-edit)
(project-am-with-config-current conf-in
(let ((aci (autoconf-parameters-for-macro "AC_INIT"))
(aia (autoconf-parameters-for-macro "AM_INIT_AUTOMAKE"))
@ -980,7 +979,7 @@ Kill the Configure buffer if it was not already in a buffer."
(t acf))))
(if (> (length outfiles) 1)
(setq configfiles outfiles)
(setq configfiles (split-string (car outfiles) " " t)))
(setq configfiles (split-string (car outfiles) "\\s-" t)))
)
))
)
@ -1005,6 +1004,18 @@ Calculates the info with `project-am-extract-package-info'."
(when top (setq dir (oref top :directory)))
(project-am-extract-package-info dir)))
;; for simple per project include path extension
(defmethod ede-system-include-path ((this project-am-makefile))
"Return `project-am-localvars-include-path', usually local variable
per file or in .dir-locals.el or similar."
(bound-and-true-p project-am-localvars-include-path))
(defmethod ede-system-include-path ((this project-am-target))
"Return `project-am-localvars-include-path', usually local variable
per file or in .dir-locals.el or similar."
(bound-and-true-p project-am-localvars-include-path))
(provide 'ede/project-am)
;; arch-tag: 528db935-f186-4240-b647-e305c5b784a2

View File

@ -70,7 +70,7 @@ COMMAND is a text string representing the thing to be run."
(defmethod ede-shell-buffer ((target ede-target))
"Get the buffer for running shell commands for TARGET."
(let ((name (ede-name target)))
(get-buffer-create (format "*EDE Shell %s" name))))
(get-buffer-create (format "*EDE Shell %s*" name))))
(provide 'ede/shell)

View File

@ -21,6 +21,10 @@
;;; Commentary:
;;
;; NOTE: EDE Simple Projects are considered obsolete. Use generic
;; projects instead. They have much better automatic support and
;; simpler configuration.
;;
;; A vast majority of projects use non-EDE project techniques, such
;; as hand written Makefiles, or other IDE's.
;;
@ -41,6 +45,14 @@
;;; Code:
(add-to-list 'ede-project-class-files
(ede-project-autoload "simple-overlay"
:name "Simple" :file 'ede-simple
:proj-file 'ede-simple-projectfile-for-dir
:load-type 'ede-simple-load
:class-sym 'ede-simple-project)
t)
(defcustom ede-simple-save-directory "~/.ede"
"*Directory where simple EDE project overlays are saved."
:group 'ede

View File

@ -108,7 +108,7 @@ Argument DIR is the directory from which to derive the list of objects."
;;; Some special commands useful in EDE
;;
(defun ede-speedbar-remove-file-from-target ()
"Remove the file at point from it's target."
"Remove the file at point from its target."
(interactive)
(if (stringp (speedbar-line-token))
(progn

View File

@ -43,7 +43,9 @@
(srecode-map-update-map t)
;; We don't call this unless we need it. Load in the templates.
(srecode-load-tables-for-mode 'makefile-mode)
(srecode-load-tables-for-mode 'makefile-mode 'ede))
(srecode-load-tables-for-mode 'makefile-mode 'ede)
(srecode-load-tables-for-mode 'autoconf-mode)
(srecode-load-tables-for-mode 'autoconf-mode 'ede))
(defmacro ede-srecode-insert-with-dictionary (template &rest forms)
"Insert TEMPLATE after executing FORMS with a dictionary.