diff --git a/Taskfile.yml b/Taskfile.yml index 780f80f0b9b..5dc842fb9b9 100755 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -7,6 +7,7 @@ tasks: - '{{ default "protoc" .PROTOC_BINARY }} --proto_path=rpc --go_out=plugins=grpc,paths=source_relative:rpc ./rpc/commands/*.proto' - '{{ default "protoc" .PROTOC_BINARY }} --proto_path=rpc --go_out=plugins=grpc,paths=source_relative:rpc ./rpc/monitor/*.proto' - '{{ default "protoc" .PROTOC_BINARY }} --proto_path=rpc --go_out=plugins=grpc,paths=source_relative:rpc ./rpc/settings/*.proto' + - '{{ default "protoc" .PROTOC_BINARY }} --proto_path=rpc --go_out=plugins=grpc,paths=source_relative:rpc ./rpc/debug/*.proto' build: desc: Build the project diff --git a/arduino/cores/packagemanager/package_manager.go b/arduino/cores/packagemanager/package_manager.go index 3d4a2b33d55..d7016566ef4 100644 --- a/arduino/cores/packagemanager/package_manager.go +++ b/arduino/cores/packagemanager/package_manager.go @@ -323,7 +323,6 @@ func (tr *ToolReleaseActions) Get() (*cores.ToolRelease, error) { // GetInstalledPlatformRelease returns the PlatformRelease installed (it is chosen) func (pm *PackageManager) GetInstalledPlatformRelease(platform *cores.Platform) *cores.PlatformRelease { - pm.Log.Infof("Selecting installed platform release for %s", platform) releases := platform.GetAllInstalled() if len(releases) == 0 { return nil diff --git a/arduino/utils/stream.go b/arduino/utils/stream.go new file mode 100644 index 00000000000..c8894a6403b --- /dev/null +++ b/arduino/utils/stream.go @@ -0,0 +1,58 @@ +// This file is part of arduino-cli. +// +// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to +// modify or otherwise use the software for commercial activities involving the +// Arduino software without disclosing the source code of your own applications. +// To purchase a commercial license, send an email to license@arduino.cc. + +package utils + +import "io" + +// FeedStreamTo creates a pipe to pass data to the writer function. +// FeedStreamTo returns the io.Writer side of the pipe, on which the user can write data +func FeedStreamTo(writer func(data []byte)) io.Writer { + r, w := io.Pipe() + go func() { + data := make([]byte, 1024) + for { + if n, err := r.Read(data); err == nil { + writer(data[:n]) + } else { + r.Close() + return + } + } + }() + return w +} + +// ConsumeStreamFrom creates a pipe to consume data from the reader function. +// ConsumeStreamFrom returns the io.Reader side of the pipe, which the user can use to consume the data +func ConsumeStreamFrom(reader func() ([]byte, error)) io.Reader { + r, w := io.Pipe() + go func() { + for { + if data, err := reader(); err != nil { + if err == io.EOF { + w.Close() + } else { + w.CloseWithError(err) + } + return + } else if _, err := w.Write(data); err != nil { + w.Close() + return + } + } + }() + return r +} diff --git a/cli/cli.go b/cli/cli.go index f1c81d7a697..c5a061d085b 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -28,6 +28,7 @@ import ( "github.com/arduino/arduino-cli/cli/config" "github.com/arduino/arduino-cli/cli/core" "github.com/arduino/arduino-cli/cli/daemon" + "github.com/arduino/arduino-cli/cli/debug" "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/generatedocs" @@ -77,6 +78,7 @@ func createCliCommandTree(cmd *cobra.Command) { cmd.AddCommand(lib.NewCommand()) cmd.AddCommand(sketch.NewCommand()) cmd.AddCommand(upload.NewCommand()) + cmd.AddCommand(debug.NewCommand()) cmd.AddCommand(version.NewCommand()) cmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Print the logs on the standard output.") diff --git a/cli/daemon/daemon.go b/cli/daemon/daemon.go index e3ea2811d9a..fc38dd11d38 100644 --- a/cli/daemon/daemon.go +++ b/cli/daemon/daemon.go @@ -31,6 +31,7 @@ import ( "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/commands/daemon" srv_commands "github.com/arduino/arduino-cli/rpc/commands" + srv_debug "github.com/arduino/arduino-cli/rpc/debug" srv_monitor "github.com/arduino/arduino-cli/rpc/monitor" srv_settings "github.com/arduino/arduino-cli/rpc/settings" "github.com/sirupsen/logrus" @@ -73,16 +74,19 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { VersionString: globals.VersionInfo.VersionString, }) - // register the monitors service + // Register the monitors service srv_monitor.RegisterMonitorServer(s, &daemon.MonitorService{}) - // register the settings service + // Register the settings service srv_settings.RegisterSettingsServer(s, &daemon.SettingsService{}) + // Register the debug session service + srv_debug.RegisterDebugServer(s, &daemon.DebugService{}) + if !daemonize { // When parent process ends terminate also the daemon go func() { - // stdin is closed when the controlling parent process ends + // Stdin is closed when the controlling parent process ends _, _ = io.Copy(ioutil.Discard, os.Stdin) os.Exit(0) }() @@ -115,6 +119,6 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { // This message will show up on the stdout of the daemon process so that gRPC clients know it is time to connect. logrus.Infof("Daemon is listening on TCP port %s...", port) if err := s.Serve(lis); err != nil { - logrus.Fatalf("failed to serve: %v", err) + logrus.Fatalf("Failed to serve: %v", err) } } diff --git a/cli/debug/debug.go b/cli/debug/debug.go new file mode 100644 index 00000000000..64e8e7150a9 --- /dev/null +++ b/cli/debug/debug.go @@ -0,0 +1,96 @@ +// This file is part of arduino-cli. +// +// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to +// modify or otherwise use the software for commercial activities involving the +// Arduino software without disclosing the source code of your own applications. +// To purchase a commercial license, send an email to license@arduino.cc. + +package debug + +import ( + "context" + "os" + + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/feedback" + "github.com/arduino/arduino-cli/cli/instance" + "github.com/arduino/arduino-cli/commands/debug" + dbg "github.com/arduino/arduino-cli/rpc/debug" + "github.com/arduino/go-paths-helper" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +var ( + fqbn string + port string + verbose bool + verify bool + importFile string +) + +// NewCommand created a new `upload` command +func NewCommand() *cobra.Command { + debugCommand := &cobra.Command{ + Use: "debug", + Short: "Debug Arduino sketches.", + Long: "Debug Arduino sketches. (this command opens an interactive gdb session)", + Example: " " + os.Args[0] + " debug -b arduino:samd:mkr1000 /home/user/Arduino/MySketch", + Args: cobra.MaximumNArgs(1), + Run: run, + } + + debugCommand.Flags().StringVarP(&fqbn, "fqbn", "b", "", "Fully Qualified Board Name, e.g.: arduino:avr:uno") + debugCommand.Flags().StringVarP(&port, "port", "p", "", "Upload port, e.g.: COM10 or /dev/ttyACM0") + debugCommand.Flags().StringVarP(&importFile, "input", "i", "", "Input file to be uploaded for debug.") + + return debugCommand +} + +func run(command *cobra.Command, args []string) { + instance, err := instance.CreateInstance() + if err != nil { + feedback.Errorf("Error during Debug: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + var path *paths.Path + if len(args) > 0 { + path = paths.New(args[0]) + } + sketchPath := initSketchPath(path) + + if _, err := debug.Debug(context.Background(), &dbg.DebugConfigReq{ + Instance: &dbg.Instance{Id: instance.GetId()}, + Fqbn: fqbn, + SketchPath: sketchPath.String(), + Port: port, + ImportFile: importFile, + }, os.Stdin, os.Stdout); err != nil { + feedback.Errorf("Error during Debug: %v", err) + os.Exit(errorcodes.ErrGeneric) + } +} + +// initSketchPath returns the current working directory +func initSketchPath(sketchPath *paths.Path) *paths.Path { + if sketchPath != nil { + return sketchPath + } + + wd, err := paths.Getwd() + if err != nil { + feedback.Errorf("Couldn't get current working directory: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + logrus.Infof("Reading sketch from dir: %s", wd) + return wd +} diff --git a/client_example/go.mod b/client_example/go.mod index 91cc576487c..7bce3c37a40 100644 --- a/client_example/go.mod +++ b/client_example/go.mod @@ -2,8 +2,9 @@ module github.com/arduino/arduino-cli/client_example go 1.13 +replace github.com/arduino/arduino-cli => ../ + require ( github.com/arduino/arduino-cli v0.0.0-20200109150215-ffa84fdaab21 - github.com/gosuri/uitable v0.0.0-20160404203958-36ee7e946282 // indirect - google.golang.org/grpc v1.23.0 -) \ No newline at end of file + google.golang.org/grpc v1.27.0 +) diff --git a/client_example/go.sum b/client_example/go.sum index 8e07356509d..b101220d43c 100644 --- a/client_example/go.sum +++ b/client_example/go.sum @@ -1,18 +1,13 @@ bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/arduino/arduino-cli v0.0.0-20190826141027-35722fda467d h1:1Rwlmz0+4ofl3wKC29IlgAwb/66f2afOTUWsGgh5NLk= -github.com/arduino/arduino-cli v0.0.0-20190826141027-35722fda467d/go.mod h1:XFDg7LwMgVGiJAkVLQ0AM3Gei5LjfuDIKwOcrU9rnsI= -github.com/arduino/arduino-cli v0.0.0-20200109150215-ffa84fdaab21 h1:KEQLrEwD+3UG3wS5vPFcudrMFzvjJHq5xOoIgvjFPaQ= -github.com/arduino/arduino-cli v0.0.0-20200109150215-ffa84fdaab21/go.mod h1:Jtn7ZeNH70MG8bW0MZRVeGGxmAf1FQ3BgnFgLZmBOTc= github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c/go.mod h1:HK7SpkEax/3P+0w78iRQx1sz1vCDYYw9RXwHjQTB5i8= -github.com/arduino/go-paths-helper v0.0.0-20190214132331-c3c98d1bf2e1/go.mod h1:OGL+FS3aTrS01YsBAJJhkGuxtEGsFRSgZYo8b3vefdc= github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck= -github.com/arduino/go-properties-orderedmap v0.0.0-20181003091528-89278049acd3/go.mod h1:kiSuHm7yz3chiy8rb2MphC7ECn3MlkQFAIe4SXmQg6o= github.com/arduino/go-properties-orderedmap v0.0.0-20190828172252-05018b28ff6c/go.mod h1:kiSuHm7yz3chiy8rb2MphC7ECn3MlkQFAIe4SXmQg6o= github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b/go.mod h1:uwGy5PpN4lqW97FiLnbcx+xx8jly5YuPMJWfVwwjJiQ= github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b/go.mod h1:iIPnclBMYm1g32Q5kXoqng4jLhMStReIP7ZxaoUC2y8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cmaglie/pb v1.0.27 h1:ynGj8vBXR+dtj4B7Q/W/qGt31771Ux5iFfRQBnwdQiA= github.com/cmaglie/pb v1.0.27/go.mod h1:GilkKZMXYjBA4NxItWFfO+lwkp59PLHQ+IOW/b/kmZI= @@ -22,23 +17,27 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/creack/goselect v0.0.0-20180328191401-176c667f75aa/go.mod h1:gHrIcH/9UZDn2qgeTUeW5K9eZsVYCH6/60J/FHysWyE= github.com/creack/goselect v0.1.1/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fluxio/iohelpers v0.0.0-20160419043813-3a4dd67a94d2/go.mod h1:c7sGIpDbBo0JZZ1tKyC1p5smWf8QcUjK4bFtZjHAecg= github.com/fluxio/multierror v0.0.0-20160419044231-9c68d39025e5/go.mod h1:BEUDl7FG1cc76sM0J0x8dqr6RhiL4uqvk6oFkwuNyuM= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gosuri/uitable v0.0.0-20160404203958-36ee7e946282/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/h2non/filetype v1.0.8/go.mod h1:isekKqOuhMj+s/7r3rIeTErIRy4Rub5uBWHfvMusLMU= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -63,10 +62,10 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmylund/sortutil v0.0.0-20120526081524-abeda66eb583/go.mod h1:sFPiU/UgDcsQVu3vkqpZLCXWFwUoQRpHGu9ATihPAl0= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -79,7 +78,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -88,7 +86,6 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1: go.bug.st/cleanup v1.0.0/go.mod h1:EqVmTg2IBk4znLbPD28xne3abjsJftMdqqJEjhn70bk= go.bug.st/downloader v1.1.0 h1:LipC9rqRCe8kwa+ah3ZDfCqneVaf34cB/TKjXZiZt54= go.bug.st/downloader v1.1.0/go.mod h1:l+RPbNbrTB+MoAIp8nrZsP22nRPDy26XJZQqmm4gNT4= -go.bug.st/relaxed-semver v0.0.0-20181022103824-0265409c5852/go.mod h1:WWVH9tve4kargu9fsX18qW/UHxE37QcgPXRtE/xSvxY= go.bug.st/relaxed-semver v0.0.0-20190922224835-391e10178d18/go.mod h1:Cx1VqMtEhE9pIkEyUj3LVVVPkv89dgW8aCKrRPDR/uE= go.bug.st/serial v1.0.0/go.mod h1:rpXPISGjuNjPTRTcMlxi9lN6LoIPxd1ixVjBd8aSk/Q= go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45/go.mod h1:dRSl/CVCTf56CkXgJMDOdSwNfo2g1orOGE/gBGdvjZw= @@ -103,10 +100,11 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -114,9 +112,15 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU= golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -125,12 +129,14 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190327125643-d831d65fe17d h1:XB2jc5XQ9uhizGTS2vWcN01bc4dI6z3C4KY5MQm8SS8= -google.golang.org/genproto v0.0.0-20190327125643-d831d65fe17d/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90 h1:7THRSvPuzF1bql5kyFzX0JM0vpGhwuhskgJrJsbZ80Y= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= diff --git a/client_example/hello.ino b/client_example/hello/hello.ino similarity index 100% rename from client_example/hello.ino rename to client_example/hello/hello.ino diff --git a/client_example/main.go b/client_example/main.go index b67e3f5de55..314c4b44edd 100644 --- a/client_example/main.go +++ b/client_example/main.go @@ -16,16 +16,19 @@ package main import ( + "bytes" "context" + "fmt" "io" "io/ioutil" "log" "os" "path" "path/filepath" - "time" + "strings" rpc "github.com/arduino/arduino-cli/rpc/commands" + dbg "github.com/arduino/arduino-cli/rpc/debug" "github.com/arduino/arduino-cli/rpc/settings" "google.golang.org/grpc" ) @@ -40,7 +43,7 @@ func main() { // Establish a connection with the gRPC server, started with the command: // arduino-cli daemon - conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(100*time.Millisecond)) + conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock()) if err != nil { log.Fatal("error connecting to arduino-cli rpc server, you can start it by running `arduino-cli daemon`") } @@ -56,8 +59,9 @@ func main() { dataDir = filepath.ToSlash(dataDir) defer os.RemoveAll(dataDir) - // Create an instance of the gRPC client. + // Create an instance of the gRPC clients. client := rpc.NewArduinoCoreClient(conn) + settingsClient := settings.NewSettingsClient(conn) // Now we can call various methods of the API... @@ -128,6 +132,17 @@ func main() { // log.Println("calling Upload(arduino:samd:mkr1000, /dev/ttyACM0, VERBOSE, hello.ino)") // callUpload(client, instance) + // Debug a sketch on a board + // Uncomment if you do have an actual board connected via debug port, + // or a board connected to a debugger. + // debugClient := dbg.NewDebugClient(conn) + // debugStreamingClient, err := debugClient.Debug(context.Background()) + // if err != nil { + // log.Fatalf("debug steraming open error: %s\n", err) + // } + // log.Println("calling Debug(arduino:samd:mkr1000, hello.ino)") + // callDebugger(debugStreamingClient, instance) + // List all boards log.Println("calling BoardListAll(mkr)") callListAll(client, instance) @@ -440,7 +455,7 @@ func callBoardAttach(client rpc.ArduinoCoreClient, instance *rpc.Instance) { &rpc.BoardAttachReq{ Instance: instance, BoardUri: "/dev/ttyACM0", - SketchPath: filepath.Join(currDir, "hello.ino"), + SketchPath: filepath.Join(currDir, "hello"), }) if err != nil { @@ -475,7 +490,7 @@ func callCompile(client rpc.ArduinoCoreClient, instance *rpc.Instance) { &rpc.CompileReq{ Instance: instance, Fqbn: "arduino:samd:mkr1000", - SketchPath: filepath.Join(currDir, "hello.ino"), + SketchPath: filepath.Join(currDir, "hello"), Verbose: true, }) @@ -514,7 +529,7 @@ func callUpload(client rpc.ArduinoCoreClient, instance *rpc.Instance) { &rpc.UploadReq{ Instance: instance, Fqbn: "arduino:samd:mkr1000", - SketchPath: filepath.Join(currDir, "hello.ino"), + SketchPath: filepath.Join(currDir, "hello"), Port: "/dev/ttyACM0", Verbose: true, }) @@ -802,3 +817,64 @@ func callLibUninstall(client rpc.ArduinoCoreClient, instance *rpc.Instance) { } } } + +func callDebugger(debugStreamingOpenClient dbg.Debug_DebugClient, instance *rpc.Instance) { + currDir, _ := os.Getwd() + log.Printf("Send debug request") + err := debugStreamingOpenClient.Send(&dbg.DebugReq{ + DebugReq: &dbg.DebugConfigReq{ + Instance: &dbg.Instance{Id: instance.GetId()}, + Fqbn: "arduino:samd:mkr1000", + SketchPath: filepath.Join(currDir, "hello"), + Port: "none", + }}) + if err != nil { + log.Fatalf("Send error: %s\n", err) + } + // Loop and consume the server stream until all the operations are done. + waitForPrompt(debugStreamingOpenClient, "(gdb)") + // Wait for gdb to init and show the prompt + log.Printf("Send 'info registers' rcommand") + err = debugStreamingOpenClient.Send(&dbg.DebugReq{Data: []byte("info registers\n")}) + if err != nil { + log.Fatalf("Send error: %s\n", err) + } + + // Loop and consume the server stream until all the operations are done. + waitForPrompt(debugStreamingOpenClient, "(gdb)") + + // Send quit command to gdb + log.Printf("Send 'quit' command") + err = debugStreamingOpenClient.Send(&dbg.DebugReq{Data: []byte("quit\n")}) + if err != nil { + log.Fatalf("Send error: %s\n", err) + } + + // Close connection with the debug server + log.Printf("Close session") + err = debugStreamingOpenClient.CloseSend() + if err != nil { + log.Fatalf("Send error: %s\n", err) + } +} + +func waitForPrompt(debugStreamingOpenClient dbg.Debug_DebugClient, prompt string) { + var buffer bytes.Buffer + for { + compResp, err := debugStreamingOpenClient.Recv() + + // There was an error. + if err != nil { + log.Fatalf("debug error: %s\n", err) + } + + // Consume output and search for the gdb prompt to exit the loop + if resp := compResp.GetData(); resp != nil { + fmt.Printf("%s", resp) + buffer.Write(resp) + if strings.Contains(buffer.String(), prompt) { + break + } + } + } +} diff --git a/commands/daemon/daemon.go b/commands/daemon/daemon.go index 38e195a3495..579e4abd0f2 100644 --- a/commands/daemon/daemon.go +++ b/commands/daemon/daemon.go @@ -19,9 +19,9 @@ package daemon import ( "context" - "io" "net/http" + "github.com/arduino/arduino-cli/arduino/utils" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/board" "github.com/arduino/arduino-cli/commands/compile" @@ -125,9 +125,9 @@ func (s *ArduinoCoreServerImpl) Version(ctx context.Context, req *rpc.VersionReq func (s *ArduinoCoreServerImpl) Compile(req *rpc.CompileReq, stream rpc.ArduinoCore_CompileServer) error { resp, err := compile.Compile( stream.Context(), req, - feedStream(func(data []byte) { stream.Send(&rpc.CompileResp{OutStream: data}) }), - feedStream(func(data []byte) { stream.Send(&rpc.CompileResp{ErrStream: data}) }), - false) // set debug to false + utils.FeedStreamTo(func(data []byte) { stream.Send(&rpc.CompileResp{OutStream: data}) }), + utils.FeedStreamTo(func(data []byte) { stream.Send(&rpc.CompileResp{ErrStream: data}) }), + false) // Set debug to false if err != nil { return err } @@ -213,8 +213,8 @@ func (s *ArduinoCoreServerImpl) PlatformList(ctx context.Context, req *rpc.Platf func (s *ArduinoCoreServerImpl) Upload(req *rpc.UploadReq, stream rpc.ArduinoCore_UploadServer) error { resp, err := upload.Upload( stream.Context(), req, - feedStream(func(data []byte) { stream.Send(&rpc.UploadResp{OutStream: data}) }), - feedStream(func(data []byte) { stream.Send(&rpc.UploadResp{ErrStream: data}) }), + utils.FeedStreamTo(func(data []byte) { stream.Send(&rpc.UploadResp{OutStream: data}) }), + utils.FeedStreamTo(func(data []byte) { stream.Send(&rpc.UploadResp{ErrStream: data}) }), ) if err != nil { return err @@ -222,21 +222,6 @@ func (s *ArduinoCoreServerImpl) Upload(req *rpc.UploadReq, stream rpc.ArduinoCor return stream.Send(resp) } -func feedStream(streamer func(data []byte)) io.Writer { - r, w := io.Pipe() - go func() { - data := make([]byte, 1024) - for { - if n, err := r.Read(data); err == nil { - streamer(data[:n]) - } else { - return - } - } - }() - return w -} - // LibraryDownload FIXMEDOC func (s *ArduinoCoreServerImpl) LibraryDownload(req *rpc.LibraryDownloadReq, stream rpc.ArduinoCore_LibraryDownloadServer) error { resp, err := lib.LibraryDownload( diff --git a/commands/daemon/debug.go b/commands/daemon/debug.go new file mode 100644 index 00000000000..a373f8c1c82 --- /dev/null +++ b/commands/daemon/debug.go @@ -0,0 +1,58 @@ +// This file is part of arduino-cli. +// +// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to +// modify or otherwise use the software for commercial activities involving the +// Arduino software without disclosing the source code of your own applications. +// To purchase a commercial license, send an email to license@arduino.cc. + +package daemon + +import ( + "github.com/arduino/arduino-cli/arduino/utils" + cmd "github.com/arduino/arduino-cli/commands/debug" + dbg "github.com/arduino/arduino-cli/rpc/debug" + "github.com/pkg/errors" +) + +// DebugService implements the `Debug` service +type DebugService struct{} + +// Debug returns a stream response that can be used to fetch data from the +// target. The first message passed through the `Debug` request must +// contain DebugReq configuration params, not data. +func (s *DebugService) Debug(stream dbg.Debug_DebugServer) error { + + // Grab the first message + msg, err := stream.Recv() + if err != nil { + return err + } + + // Ensure it's a config message and not data + req := msg.GetDebugReq() + if req == nil { + return errors.Errorf("First message must contain debug request, not data") + } + + // Launch debug recipe attaching stdin and out to grpc streaming + resp, err := cmd.Debug(stream.Context(), req, + utils.ConsumeStreamFrom(func() ([]byte, error) { + command, err := stream.Recv() + return command.GetData(), err + }), + utils.FeedStreamTo(func(data []byte) { + stream.Send(&dbg.DebugResp{Data: data}) + })) + if err != nil { + return (err) + } + return stream.Send(resp) +} diff --git a/commands/debug/debug.go b/commands/debug/debug.go new file mode 100644 index 00000000000..f329f3b911f --- /dev/null +++ b/commands/debug/debug.go @@ -0,0 +1,221 @@ +// This file is part of arduino-cli. +// +// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to +// modify or otherwise use the software for commercial activities involving the +// Arduino software without disclosing the source code of your own applications. +// To purchase a commercial license, send an email to license@arduino.cc. + +package debug + +import ( + "context" + "fmt" + "github.com/pkg/errors" + "io" + "os" + "path/filepath" + "strings" + "time" + + "github.com/arduino/arduino-cli/arduino/cores" + "github.com/arduino/arduino-cli/arduino/cores/packagemanager" + "github.com/arduino/arduino-cli/arduino/sketches" + "github.com/arduino/arduino-cli/commands" + "github.com/arduino/arduino-cli/executils" + dbg "github.com/arduino/arduino-cli/rpc/debug" + "github.com/arduino/go-paths-helper" + "github.com/arduino/go-properties-orderedmap" + "github.com/sirupsen/logrus" +) + +// Debug command launches a debug tool for a sketch. +// It also implements streams routing: +// gRPC In -> tool stdIn +// grpc Out <- tool stdOut +// grpc Out <- tool stdErr +// It also implements tool process lifecycle management +func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream io.Reader, out io.Writer) (*dbg.DebugResp, error) { + + // Get tool commandLine from core recipe + pm := commands.GetPackageManager(req.GetInstance().GetId()) + commandLine, err := getCommandLine(req, pm) + if err != nil { + return nil, errors.Wrap(err, "Cannot get command line for tool") + } + + // Run Tool + cmd, err := executils.Command(commandLine) + if err != nil { + return nil, errors.Wrap(err, "Cannot execute debug tool") + } + + // Get stdIn pipe from tool + in, err := cmd.StdinPipe() + if err != nil { + return &dbg.DebugResp{Error: err.Error()}, nil + } + defer in.Close() + + // Merge tool StdOut and StdErr to stream them in the io.Writer passed stream + cmd.Stdout = out + cmd.Stderr = out + + // Start the debug command + if err := cmd.Start(); err != nil { + return &dbg.DebugResp{Error: err.Error()}, nil + } + + go func() { + // Copy data from passed inStream into command stdIn + io.Copy(in, inStream) + // In any case, try process termination after a second to avoid leaving + // zombie process. + time.Sleep(time.Second) + cmd.Process.Kill() + }() + + // Wait for process to finish + if err := cmd.Wait(); err != nil { + return &dbg.DebugResp{Error: err.Error()}, nil + } + return &dbg.DebugResp{}, nil +} + +// getCommandLine compose a debug command represented by a core recipe +func getCommandLine(req *dbg.DebugConfigReq, pm *packagemanager.PackageManager) ([]string, error) { + // TODO: make a generic function to extract sketch from request + // and remove duplication in commands/compile.go + if req.GetSketchPath() == "" { + return nil, fmt.Errorf("missing sketchPath") + } + sketchPath := paths.New(req.GetSketchPath()) + sketch, err := sketches.NewSketchFromPath(sketchPath) + if err != nil { + return nil, errors.Wrap(err, "opening sketch") + } + + // FIXME: make a specification on how a port is specified via command line + port := req.GetPort() + if port == "" { + return nil, fmt.Errorf("no debug port provided") + } + + fqbnIn := req.GetFqbn() + if fqbnIn == "" && sketch != nil && sketch.Metadata != nil { + fqbnIn = sketch.Metadata.CPU.Fqbn + } + if fqbnIn == "" { + return nil, fmt.Errorf("no Fully Qualified Board Name provided") + } + fqbn, err := cores.ParseFQBN(fqbnIn) + if err != nil { + return nil, errors.Wrap(err, "error parsing FQBN") + } + + // Find target board and board properties + _, _, board, boardProperties, _, err := pm.ResolveFQBN(fqbn) + if err != nil { + return nil, errors.Wrap(err, "error resolving FQBN") + } + + // Load programmer tool + 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(toolName, ":"); len(split) > 2 { + return nil, fmt.Errorf("invalid 'debug.tool' property: %s", toolName) + } else if len(split) == 2 { + referencedPackageName := split[0] + toolName = split[1] + architecture := board.PlatformRelease.Platform.Architecture + + if referencedPackage := pm.Packages[referencedPackageName]; referencedPackage == nil { + return nil, fmt.Errorf("required platform %s:%s not installed", referencedPackageName, architecture) + } else if referencedPlatform := referencedPackage.Platforms[architecture]; referencedPlatform == nil { + return nil, fmt.Errorf("required platform %s:%s not installed", referencedPackageName, architecture) + } else { + referencedPlatformRelease = pm.GetInstalledPlatformRelease(referencedPlatform) + } + } + + // Build configuration for debug + toolProperties := properties.NewMap() + if referencedPlatformRelease != nil { + toolProperties.Merge(referencedPlatformRelease.Properties) + } + toolProperties.Merge(board.PlatformRelease.Properties) + toolProperties.Merge(board.PlatformRelease.RuntimeProperties()) + toolProperties.Merge(boardProperties) + + 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 debug") + toolProperties.Merge(requiredTool.RuntimeProperties()) + } + } + + // Set path to compiled binary + // Make the filename without the FQBN configs part + fqbn.Configs = properties.NewMap() + fqbnSuffix := strings.Replace(fqbn.String(), ":", ".", -1) + + var importPath *paths.Path + var importFile string + if req.GetImportFile() == "" { + importPath = sketch.FullPath + importFile = sketch.Name + "." + fqbnSuffix + } else { + importPath = paths.New(req.GetImportFile()).Parent() + importFile = paths.New(req.GetImportFile()).Base() + } + + 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") + } + ext := filepath.Ext(outputTmpFile) + if strings.HasSuffix(importFile, ext) { + importFile = importFile[:len(importFile)-len(ext)] + } + + 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) { + return nil, fmt.Errorf("compiled sketch %s not found", uploadFile.String()) + } + return nil, errors.Wrap(err, "cannot open sketch") + } + + // Set debug port property + toolProperties.Set("debug.port", port) + if strings.HasPrefix(port, "/dev/") { + toolProperties.Set("debug.port.file", port[5:]) + } else { + toolProperties.Set("debug.port.file", port) + } + + // 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) + } + return cmdArgs, nil +} diff --git a/commands/debug/debug_test.go b/commands/debug/debug_test.go new file mode 100644 index 00000000000..73d0a1f4c43 --- /dev/null +++ b/commands/debug/debug_test.go @@ -0,0 +1,87 @@ +// This file is part of arduino-cli. +// +// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to +// modify or otherwise use the software for commercial activities involving the +// Arduino software without disclosing the source code of your own applications. +// To purchase a commercial license, send an email to license@arduino.cc. +package debug + +import ( + "fmt" + "path/filepath" + "runtime" + "strings" + "testing" + + "github.com/arduino/arduino-cli/arduino/cores/packagemanager" + dbg "github.com/arduino/arduino-cli/rpc/debug" + "github.com/arduino/go-paths-helper" + "github.com/stretchr/testify/assert" +) + +var customHardware = paths.New("testdata", "custom_hardware") +var dataDir = paths.New("testdata", "data_dir", "packages") +var sketch = "hello" +var sketchPath = paths.New("testdata", sketch) + +func TestGetCommandLine(t *testing.T) { + pm := packagemanager.NewPackageManager(nil, nil, nil, nil) + pm.LoadHardwareFromDirectory(customHardware) + pm.LoadHardwareFromDirectory(dataDir) + + // Windows tools have .exe extension + var toolExtension = "" + if runtime.GOOS == "windows" { + toolExtension = ".exe" + } + + // Arduino Zero has an integrated debugger port, anc it could be debugged directly using USB + req := &dbg.DebugConfigReq{ + Instance: &dbg.Instance{Id: 1}, + Fqbn: "arduino-test:samd:arduino_zero_edbg", + SketchPath: sketchPath.String(), + Port: "none", + } + + goldCommand := fmt.Sprintf("%s/arduino-test/tools/arm-none-eabi-gcc/7-2017q4/bin//arm-none-eabi-gdb%s", dataDir, toolExtension) + + " -ex target extended-remote |" + + fmt.Sprintf(" %s/arduino-test/tools/openocd/0.10.0-arduino7/bin/openocd%s", dataDir, toolExtension) + + fmt.Sprintf(" -s \"%s/arduino-test/tools/openocd/0.10.0-arduino7/share/openocd/scripts/\"", dataDir) + + fmt.Sprintf(" --file \"%s/arduino-test/samd/variants/arduino_zero/openocd_scripts/arduino_zero.cfg\"", customHardware) + + fmt.Sprintf(" -c \"gdb_port pipe\" -c \"telnet_port 0\" -c init -c halt %s/hello.arduino-test.samd.arduino_zero_edbg.elf", sketchPath) + + command, err := getCommandLine(req, pm) + assert.Nil(t, err) + commandToTest := strings.Join(command[:], " ") + assert.Equal(t, filepath.FromSlash(goldCommand), filepath.FromSlash(commandToTest)) + + // Other samd boards such as mkr1000 can be debugged using an external tool such as Atmel ICE connected to + // the board debug port + req2 := &dbg.DebugConfigReq{ + Instance: &dbg.Instance{Id: 1}, + Fqbn: "arduino-test:samd:mkr1000", + SketchPath: sketchPath.String(), + Port: "none", + } + + goldCommand2 := fmt.Sprintf("%s/arduino-test/tools/arm-none-eabi-gcc/7-2017q4/bin//arm-none-eabi-gdb%s", dataDir, toolExtension) + + " -ex target extended-remote |" + + fmt.Sprintf(" %s/arduino-test/tools/openocd/0.10.0-arduino7/bin/openocd%s", dataDir, toolExtension) + + fmt.Sprintf(" -s \"%s/arduino-test/tools/openocd/0.10.0-arduino7/share/openocd/scripts/\"", dataDir) + + fmt.Sprintf(" --file \"%s/arduino-test/samd/variants/mkr1000/openocd_scripts/arduino_zero.cfg\"", customHardware) + + fmt.Sprintf(" -c \"gdb_port pipe\" -c \"telnet_port 0\" -c init -c halt %s/hello.arduino-test.samd.mkr1000.elf", sketchPath) + + command2, err := getCommandLine(req2, pm) + assert.Nil(t, err) + commandToTest2 := strings.Join(command2[:], " ") + assert.Equal(t, filepath.FromSlash(goldCommand2), filepath.FromSlash(commandToTest2)) + +} diff --git a/commands/debug/testdata/custom_hardware/arduino-test/samd/boards.txt b/commands/debug/testdata/custom_hardware/arduino-test/samd/boards.txt new file mode 100644 index 00000000000..ce473db2ef9 --- /dev/null +++ b/commands/debug/testdata/custom_hardware/arduino-test/samd/boards.txt @@ -0,0 +1,114 @@ +# Copyright (c) 2014-2017 Arduino LLC. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +# Arduino Zero (Prorgamming Port) +# --------------------------------------- +arduino_zero_edbg.name=Arduino Zero (Programming Port) +arduino_zero_edbg.vid.0=0x03eb +arduino_zero_edbg.pid.0=0x2157 + +arduino_zero_edbg.debug.tool=gdb +arduino_zero_edbg.upload.tool=openocd +arduino_zero_edbg.upload.protocol=sam-ba +arduino_zero_edbg.upload.maximum_size=262144 +arduino_zero_edbg.upload.use_1200bps_touch=false +arduino_zero_edbg.upload.wait_for_upload_port=false +arduino_zero_edbg.upload.native_usb=false +arduino_zero_edbg.build.mcu=cortex-m0plus +arduino_zero_edbg.build.f_cpu=48000000L +arduino_zero_edbg.build.usb_product="Arduino Zero" +arduino_zero_edbg.build.usb_manufacturer="Arduino LLC" +arduino_zero_edbg.build.board=SAMD_ZERO +arduino_zero_edbg.build.core=arduino +arduino_zero_edbg.build.extra_flags=-D__SAMD21G18A__ {build.usb_flags} +arduino_zero_edbg.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld +arduino_zero_edbg.build.openocdscript=openocd_scripts/arduino_zero.cfg +arduino_zero_edbg.build.variant=arduino_zero +arduino_zero_edbg.build.variant_system_lib= +arduino_zero_edbg.build.vid=0x2341 +arduino_zero_edbg.build.pid=0x804d +arduino_zero_edbg.bootloader.tool=openocd +arduino_zero_edbg.bootloader.file=zero/samd21_sam_ba.bin + +# Arduino MKR1000 +# ----------------------- +mkr1000.name=Arduino MKR1000 +mkr1000.vid.0=0x2341 +mkr1000.pid.0=0x804e +mkr1000.vid.1=0x2341 +mkr1000.pid.1=0x004e +mkr1000.vid.2=0x2341 +mkr1000.pid.2=0x824e +mkr1000.vid.3=0x2341 +mkr1000.pid.3=0x024e + +mkr1000.debug.tool=gdb +mkr1000.upload.tool=bossac +mkr1000.upload.protocol=sam-ba +mkr1000.upload.maximum_size=262144 +mkr1000.upload.use_1200bps_touch=true +mkr1000.upload.wait_for_upload_port=true +mkr1000.upload.native_usb=true +mkr1000.build.mcu=cortex-m0plus +mkr1000.build.f_cpu=48000000L +mkr1000.build.usb_product="Arduino MKR1000" +mkr1000.build.usb_manufacturer="Arduino LLC" +mkr1000.build.board=SAMD_MKR1000 +mkr1000.build.core=arduino +mkr1000.build.extra_flags=-DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ {build.usb_flags} +mkr1000.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld +mkr1000.build.openocdscript=openocd_scripts/arduino_zero.cfg +mkr1000.build.variant=mkr1000 +mkr1000.build.vid=0x2341 +mkr1000.build.pid=0x804e +mkr1000.bootloader.tool=openocd +mkr1000.bootloader.file=mkr1000/samd21_sam_ba_arduino_mkr1000.bin + +# Arduino Tian (with) Bootloader +# ------------------------------ +tian.name=Arduino Tian +tian.upload.via_ssh=true +tian.vid.0=0x10C4 +tian.pid.0=0xEA70 +tian.descriptor.0=Enhanced Com Port + +tian.upload.tool=avrdude +#tian.upload.protocol=stk500v2 +tian.upload.protocol=wiring +tian.upload.maximum_size=262144 +tian.upload.use_1200bps_touch=true +tian.upload.wait_for_upload_port=true +tian.upload.native_usb=true +tian.upload.speed=57600 +tian.build.mcu=cortex-m0plus +tian.build.f_cpu=48000000L +tian.build.usb_product="Arduino Tian" +tian.build.board=SAMD_TIAN +tian.build.core=arduino +tian.build.extra_flags=-D__SAMD21G18A__ -mthumb {build.usb_flags} +tian.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld +tian.build.openocdscript=openocd_scripts/arduino_zero.cfg +tian.build.variant=arduino_mzero +tian.build.variant_system_lib= +tian.build.vid=0x2a03 +tian.build.pid=0x8052 +tian.build.preferred_out_format=hex +tian.bootloader.size=0x4000 +tian.build.emu.mcu=atmega2560 +tian.bootloader.tool=openocd-withbootsize +tian.bootloader.low_fuses=0xff +tian.bootloader.file=sofia/Sofia_Tian_151118.hex +tian.drivers=SiliconLabs-CP2105/Silicon Labs VCP Driver.pkg diff --git a/commands/debug/testdata/custom_hardware/arduino-test/samd/platform.txt b/commands/debug/testdata/custom_hardware/arduino-test/samd/platform.txt new file mode 100644 index 00000000000..ded30da7c9e --- /dev/null +++ b/commands/debug/testdata/custom_hardware/arduino-test/samd/platform.txt @@ -0,0 +1,231 @@ +# Copyright (c) 2014-2015 Arduino LLC. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +# Arduino SAMD Core and platform. +# +# For more info: +# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification + +name=Arduino SAMD (32-bits ARM Cortex-M0+) Boards +version=1.8.5 + +# Compile variables +# ----------------- + +compiler.warning_flags=-w +compiler.warning_flags.none=-w +compiler.warning_flags.default= +compiler.warning_flags.more=-Wall -Wno-expansion-to-defined +compiler.warning_flags.all=-Wall -Wextra -Wno-expansion-to-defined + +compiler.path={runtime.tools.arm-none-eabi-gcc-7-2017q4.path}/bin/ +compiler.c.cmd=arm-none-eabi-gcc +compiler.c.flags=-mcpu={build.mcu} -mthumb -c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -MMD +compiler.c.elf.cmd=arm-none-eabi-g++ +compiler.c.elf.flags=-Os -Wl,--gc-sections -save-temps +compiler.S.cmd=arm-none-eabi-gcc +compiler.S.flags=-c -g -x assembler-with-cpp -MMD +compiler.cpp.cmd=arm-none-eabi-g++ +compiler.cpp.flags=-mcpu={build.mcu} -mthumb -c -g -Os {compiler.warning_flags} -std=gnu++11 -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -MMD +compiler.ar.cmd=arm-none-eabi-ar +compiler.ar.flags=rcs +compiler.objcopy.cmd=arm-none-eabi-objcopy +compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 +compiler.elf2hex.bin.flags=-O binary +compiler.elf2hex.hex.flags=-O ihex -R .eeprom +compiler.elf2hex.cmd=arm-none-eabi-objcopy +compiler.ldflags=-mcpu={build.mcu} -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align +compiler.size.cmd=arm-none-eabi-size +compiler.define=-DARDUINO= +compiler.readelf.cmd=arm-none-eabi-readelf + +# this can be overriden in boards.txt +build.extra_flags= + +# These can be overridden in platform.local.txt +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +#compiler.c.elf.extra_flags=-v +compiler.cpp.extra_flags= +compiler.S.extra_flags= +compiler.ar.extra_flags= +compiler.elf2hex.extra_flags= + +compiler.arm.cmsis.c.flags="-I{runtime.tools.CMSIS-4.5.0.path}/CMSIS/Include/" "-I{runtime.tools.CMSIS-Atmel-1.2.0.path}/CMSIS/Device/ATMEL/" +compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-4.5.0.path}/CMSIS/Lib/GCC/" -larm_cortexM0l_math + +compiler.libraries.ldflags= + +# USB Flags +# --------- +build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSBCON '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' + +# Default usb manufacturer will be replaced at compile time using +# numeric vendor ID if available or by board's specific value. +build.usb_manufacturer="Unknown" + +# Compile patterns +# ---------------- + +## Compile c files +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}" + +## Compile c++ files +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}" + +## Compile S files +recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}" + +## Create archives +# archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value +archive_file_path={build.path}/{archive_file} +recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" + +## Combine gc-sections, archives, and objects +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nano.specs --specs=nosys.specs {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} {compiler.libraries.ldflags} -Wl,--start-group {compiler.arm.cmsis.ldflags} -lm "{build.path}/{archive_file}" -Wl,--end-group + +## Create output (bin file) +recipe.objcopy.bin.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.bin.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin" + +## Create output (hex file) +recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" + +build.preferred_out_format=bin + +## Save hex +recipe.output.tmp_file={build.project_name}.{build.preferred_out_format} +recipe.output.save_file={build.project_name}.{build.variant}.{build.preferred_out_format} + +## Compute size +recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" +recipe.size.regex=\.text\s+([0-9]+).* + +# Upload/Debug tools +# ------------------ + +# +# AVRDUDE +# +tools.avrdude.path={runtime.tools.avrdude.path} +tools.avrdude.cmd={path}/bin/avrdude +tools.avrdude.config.path={path}/etc/avrdude.conf + +tools.avrdude.upload.params.verbose=-v -v +tools.avrdude.upload.params.quiet=-q -q +tools.avrdude.upload.params.noverify=-V +tools.avrdude.upload.pattern="{cmd}" "-C{config.path}" {upload.verbose} -p{build.emu.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} "-Uflash:w:{build.path}/{build.project_name}.hex:i" + +tools.avrdude_remote.upload.pattern="openocd --version 2>&1 | grep 2016 && if opkg update; then opkg upgrade openocd; exit 1; else echo 'Please connect your board to the Internet in order to upgrade tools' >&2; exit 1; fi || /usr/bin/run-avrdude /tmp/sketch.hex" + +tools.avrdude.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA +tools.avrdude.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b + +# +# BOSSA +# +tools.bossac.path={runtime.tools.bossac-1.7.0-arduino3.path} +tools.bossac.cmd=bossac +tools.bossac.cmd.windows=bossac.exe + +tools.bossac.upload.params.verbose=-i -d +tools.bossac.upload.params.quiet= +tools.bossac.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port.file} -U {upload.native_usb} -i -e -w -v "{build.path}/{build.project_name}.bin" -R + +tools.bossac_remote.upload.pattern=/usr/bin/run-bossac {upload.verbose} --port=ttyATH0 -U {upload.native_usb} -e -w -v /tmp/sketch.bin -R + +tools.bossac.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA +tools.bossac.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b + +# +# BOSSA (ignore binary size) +# +tools.bossacI.path={runtime.tools.bossac-1.7.0-arduino3.path} +tools.bossacI.cmd=bossac +tools.bossacI.cmd.windows=bossac.exe + +tools.bossacI.upload.params.verbose=-i -d +tools.bossacI.upload.params.quiet= +tools.bossacI.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port.file} -I -U {upload.native_usb} -i -e -w "{build.path}/{build.project_name}.bin" -R + +tools.bossacI_remote.upload.pattern=/usr/bin/run-bossac {upload.verbose} --port=ttyATH0 -U {upload.native_usb} -e -w -v /tmp/sketch.bin -R + +tools.bossacI.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA +tools.bossacI.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b + + +# +# OpenOCD sketch upload +# + +tools.openocd.path={runtime.tools.openocd.path} +tools.openocd.cmd=bin/openocd +tools.openocd.cmd.windows=bin/openocd.exe + +tools.openocd.upload.params.verbose=-d2 +tools.openocd.upload.params.quiet=-d0 +tools.openocd.upload.pattern="{path}/{cmd}" {upload.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{build.path}/{build.project_name}.bin} verify reset 0x2000; shutdown" + +tools.openocd.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA +tools.openocd.upload.network_pattern={network_cmd} -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b + +# Program flashes the binary at 0x0000, so use the linker script without_bootloader +tools.openocd.program.params.verbose=-d2 +tools.openocd.program.params.quiet=-d0 +tools.openocd.program.pattern="{path}/{cmd}" {program.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{build.path}/{build.project_name}.elf} verify reset; shutdown" + +tools.openocd.erase.params.verbose=-d3 +tools.openocd.erase.params.quiet=-d0 +tools.openocd.erase.pattern= + +tools.openocd.bootloader.params.verbose=-d2 +tools.openocd.bootloader.params.quiet=-d0 +tools.openocd.bootloader.pattern="{path}/{cmd}" {bootloader.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; init; halt; at91samd bootloader 0; program {{runtime.platform.path}/bootloaders/{bootloader.file}} verify reset; shutdown" + +# +# OpenOCD sketch upload - version with configurable bootloader size +# FIXME: this programmer is a workaround for default options being overwritten by uploadUsingPreferences +# + +tools.openocd-withbootsize.path={runtime.tools.openocd-0.10.0-arduino7.path} +tools.openocd-withbootsize.cmd=bin/openocd +tools.openocd-withbootsize.cmd.windows=bin/openocd.exe + +tools.openocd-withbootsize.upload.params.verbose=-d2 +tools.openocd-withbootsize.upload.params.quiet=-d0 +tools.openocd-withbootsize.upload.pattern="{path}/{cmd}" {upload.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{build.path}/{build.project_name}.bin} verify reset {bootloader.size}; shutdown" + +# Program flashes the binary at 0x0000, so use the linker script without_bootloader +tools.openocd-withbootsize.program.params.verbose=-d2 +tools.openocd-withbootsize.program.params.quiet=-d0 +tools.openocd-withbootsize.program.pattern="{path}/{cmd}" {program.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{build.path}/{build.project_name}.elf} verify reset; shutdown" + +tools.openocd-withbootsize.erase.params.verbose=-d3 +tools.openocd-withbootsize.erase.params.quiet=-d0 +tools.openocd-withbootsize.erase.pattern= + +tools.openocd-withbootsize.bootloader.params.verbose=-d2 +tools.openocd-withbootsize.bootloader.params.quiet=-d0 +tools.openocd-withbootsize.bootloader.pattern="{path}/{cmd}" {bootloader.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; init; halt; at91samd bootloader 0; program {{runtime.platform.path}/bootloaders/{bootloader.file}} verify reset; shutdown" + +# +# GDB (Debugger) +# + +tools.gdb.path={runtime.tools.arm-none-eabi-gcc-7-2017q4.path}/bin/ +tools.gdb.cmd=arm-none-eabi-gdb +tools.gdb.cmd.windows=arm-none-eabi-gdb.exe + +tools.gdb.debug.pattern="{path}/{cmd}" -ex 'target extended-remote | {tools.openocd.path}/{tools.openocd.cmd} -s "{tools.openocd.path}/share/openocd/scripts/" --file "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "gdb_port pipe" -c "telnet_port 0" -c init -c halt' {build.path}/{build.project_name}.elf \ No newline at end of file diff --git a/commands/debug/testdata/data_dir/packages/arduino-test/tools/arm-none-eabi-gcc/7-2017q4/bin/arm-none-eabi-gdb b/commands/debug/testdata/data_dir/packages/arduino-test/tools/arm-none-eabi-gcc/7-2017q4/bin/arm-none-eabi-gdb new file mode 100644 index 00000000000..e69de29bb2d diff --git a/commands/debug/testdata/data_dir/packages/arduino-test/tools/openocd/0.10.0-arduino7/bin/openocd b/commands/debug/testdata/data_dir/packages/arduino-test/tools/openocd/0.10.0-arduino7/bin/openocd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/commands/debug/testdata/hello/hello.arduino-test.samd.arduino_zero_edbg.bin b/commands/debug/testdata/hello/hello.arduino-test.samd.arduino_zero_edbg.bin new file mode 100644 index 00000000000..e69de29bb2d diff --git a/commands/debug/testdata/hello/hello.arduino-test.samd.mkr1000.bin b/commands/debug/testdata/hello/hello.arduino-test.samd.mkr1000.bin new file mode 100644 index 00000000000..e69de29bb2d diff --git a/go.sum b/go.sum index db46a426af6..a07a80b85a8 100644 --- a/go.sum +++ b/go.sum @@ -184,6 +184,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/rpc/commands/commands.pb.go b/rpc/commands/commands.pb.go index 780bbed2f1e..59fe7937ed8 100644 --- a/rpc/commands/commands.pb.go +++ b/rpc/commands/commands.pb.go @@ -8,8 +8,6 @@ import ( fmt "fmt" proto "github.com/golang/protobuf/proto" grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" math "math" ) @@ -599,11 +597,11 @@ var fileDescriptor_3690061a1131852d = []byte{ // Reference imports to suppress errors if they are not otherwise used. var _ context.Context -var _ grpc.ClientConnInterface +var _ grpc.ClientConn // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 +const _ = grpc.SupportPackageIsVersion4 // ArduinoCoreClient is the client API for ArduinoCore service. // @@ -643,10 +641,10 @@ type ArduinoCoreClient interface { } type arduinoCoreClient struct { - cc grpc.ClientConnInterface + cc *grpc.ClientConn } -func NewArduinoCoreClient(cc grpc.ClientConnInterface) ArduinoCoreClient { +func NewArduinoCoreClient(cc *grpc.ClientConn) ArduinoCoreClient { return &arduinoCoreClient{cc} } @@ -1232,86 +1230,6 @@ type ArduinoCoreServer interface { LibraryList(context.Context, *LibraryListReq) (*LibraryListResp, error) } -// UnimplementedArduinoCoreServer can be embedded to have forward compatible implementations. -type UnimplementedArduinoCoreServer struct { -} - -func (*UnimplementedArduinoCoreServer) Init(req *InitReq, srv ArduinoCore_InitServer) error { - return status.Errorf(codes.Unimplemented, "method Init not implemented") -} -func (*UnimplementedArduinoCoreServer) Destroy(ctx context.Context, req *DestroyReq) (*DestroyResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method Destroy not implemented") -} -func (*UnimplementedArduinoCoreServer) Rescan(ctx context.Context, req *RescanReq) (*RescanResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method Rescan not implemented") -} -func (*UnimplementedArduinoCoreServer) UpdateIndex(req *UpdateIndexReq, srv ArduinoCore_UpdateIndexServer) error { - return status.Errorf(codes.Unimplemented, "method UpdateIndex not implemented") -} -func (*UnimplementedArduinoCoreServer) UpdateLibrariesIndex(req *UpdateLibrariesIndexReq, srv ArduinoCore_UpdateLibrariesIndexServer) error { - return status.Errorf(codes.Unimplemented, "method UpdateLibrariesIndex not implemented") -} -func (*UnimplementedArduinoCoreServer) Version(ctx context.Context, req *VersionReq) (*VersionResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method Version not implemented") -} -func (*UnimplementedArduinoCoreServer) BoardDetails(ctx context.Context, req *BoardDetailsReq) (*BoardDetailsResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method BoardDetails not implemented") -} -func (*UnimplementedArduinoCoreServer) BoardAttach(req *BoardAttachReq, srv ArduinoCore_BoardAttachServer) error { - return status.Errorf(codes.Unimplemented, "method BoardAttach not implemented") -} -func (*UnimplementedArduinoCoreServer) BoardList(ctx context.Context, req *BoardListReq) (*BoardListResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method BoardList not implemented") -} -func (*UnimplementedArduinoCoreServer) BoardListAll(ctx context.Context, req *BoardListAllReq) (*BoardListAllResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method BoardListAll not implemented") -} -func (*UnimplementedArduinoCoreServer) Compile(req *CompileReq, srv ArduinoCore_CompileServer) error { - return status.Errorf(codes.Unimplemented, "method Compile not implemented") -} -func (*UnimplementedArduinoCoreServer) PlatformInstall(req *PlatformInstallReq, srv ArduinoCore_PlatformInstallServer) error { - return status.Errorf(codes.Unimplemented, "method PlatformInstall not implemented") -} -func (*UnimplementedArduinoCoreServer) PlatformDownload(req *PlatformDownloadReq, srv ArduinoCore_PlatformDownloadServer) error { - return status.Errorf(codes.Unimplemented, "method PlatformDownload not implemented") -} -func (*UnimplementedArduinoCoreServer) PlatformUninstall(req *PlatformUninstallReq, srv ArduinoCore_PlatformUninstallServer) error { - return status.Errorf(codes.Unimplemented, "method PlatformUninstall not implemented") -} -func (*UnimplementedArduinoCoreServer) PlatformUpgrade(req *PlatformUpgradeReq, srv ArduinoCore_PlatformUpgradeServer) error { - return status.Errorf(codes.Unimplemented, "method PlatformUpgrade not implemented") -} -func (*UnimplementedArduinoCoreServer) Upload(req *UploadReq, srv ArduinoCore_UploadServer) error { - return status.Errorf(codes.Unimplemented, "method Upload not implemented") -} -func (*UnimplementedArduinoCoreServer) PlatformSearch(ctx context.Context, req *PlatformSearchReq) (*PlatformSearchResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PlatformSearch not implemented") -} -func (*UnimplementedArduinoCoreServer) PlatformList(ctx context.Context, req *PlatformListReq) (*PlatformListResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PlatformList not implemented") -} -func (*UnimplementedArduinoCoreServer) LibraryDownload(req *LibraryDownloadReq, srv ArduinoCore_LibraryDownloadServer) error { - return status.Errorf(codes.Unimplemented, "method LibraryDownload not implemented") -} -func (*UnimplementedArduinoCoreServer) LibraryInstall(req *LibraryInstallReq, srv ArduinoCore_LibraryInstallServer) error { - return status.Errorf(codes.Unimplemented, "method LibraryInstall not implemented") -} -func (*UnimplementedArduinoCoreServer) LibraryUninstall(req *LibraryUninstallReq, srv ArduinoCore_LibraryUninstallServer) error { - return status.Errorf(codes.Unimplemented, "method LibraryUninstall not implemented") -} -func (*UnimplementedArduinoCoreServer) LibraryUpgradeAll(req *LibraryUpgradeAllReq, srv ArduinoCore_LibraryUpgradeAllServer) error { - return status.Errorf(codes.Unimplemented, "method LibraryUpgradeAll not implemented") -} -func (*UnimplementedArduinoCoreServer) LibraryResolveDependencies(ctx context.Context, req *LibraryResolveDependenciesReq) (*LibraryResolveDependenciesResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method LibraryResolveDependencies not implemented") -} -func (*UnimplementedArduinoCoreServer) LibrarySearch(ctx context.Context, req *LibrarySearchReq) (*LibrarySearchResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method LibrarySearch not implemented") -} -func (*UnimplementedArduinoCoreServer) LibraryList(ctx context.Context, req *LibraryListReq) (*LibraryListResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method LibraryList not implemented") -} - func RegisterArduinoCoreServer(s *grpc.Server, srv ArduinoCoreServer) { s.RegisterService(&_ArduinoCore_serviceDesc, srv) } diff --git a/rpc/debug/debug.pb.go b/rpc/debug/debug.pb.go new file mode 100644 index 00000000000..fad8b92d951 --- /dev/null +++ b/rpc/debug/debug.pb.go @@ -0,0 +1,385 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: debug/debug.proto + +package debug + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// The top-level message sent by the client for the `Debug` method. +// Multiple `DebugReq` messages can be sent but the first message +// must contain a `DebugReq` message to initialize the debug session. +// All subsequent messages must contain bytes to be sent to the debug session +// and must not contain a `DebugReq` message. +type DebugReq struct { + // Provides information to the debug that specifies which is the target. + // The first `StreamingOpenReq` message must contain a `DebugReq` + // message. + DebugReq *DebugConfigReq `protobuf:"bytes,1,opt,name=debugReq,proto3" json:"debugReq,omitempty"` + // The data to be sent to the target being monitored. + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DebugReq) Reset() { *m = DebugReq{} } +func (m *DebugReq) String() string { return proto.CompactTextString(m) } +func (*DebugReq) ProtoMessage() {} +func (*DebugReq) Descriptor() ([]byte, []int) { + return fileDescriptor_5ae24eab94cb53d5, []int{0} +} + +func (m *DebugReq) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DebugReq.Unmarshal(m, b) +} +func (m *DebugReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DebugReq.Marshal(b, m, deterministic) +} +func (m *DebugReq) XXX_Merge(src proto.Message) { + xxx_messageInfo_DebugReq.Merge(m, src) +} +func (m *DebugReq) XXX_Size() int { + return xxx_messageInfo_DebugReq.Size(m) +} +func (m *DebugReq) XXX_DiscardUnknown() { + xxx_messageInfo_DebugReq.DiscardUnknown(m) +} + +var xxx_messageInfo_DebugReq proto.InternalMessageInfo + +func (m *DebugReq) GetDebugReq() *DebugConfigReq { + if m != nil { + return m.DebugReq + } + return nil +} + +func (m *DebugReq) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +type DebugConfigReq struct { + Instance *Instance `protobuf:"bytes,1,opt,name=instance,proto3" json:"instance,omitempty"` + Fqbn string `protobuf:"bytes,2,opt,name=fqbn,proto3" json:"fqbn,omitempty"` + SketchPath string `protobuf:"bytes,3,opt,name=sketch_path,json=sketchPath,proto3" json:"sketch_path,omitempty"` + Port string `protobuf:"bytes,4,opt,name=port,proto3" json:"port,omitempty"` + Verbose bool `protobuf:"varint,5,opt,name=verbose,proto3" json:"verbose,omitempty"` + ImportFile string `protobuf:"bytes,7,opt,name=import_file,json=importFile,proto3" json:"import_file,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DebugConfigReq) Reset() { *m = DebugConfigReq{} } +func (m *DebugConfigReq) String() string { return proto.CompactTextString(m) } +func (*DebugConfigReq) ProtoMessage() {} +func (*DebugConfigReq) Descriptor() ([]byte, []int) { + return fileDescriptor_5ae24eab94cb53d5, []int{1} +} + +func (m *DebugConfigReq) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DebugConfigReq.Unmarshal(m, b) +} +func (m *DebugConfigReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DebugConfigReq.Marshal(b, m, deterministic) +} +func (m *DebugConfigReq) XXX_Merge(src proto.Message) { + xxx_messageInfo_DebugConfigReq.Merge(m, src) +} +func (m *DebugConfigReq) XXX_Size() int { + return xxx_messageInfo_DebugConfigReq.Size(m) +} +func (m *DebugConfigReq) XXX_DiscardUnknown() { + xxx_messageInfo_DebugConfigReq.DiscardUnknown(m) +} + +var xxx_messageInfo_DebugConfigReq proto.InternalMessageInfo + +func (m *DebugConfigReq) GetInstance() *Instance { + if m != nil { + return m.Instance + } + return nil +} + +func (m *DebugConfigReq) GetFqbn() string { + if m != nil { + return m.Fqbn + } + return "" +} + +func (m *DebugConfigReq) GetSketchPath() string { + if m != nil { + return m.SketchPath + } + return "" +} + +func (m *DebugConfigReq) GetPort() string { + if m != nil { + return m.Port + } + return "" +} + +func (m *DebugConfigReq) GetVerbose() bool { + if m != nil { + return m.Verbose + } + return false +} + +func (m *DebugConfigReq) GetImportFile() string { + if m != nil { + return m.ImportFile + } + return "" +} + +// +type DebugResp struct { + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DebugResp) Reset() { *m = DebugResp{} } +func (m *DebugResp) String() string { return proto.CompactTextString(m) } +func (*DebugResp) ProtoMessage() {} +func (*DebugResp) Descriptor() ([]byte, []int) { + return fileDescriptor_5ae24eab94cb53d5, []int{2} +} + +func (m *DebugResp) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DebugResp.Unmarshal(m, b) +} +func (m *DebugResp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DebugResp.Marshal(b, m, deterministic) +} +func (m *DebugResp) XXX_Merge(src proto.Message) { + xxx_messageInfo_DebugResp.Merge(m, src) +} +func (m *DebugResp) XXX_Size() int { + return xxx_messageInfo_DebugResp.Size(m) +} +func (m *DebugResp) XXX_DiscardUnknown() { + xxx_messageInfo_DebugResp.DiscardUnknown(m) +} + +var xxx_messageInfo_DebugResp proto.InternalMessageInfo + +func (m *DebugResp) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *DebugResp) GetError() string { + if m != nil { + return m.Error + } + return "" +} + +// duplicate from commands/common.proto +// as module imports seems not to work +type Instance struct { + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Instance) Reset() { *m = Instance{} } +func (m *Instance) String() string { return proto.CompactTextString(m) } +func (*Instance) ProtoMessage() {} +func (*Instance) Descriptor() ([]byte, []int) { + return fileDescriptor_5ae24eab94cb53d5, []int{3} +} + +func (m *Instance) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Instance.Unmarshal(m, b) +} +func (m *Instance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Instance.Marshal(b, m, deterministic) +} +func (m *Instance) XXX_Merge(src proto.Message) { + xxx_messageInfo_Instance.Merge(m, src) +} +func (m *Instance) XXX_Size() int { + return xxx_messageInfo_Instance.Size(m) +} +func (m *Instance) XXX_DiscardUnknown() { + xxx_messageInfo_Instance.DiscardUnknown(m) +} + +var xxx_messageInfo_Instance proto.InternalMessageInfo + +func (m *Instance) GetId() int32 { + if m != nil { + return m.Id + } + return 0 +} + +func init() { + proto.RegisterType((*DebugReq)(nil), "cc.arduino.cli.debug.DebugReq") + proto.RegisterType((*DebugConfigReq)(nil), "cc.arduino.cli.debug.DebugConfigReq") + proto.RegisterType((*DebugResp)(nil), "cc.arduino.cli.debug.DebugResp") + proto.RegisterType((*Instance)(nil), "cc.arduino.cli.debug.Instance") +} + +func init() { proto.RegisterFile("debug/debug.proto", fileDescriptor_5ae24eab94cb53d5) } + +var fileDescriptor_5ae24eab94cb53d5 = []byte{ + // 332 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0x41, 0x4b, 0xf3, 0x40, + 0x10, 0xfd, 0xb6, 0x5f, 0x63, 0xd3, 0xa9, 0x14, 0x5c, 0x7a, 0x58, 0x7a, 0x68, 0x4b, 0xf0, 0x10, + 0x04, 0xb7, 0x52, 0xf1, 0xe2, 0x49, 0x54, 0x04, 0x2f, 0x22, 0x7b, 0x11, 0xbc, 0xd4, 0x64, 0xb3, + 0x6d, 0x16, 0xd3, 0x6c, 0xba, 0xd9, 0xfa, 0x3b, 0xfd, 0x49, 0xb2, 0x9b, 0x4d, 0x45, 0x28, 0xbd, + 0x24, 0x6f, 0x66, 0xde, 0x9b, 0xb7, 0x33, 0x0c, 0x9c, 0x65, 0x22, 0xdd, 0xad, 0xe7, 0xee, 0x4b, + 0x2b, 0xad, 0x8c, 0xc2, 0x23, 0xce, 0x69, 0xa2, 0xb3, 0x9d, 0x2c, 0x15, 0xe5, 0x85, 0xa4, 0xae, + 0x16, 0x7d, 0x40, 0xf8, 0x68, 0x01, 0x13, 0x5b, 0x7c, 0x07, 0x61, 0xe6, 0x31, 0x41, 0x33, 0x14, + 0x0f, 0x16, 0xe7, 0xf4, 0x90, 0x88, 0x3a, 0xc5, 0x83, 0x2a, 0x57, 0xd2, 0x72, 0xd9, 0x5e, 0x85, + 0x31, 0x74, 0xb3, 0xc4, 0x24, 0xa4, 0x33, 0x43, 0xf1, 0x29, 0x73, 0x38, 0xfa, 0x46, 0x30, 0xfc, + 0x2b, 0xc0, 0xb7, 0x10, 0xca, 0xb2, 0x36, 0x49, 0xc9, 0x85, 0x37, 0x9a, 0x1c, 0x36, 0x7a, 0xf6, + 0x2c, 0xb6, 0xe7, 0x5b, 0x8b, 0xd5, 0x36, 0x2d, 0x9d, 0x45, 0x9f, 0x39, 0x8c, 0xa7, 0x30, 0xa8, + 0x3f, 0x85, 0xe1, 0xf9, 0xb2, 0x4a, 0x4c, 0x4e, 0xfe, 0xbb, 0x12, 0x34, 0xa9, 0xd7, 0xc4, 0xe4, + 0x56, 0x54, 0x29, 0x6d, 0x48, 0xb7, 0x11, 0x59, 0x8c, 0x09, 0xf4, 0xbe, 0x84, 0x4e, 0x55, 0x2d, + 0x48, 0x30, 0x43, 0x71, 0xc8, 0xda, 0xd0, 0xb6, 0x93, 0x1b, 0xcb, 0x59, 0xae, 0x64, 0x21, 0x48, + 0xaf, 0x69, 0xd7, 0xa4, 0x9e, 0x64, 0x21, 0xa2, 0x1b, 0xe8, 0xfb, 0xa5, 0xd5, 0xd5, 0x7e, 0x66, + 0xf4, 0x3b, 0x33, 0x1e, 0x41, 0x20, 0xb4, 0x56, 0xda, 0xbf, 0xb2, 0x09, 0xa2, 0x31, 0x84, 0xed, + 0x40, 0x78, 0x08, 0x1d, 0x99, 0x39, 0x4d, 0xc0, 0x3a, 0x32, 0x5b, 0xbc, 0x41, 0xe0, 0x5a, 0xe2, + 0x97, 0x16, 0x4c, 0x8e, 0xec, 0x9e, 0x89, 0xed, 0x78, 0x7a, 0xb4, 0x5e, 0x57, 0xd1, 0xbf, 0x18, + 0x5d, 0xa1, 0xfb, 0x8b, 0xf7, 0x78, 0x2d, 0x4d, 0xbe, 0x4b, 0x29, 0x57, 0x9b, 0xb9, 0xe7, 0xb7, + 0xff, 0x4b, 0x5e, 0xc8, 0xb9, 0xae, 0x78, 0x73, 0x28, 0xe9, 0x89, 0xbb, 0x94, 0xeb, 0x9f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xfc, 0x58, 0x74, 0x88, 0x3e, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// DebugClient is the client API for Debug service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type DebugClient interface { + Debug(ctx context.Context, opts ...grpc.CallOption) (Debug_DebugClient, error) +} + +type debugClient struct { + cc *grpc.ClientConn +} + +func NewDebugClient(cc *grpc.ClientConn) DebugClient { + return &debugClient{cc} +} + +func (c *debugClient) Debug(ctx context.Context, opts ...grpc.CallOption) (Debug_DebugClient, error) { + stream, err := c.cc.NewStream(ctx, &_Debug_serviceDesc.Streams[0], "/cc.arduino.cli.debug.Debug/Debug", opts...) + if err != nil { + return nil, err + } + x := &debugDebugClient{stream} + return x, nil +} + +type Debug_DebugClient interface { + Send(*DebugReq) error + Recv() (*DebugResp, error) + grpc.ClientStream +} + +type debugDebugClient struct { + grpc.ClientStream +} + +func (x *debugDebugClient) Send(m *DebugReq) error { + return x.ClientStream.SendMsg(m) +} + +func (x *debugDebugClient) Recv() (*DebugResp, error) { + m := new(DebugResp) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// DebugServer is the server API for Debug service. +type DebugServer interface { + Debug(Debug_DebugServer) error +} + +func RegisterDebugServer(s *grpc.Server, srv DebugServer) { + s.RegisterService(&_Debug_serviceDesc, srv) +} + +func _Debug_Debug_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(DebugServer).Debug(&debugDebugServer{stream}) +} + +type Debug_DebugServer interface { + Send(*DebugResp) error + Recv() (*DebugReq, error) + grpc.ServerStream +} + +type debugDebugServer struct { + grpc.ServerStream +} + +func (x *debugDebugServer) Send(m *DebugResp) error { + return x.ServerStream.SendMsg(m) +} + +func (x *debugDebugServer) Recv() (*DebugReq, error) { + m := new(DebugReq) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _Debug_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cc.arduino.cli.debug.Debug", + HandlerType: (*DebugServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "Debug", + Handler: _Debug_Debug_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "debug/debug.proto", +} diff --git a/rpc/debug/debug.proto b/rpc/debug/debug.proto new file mode 100644 index 00000000000..7a8b7bb2eec --- /dev/null +++ b/rpc/debug/debug.proto @@ -0,0 +1,62 @@ +// This file is part of arduino-cli. +// +// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to +// modify or otherwise use the software for commercial activities involving the +// Arduino software without disclosing the source code of your own applications. +// To purchase a commercial license, send an email to license@arduino.cc. + +syntax = "proto3"; + +package cc.arduino.cli.debug; + +option go_package = "github.com/arduino/arduino-cli/rpc/debug"; + + +// Service that abstract a debug Session usage +service Debug { + rpc Debug(stream DebugReq) returns (stream DebugResp) { } +} + +// The top-level message sent by the client for the `Debug` method. +// Multiple `DebugReq` messages can be sent but the first message +// must contain a `DebugReq` message to initialize the debug session. +// All subsequent messages must contain bytes to be sent to the debug session +// and must not contain a `DebugReq` message. +message DebugReq { + // Content must be either a debug session config or data to be sent. + + // Provides information to the debug that specifies which is the target. + // The first `StreamingOpenReq` message must contain a `DebugReq` + // message. + DebugConfigReq debugReq = 1; + + // The data to be sent to the target being monitored. + bytes data = 2; +} + +message DebugConfigReq { + Instance instance = 1; + string fqbn = 2; + string sketch_path = 3; + string port = 4; + bool verbose = 5; + string import_file = 7; +} + + +// +message DebugResp { + bytes data = 1; + string error = 2; +} + +// TODO remove this in next proto refactoring because is a duplicate from commands/common.proto +message Instance { int32 id = 1; } diff --git a/rpc/monitor/monitor.pb.go b/rpc/monitor/monitor.pb.go index 1a06ba48521..78238c1565a 100644 --- a/rpc/monitor/monitor.pb.go +++ b/rpc/monitor/monitor.pb.go @@ -9,8 +9,6 @@ import ( proto "github.com/golang/protobuf/proto" _struct "github.com/golang/protobuf/ptypes/struct" grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" math "math" ) @@ -268,11 +266,11 @@ var fileDescriptor_94d5950496a7550d = []byte{ // Reference imports to suppress errors if they are not otherwise used. var _ context.Context -var _ grpc.ClientConnInterface +var _ grpc.ClientConn // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 +const _ = grpc.SupportPackageIsVersion4 // MonitorClient is the client API for Monitor service. // @@ -282,10 +280,10 @@ type MonitorClient interface { } type monitorClient struct { - cc grpc.ClientConnInterface + cc *grpc.ClientConn } -func NewMonitorClient(cc grpc.ClientConnInterface) MonitorClient { +func NewMonitorClient(cc *grpc.ClientConn) MonitorClient { return &monitorClient{cc} } @@ -325,14 +323,6 @@ type MonitorServer interface { StreamingOpen(Monitor_StreamingOpenServer) error } -// UnimplementedMonitorServer can be embedded to have forward compatible implementations. -type UnimplementedMonitorServer struct { -} - -func (*UnimplementedMonitorServer) StreamingOpen(srv Monitor_StreamingOpenServer) error { - return status.Errorf(codes.Unimplemented, "method StreamingOpen not implemented") -} - func RegisterMonitorServer(s *grpc.Server, srv MonitorServer) { s.RegisterService(&_Monitor_serviceDesc, srv) } diff --git a/rpc/settings/settings.pb.go b/rpc/settings/settings.pb.go index 0537c7d9e3a..1bbc54f255d 100644 --- a/rpc/settings/settings.pb.go +++ b/rpc/settings/settings.pb.go @@ -8,8 +8,6 @@ import ( fmt "fmt" proto "github.com/golang/protobuf/proto" grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" math "math" ) @@ -277,11 +275,11 @@ var fileDescriptor_a4bfd59e429426d0 = []byte{ // Reference imports to suppress errors if they are not otherwise used. var _ context.Context -var _ grpc.ClientConnInterface +var _ grpc.ClientConn // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 +const _ = grpc.SupportPackageIsVersion4 // SettingsClient is the client API for Settings service. // @@ -294,10 +292,10 @@ type SettingsClient interface { } type settingsClient struct { - cc grpc.ClientConnInterface + cc *grpc.ClientConn } -func NewSettingsClient(cc grpc.ClientConnInterface) SettingsClient { +func NewSettingsClient(cc *grpc.ClientConn) SettingsClient { return &settingsClient{cc} } @@ -345,23 +343,6 @@ type SettingsServer interface { SetValue(context.Context, *Value) (*SetValueResponse, error) } -// UnimplementedSettingsServer can be embedded to have forward compatible implementations. -type UnimplementedSettingsServer struct { -} - -func (*UnimplementedSettingsServer) GetAll(ctx context.Context, req *GetAllRequest) (*RawData, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetAll not implemented") -} -func (*UnimplementedSettingsServer) Merge(ctx context.Context, req *RawData) (*MergeResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Merge not implemented") -} -func (*UnimplementedSettingsServer) GetValue(ctx context.Context, req *GetValueRequest) (*Value, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetValue not implemented") -} -func (*UnimplementedSettingsServer) SetValue(ctx context.Context, req *Value) (*SetValueResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method SetValue not implemented") -} - func RegisterSettingsServer(s *grpc.Server, srv SettingsServer) { s.RegisterService(&_Settings_serviceDesc, srv) } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy