Skip to content

Commit 3586d73

Browse files
committed
New post: debugging golang app on a fedora atomic desktop
1 parent 7a030fa commit 3586d73

File tree

1 file changed

+202
-0
lines changed

1 file changed

+202
-0
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
---
2+
title: Debuging a Golang project on a Fedora Atomic Desktop (with Emacs and Dape)
3+
---
4+
A couple months ago, I tried to get [Dape](https://github.com/svaante/dape) working with a Golang project and ran into a couple of problems that prevented me from being able to use it. Today I decided to revisit it, and I'm glad I did, because it was one of the last remaining reasons I had for ever needing to open VSCode.
5+
## First attempt at using Dape with a Golang project
6+
### Problem 1 - passing arguments
7+
In the top-level of my repo, I created the file `.dir-locals.el` with the following content:
8+
9+
```lisp
10+
((go-mode . ((dape-configs .
11+
((go-debug-main
12+
modes (go-mode go-ts-mode)
13+
command "dlv"
14+
command-args ("dap" "--listen" "127.0.0.1:55878" "--log-dest" "/tmp/dlv.log")
15+
command-cwd "/home/shanemcd/github/GoogleContainerTools/skaffold/examples/simple-artifact-dependency"
16+
host "127.0.0.1"
17+
port 55878
18+
:request "launch"
19+
:mode "debug"
20+
:type "go"
21+
:showLog "true"
22+
:program "/home/shanemcd/github/GoogleContainerTools/skaffold/cmd/skaffold/skaffold.go"
23+
:args ("build")))))))
24+
25+
```
26+
27+
I am using Google's [Skaffold](https://skaffold.dev/) here in my example, but any program that accepts command line arguments will serve the purpose.
28+
29+
With this config in place, I navigated to the program's entrypoint (`cmd/skaffold/skaffold.go`) and was prompted with this:
30+
31+
```
32+
The local variables list in /home/shanemcd/github/GoogleContainerTools/skaffold/
33+
or .dir-locals.el contains values that may not be safe (*).
34+
35+
Do you want to apply it? You can type
36+
y -- to apply the local variables list.
37+
n -- to ignore the local variables list.
38+
! -- to apply the local variables list, and permanently mark these
39+
values (*) as safe (in the future, they will be set automatically.)
40+
i -- to ignore the local variables list, and permanently mark these
41+
values (*) as ignored
42+
+ -- to apply the local variables list, and trust all directory-local
43+
variables in this directory
44+
45+
* dape-configs : ((go-debug-main modes (go-mode go-ts-mode) command "dlv" command-args ("dap" "--listen" "127.0.0.1:55878" "--log-dest" "/tmp/dlv.log") command-cwd "/var/home/shanemcd/github/GoogleContainerTools/skaffold/examples/simple-artifact-dependency" host "127.0.0.1" port 55878 :request "launch" :mode "debug" :type "go" :showLog "true" :program "/var/home/shanemcd/github/GoogleContainerTools/skaffold/cmd/skaffold/skaffold.go" :args ("build")))
46+
```
47+
48+
After typing `y` and pressing `Return`. With the file open, I then ran `M-x dape` and saw the following output in the `*dape-repl*` buffer:
49+
50+
```
51+
* Welcome to Dape REPL! *
52+
Available Dape commands: debug, next, continue, pause, step, out, up, down, threads, stack, modules, sources, breakpoints, scope, watch, restart, kill, disconnect, quit
53+
Empty input will rerun last command.
54+
55+
* Process launched /var/home/shanemcd/github/GoogleContainerTools/skaffold/examples/simple-artifact-dependency/__debug_bin1126826703 *
56+
Type 'dlv help' for list of commands.
57+
Hello
58+
A tool that facilitates continuous development for Kubernetes applications.
59+
60+
Find more information at: https://skaffold.dev/docs/getting-started/
61+
62+
End-to-end Pipelines:
63+
run Run a pipeline
64+
dev Run a pipeline in development mode
65+
debug Run a pipeline in debug mode
66+
67+
Pipeline Building Blocks:
68+
build Build the artifacts
69+
test Run tests against your built application images
70+
deploy Deploy pre-built artifacts
71+
delete Delete any resources deployed by Skaffold
72+
render Generate rendered Kubernetes manifests
73+
apply Apply hydrated manifests to a cluster
74+
verify Run verification tests against skaffold deployments
75+
76+
Getting Started With a New Project:
77+
init Generate configuration for deploying an application
78+
79+
Other Commands:
80+
completion Output shell completion for the given shell (bash, fish or zsh)
81+
config Interact with the global Skaffold config file (defaults to `$HOME/.skaffold/config`)
82+
diagnose Run a diagnostic on Skaffold
83+
exec Execute a custom action
84+
fix Update old configuration to a newer schema version
85+
schema List JSON schemas used to validate skaffold.yaml configuration
86+
survey Opens a web browser to fill out the Skaffold survey
87+
version Print the version information
88+
89+
Usage:
90+
skaffold [flags] [options]
91+
92+
Use "skaffold <command> --help" for more information about a given command.
93+
Use "skaffold options" for a list of global command-line options (applies to all commands).
94+
```
95+
96+
Well, that didn't work as I had expected.
97+
98+
Reading over the `dape` README, I saw this under the `C, C++ and Rust - lldb-dap` heading:
99+
100+
> To pass arguments, use `:args ["arg1" "arg2" ..]`
101+
102+
At first I did not try this because I assumed if it also applied to other languages it would have been called out explicitly, but sure enough, it worked after running `dape` and then appending my args:
103+
104+
```
105+
go-debug-main :args ["build"]
106+
```
107+
108+
I then tried to update my `.dir-locals.el` with the bracket notation:
109+
110+
```diff
111+
diff --git a/.dir-locals.el b/.dir-locals.el
112+
index 65e164b..9995c3a 100644
113+
--- a/.dir-locals.el
114+
+++ b/.dir-locals.el
115+
@@ -11,4 +11,4 @@
116+
          :type "go"
117+
          :showLog "true"
118+
          :program "/home/shanemcd/github/GoogleContainerTools/skaffold/cmd/skaffold/skaffold.go"
119+
-          :args ("build")))))))
120+
+          :args ["build"]))))))
121+
```
122+
123+
... and it worked! 🎉 (but also🤦‍♂️)
124+
125+
```
126+
* Welcome to Dape REPL! *
127+
Available Dape commands: debug, next, continue, pause, step, out, up, down, threads, stack, modules, sources, breakpoints, scope, watch, restart, kill, disconnect, quit
128+
Empty input will rerun last command.
129+
130+
* Process launched /var/home/shanemcd/github/GoogleContainerTools/skaffold/examples/simple-artifact-dependency/__debug_bin2338563526 build *
131+
Type 'dlv help' for list of commands.
132+
Generating tags...
133+
- app -> app:v2.15.0-4-g8c00b98d7
134+
- base -> base:v2.15.0-4-g8c00b98d7
135+
Checking cache...
136+
- app: Not found. Building
137+
- base: Not found. Building
138+
Starting build...
139+
Building [base]...
140+
Sending build context to Docker daemon 3.072kB
141+
142+
Step 1/3 : FROM alpine:3
143+
---> aded1e1a5b37
144+
Step 2/3 : COPY hello.txt .
145+
---> Using cache
146+
---> 5739d7557ae4
147+
Step 3/3 : CMD ["./app"]
148+
---> Using cache
149+
---> 17979f81cffb
150+
Successfully built 17979f81cffb
151+
Successfully tagged base:v2.15.0-4-g8c00b98d7
152+
The push refers to repository [docker.io/library/base]
153+
23deea18e759: Preparing
154+
08000c18d16d: Preparing
155+
Process 160667 has exited with status 1
156+
Detaching
157+
* Session terminated *
158+
```
159+
160+
### Problem 2 - breakpoints not working
161+
162+
Now with the command invocation working, I proceeded with trying to set a breakpoint in the Skaffold code with `dape-breakpoint-toggle C-x C-a b`. Doing that and then re-running `dape`, I was surprised to see that the breakpoint did not hit as I was expecting.
163+
164+
After describing my problem to ChatGPT, it inferred from our previous chats that I was using Fedora Kinoite, and it pointed out right away that symlinks (Fedora Atomic Desktops link `/home/` to `/var/home`) were known to cause problem in debuggers. After a quick search, that was easy to confirm after locating [this note](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#debug-symlink-directories) in the `vscode-go` docs. I was able to get around this by setting `HOME` to the full path when in my `.dir-locals.el`
165+
166+
```diff
167+
diff --git a/.dir-locals.el b/.dir-locals.el
168+
index 9995c3a..fba8c9f 100644
169+
--- a/.dir-locals.el
170+
+++ b/.dir-locals.el
171+
@@ -3,12 +3,12 @@
172+
          modes (go-mode go-ts-mode)
173+
          command "dlv"
174+
          command-args ("dap" "--listen" "127.0.0.1:55878" "--log-dest" "/tmp/dlv.log")
175+
-          command-cwd "/home/shanemcd/github/GoogleContainerTools/skaffold/examples/simple-artifact-dependency"
176+
+          command-cwd "/var/home/shanemcd/github/GoogleContainerTools/skaffold/examples/simple-artifact-dependency"
177+
          host "127.0.0.1"
178+
          port 55878
179+
          :request "launch"
180+
          :mode "debug"
181+
          :type "go"
182+
          :showLog "true"
183+
-          :program "/home/shanemcd/github/GoogleContainerTools/skaffold/cmd/skaffold/skaffold.go"
184+
+          :program "/var/home/shanemcd/github/GoogleContainerTools/skaffold/cmd/skaffold/skaffold.go"
185+
          :args ["build"]))))))
186+
```
187+
188+
And when launching emacs:
189+
190+
```
191+
$ env HOME=/var/home/shanemcd emacs
192+
```
193+
194+
Seeking a more long-term solution, I was able to add this to my emacs configuration, which handles setting `HOME` correctly whenever it is symlinked:
195+
196+
```lisp
197+
(when-let ((real-home (file-truename (getenv "HOME"))))
198+
(when (not (string= (getenv "HOME") real-home))
199+
(setenv "HOME" real-home)))
200+
```
201+
202+
I still have a lot more to learn, but with this, I am at least able to set breakpoints in my Golang application, step through the code, and inspect variables. I hope this blog post proves to be useful for others, but if nothing else I will be able to copy + paste these configs the next time I lose them. 🙂

0 commit comments

Comments
 (0)