44 "bytes"
55 "context"
66 "fmt"
7+ "io"
78 "runtime"
89 "strings"
910 "sync"
@@ -12,6 +13,7 @@ import (
1213 "github.com/arduino/arduino-cli/arduino/builder"
1314 "github.com/arduino/arduino-cli/arduino/libraries"
1415 "github.com/arduino/arduino-cli/executils"
16+ rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
1517 "github.com/arduino/arduino-language-server/sourcemapper"
1618 "github.com/arduino/arduino-language-server/streams"
1719 "github.com/arduino/go-paths-helper"
@@ -20,6 +22,7 @@ import (
2022 "go.bug.st/json"
2123 "go.bug.st/lsp"
2224 "go.bug.st/lsp/jsonrpc"
25+ "google.golang.org/grpc"
2326)
2427
2528type SketchRebuilder struct {
@@ -172,65 +175,116 @@ func (ls *INOLanguageServer) generateBuildEnvironment(ctx context.Context, logge
172175 }
173176 ls .readUnlock (logger )
174177
175- // Run arduino-cli to perform the build
176- for filename , override := range data .Overrides {
177- logger .Logf ("Dumping %s override:\n %s" , filename , override )
178- }
179- var overridesJSON * paths.Path
180- if jsonBytes , err := json .MarshalIndent (data , "" , " " ); err != nil {
181- return false , errors .WithMessage (err , "dumping tracked files" )
182- } else if tmp , err := paths .WriteToTempFile (jsonBytes , nil , "" ); err != nil {
183- return false , errors .WithMessage (err , "dumping tracked files" )
178+ var success bool
179+ if true {
180+ // Establish a connection with the gRPC server, started with the command:
181+ // arduino-cli daemon
182+ conn , err := grpc .Dial ("localhost:50051" , grpc .WithInsecure (), grpc .WithBlock ())
183+ if err != nil {
184+ return false , fmt .Errorf ("error connecting to arduino-cli rpc server: %w" , err )
185+ }
186+ defer conn .Close ()
187+
188+ client := rpc .NewArduinoCoreServiceClient (conn )
189+ compRespStream , err := client .Compile (context .Background (),
190+ & rpc.CompileRequest {
191+ Instance : & rpc.Instance {Id : 1 }, // XXX
192+ Fqbn : fqbn ,
193+ SketchPath : sketchRoot .String (),
194+ SourceOverride : data .Overrides ,
195+ BuildPath : buildPath .String (),
196+ CreateCompilationDatabaseOnly : true ,
197+ },
198+ )
199+ if err != nil {
200+ return false , fmt .Errorf ("error running compile: %w" , err )
201+ }
202+
203+ // Loop and consume the server stream until all the operations are done.
204+ for {
205+ compResp , err := compRespStream .Recv ()
206+ if err == io .EOF {
207+ success = true
208+ logger .Logf ("Compile successful!" )
209+ break
210+ }
211+ if err != nil {
212+ return false , fmt .Errorf ("error running compile: %w" , err )
213+ }
214+
215+ // TODO: we can accumulate stdout/stderr buffer if needed
216+ _ = compResp
217+ // if resp := compResp.GetOutStream(); resp != nil {
218+ // logger.Logf("STDOUT: %s", resp)
219+ // }
220+ // if resperr := compResp.GetErrStream(); resperr != nil {
221+ // logger.Logf("STDERR: %s", resperr)
222+ // }
223+ }
224+
184225 } else {
185- overridesJSON = tmp
186- defer tmp .Remove ()
187- }
188226
189- // XXX: do this from IDE or via gRPC
190- args := []string {globalCliPath ,
191- "--config-file" , globalCliConfigPath ,
192- "compile" ,
193- "--fqbn" , fqbn ,
194- "--only-compilation-database" ,
195- //"--clean",
196- "--source-override" , overridesJSON .String (),
197- "--build-path" , buildPath .String (),
198- "--format" , "json" ,
199- sketchRoot .String (),
200- }
201- cmd , err := executils .NewProcess (args ... )
202- if err != nil {
203- return false , errors .Errorf ("running %s: %s" , strings .Join (args , " " ), err )
204- }
205- cmdOutput := & bytes.Buffer {}
206- cmd .RedirectStdoutTo (cmdOutput )
207- cmd .SetDirFromPath (sketchRoot )
208- logger .Logf ("running: %s" , strings .Join (args , " " ))
209- if err := cmd .RunWithinContext (ctx ); err != nil {
210- return false , errors .Errorf ("running %s: %s" , strings .Join (args , " " ), err )
211- }
227+ // Dump overrides into a temporary json file
228+ for filename , override := range data .Overrides {
229+ logger .Logf ("Dumping %s override:\n %s" , filename , override )
230+ }
231+ var overridesJSON * paths.Path
232+ if jsonBytes , err := json .MarshalIndent (data , "" , " " ); err != nil {
233+ return false , errors .WithMessage (err , "dumping tracked files" )
234+ } else if tmp , err := paths .WriteToTempFile (jsonBytes , nil , "" ); err != nil {
235+ return false , errors .WithMessage (err , "dumping tracked files" )
236+ } else {
237+ overridesJSON = tmp
238+ defer tmp .Remove ()
239+ }
212240
213- // Currently those values are not used, keeping here for future improvements
214- type cmdBuilderRes struct {
215- BuildPath * paths.Path `json:"build_path"`
216- UsedLibraries []* libraries.Library
217- }
218- type cmdRes struct {
219- CompilerOut string `json:"compiler_out"`
220- CompilerErr string `json:"compiler_err"`
221- BuilderResult cmdBuilderRes `json:"builder_result"`
222- Success bool `json:"success"`
223- }
224- var res cmdRes
225- if err := json .Unmarshal (cmdOutput .Bytes (), & res ); err != nil {
226- return false , errors .Errorf ("parsing arduino-cli output: %s" , err )
241+ // Run arduino-cli to perform the build
242+ args := []string {globalCliPath ,
243+ "--config-file" , globalCliConfigPath ,
244+ "compile" ,
245+ "--fqbn" , fqbn ,
246+ "--only-compilation-database" ,
247+ //"--clean",
248+ "--source-override" , overridesJSON .String (),
249+ "--build-path" , buildPath .String (),
250+ "--format" , "json" ,
251+ sketchRoot .String (),
252+ }
253+ cmd , err := executils .NewProcess (args ... )
254+ if err != nil {
255+ return false , errors .Errorf ("running %s: %s" , strings .Join (args , " " ), err )
256+ }
257+ cmdOutput := & bytes.Buffer {}
258+ cmd .RedirectStdoutTo (cmdOutput )
259+ cmd .SetDirFromPath (sketchRoot )
260+ logger .Logf ("running: %s" , strings .Join (args , " " ))
261+ if err := cmd .RunWithinContext (ctx ); err != nil {
262+ return false , errors .Errorf ("running %s: %s" , strings .Join (args , " " ), err )
263+ }
264+
265+ // Currently those values are not used, keeping here for future improvements
266+ type cmdBuilderRes struct {
267+ BuildPath * paths.Path `json:"build_path"`
268+ UsedLibraries []* libraries.Library
269+ }
270+ type cmdRes struct {
271+ CompilerOut string `json:"compiler_out"`
272+ CompilerErr string `json:"compiler_err"`
273+ BuilderResult cmdBuilderRes `json:"builder_result"`
274+ Success bool `json:"success"`
275+ }
276+ var res cmdRes
277+ if err := json .Unmarshal (cmdOutput .Bytes (), & res ); err != nil {
278+ return false , errors .Errorf ("parsing arduino-cli output: %s" , err )
279+ }
280+ logger .Logf ("arduino-cli output: %s" , cmdOutput )
281+ success = res .Success
227282 }
228- logger .Logf ("arduino-cli output: %s" , cmdOutput )
229283
230284 // TODO: do canonicalization directly in `arduino-cli`
231285 canonicalizeCompileCommandsJSON (buildPath .Join ("compile_commands.json" ))
232286
233- return res . Success , nil
287+ return success , nil
234288}
235289
236290func canonicalizeCompileCommandsJSON (compileCommandsJSONPath * paths.Path ) {
0 commit comments