Skip to content

Commit 27c3eb6

Browse files
committed
Use arduino-cli RPC to ger sketch compiled
1 parent e709702 commit 27c3eb6

File tree

1 file changed

+105
-51
lines changed

1 file changed

+105
-51
lines changed

Diff for: ls/builder.go

+105-51
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
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

2528
type 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

236290
func canonicalizeCompileCommandsJSON(compileCommandsJSONPath *paths.Path) {

0 commit comments

Comments
 (0)