@@ -18,164 +18,87 @@ package debug
1818import (
1919 "context"
2020 "fmt"
21- "github.com/arduino/arduino-cli/arduino/cores"
22- "github.com/arduino/arduino-cli/arduino/sketches"
23- "github.com/arduino/arduino-cli/commands"
21+ "io"
22+
2423 "github.com/arduino/arduino-cli/executils"
2524 dbg "github.com/arduino/arduino-cli/rpc/debug"
26- "github.com/arduino/go-paths-helper"
27- "github.com/arduino/go-properties-orderedmap"
28- "github.com/sirupsen/logrus"
29- "os"
30- "os/exec"
31- "path/filepath"
32- "strings"
3325)
3426
3527// Debug FIXMEDOC
36- func Debug (ctx context.Context , req * dbg.DebugReq , in func (data []bytes ), out func (data []bytes )) (* exec.Cmd , error ) {
37- //logrus.Tracef("Debug %s on %s started", req.GetSketchPath(), req.GetFqbn())
38-
39- //// TODO: make a generic function to extract sketch from request
40- // and remove duplication in commands/compile.go
41- if req .GetSketchPath () == "" {
42- return fmt .Errorf ("missing sketchPath" )
43- }
44- sketchPath := paths .New (req .GetSketchPath ())
45- sketch , err := sketches .NewSketchFromPath (sketchPath )
28+ func Debug (ctx context.Context , req * dbg.DebugReq , inStream dbg.Debug_StreamingOpenServer , out io.Writer ) (* dbg.StreamingOpenResp , error ) {
29+ cmdArgs := []string {"gdb" }
30+ // Run Tool
31+ cmd , err := executils .Command (cmdArgs )
4632 if err != nil {
47- return fmt .Errorf ("opening sketch: %s" , err )
48- }
49-
50- // FIXME: make a specification on how a port is specified via command line
51- port := req .GetPort ()
52- if port == "" {
53- return fmt .Errorf ("no upload port provided" )
33+ return nil , fmt .Errorf ("cannot execute upload tool: %s" , err )
5434 }
5535
56- fqbnIn := req .GetFqbn ()
57- if fqbnIn == "" && sketch != nil && sketch .Metadata != nil {
58- fqbnIn = sketch .Metadata .CPU .Fqbn
59- }
60- if fqbnIn == "" {
61- return fmt .Errorf ("no Fully Qualified Board Name provided" )
62- }
63- fqbn , err := cores .ParseFQBN (fqbnIn )
36+ in , err := cmd .StdinPipe ()
6437 if err != nil {
65- return fmt .Errorf ("incorrect FQBN: %s" , err )
38+ fmt .Println ("%v\n " , err )
39+ return & dbg.StreamingOpenResp {}, nil // TODO: send error in response
6640 }
41+ defer in .Close ()
6742
68- pm := commands . GetPackageManager ( req . GetInstance (). GetId ())
43+ cmd . Stdout = out
6944
70- // Find target board and board properties
71- _ , _ , board , boardProperties , _ , err := pm .ResolveFQBN (fqbn )
45+ err = cmd .Start ()
7246 if err != nil {
73- return fmt .Errorf ("incorrect FQBN: %s" , err )
74- }
75-
76- // Load programmer tool
77- uploadToolPattern , have := boardProperties .GetOk ("upload.tool" )
78- if ! have || uploadToolPattern == "" {
79- return fmt .Errorf ("cannot get programmer tool: undefined 'upload.tool' property" )
80- }
81-
82- var referencedPlatformRelease * cores.PlatformRelease
83- if split := strings .Split (uploadToolPattern , ":" ); len (split ) > 2 {
84- return fmt .Errorf ("invalid 'upload.tool' property: %s" , uploadToolPattern )
85- } else if len (split ) == 2 {
86- referencedPackageName := split [0 ]
87- uploadToolPattern = split [1 ]
88- architecture := board .PlatformRelease .Platform .Architecture
89-
90- if referencedPackage := pm .Packages [referencedPackageName ]; referencedPackage == nil {
91- return fmt .Errorf ("required platform %s:%s not installed" , referencedPackageName , architecture )
92- } else if referencedPlatform := referencedPackage .Platforms [architecture ]; referencedPlatform == nil {
93- return fmt .Errorf ("required platform %s:%s not installed" , referencedPackageName , architecture )
94- } else {
95- referencedPlatformRelease = pm .GetInstalledPlatformRelease (referencedPlatform )
96- }
97- }
98-
99- // Build configuration for upload
100- uploadProperties := properties .NewMap ()
101- if referencedPlatformRelease != nil {
102- uploadProperties .Merge (referencedPlatformRelease .Properties )
103- }
104- uploadProperties .Merge (board .PlatformRelease .Properties )
105- uploadProperties .Merge (board .PlatformRelease .RuntimeProperties ())
106- uploadProperties .Merge (boardProperties )
107-
108- uploadToolProperties := uploadProperties .SubTree ("tools." + uploadToolPattern )
109- uploadProperties .Merge (uploadToolProperties )
110-
111- if requiredTools , err := pm .FindToolsRequiredForBoard (board ); err == nil {
112- for _ , requiredTool := range requiredTools {
113- logrus .WithField ("tool" , requiredTool ).Info ("Tool required for upload" )
114- uploadProperties .Merge (requiredTool .RuntimeProperties ())
47+ fmt .Println ("%v\n " , err )
48+ return & dbg.StreamingOpenResp {}, nil // TODO: send error in response
49+ }
50+
51+ // we'll use these channels to communicate with the goroutines
52+ // handling the stream and the target respectively
53+ streamClosed := make (chan error )
54+ targetClosed := make (chan error )
55+ defer close (streamClosed )
56+ defer close (targetClosed )
57+
58+ // now we can read the other commands and re-route to the Debug Client...
59+ go func () {
60+ for {
61+ command , err := inStream .Recv ()
62+ if err == io .EOF {
63+ // stream was closed
64+ streamClosed <- nil
65+ break
66+ }
67+
68+ if err != nil {
69+ // error reading from stream
70+ streamClosed <- err
71+ break
72+ }
73+
74+ if _ , err := in .Write (command .GetData ()); err != nil {
75+ // error writing to target
76+ targetClosed <- err
77+ break
78+ }
11579 }
116- }
117-
118- // Set properties for verbose upload
119- Verbose := req .GetVerbose ()
120- if Verbose {
121- if v , ok := uploadProperties .GetOk ("upload.params.verbose" ); ok {
122- uploadProperties .Set ("upload.verbose" , v )
123- }
124- } else {
125- if v , ok := uploadProperties .GetOk ("upload.params.quiet" ); ok {
126- uploadProperties .Set ("upload.verbose" , v )
127- }
128- }
129-
130- // Set path to compiled binary
131- // Make the filename without the FQBN configs part
132- fqbn .Configs = properties .NewMap ()
133- fqbnSuffix := strings .Replace (fqbn .String (), ":" , "." , - 1 )
134-
135- var importPath * paths.Path
136- var importFile string
137- if req .GetImportFile () == "" {
138- importPath = sketch .FullPath
139- importFile = sketch .Name + "." + fqbnSuffix
140- } else {
141- importPath = paths .New (req .GetImportFile ()).Parent ()
142- importFile = paths .New (req .GetImportFile ()).Base ()
143- }
144-
145- outputTmpFile , ok := uploadProperties .GetOk ("recipe.output.tmp_file" )
146- outputTmpFile = uploadProperties .ExpandPropsInString (outputTmpFile )
147- if ! ok {
148- return fmt .Errorf ("property 'recipe.output.tmp_file' not defined" )
149- }
150- ext := filepath .Ext (outputTmpFile )
151- if strings .HasSuffix (importFile , ext ) {
152- importFile = importFile [:len (importFile )- len (ext )]
153- }
154-
155- uploadProperties .SetPath ("build.path" , importPath )
156- uploadProperties .Set ("build.project_name" , importFile )
157- uploadFile := importPath .Join (importFile + ext )
158- if _ , err := uploadFile .Stat (); err != nil {
159- if os .IsNotExist (err ) {
160- return fmt .Errorf ("compiled sketch %s not found" , uploadFile .String ())
80+ }()
81+
82+ // let goroutines route messages from/to the Debug
83+ // until either the client closes the stream or the
84+ // Debug target is closed
85+ for {
86+ select {
87+ case <- ctx .Done ():
88+ cmd .Process .Kill ()
89+ cmd .Wait ()
90+ case err := <- streamClosed :
91+ fmt .Println ("streamClosed" )
92+ cmd .Process .Kill ()
93+ cmd .Wait ()
94+ return & dbg.StreamingOpenResp {}, err // TODO: send error in response
95+ case err := <- targetClosed :
96+ fmt .Println ("targetClosed" )
97+ cmd .Process .Kill ()
98+ cmd .Wait ()
99+ return & dbg.StreamingOpenResp {}, err // TODO: send error in response
161100 }
162- return fmt .Errorf ("cannot open sketch: %s" , err )
163- }
164-
165- // Build recipe for upload
166- recipe := uploadProperties .Get ("upload.pattern" )
167- cmdLine := uploadProperties .ExpandPropsInString (recipe )
168- cmdArgs , err := properties .SplitQuotedString (cmdLine , `"'` , false )
169- if err != nil {
170- return fmt .Errorf ("invalid recipe '%s': %s" , recipe , err )
171- }
172-
173- cmdArgs := []string {"gdb" }
174- // Run Tool
175- cmd , err := executils .Command (cmdArgs )
176- if err != nil {
177- return nil , fmt .Errorf ("cannot execute upload tool: %s" , err )
178101 }
179102
180- return cmd , nil
103+ return & dbg. StreamingOpenResp {} , nil
181104}
0 commit comments