4
4
"bytes"
5
5
"context"
6
6
"fmt"
7
+ "io"
7
8
"runtime"
8
9
"strings"
9
10
"sync"
@@ -12,6 +13,7 @@ import (
12
13
"github.com/arduino/arduino-cli/arduino/builder"
13
14
"github.com/arduino/arduino-cli/arduino/libraries"
14
15
"github.com/arduino/arduino-cli/executils"
16
+ rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
15
17
"github.com/arduino/arduino-language-server/sourcemapper"
16
18
"github.com/arduino/arduino-language-server/streams"
17
19
"github.com/arduino/go-paths-helper"
@@ -20,6 +22,7 @@ import (
20
22
"go.bug.st/json"
21
23
"go.bug.st/lsp"
22
24
"go.bug.st/lsp/jsonrpc"
25
+ "google.golang.org/grpc"
23
26
)
24
27
25
28
type SketchRebuilder struct {
@@ -172,65 +175,116 @@ func (ls *INOLanguageServer) generateBuildEnvironment(ctx context.Context, logge
172
175
}
173
176
ls .readUnlock (logger )
174
177
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
+
184
225
} else {
185
- overridesJSON = tmp
186
- defer tmp .Remove ()
187
- }
188
226
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
+ }
212
240
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
227
282
}
228
- logger .Logf ("arduino-cli output: %s" , cmdOutput )
229
283
230
284
// TODO: do canonicalization directly in `arduino-cli`
231
285
canonicalizeCompileCommandsJSON (buildPath .Join ("compile_commands.json" ))
232
286
233
- return res . Success , nil
287
+ return success , nil
234
288
}
235
289
236
290
func canonicalizeCompileCommandsJSON (compileCommandsJSONPath * paths.Path ) {
0 commit comments