Commit | Line | Data |
---|---|---|
acc33231 CY |
1 | ;;; ede/cpp-root.el --- A simple way to wrap a C++ project with a single root |
2 | ||
49f70d46 | 3 | ;; Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. |
acc33231 CY |
4 | |
5 | ;; Author: Eric M. Ludlam <eric@siege-engine.com> | |
6 | ||
7 | ;; This file is part of GNU Emacs. | |
8 | ||
9 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
10 | ;; it under the terms of the GNU General Public License as published by | |
11 | ;; the Free Software Foundation, either version 3 of the License, or | |
12 | ;; (at your option) any later version. | |
13 | ||
14 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | ;; GNU General Public License for more details. | |
18 | ||
19 | ;; You should have received a copy of the GNU General Public License | |
20 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
21 | ||
22 | ;;; Commentary: | |
23 | ;; | |
24 | ;; NOTE: ede-cpp-root.el has been commented so as to also make it | |
25 | ;; useful for learning how to make similar project types. | |
26 | ;; | |
27 | ;; Not everyone can use automake, or an EDE project type. For | |
28 | ;; pre-existing code, it is often helpful jut to be able to wrap the | |
29 | ;; whole thing up in as simple a way as possible. | |
30 | ;; | |
31 | ;; The cpp-root project type will allow you to create a single object | |
32 | ;; with no save-file in your .emacs file that will be recognized, and | |
a785b776 | 33 | ;; provide a way to easily allow EDE to provide Semantic with the |
acc33231 CY |
34 | ;; ability to find header files, and other various source files |
35 | ;; quickly. | |
36 | ;; | |
37 | ;; The cpp-root class knows a few things about C++ projects, such as | |
38 | ;; the prevalence of "include" directories, and typical file-layout | |
39 | ;; stuff. If this isn't sufficient, you can subclass | |
40 | ;; `ede-cpp-root-project' and add your own tweaks in just a few lines. | |
41 | ;; See the end of this file for an example. | |
42 | ;; | |
43 | ;;; EXAMPLE | |
44 | ;; | |
a785b776 | 45 | ;; Add this to your .emacs file, modifying appropriate bits as needed. |
acc33231 CY |
46 | ;; |
47 | ;; (ede-cpp-root-project "SOMENAME" :file "/dir/to/some/file") | |
48 | ;; | |
49 | ;; Replace SOMENAME with whatever name you want, and the filename to | |
50 | ;; an actual file at the root of your project. It might be a | |
51 | ;; Makefile, a README file. Whatever. It doesn't matter. It's just | |
52 | ;; a key to hang the rest of EDE off of. | |
53 | ;; | |
54 | ;; The most likely reason to create this project, is to help make | |
55 | ;; finding files within the project faster. In conjunction with | |
56 | ;; Semantic completion, having a short include path is key. You can | |
57 | ;; override the include path like this: | |
58 | ;; | |
59 | ;; (ede-cpp-root-project "NAME" :file "FILENAME" | |
60 | ;; :include-path '( "/include" "../include" "/c/include" ) | |
61 | ;; :system-include-path '( "/usr/include/c++/3.2.2/" ) | |
62 | ;; :spp-table '( ("MOOSE" . "") | |
63 | ;; ("CONST" . "const") ) | |
64 | ;; :spp-files '( "include/config.h" ) | |
65 | ;; ) | |
66 | ;; | |
67 | ;; In this case each item in the include path list is searched. If | |
68 | ;; the directory starts with "/", then that expands to the project | |
69 | ;; root directory. If a directory does not start with "/", then it | |
70 | ;; is relative to the default-directory of the current buffer when | |
71 | ;; the file name is expanded. | |
72 | ;; | |
73 | ;; The include path only affects C/C++ header files. Use the slot | |
74 | ;; :header-match-regexp to change it. | |
75 | ;; | |
76 | ;; The :system-include-path allows you to specify full directory | |
77 | ;; names to include directories where system header files can be | |
78 | ;; found. These will be applied to files in this project only. | |
79 | ;; | |
80 | ;; The :spp-table provides a list of project specific #define style | |
81 | ;; macros that are unique to this project, passed in to the compiler | |
82 | ;; on the command line, or are in special headers. | |
83 | ;; | |
84 | ;; The :spp-files option is like :spp-table, except you can provide a | |
85 | ;; file name for a header in your project where most of your CPP | |
86 | ;; macros reside. Doing this can be easier than listing everything in | |
87 | ;; the :spp-table option. The files listed in :spp-files should not | |
88 | ;; start with a /, and are relative to something in :include-path.;; | |
89 | ;; | |
90 | ;; If you want to override the file-finding tool with your own | |
91 | ;; function you can do this: | |
92 | ;; | |
93 | ;; (ede-cpp-root-project "NAME" :file "FILENAME" :locate-fcn 'MYFCN) | |
94 | ;; | |
95 | ;; Where FILENAME is a file in the root directory of the project. | |
96 | ;; Where MYFCN is a symbol for a function. See: | |
97 | ;; | |
98 | ;; M-x describe-class RET ede-cpp-root-project RET | |
99 | ;; | |
100 | ;; for documentation about the locate-fcn extension. | |
101 | ;; | |
102 | ;;; ADVANCED EXAMPLE | |
103 | ;; | |
104 | ;; If the cpp-root project style is right for you, but you want a | |
105 | ;; dynamic loader, instead of hard-coding values in your .emacs, you | |
106 | ;; can do that too, but you will need to write some lisp code. | |
107 | ;; | |
108 | ;; To do that, you need to add an entry to the | |
109 | ;; `ede-project-class-files' list, and also provide two functions to | |
110 | ;; teach EDE how to load your project pattern | |
111 | ;; | |
a785b776 | 112 | ;; It would look like this: |
acc33231 CY |
113 | ;; |
114 | ;; (defun MY-FILE-FOR-DIR (&optional dir) | |
115 | ;; "Return a full file name to the project file stored in DIR." | |
116 | ;; <write your code here, or return nil> | |
117 | ;; ) | |
118 | ;; | |
119 | ;; (defun MY-ROOT-FCN () | |
120 | ;; "Return the root directory for `default-directory'" | |
121 | ;; ;; You might be able to use `ede-cpp-root-project-root'. | |
122 | ;; ) | |
123 | ;; | |
124 | ;; (defun MY-LOAD (dir) | |
125 | ;; "Load a project of type `cpp-root' for the directory DIR. | |
126 | ;; Return nil if there isn't one." | |
127 | ;; (ede-cpp-root-project "NAME" :file (expand-file-name "FILE" dir) | |
128 | ;; :locate-fcn 'MYFCN) | |
129 | ;; ) | |
130 | ;; | |
131 | ;; (add-to-list 'ede-project-class-files | |
132 | ;; (ede-project-autoload "cpp-root" | |
133 | ;; :name "CPP ROOT" | |
b93e37e5 | 134 | ;; :file 'ede/cpp-root |
acc33231 CY |
135 | ;; :proj-file 'MY-FILE-FOR-DIR |
136 | ;; :proj-root 'MY-ROOT-FCN | |
137 | ;; :load-type 'MY-LOAD | |
138 | ;; :class-sym 'ede-cpp-root) | |
139 | ;; t) | |
140 | ;; | |
141 | ;;; TODO | |
142 | ;; | |
143 | ;; Need a way to reconfigure a project, and have it affect all open buffers. | |
144 | ;; From Tobias Gerdin: | |
145 | ;; | |
146 | ;; >>3) Is there any way to refresh a ede-cpp-root-project dynamically? I have | |
147 | ;; >>some file open part of the project, fiddle with the include paths and would | |
148 | ;; >>like the open buffer to notice this when I re-evaluate the | |
149 | ;; >>ede-cpp-root-project constructor. | |
150 | ;; > | |
151 | ;; > Another good idea. The easy way is to "revert-buffer" as needed. The | |
152 | ;; > ede "project local variables" does this already, so it should be easy | |
153 | ;; > to adapt something. | |
154 | ;; | |
155 | ;; I actually tried reverting the buffer but Semantic did not seem to pick | |
156 | ;; up the differences (the "include summary" reported the same include paths). | |
157 | ||
158 | (require 'ede) | |
159 | ||
160 | (defvar semantic-lex-spp-project-macro-symbol-obarray) | |
161 | (declare-function semantic-lex-make-spp-table "semantic/lex-spp") | |
162 | (declare-function semanticdb-file-table-object "semantic/db") | |
163 | (declare-function semanticdb-needs-refresh-p "semantic/db") | |
164 | (declare-function semanticdb-refresh-table "semantic/db") | |
165 | ||
166 | ;;; Code: | |
167 | ||
168 | ;;; PROJECT CACHE: | |
169 | ;; | |
170 | ;; cpp-root projects are created in a .emacs or other config file, but | |
171 | ;; there still needs to be a way for a particular file to be | |
172 | ;; identified against it. The cache is where we look to map a file | |
173 | ;; against a project. | |
174 | ;; | |
175 | ;; Setting up a simple in-memory cache of active projects allows the | |
176 | ;; user to re-load their configuration file several times without | |
177 | ;; messing up the active project set. | |
178 | ;; | |
179 | (defvar ede-cpp-root-project-list nil | |
180 | "List of projects created by option `ede-cpp-root-project'.") | |
181 | ||
182 | (defun ede-cpp-root-file-existing (dir) | |
183 | "Find a cpp-root project in the list of cpp-root projects. | |
184 | DIR is the directory to search from." | |
185 | (let ((projs ede-cpp-root-project-list) | |
186 | (ans nil)) | |
187 | (while (and projs (not ans)) | |
188 | (let ((root (ede-project-root-directory (car projs)))) | |
189 | (when (string-match (concat "^" (regexp-quote root)) dir) | |
190 | (setq ans (car projs)))) | |
191 | (setq projs (cdr projs))) | |
192 | ans)) | |
193 | ||
194 | ;;; PROJECT AUTOLOAD CONFIG | |
195 | ;; | |
196 | ;; Each project type registers itself into the project-class list. | |
197 | ;; This way, each time a file is loaded, EDE can map that file to a | |
198 | ;; project. This project type checks files against the internal cache | |
199 | ;; of projects created by the user. | |
200 | ;; | |
201 | ;; EDE asks two kinds of questions. One is, does this DIR belong to a | |
202 | ;; project. If it does, it then asks, what is the ROOT directory to | |
203 | ;; the project in DIR. This is easy for cpp-root projects, but more | |
204 | ;; complex for multiply nested projects. | |
205 | ;; | |
206 | ;; If EDE finds out that a project exists for DIR, it then loads that | |
207 | ;; project. The LOAD routine can either create a new project object | |
208 | ;; (if it needs to load it off disk) or more likely can return an | |
209 | ;; existing object for the discovered directory. cpp-root always uses | |
210 | ;; the second case. | |
211 | ||
212 | (defun ede-cpp-root-project-file-for-dir (&optional dir) | |
213 | "Return a full file name to the project file stored in DIR." | |
214 | (let ((proj (ede-cpp-root-file-existing dir))) | |
215 | (when proj (oref proj :file)))) | |
216 | ||
217 | (defvar ede-cpp-root-count 0 | |
218 | "Count number of hits to the cpp root thing. | |
219 | This is a debugging variable to test various optimizations in file | |
220 | lookup in the main EDE logic.") | |
221 | ||
222 | ;;;###autoload | |
223 | (defun ede-cpp-root-project-root (&optional dir) | |
224 | "Get the root directory for DIR." | |
225 | (let ((projfile (ede-cpp-root-project-file-for-dir | |
226 | (or dir default-directory)))) | |
227 | (setq ede-cpp-root-count (1+ ede-cpp-root-count)) | |
228 | ;(debug) | |
229 | (when projfile | |
230 | (file-name-directory projfile)))) | |
231 | ||
232 | (defun ede-cpp-root-load (dir &optional rootproj) | |
233 | "Return a CPP root object if you created one. | |
234 | Return nil if there isn't one. | |
235 | Argument DIR is the directory it is created for. | |
236 | ROOTPROJ is nil, since there is only one project." | |
237 | ;; Snoop through our master list. | |
238 | (ede-cpp-root-file-existing dir)) | |
239 | ||
cb85c0d8 EL |
240 | ;;;###autoload |
241 | (add-to-list 'ede-project-class-files | |
242 | (ede-project-autoload "cpp-root" | |
243 | :name "CPP ROOT" | |
b93e37e5 | 244 | :file 'ede/cpp-root |
cb85c0d8 EL |
245 | :proj-file 'ede-cpp-root-project-file-for-dir |
246 | :proj-root 'ede-cpp-root-project-root | |
247 | :load-type 'ede-cpp-root-load | |
248 | :class-sym 'ede-cpp-root | |
249 | :new-p nil) | |
250 | t) | |
251 | ||
acc33231 CY |
252 | ;;; CLASSES |
253 | ;; | |
254 | ;; EDE sets up projects with two kinds of objects. | |
255 | ;; | |
256 | ;; The PROJECT is a class that represents everything under a directory | |
257 | ;; hierarchy. A TARGET represents a subset of files within a project. | |
258 | ;; A project can have multiple targets, and multiple sub-projects. | |
259 | ;; Sub projects should map to sub-directories. | |
260 | ;; | |
261 | ;; The CPP-ROOT project maps any file in C or C++ mode to a target for | |
262 | ;; C files. | |
263 | ;; | |
264 | ;; When creating a custom project the project developer an opportunity | |
265 | ;; to run code to setup various tools whenever an associated buffer is | |
266 | ;; loaded. The CPP-ROOT project spends most of its time setting up C | |
267 | ;; level include paths, and PreProcessor macro tables. | |
268 | ||
269 | (defclass ede-cpp-root-target (ede-target) | |
270 | () | |
271 | "EDE cpp-root project target. | |
272 | All directories need at least one target.") | |
273 | ||
274 | (defclass ede-cpp-root-project (ede-project eieio-instance-tracker) | |
275 | ((tracking-symbol :initform 'ede-cpp-root-project-list) | |
276 | (include-path :initarg :include-path | |
277 | :initform '( "/include" "../include/" ) | |
278 | :type list | |
279 | :documentation | |
280 | "The default locate function expands filenames within a project. | |
281 | If a header file (.h, .hh, etc) name is expanded, and | |
282 | the :locate-fcn slot is nil, then the include path is checked | |
283 | first, and other directories are ignored. For very large | |
284 | projects, this optimization can save a lot of time. | |
285 | ||
286 | Directory names in the path can be relative to the current | |
287 | buffer's `default-directory' (not starting with a /). Directories | |
288 | that are relative to the project's root should start with a /, such | |
289 | as \"/include\", meaning the directory `include' off the project root | |
290 | directory.") | |
291 | (system-include-path :initarg :system-include-path | |
292 | :initform nil | |
293 | :type list | |
294 | :documentation | |
295 | "The system include path for files in this project. | |
296 | C files initialized in an ede-cpp-root-project have their semantic | |
297 | system include path set to this value. If this is nil, then the | |
298 | semantic path is not modified.") | |
299 | (spp-table :initarg :spp-table | |
300 | :initform nil | |
301 | :type list | |
302 | :documentation | |
303 | "C Preprocessor macros for your files. | |
304 | Preprocessor symbols will be used while parsing your files. | |
305 | These macros might be passed in through the command line compiler, or | |
306 | are critical symbols derived from header files. Providing header files | |
307 | macro values through this slot improves accuracy and performance. | |
308 | Use `:spp-files' to use these files directly.") | |
309 | (spp-files :initarg :spp-files | |
310 | :initform nil | |
311 | :type list | |
312 | :documentation | |
313 | "C header file with Preprocessor macros for your files. | |
314 | The PreProcessor symbols appearing in these files will be used while | |
315 | parsing files in this project. | |
316 | See `semantic-lex-c-preprocessor-symbol-map' for more on how this works.") | |
317 | (header-match-regexp :initarg :header-match-regexp | |
318 | :initform | |
319 | "\\.\\(h\\(h\\|xx\\|pp\\|\\+\\+\\)?\\|H\\)$\\|\\<\\w+$" | |
320 | :type string | |
321 | :documentation | |
322 | "Regexp used to identify C/C++ header files.") | |
323 | (locate-fcn :initarg :locate-fcn | |
324 | :initform nil | |
325 | :type (or null function) | |
326 | :documentation | |
327 | "The locate function can be used in place of | |
328 | `ede-expand-filename' so you can quickly customize your custom target | |
329 | to use specialized local routines instead of the EDE routines. | |
330 | The function symbol must take two arguments: | |
331 | NAME - The name of the file to find. | |
332 | DIR - The directory root for this cpp-root project. | |
333 | ||
334 | It should return the fully qualified file name passed in from NAME. If that file does not | |
335 | exist, it should return nil." | |
336 | ) | |
337 | ) | |
338 | "EDE cpp-root project class. | |
045b9da7 | 339 | Each directory needs a project file to control it.") |
acc33231 CY |
340 | |
341 | ;;; INIT | |
342 | ;; | |
343 | ;; Most projects use `initialize-instance' to do special setup | |
344 | ;; on the object when it is created. In this case, EDE-CPP-ROOT can | |
345 | ;; find previous copies of this project, and make sure that one of the | |
346 | ;; objects is deleted. | |
347 | ||
348 | (defmethod initialize-instance ((this ede-cpp-root-project) | |
349 | &rest fields) | |
350 | "Make sure the :file is fully expanded." | |
351 | ;; Add ourselves to the master list | |
352 | (call-next-method) | |
353 | (let ((f (expand-file-name (oref this :file)))) | |
354 | ;; Remove any previous entries from the main list. | |
355 | (let ((old (eieio-instance-tracker-find (file-name-directory f) | |
356 | :directory 'ede-cpp-root-project-list))) | |
357 | ;; This is safe, because :directory isn't filled in till later. | |
358 | (when (and old (not (eq old this))) | |
359 | (delete-instance old))) | |
360 | ;; Basic initialization. | |
361 | (when (or (not (file-exists-p f)) | |
362 | (file-directory-p f)) | |
363 | (delete-instance this) | |
a785b776 | 364 | (error ":file for ede-cpp-root must be a file")) |
acc33231 CY |
365 | (oset this :file f) |
366 | (oset this :directory (file-name-directory f)) | |
367 | (ede-project-directory-remove-hash (file-name-directory f)) | |
368 | (ede-add-project-to-global-list this) | |
369 | (unless (slot-boundp this 'targets) | |
370 | (oset this :targets nil)) | |
371 | ;; We need to add ourselves to the master list. | |
372 | ;;(setq ede-projects (cons this ede-projects)) | |
373 | )) | |
374 | ||
375 | ;;; SUBPROJ Management. | |
376 | ;; | |
377 | ;; This is a way to allow a subdirectory to point back to the root | |
378 | ;; project, simplifying authoring new single-point projects. | |
379 | ||
380 | (defmethod ede-find-subproject-for-directory ((proj ede-cpp-root-project) | |
381 | dir) | |
382 | "Return PROJ, for handling all subdirs below DIR." | |
383 | proj) | |
384 | ||
385 | ;;; TARGET MANAGEMENT | |
386 | ;; | |
387 | ;; Creating new targets on a per directory basis is a good way to keep | |
388 | ;; files organized. See ede-emacs for an example with multiple file | |
389 | ;; types. | |
390 | (defmethod ede-find-target ((proj ede-cpp-root-project) buffer) | |
391 | "Find an EDE target in PROJ for BUFFER. | |
392 | If one doesn't exist, create a new one for this directory." | |
393 | (let* ((targets (oref proj targets)) | |
394 | (dir default-directory) | |
395 | (ans (object-assoc dir :path targets)) | |
396 | ) | |
397 | (when (not ans) | |
398 | (setq ans (ede-cpp-root-target dir | |
399 | :name (file-name-nondirectory | |
400 | (directory-file-name dir)) | |
401 | :path dir | |
402 | :source nil)) | |
403 | (object-add-to-list proj :targets ans) | |
404 | ) | |
405 | ans)) | |
406 | ||
407 | ;;; FILE NAMES | |
408 | ;; | |
409 | ;; One of the more important jobs of EDE is to find files in a | |
410 | ;; directory structure. cpp-root has tricks it knows about how most C | |
411 | ;; projects are set up with include paths. | |
412 | ;; | |
413 | ;; This tools also uses the ede-locate setup for augmented file name | |
414 | ;; lookup using external tools. | |
415 | (defmethod ede-expand-filename-impl ((proj ede-cpp-root-project) name) | |
416 | "Within this project PROJ, find the file NAME. | |
417 | This knows details about or source tree." | |
418 | ;; The slow part of the original is looping over subprojects. | |
419 | ;; This version has no subprojects, so this will handle some | |
420 | ;; basic cases. | |
421 | (let ((ans (call-next-method))) | |
422 | (unless ans | |
423 | (let* ((lf (oref proj locate-fcn)) | |
424 | (dir (file-name-directory (oref proj file)))) | |
425 | (if lf | |
426 | (setq ans (funcall lf name dir)) | |
427 | (if (ede-cpp-root-header-file-p proj name) | |
428 | ;; Else, use our little hack. | |
429 | (let ((ip (oref proj include-path)) | |
430 | (tmp nil)) | |
431 | (while ip | |
432 | ;; Translate | |
433 | (setq tmp (ede-cpp-root-translate-file proj (car ip))) | |
434 | ;; Test this name. | |
435 | (setq tmp (expand-file-name name tmp)) | |
436 | (if (file-exists-p tmp) | |
437 | (setq ans tmp)) | |
438 | (setq ip (cdr ip)) )) | |
439 | ;; Else, do the usual. | |
440 | (setq ans (call-next-method))) | |
441 | ))) | |
442 | (or ans (call-next-method)))) | |
443 | ||
444 | (defmethod ede-project-root ((this ede-cpp-root-project)) | |
445 | "Return my root." | |
446 | this) | |
447 | ||
448 | (defmethod ede-project-root-directory ((this ede-cpp-root-project)) | |
449 | "Return my root." | |
450 | (file-name-directory (oref this file))) | |
451 | ||
452 | ;;; C/CPP SPECIFIC CODE | |
453 | ;; | |
454 | ;; The following code is specific to setting up header files, | |
455 | ;; include lists, and Preprocessor symbol tables. | |
456 | ||
457 | (defmethod ede-cpp-root-header-file-p ((proj ede-cpp-root-project) name) | |
458 | "Non nil if in PROJ the filename NAME is a header." | |
459 | (save-match-data | |
460 | (string-match (oref proj header-match-regexp) name))) | |
461 | ||
462 | (defmethod ede-cpp-root-translate-file ((proj ede-cpp-root-project) filename) | |
463 | "For PROJ, translate a user specified FILENAME. | |
464 | This is for project include paths and spp source files." | |
465 | ;; Step one: Root of this project. | |
466 | (let ((dir (file-name-directory (oref proj file)))) | |
467 | ||
468 | ;; Step two: Analyze first char, and rehost | |
469 | (if (and (not (string= filename "")) (= (aref filename 0) ?/)) | |
470 | ;; Check relative to root of project | |
471 | (setq filename (expand-file-name (substring filename 1) | |
472 | dir)) | |
473 | ;; Relative to current directory. | |
474 | (setq filename (expand-file-name filename))) | |
475 | ||
476 | filename)) | |
477 | ||
478 | (defmethod ede-set-project-variables ((project ede-cpp-root-project) &optional buffer) | |
479 | "Set variables local to PROJECT in BUFFER. | |
480 | Also set up the lexical preprocessor map." | |
481 | (call-next-method) | |
9b937f37 | 482 | (when (and (featurep 'semantic/bovine/c) (featurep 'semantic/lex-spp)) |
acc33231 CY |
483 | (setq semantic-lex-spp-project-macro-symbol-obarray |
484 | (semantic-lex-make-spp-table (oref project spp-table))) | |
485 | )) | |
486 | ||
487 | (defmethod ede-system-include-path ((this ede-cpp-root-project)) | |
488 | "Get the system include path used by project THIS." | |
489 | (oref this system-include-path)) | |
490 | ||
491 | (defmethod ede-preprocessor-map ((this ede-cpp-root-project)) | |
492 | "Get the pre-processor map for project THIS." | |
493 | (require 'semantic/db) | |
494 | (let ((spp (oref this spp-table)) | |
495 | (root (ede-project-root this)) | |
496 | ) | |
497 | (mapc | |
498 | (lambda (F) | |
499 | (let* ((expfile (ede-expand-filename root F)) | |
500 | (table (when expfile | |
501 | (semanticdb-file-table-object expfile))) | |
502 | ) | |
503 | (when (not table) | |
504 | (message "Cannot find file %s in project." F)) | |
505 | (when (and table (semanticdb-needs-refresh-p table)) | |
e6e267fc CY |
506 | (semanticdb-refresh-table table) |
507 | (setq spp (append spp (oref table lexical-table)))))) | |
acc33231 CY |
508 | (oref this spp-files)) |
509 | spp)) | |
510 | ||
511 | (defmethod ede-system-include-path ((this ede-cpp-root-target)) | |
512 | "Get the system include path used by project THIS." | |
513 | (ede-system-include-path (ede-target-parent this))) | |
514 | ||
515 | (defmethod ede-preprocessor-map ((this ede-cpp-root-target)) | |
516 | "Get the pre-processor map for project THIS." | |
517 | (ede-preprocessor-map (ede-target-parent this))) | |
518 | ||
cb85c0d8 EL |
519 | ;;; Quick Hack |
520 | (defun ede-create-lots-of-projects-under-dir (dir projfile &rest attributes) | |
521 | "Create a bunch of projects under directory DIR. | |
522 | PROJFILE is a file name sans directory that indicates a subdirectory | |
523 | is a project directory. | |
524 | Generic ATTRIBUTES, such as :include-path can be added. | |
525 | Note: This needs some work." | |
526 | (let ((files (directory-files dir t))) | |
527 | (dolist (F files) | |
528 | (if (file-exists-p (expand-file-name projfile F)) | |
529 | `(ede-cpp-root-project (file-name-nondirectory F) | |
530 | :name (file-name-nondirectory F) | |
531 | :file (expand-file-name projfile F) | |
532 | attributes))))) | |
533 | ||
acc33231 CY |
534 | (provide 'ede/cpp-root) |
535 | ||
536 | ;; Local variables: | |
537 | ;; generated-autoload-file: "loaddefs.el" | |
acc33231 CY |
538 | ;; generated-autoload-load-name: "ede/cpp-root" |
539 | ;; End: | |
540 | ||
3999968a | 541 | ;; arch-tag: c3ac8160-cba6-447e-8b9c-accb7e2d942e |
acc33231 | 542 | ;;; ede/cpp-root.el ends here |