PageRenderTime 44ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/lisp/cedet/ede/generic.el

https://gitlab.com/wilfred/emacs
Emacs Lisp | 375 lines | 221 code | 43 blank | 111 comment | 23 complexity | 272692d9103aa278326e5c5a9df95407 MD5 | raw file
  1. ;;; ede/generic.el --- Base Support for generic build systems
  2. ;; Copyright (C) 2010-2016 Free Software Foundation, Inc.
  3. ;; Author: Eric M. Ludlam <eric@siege-engine.com>
  4. ;; This file is part of GNU Emacs.
  5. ;; GNU Emacs is free software: you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; GNU Emacs is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;;
  17. ;; There are a lot of build systems out there, and EDE can't support
  18. ;; them all fully. The ede/generic.el system is the base for
  19. ;; supporting alternate build systems in a simple way, automatically.
  20. ;;
  21. ;; The structure is for the ede-generic baseclass, which is augmented
  22. ;; by simple sub-classes that can be created by users on an as needed
  23. ;; basis. The generic system will have targets for many language
  24. ;; types, and create the targets on an as needed basis. All
  25. ;; sub-project types will recycle the same generic target types.
  26. ;;
  27. ;; The generic target types will only be implemented for languages
  28. ;; where having EDE support actually matters, with a single MISC to
  29. ;; represent anything else.
  30. ;;
  31. ;; TOO MANY PROJECTS DETECTED:
  32. ;;
  33. ;; If enabling ede-generic support starts identifying too many
  34. ;; projects, drop a file called `.ede-ignore' into any directory where
  35. ;; you do not want a project to be.
  36. ;;
  37. ;; Customization:
  38. ;;
  39. ;; Since these projects are all so incredibly generic, a user will
  40. ;; need to configure some aspects of the project by hand. In order to
  41. ;; enable this without configuring the project objects directly (which
  42. ;; are auto-generated) a special ede-generic-config object is defined to
  43. ;; hold the basics. Generic projects will identify and use these
  44. ;; config files.
  45. ;;
  46. ;; Adding support for new projects:
  47. ;;
  48. ;; To add support to EDE Generic for new project types is very quick.
  49. ;; See the end of this file for examples such as CMake and SCons.
  50. ;;
  51. ;; Support consists of one class for your project, specifying the file
  52. ;; name used by the project system you want to support. It also
  53. ;; should implement th method `ede-generic-setup-configuration' to
  54. ;; prepopulate the configurable portion of the generic project with
  55. ;; build details.
  56. ;;
  57. ;; Lastly, call `ede-generic-new-autoloader' to setup your project so
  58. ;; EDE can use it.
  59. ;;
  60. ;; Adding support for new types of source code:
  61. ;;
  62. ;; Sources of different types are supported with a simple class which
  63. ;; subclasses `ede-generic-target'. The slots `shortname' and
  64. ;; `extension' should be given new initial values.
  65. ;;
  66. ;; Optionally, any target method used by EDE can then be overridden.
  67. ;; The ede-generic-target-c-cpp has some example methods setting up
  68. ;; the pre-processor map and system include path.
  69. ;;
  70. ;; NOTE: It is not necessary to modify ede/generic.el to add any of
  71. ;; the above described support features.
  72. (require 'eieio-opt)
  73. (require 'ede/config)
  74. (require 'ede/shell)
  75. (require 'semantic/db)
  76. ;;; Code:
  77. ;;
  78. ;; Start with the configuration system
  79. (defclass ede-generic-config (ede-extra-config
  80. ede-extra-config-build
  81. ede-extra-config-program
  82. ede-extra-config-c)
  83. ((file-header-line :initform ";; EDE Generic Project Configuration")
  84. )
  85. "User Configuration object for a generic project.")
  86. (defun ede-generic-load (dir &optional rootproj)
  87. "Return a Generic Project object if there is a match.
  88. Return nil if there isn't one.
  89. Argument DIR is the directory it is created for.
  90. ROOTPROJ is nil, since there is only one project."
  91. ;; Doesn't already exist, so let's make one.
  92. (let* ((alobj ede-constructing))
  93. (when (not alobj) (error "Cannot load generic project without the autoload instance"))
  94. ;;;
  95. ;; TODO - find the root dir.
  96. (let ((rootdir dir))
  97. (funcall (oref alobj class-sym)
  98. (symbol-name (oref alobj class-sym))
  99. :name (file-name-nondirectory (directory-file-name dir))
  100. :version "1.0"
  101. :directory (file-name-as-directory rootdir)
  102. :file (expand-file-name (oref alobj proj-file)
  103. rootdir)))
  104. ))
  105. ;;; Base Classes for the system
  106. (defclass ede-generic-target (ede-target-with-config
  107. ede-target-with-config-build
  108. ede-target-with-config-program)
  109. ((shortname :initform ""
  110. :type string
  111. :allocation :class
  112. :documentation
  113. "Something prepended to the target name.")
  114. (extension :initform ""
  115. :type string
  116. :allocation :class
  117. :documentation
  118. "Regular expression representing the extension used for this target.
  119. subclasses of this base target will override the default value.")
  120. )
  121. "Baseclass for all targets belonging to the generic ede system."
  122. :abstract t)
  123. (defclass ede-generic-project (ede-project-with-config
  124. ede-project-with-config-build
  125. ede-project-with-config-program
  126. ede-project-with-config-c
  127. ede-project-with-config-java)
  128. ((config-class :initform ede-generic-config)
  129. (config-file-basename :initform "EDEConfig.el")
  130. (buildfile :initform ""
  131. :type string
  132. :allocation :class
  133. :documentation "The file name that identifies a project of this type.
  134. The class allocated value is replace by different sub classes.")
  135. )
  136. "The baseclass for all generic EDE project types."
  137. :abstract t)
  138. (cl-defmethod initialize-instance ((this ede-generic-project)
  139. &rest fields)
  140. "Make sure the targets slot is bound."
  141. (cl-call-next-method)
  142. (unless (slot-boundp this 'targets)
  143. (oset this :targets nil))
  144. )
  145. (cl-defmethod ede-project-root ((this ede-generic-project))
  146. "Return my root."
  147. this)
  148. (cl-defmethod ede-find-subproject-for-directory ((proj ede-generic-project)
  149. dir)
  150. "Return PROJ, for handling all subdirs below DIR."
  151. proj)
  152. ;;; A list of different targets
  153. (defclass ede-generic-target-c-cpp (ede-generic-target
  154. ede-target-with-config-c)
  155. ((shortname :initform "C/C++")
  156. (extension :initform "\\([ch]\\(pp\\|xx\\|\\+\\+\\)?\\|cc\\|hh\\|CC?\\)"))
  157. "EDE Generic Project target for C and C++ code.
  158. All directories need at least one target.")
  159. (defclass ede-generic-target-el (ede-generic-target)
  160. ((shortname :initform "ELisp")
  161. (extension :initform "el"))
  162. "EDE Generic Project target for Emacs Lisp code.
  163. All directories need at least one target.")
  164. (defclass ede-generic-target-fortran (ede-generic-target)
  165. ((shortname :initform "Fortran")
  166. (extension :initform "[fF]9[05]\\|[fF]\\|for"))
  167. "EDE Generic Project target for Fortran code.
  168. All directories need at least one target.")
  169. (defclass ede-generic-target-texi (ede-generic-target)
  170. ((shortname :initform "Texinfo")
  171. (extension :initform "texi"))
  172. "EDE Generic Project target for texinfo code.
  173. All directories need at least one target.")
  174. (defclass ede-generic-target-java (ede-generic-target
  175. ede-target-with-config-java)
  176. ((shortname :initform "Java")
  177. (extension :initform "java"))
  178. "EDE Generic Project target for texinfo code.
  179. All directories need at least one target.")
  180. ;; MISC must always be last since it will always match the file.
  181. (defclass ede-generic-target-misc (ede-generic-target)
  182. ((shortname :initform "Misc")
  183. (extension :initform ""))
  184. "EDE Generic Project target for Misc files.
  185. All directories need at least one target.")
  186. ;;; Automatic target acquisition.
  187. (defun ede-generic-find-matching-target (class dir targets)
  188. "Find a target that is a CLASS and is in DIR in the list of TARGETS."
  189. (let ((match nil))
  190. (dolist (T targets)
  191. (when (and (object-of-class-p T class)
  192. (string= (oref T path) dir))
  193. (setq match T)
  194. ))
  195. match))
  196. (cl-defmethod ede-find-target ((proj ede-generic-project) buffer)
  197. "Find an EDE target in PROJ for BUFFER.
  198. If one doesn't exist, create a new one for this directory."
  199. (let* ((ext (file-name-extension (buffer-file-name buffer)))
  200. (classes (eieio-build-class-alist 'ede-generic-target t))
  201. (cls nil)
  202. (targets (oref proj targets))
  203. (dir default-directory)
  204. (ans nil)
  205. )
  206. ;; Pick a matching class type.
  207. (when ext
  208. (dolist (C classes)
  209. (let* ((classsym (intern (car C)))
  210. (extreg (oref-default classsym extension)))
  211. (when (and (not (string= extreg ""))
  212. (string-match (concat "\\`\\(?:" extreg "\\)\\'") ext))
  213. (setq cls classsym)))))
  214. (when (not cls) (setq cls 'ede-generic-target-misc))
  215. ;; find a pre-existing matching target
  216. (setq ans (ede-generic-find-matching-target cls dir targets))
  217. ;; Create a new instance if there wasn't one
  218. (when (not ans)
  219. (setq ans (make-instance
  220. cls
  221. :name (oref-default cls shortname)
  222. :path dir
  223. :source nil))
  224. (object-add-to-list proj :targets ans)
  225. )
  226. ans))
  227. ;;; Creating Derived Projects:
  228. ;;
  229. ;; Derived projects need an autoloader so that EDE can find the
  230. ;; different projects on disk.
  231. (defun ede-generic-new-autoloader (_internal-name external-name
  232. projectfile class)
  233. "Add a new EDE Autoload instance for identifying a generic project.
  234. INTERNAL-NAME is obsolete and ignored.
  235. EXTERNAL-NAME is a human readable name to describe the project; it
  236. must be unique among all autoloaded projects.
  237. PROJECTFILE is a file name that identifies a project of this type to EDE, such as
  238. a Makefile, or SConstruct file.
  239. CLASS is the EIEIO class that is used to track this project. It should subclass
  240. `ede-generic-project'."
  241. (ede-add-project-autoload
  242. (ede-project-autoload :name external-name
  243. :file 'ede/generic
  244. :proj-file projectfile
  245. :root-only nil
  246. :load-type 'ede-generic-load
  247. :class-sym class
  248. :new-p nil
  249. ;; NOTE: This project type is SAFE because it handles
  250. ;; the user-query before loading its config file. These
  251. ;; project types are useful without the config file so
  252. ;; do the safe part until the user creates a saved config
  253. ;; file for it.
  254. :safe-p t)
  255. ;; Generics must go at the end, since more specific types
  256. ;; can create Makefiles also.
  257. 'generic))
  258. ;;;###autoload
  259. (defun ede-enable-generic-projects ()
  260. "Enable generic project loaders."
  261. (interactive)
  262. (ede-generic-new-autoloader "generic-makefile" "Generic Make"
  263. "Makefile" 'ede-generic-makefile-project)
  264. (ede-generic-new-autoloader "generic-scons" "Generic SCons"
  265. "SConstruct" 'ede-generic-scons-project)
  266. (ede-generic-new-autoloader "generic-cmake" "Generic CMake"
  267. "CMakeLists" 'ede-generic-cmake-project)
  268. ;; Super Generic found via revision control tags.
  269. (ede-generic-new-autoloader "generic-git" "Generic Git"
  270. ".git" 'ede-generic-vc-project)
  271. (ede-generic-new-autoloader "generic-bzr" "Generic Bazaar"
  272. ".bzr" 'ede-generic-vc-project)
  273. (ede-generic-new-autoloader "generic-hg" "Generic Mercurial"
  274. ".hg" 'ede-generic-vc-project)
  275. (ede-generic-new-autoloader "generic-svn" "Generic Subversions"
  276. ".svn" 'ede-generic-vc-project)
  277. (ede-generic-new-autoloader "generic-cvs" "Generic CVS"
  278. "CVS" 'ede-generic-vc-project)
  279. (ede-generic-new-autoloader "generic-mtn" "Generic Monotone"
  280. "_MTN" 'ede-generic-vc-project)
  281. ;; Take advantage of existing 'projectile' based projects.
  282. ;; @TODO - if projectile supports compile commands etc, can we
  283. ;; read that out? Howto if projectile is not part of core emacs.
  284. (ede-generic-new-autoloader "generic-projectile" "Generic .projectile"
  285. ".projectile" 'ede-generic-vc-project)
  286. )
  287. ;;; SPECIFIC TYPES OF GENERIC BUILDS
  288. ;;
  289. ;;; MAKEFILE
  290. (defclass ede-generic-makefile-project (ede-generic-project)
  291. ((buildfile :initform "Makefile")
  292. )
  293. "Generic Project for makefiles.")
  294. (cl-defmethod ede-generic-setup-configuration ((proj ede-generic-makefile-project) config)
  295. "Setup a configuration for Make."
  296. (oset config build-command "make -k")
  297. (oset config debug-command "gdb ")
  298. )
  299. ;;; SCONS
  300. (defclass ede-generic-scons-project (ede-generic-project)
  301. ((buildfile :initform "SConstruct")
  302. )
  303. "Generic Project for scons.")
  304. (cl-defmethod ede-generic-setup-configuration ((proj ede-generic-scons-project) config)
  305. "Setup a configuration for SCONS."
  306. (oset config build-command "scons")
  307. (oset config debug-command "gdb ")
  308. )
  309. ;;; CMAKE
  310. (defclass ede-generic-cmake-project (ede-generic-project)
  311. ((buildfile :initform "CMakeLists")
  312. )
  313. "Generic Project for cmake.")
  314. (cl-defmethod ede-generic-setup-configuration ((proj ede-generic-cmake-project) config)
  315. "Setup a configuration for CMake."
  316. (oset config build-command "cmake")
  317. (oset config debug-command "gdb ")
  318. )
  319. ;;; Generic Version Control System
  320. (defclass ede-generic-vc-project (ede-generic-project)
  321. ()
  322. "Generic project found via Version Control files.")
  323. (cl-defmethod ede-generic-setup-configuration ((proj ede-generic-vc-project) config)
  324. "Setup a configuration for projects identified by revision control."
  325. )
  326. (provide 'ede/generic)
  327. ;; Local variables:
  328. ;; generated-autoload-file: "loaddefs.el"
  329. ;; generated-autoload-load-name: "ede/generic"
  330. ;; End:
  331. ;;; ede/generic.el ends here