I often run Gdb in a dedicated Emacs session. I have code to run gdb when Emacs start and set up Many-Windows mode.
For one particular project, there are many programs, all written in C, that share a main()
function but where the interesting part is in a separate source file whose base name is the same as the executable: hello
is built from hello.c
and main.c
, foo
is built from foo.c
and main.c
, etc. Gdb sees the main()
function in main.c
and therefore opens main.c
initially, which makes perfect sense. But for this project, main.c
is mostly irrelevant and I want to start with the program-specific source file open, e.g. hello.c
.
I want to either instruct Gdb to consider a different file to be the “main” source, or instruct Emacs to display a different source file initially.
I wrote the code below to instruct Emacs to display a different source file. It doesn't work, and I don't understand why.
;; Specific code for my project, where the main() function is in a boring
;; file that is shared between many executables and the interesting source
;; file is the one based on the executable name.
;; The code here is simplified from my real code and only works if all the
;; files are in the current directory.
(defvar actual-source-file (concat default-directory "/"
(car command-line-args-left) ".c"))
(defun visit-actual-source ()
(interactive)
(gdb-display-source-buffer (find-file-noselect actual-source-file)))
(add-hook 'window-setup-hook 'visit-actual-source)
;; Don't ask for confirmation on exit even if a process is running.
;; This doesn't have any impact on the question, but makes testing easier.
(defun clear-buffer-process-query-on-exit-flag ()
(let ((proc (get-buffer-process (current-buffer))))
(if proc
(set-process-query-on-exit-flag proc nil))))
(defun clear-gdb-inferior-process-query-on-exit-flag ()
(if (equal (process-name (get-buffer-process (current-buffer))) "gdb-inferior")
(clear-buffer-process-query-on-exit-flag)))
(add-hook 'comint-exec-hook 'clear-gdb-inferior-process-query-on-exit-flag)
(defadvice gud-common-init
(after gud-common-init-set-process-query-on-exit-flag activate)
"Don't ask for confirmation if exiting Emacs during the debug session."
(clear-buffer-process-query-on-exit-flag))
;; Run gdb.
(let ((command-string (combine-and-quote-strings command-line-args-left)))
(set-frame-name (concat "gdb: " command-string))
(gdb (concat "gdb -i=mi --args " command-string)))
(setq command-line-args-left nil)
;; Set up a nice window configuration.
(gdb-many-windows)
Set up a test environment:
cat <<'EOF' >main.c
void do_stuff(void);
int main() {
do_stuff();
return 0;
}
EOF
cat <<'EOF' >hello.c
#include <stdio.h>
void do_stuff(void) {
puts("Hello world");
}
EOF
cc -g -o hello hello.c main.c
Then run Emacs with the Lisp code above in gdb-alternate-source.el
.
emacs -q -l gdb-alternate-source.el hello
Desired effect: display the 6 windows of Gdb Many-Windows mode, with hello.c
in the middle left window.
Actual effect: display the 6 windows of Gdb Many-Windows mode, with main.c
in the middle left window. hello.c
is open but not displayed.
If I run M-x visit-actual-source
after Emacs starts, it has the desired effect: hello.c
becomes displayed instead of main.c
.
If I add (recursive-edit)
after (gdb-many-windows)
or before the call to gdb-display-source-buffer
in visit-actual-source
, then after I exit the recursive edit, hello.c
replaces main.c
in the middle left window and *GNU Emacs*
(“Welcome to GNU Emacs …”) replaces *gud-hello*
in the top left window. On the other hand, adding (force-window-update)
or (redisplay)
doesn't make any difference.
I guess I need to add some code to update something related to the window configuration, but what? How do I get the desired file displayed automatically when Emacs starts?