Stephen Leake writes:
> Ludovic Brenta writes:
>
>> In the same context as my follow-up post, ada-mode 5.0.1 does not
>> directly support our workflow.  Suppose a developer wants to browse
>> the sources in the baseline (i.e. multiple read-only directories
>> containing the sources and, separately, the .ali files) without
>> creating a working view.  They normally start by find-tag
>> <some_file_or_identifier>; this opens a read-only source file in a
>> read-only directory.  Now they place point on an identifier and do
>> ada-goto-declaration: this does not work.
>
> Have they specified an Emacs Ada mode project file somewhere in there?
> Either a .prj or a .gpr?

Not explicitly; I do it myself by installing a hook in ada-mode-hooks.
This hook generates a .gpr project file in /tmp, which extends the
top-level project file from the baseline.  Then my hook calls
ada-parse-prj-file and ada-select-prj-file.

>> As I found, there are two reasons why it does not work:
>>
>> 1. gnat-run-gnat calls "gnat find -Pproject.gpr" without specifying
>>    the absolute pathname of "project.gpr".
>
> At this point, `default-directory' is supposed to be the directory
> containing the Emacs Ada mode project file. So this should be ok.

Not in my experience; gnat find would not find the project file from its
command line.  Maybe I'd need to add /tmp to the ADA_PROJECT_PATH
environment variable for this to work but I prefer to be explicit,
rather than implicit, on the command line.

>> In my situation, the generated project file is in /tmp, not in the
>> same directory as the source file.
>
> How are you telling Emacs where that project file is?
>
>>    Even in the absence of a generated project file, the top-level
>> project file would most probably not be in the same directory as the
>> visited file, either.
>
> Right, that's expected.
>
>> 2. "gnat find" creates temporary files in $TMPDIR but, if TMPDIR is
>>    unset, it tries to create them in the current, read-only, directory
>>    containing the visited source file.
>
> Ah; you are saying 'default-directory' above is the source directory,
> not /tmp. That's a bug.

I don't actually know the value of 'default-directory' but the current
directory (containing the Ada file visited) is certainly not /tmp.

>> The error reporting and recovery from gnat-run-calls in this case is,
>> unfortunately, not very useful but I don't see how it could be
>> improved without becoming bloated.
>
> Ok.
>
>> The attached patch solves the first problem;
>
> That may work, but it's not the best fix.

I suspected as much, that's why my fix is tentative only.

> Can you investigate why gnat-run-buffer is created with the wrong
> default-directory?
>
> Or give me a recipe for reproducing; how you specify the project file
> in the first place is the critical step.

Reconstructing from memory as I'm no longer at work, it goes something like:

(defun top-level-project-file ()
  "Discovers and returns the first GNAT project file in $ADA_PROJECT_PATH;
in our workflow, this is by construction the top-level system project file."
  (expand-file-name
   (concat (car (parse-colon-path (getenv "ADA_PROJECT_PATH"))) "*.gpr")))

(defun project-from-project-file (project-file-name)
  "Returns the name of a GNAT project contained in the specified file."
  (file-name-nondirectory
   (file-name-sans-extension project-file-name)))

(defun create-and-select-project-file ()
  (let ((file (make-temp-file "project_" nil ".gpr")) ; typically in /tmp
        (top-level-file (top-level-project-file)) ; typically under /cm/ot/...
        (working-view-dir (getenv "CM_VIEW"))) ; typically under $HOME/cm/
    (save-current-buffer
      (let ((name (project-from-project-file file)))
        (set-buffer (find-file-noselect file))
        (insert (concat "project " name " extends \"" top-level-file "\" is\n"))
        (insert (concat "   for Source_Dirs use (\"" working-view-dir "\");\n"))
        (insert (concat "   for Object_Dir use \"" working-view-dir "\";\n"))
        (insert (concat "end " name ";\n"))
        (save-buffer 0)
        (bury-buffer) ; might as well kill the buffer but good for debugging
        (ada-parse-prj-file file)
        (ada-select-prj-file file))))))

(add-hook ada-mode-hooks
          (lambda ()
            (if (not ada-current-project) ; no current project? create one
                (create-and-select-project-file))))

The function create-and-select-project-file runs only once, after the
first Ada file is visited; this file is typically part of the baseline,
somewhere under /cm/ot/....  The working view might or might not exist
yet; we do not require a view to browse the baseline.  The function
creates a GNAT project file under /tmp, parses and selects it as the
current project file.  (We don't switch projects in an emacs session;
when working in multiple views, we use multiple emacsen).

>> setting TMPDIR is outside the scope of ada-mode, I think.
>
> You can set it in an Emacs Ada mode project file;
>
> $TMPDIR=<path>
>
> or in an elisp file referenced from the Emacs Ada mode file:
>
> el_file=foo.el
>
> in foo.el:
>
> (setenv "TMPDIR" "path")

That's the way I do it: in the file, called from ~/.emacs, that installs
the hook.

Thanks!

-- 
Ludovic Brenta.

_______________________________________________
Emacs-ada-mode mailing list
[email protected]
http://host114.hostmonster.com/mailman/listinfo/emacs-ada-mode_stephe-leake.org

Reply via email to