Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3e861b7
Implement first draft of debugger gRPC service
Feb 14, 2020
0119a90
Working stdio streaming
cmaglie Feb 17, 2020
a106a4f
Improved stdio passing via GRPC
cmaglie Feb 17, 2020
b16874d
Adjusted protoc definitions
cmaglie Feb 17, 2020
d9077eb
Handle errors gracefully
cmaglie Feb 17, 2020
e86ae80
Add recipe calculation to debug command
Feb 17, 2020
879367b
First implementation of debug
cmaglie Feb 17, 2020
7648814
updated client example for testing
Feb 17, 2020
3960fea
Implement debug command
Feb 19, 2020
5228709
Implement copyStream
Feb 19, 2020
9d314ab
Refactor stream helpers
Feb 19, 2020
8d44e6f
Extract recipe creation from debug command
Feb 19, 2020
9923f62
Add test for debug recipe generation
Feb 19, 2020
378b8bf
Cosmetics here and there
Feb 19, 2020
74fa6df
Refreshed client example
Feb 19, 2020
e8d9071
Replace with utils function
Feb 20, 2020
3888017
Remove debug leftover
Feb 20, 2020
e0e07c5
Refreshed client example
Feb 20, 2020
c2681b3
Moved debug proto to its package
Feb 20, 2020
11452d5
Removed sketch.json
Feb 20, 2020
a85376f
Apply general cosmetics
Feb 20, 2020
83cf94e
Add test binaries
Feb 20, 2020
da07d3d
Added test case for windows path flavor
Feb 20, 2020
abc9353
Use path.FromSlash to test debug tool command generation cross platfo…
Feb 21, 2020
fa39675
Avoid pipe leaking via closing readers and writes in case of abnormal…
Feb 21, 2020
3650865
Update client example to better catch gdb prompt
Feb 21, 2020
34e7854
Error messages cosmetics
Feb 21, 2020
5d9be12
Use errors.Wrap instead of fmt.Errorf
cmaglie Feb 21, 2020
600c1d5
Use errors.Wrap instead of fmt.Errorf
cmaglie Feb 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
First implementation of debug
  • Loading branch information
cmaglie authored and rsora committed Feb 21, 2020
commit 879367b8e4c83fa578e35432e0a884d0feebd206
101 changes: 54 additions & 47 deletions client_example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func main() {

// Create an instance of the gRPC client.
client := rpc.NewArduinoCoreClient(conn)
//settingsClient := settings.NewSettingsClient(conn)
instance := initInstance(client)
/////////////////////////////////////////////////////////////////////////
debugClient := dbg.NewDebugClient(conn)

Expand All @@ -72,18 +72,24 @@ func main() {
callVersion(client)

// debug calls
debugStreamingOpenClient, err := debugClient.StreamingOpen(context.Background())
debugStreamingOpenClient, err := debugClient.Debug(context.Background())
if err != nil {
log.Fatalf("steraming open error: %s\n", err)
}

err = debugStreamingOpenClient.Send(&dbg.StreamingOpenReq{Content: &dbg.StreamingOpenReq_DebugReq{DebugReq: &dbg.DebugReq{Instance: &dbg.Instance{Id: 1}}}})
err = debugStreamingOpenClient.Send(&dbg.DebugReq{
DebugReq: &dbg.DebugConfigReq{
Instance: &dbg.Instance{Id: instance.GetId()},
Fqbn: "arduino-sadsadasd:samd:arduino_zero_edbg",
SketchPath: os.Args[1],
Port: "none",
}})
if err != nil {
log.Fatalf("Send error: %s\n", err)
}
log.Println("calling StreamingOpenReq_DebugReq")

err = debugStreamingOpenClient.Send(&dbg.StreamingOpenReq{Content: &dbg.StreamingOpenReq_Data{Data: []byte("\n")}})
err = debugStreamingOpenClient.Send(&dbg.DebugReq{Data: []byte("\n")})
if err != nil {
log.Fatalf("Send error: %s\n", err)
}
Expand Down Expand Up @@ -114,7 +120,7 @@ func main() {

}

err = debugStreamingOpenClient.Send(&dbg.StreamingOpenReq{Content: &dbg.StreamingOpenReq_Data{Data: []byte("quit\n")}})
err = debugStreamingOpenClient.Send(&dbg.DebugReq{Data: []byte("quit\n")})
if err != nil {
log.Fatalf("Send error: %s\n", err)
}
Expand Down Expand Up @@ -300,48 +306,49 @@ func callVersion(client rpc.ArduinoCoreClient) {
// log.Printf("Settings: %s", getAllResp.GetJsonData())
//}
//
//func initInstance(client rpc.ArduinoCoreClient) *rpc.Instance {
// // The configuration for this example client only contains the path to
// // the data folder.
// initRespStream, err := client.Init(context.Background(), &rpc.InitReq{})
// if err != nil {
// log.Fatalf("Error creating server instance: %s", err)
//
// }
//
// var instance *rpc.Instance
// // Loop and consume the server stream until all the setup procedures are done.
// for {
// initResp, err := initRespStream.Recv()
// // The server is done.
// if err == io.EOF {
// break
// }
//
// // There was an error.
// if err != nil {
// log.Fatalf("Init error: %s", err)
// }
//
// // The server sent us a valid instance, let's print its ID.
// if initResp.GetInstance() != nil {
// instance = initResp.GetInstance()
// log.Printf("Got a new instance with ID: %v", instance.GetId())
// }
//
// // When a download is ongoing, log the progress
// if initResp.GetDownloadProgress() != nil {
// log.Printf("DOWNLOAD: %s", initResp.GetDownloadProgress())
// }
//
// // When an overall task is ongoing, log the progress
// if initResp.GetTaskProgress() != nil {
// log.Printf("TASK: %s", initResp.GetTaskProgress())
// }
// }
//
// return instance
//}
func initInstance(client rpc.ArduinoCoreClient) *rpc.Instance {
// The configuration for this example client only contains the path to
// the data folder.
initRespStream, err := client.Init(context.Background(), &rpc.InitReq{})
if err != nil {
log.Fatalf("Error creating server instance: %s", err)

}

var instance *rpc.Instance
// Loop and consume the server stream until all the setup procedures are done.
for {
initResp, err := initRespStream.Recv()
// The server is done.
if err == io.EOF {
break
}

// There was an error.
if err != nil {
log.Fatalf("Init error: %s", err)
}

// The server sent us a valid instance, let's print its ID.
if initResp.GetInstance() != nil {
instance = initResp.GetInstance()
log.Printf("Got a new instance with ID: %v", instance.GetId())
}

// When a download is ongoing, log the progress
if initResp.GetDownloadProgress() != nil {
log.Printf("DOWNLOAD: %s", initResp.GetDownloadProgress())
}

// When an overall task is ongoing, log the progress
if initResp.GetTaskProgress() != nil {
log.Printf("TASK: %s", initResp.GetTaskProgress())
}
}

return instance
}

//
//func callUpdateIndex(client rpc.ArduinoCoreClient, instance *rpc.Instance) {
// uiRespStream, err := client.UpdateIndex(context.Background(), &rpc.UpdateIndexReq{
Expand Down
77 changes: 42 additions & 35 deletions commands/debug/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@ package debug
import (
"context"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"time"

"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/sketches"
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/go-paths-helper"
"github.com/arduino/go-properties-orderedmap"
"github.com/sirupsen/logrus"
"io"
"os"
"path/filepath"
"strings"
"time"

"github.com/arduino/arduino-cli/executils"
dbg "github.com/arduino/arduino-cli/rpc/debug"
Expand Down Expand Up @@ -75,17 +76,17 @@ func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream dbg.Debug_Debu
}

// Load programmer tool
uploadToolPattern, have := boardProperties.GetOk("debug.tool")
if !have || uploadToolPattern == "" {
toolName, have := boardProperties.GetOk("debug.tool")
if !have || toolName == "" {
return nil, fmt.Errorf("cannot get programmer tool: undefined 'debug.tool' property")
}

var referencedPlatformRelease *cores.PlatformRelease
if split := strings.Split(uploadToolPattern, ":"); len(split) > 2 {
return nil, fmt.Errorf("invalid 'debug.tool' property: %s", uploadToolPattern)
if split := strings.Split(toolName, ":"); len(split) > 2 {
return nil, fmt.Errorf("invalid 'debug.tool' property: %s", toolName)
} else if len(split) == 2 {
referencedPackageName := split[0]
uploadToolPattern = split[1]
toolName = split[1]
architecture := board.PlatformRelease.Platform.Architecture

if referencedPackage := pm.Packages[referencedPackageName]; referencedPackage == nil {
Expand All @@ -98,33 +99,33 @@ func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream dbg.Debug_Debu
}

// Build configuration for upload
debugProperties := properties.NewMap()
toolProperties := properties.NewMap()
if referencedPlatformRelease != nil {
debugProperties.Merge(referencedPlatformRelease.Properties)
toolProperties.Merge(referencedPlatformRelease.Properties)
}
debugProperties.Merge(board.PlatformRelease.Properties)
debugProperties.Merge(board.PlatformRelease.RuntimeProperties())
debugProperties.Merge(boardProperties)
toolProperties.Merge(board.PlatformRelease.Properties)
toolProperties.Merge(board.PlatformRelease.RuntimeProperties())
toolProperties.Merge(boardProperties)

uploadToolProperties := debugProperties.SubTree("tools." + uploadToolPattern)
debugProperties.Merge(uploadToolProperties)
requestedToolProperties := toolProperties.SubTree("tools." + toolName)
toolProperties.Merge(requestedToolProperties)

if requiredTools, err := pm.FindToolsRequiredForBoard(board); err == nil {
for _, requiredTool := range requiredTools {
logrus.WithField("tool", requiredTool).Info("Tool required for upload")
debugProperties.Merge(requiredTool.RuntimeProperties())
toolProperties.Merge(requiredTool.RuntimeProperties())
}
}

// Set properties for verbose upload
Verbose := req.GetVerbose()
if Verbose {
if v, ok := debugProperties.GetOk("debug.params.verbose"); ok {
debugProperties.Set("debug.verbose", v)
verbose := req.GetVerbose()
if verbose {
if v, ok := toolProperties.GetOk("debug.params.verbose"); ok {
toolProperties.Set("debug.verbose", v)
}
} else {
if v, ok := debugProperties.GetOk("debug.params.quiet"); ok {
debugProperties.Set("debug.verbose", v)
if v, ok := toolProperties.GetOk("debug.params.quiet"); ok {
toolProperties.Set("debug.verbose", v)
}
}

Expand All @@ -143,8 +144,8 @@ func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream dbg.Debug_Debu
importFile = paths.New(req.GetImportFile()).Base()
}

outputTmpFile, ok := debugProperties.GetOk("recipe.output.tmp_file")
outputTmpFile = debugProperties.ExpandPropsInString(outputTmpFile)
outputTmpFile, ok := toolProperties.GetOk("recipe.output.tmp_file")
outputTmpFile = toolProperties.ExpandPropsInString(outputTmpFile)
if !ok {
return nil, fmt.Errorf("property 'recipe.output.tmp_file' not defined")
}
Expand All @@ -153,8 +154,8 @@ func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream dbg.Debug_Debu
importFile = importFile[:len(importFile)-len(ext)]
}

debugProperties.SetPath("build.path", importPath)
debugProperties.Set("build.project_name", importFile)
toolProperties.SetPath("build.path", importPath)
toolProperties.Set("build.project_name", importFile)
uploadFile := importPath.Join(importFile + ext)
if _, err := uploadFile.Stat(); err != nil {
if os.IsNotExist(err) {
Expand All @@ -163,22 +164,27 @@ func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream dbg.Debug_Debu
return nil, fmt.Errorf("cannot open sketch: %s", err)
}

// Set serial port property
debugProperties.Set("serial.port", port)
// Set debug port property
toolProperties.Set("debug.port", port)
if strings.HasPrefix(port, "/dev/") {
debugProperties.Set("serial.port.file", port[5:])
toolProperties.Set("debug.port.file", port[5:])
} else {
debugProperties.Set("serial.port.file", port)
toolProperties.Set("debug.port.file", port)
}

// Build recipe for upload
recipe := debugProperties.Get("debug.pattern")
cmdLine := debugProperties.ExpandPropsInString(recipe)
// Build recipe for tool
recipe := toolProperties.Get("debug.pattern")
cmdLine := toolProperties.ExpandPropsInString(recipe)
cmdArgs, err := properties.SplitQuotedString(cmdLine, `"'`, false)
if err != nil {
return nil, fmt.Errorf("invalid recipe '%s': %s", recipe, err)
}

// for _, arg := range cmdArgs {
// fmt.Println(">>", arg)
// }
// time.Sleep(time.Hour)

// Run Tool
cmd, err := executils.Command(cmdArgs)
if err != nil {
Expand All @@ -193,6 +199,7 @@ func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream dbg.Debug_Debu
defer in.Close()

cmd.Stdout = out
cmd.Stderr = out

if err := cmd.Start(); err != nil {
fmt.Printf("%v\n", err)
Expand Down
Loading