Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Customizable API for setting debug target #31

Open
mohkale opened this issue Dec 2, 2023 · 7 comments
Open

Customizable API for setting debug target #31

mohkale opened this issue Dec 2, 2023 · 7 comments

Comments

@mohkale
Copy link

mohkale commented Dec 2, 2023

Hi there,

Thanks for this wonderful package. I've been wanting a DAP client in Emacs that isn't lsp-mode dependent 😎.

One other thing I've been wanting for a while is a way to debug individual build targets easily. For example in a C++ project using CMake you can setup multiple test binaries as possible targets and run them through CMake directly. I'm the maintainer of an Emacs package called projection and because projection interfaces with CMake I can expose something to read available test targets from it.

Currently it looks like dap just asks you which executable you want to debug with find-file. What are your thoughts about a more customizable interface for this that can plug in build system related metadata my projection package can provide.

Originally I was thinking a hook and I can just prefix a projection-executable-target command to it and you keep calling functions in the hook until it returns a non-nil variable. But I'm not sure how flexible that would be with the different requirements of each debugger. go-delve for example seems to accept a package argument instead of an executable. Maybe the hooks should be tailored based on the kind of target the dap client requires so it should be an alist 🤔. What are youur thoughts?

@svaante
Copy link
Owner

svaante commented Dec 6, 2023

Sounds interesting!

I don't really grok, maybe I am a bit slow.

Could you help me out with what your dream API would look like!

Is it something like(defun dape-start-debug (language binary) ...)?

@mohkale
Copy link
Author

mohkale commented Dec 31, 2023

Hi there,

Sorry for taking so long to get back to you. I wanted to experiment a bit and then propose something. I've added a new projection-artifacts-read-debug-targets function which can source available programs for debugging from (currently just) a projects go modules or a CMake projects CMake and CTest metadata.

Screenshot_20231231_153222

Screenshot_20231231_153302

Now by default this function just matches all possible project types for the current project, queries debug targets and then gives you back an alist of properties for that target. For a CTest target it gives back:

((name . "projection-demo-test")
 (category . "CTest")
 (arg0 .
       "/home/mohkale/Develop/repos/projection-demo/build/tests/Debug/projection-demo-test")
 (argv "foobar")
 (type . executable)
 (debuggable . t)
 (working-directory . "/home/mohkale/Develop/repos/projection-demo/build/tests")
 (environment ("FOO" . "1")))

For a golang project it gives back:

((name . "cmd/guru")
 (type . go-package)
 (category . "Go package")
 (go-package . "golang.org/x/tools/cmd/guru")
 (debuggable . t))

Some of these properties are just internal but the common theme is a name and a type. Then based on that type different options for the target which I think you could map to an appropriate debugger and then invoke. What do you think about this? A function which returns an alist is as simple as it gets and you can call this, use the type to narrow down a series of debuggers, then if there's multiple interactively ask the user to select one of those as well. So rather than going from debugger -> debug target, we go from debug target -> debugger. I think that would be a nicer interface than asking for a debugger and then asking what to debug because it presents you all possible targets upfront. Thoughts?

@mohkale
Copy link
Author

mohkale commented Dec 31, 2023

I've written a rudimentary projection-dape+ wrapper command that reads a debug target of the form I've defined and then converts the alist into the plist style format dape expects. I'm having some issues figuring out how to the interpret the environment-variable setting but everything else seems to work as expected. I can load a project, compile, start a debugger for a specific target, then set breakpoints from my editor. Kick ass 🥳.

(use-package projection
  :commands projection-dape+
  :config
  (defun projection-dape--run-debugger+ (config)
    (thread-last
      (thread-first
        (let-alist config
          ;; TODO: Support .environment property for debug invocation.
          (pcase .type
            ('executable
             `(lldb-vscode ,@(when .working-directory
                               (list :cwd .working-directory))
                           :program ,.arg0
                           ,@(when .argv
                               (list :command-args (apply #'vector .argv)))))
            ('go-package `(dlv :program .go-package))
            (_ (error "Don't know how to derive debugger config from %S" config))))
        (prin1-to-string)
        (substring 1 -1)
        (dape--config-from-string))
      (apply 'dape--config-eval)
      (dape)))

  (defun projection-dape+ (debug-target)
    (interactive (list (projection-artifacts-read-debug-targets)))
    (projection-dape--run-debugger+ debug-target))

  :leader
  ("lv" 'projection-dape+
   "vv" 'projection-dape+))

I'll refine this a little more and maybe turn into an extension package for projection itself.

@svaante
Copy link
Owner

svaante commented Jan 15, 2024

Looks pretty sweet. No need tho to convert from config to string (if not something has changed on master that I can't remember). Maybe it would be good to mark `dape-config-eval' as an stable api.

(defun projection-dape--run-debugger+ (config)
  (let-alist config
    ;; TODO: Support .environment property for debug invocation.
    (dape (pcase .type
            ('executable
             (dape--config-eval 'lldb-vscode
                                (append (list :program .arg0)
                                        (when .working-directory
                                          (list :cwd .working-directory))
                                        (when .argv
                                          (list :args (apply #'vector .argv))))))
            (_ (error "Don't know how to derive debugger config from %S" config))))))

(projection-dape--run-debugger+ '((type . executable)
                                  (arg0 . "/Users/dpettersson/Workspace/c_test/a.out")))

For both go and lldb environment is passed in as an plist (:MY_ENV_1 "MY_ENV_VAL_1")etc.

@1925381584
Copy link

Hi,there
i like this package too. Thanks for your job.
I think target -> debugger. is better than debugger->target when debug Scripts like Python.
I hope there is an option that can achieve debugging from the current file by default, similar to vscode

@svaante
Copy link
Owner

svaante commented Feb 3, 2024

@1925381584 I am not sure I follow, the default configuration is to debug the current buffer and I don't understand what target -> debugger means? Are you referencing that you need to write debugpy :program "main.py" instead of :program "main.py" debugpy?

@1925381584
Copy link

I mean when I open a file like 1.py, then I call dape, Just start debugging 1.py directly, instead of going to the run adapter panel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants