@@ -38,8 +38,33 @@ import (
38
38
"github.com/sirupsen/logrus"
39
39
)
40
40
41
- // Compile FIXMEDOC
42
- func Compile (ctx context.Context , req * rpc.CompileRequest , outStream , errStream io.Writer , progressCB rpc.TaskProgressCB ) (r * rpc.BuilderResult , e error ) {
41
+ // CompilerServerToStreams creates a gRPC CompileServer that sends the responses to the provided streams.
42
+ // The returned callback function can be used to retrieve the builder result after the compilation is done.
43
+ func CompilerServerToStreams (ctx context.Context , stdOut , stderr io.Writer ) (server rpc.ArduinoCoreService_CompileServer , resultCB func () * rpc.BuilderResult ) {
44
+ var builderResult * rpc.BuilderResult
45
+ stream := streamResponseToCallback (ctx , func (resp * rpc.CompileResponse ) error {
46
+ if out := resp .GetOutStream (); len (out ) > 0 {
47
+ if _ , err := stdOut .Write (out ); err != nil {
48
+ return err
49
+ }
50
+ }
51
+ if err := resp .GetErrStream (); len (err ) > 0 {
52
+ if _ , err := stderr .Write (err ); err != nil {
53
+ return err
54
+ }
55
+ }
56
+ if result := resp .GetResult (); result != nil {
57
+ builderResult = result
58
+ }
59
+ return nil
60
+ })
61
+ return stream , func () * rpc.BuilderResult { return builderResult }
62
+ }
63
+
64
+ // Compile performs a compilation of a sketch.
65
+ func (s * arduinoCoreServerImpl ) Compile (req * rpc.CompileRequest , stream rpc.ArduinoCoreService_CompileServer ) error {
66
+ ctx := stream .Context ()
67
+ syncSend := NewSynchronizedSend (stream .Send )
43
68
44
69
// There is a binding between the export binaries setting and the CLI flag to explicitly set it,
45
70
// since we want this binding to work also for the gRPC interface we must read it here in this
@@ -56,27 +81,27 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
56
81
57
82
pme , release , err := instances .GetPackageManagerExplorer (req .GetInstance ())
58
83
if err != nil {
59
- return nil , err
84
+ return err
60
85
}
61
86
defer release ()
62
87
63
88
if pme .Dirty () {
64
- return nil , & cmderrors.InstanceNeedsReinitialization {}
89
+ return & cmderrors.InstanceNeedsReinitialization {}
65
90
}
66
91
67
92
lm , err := instances .GetLibraryManager (req .GetInstance ())
68
93
if err != nil {
69
- return nil , err
94
+ return err
70
95
}
71
96
72
97
logrus .Tracef ("Compile %s for %s started" , req .GetSketchPath (), req .GetFqbn ())
73
98
if req .GetSketchPath () == "" {
74
- return nil , & cmderrors.MissingSketchPathError {}
99
+ return & cmderrors.MissingSketchPathError {}
75
100
}
76
101
sketchPath := paths .New (req .GetSketchPath ())
77
102
sk , err := sketch .New (sketchPath )
78
103
if err != nil {
79
- return nil , & cmderrors.CantOpenSketchError {Cause : err }
104
+ return & cmderrors.CantOpenSketchError {Cause : err }
80
105
}
81
106
82
107
fqbnIn := req .GetFqbn ()
@@ -88,25 +113,30 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
88
113
}
89
114
}
90
115
if fqbnIn == "" {
91
- return nil , & cmderrors.MissingFQBNError {}
116
+ return & cmderrors.MissingFQBNError {}
92
117
}
93
118
94
119
fqbn , err := cores .ParseFQBN (fqbnIn )
95
120
if err != nil {
96
- return nil , & cmderrors.InvalidFQBNError {Cause : err }
121
+ return & cmderrors.InvalidFQBNError {Cause : err }
97
122
}
98
123
_ , targetPlatform , targetBoard , boardBuildProperties , buildPlatform , err := pme .ResolveFQBN (fqbn )
99
124
if err != nil {
100
125
if targetPlatform == nil {
101
- return nil , & cmderrors.PlatformNotFoundError {
126
+ return & cmderrors.PlatformNotFoundError {
102
127
Platform : fmt .Sprintf ("%s:%s" , fqbn .Package , fqbn .PlatformArch ),
103
128
Cause : fmt .Errorf (tr ("platform not installed" )),
104
129
}
105
130
}
106
- return nil , & cmderrors.InvalidFQBNError {Cause : err }
131
+ return & cmderrors.InvalidFQBNError {Cause : err }
107
132
}
108
133
109
- r = & rpc.BuilderResult {}
134
+ r := & rpc.BuilderResult {}
135
+ defer func () {
136
+ syncSend .Send (& rpc.CompileResponse {
137
+ Message : & rpc.CompileResponse_Result {Result : r },
138
+ })
139
+ }()
110
140
r .BoardPlatform = targetPlatform .ToRPCPlatformReference ()
111
141
r .BuildPlatform = buildPlatform .ToRPCPlatformReference ()
112
142
@@ -129,7 +159,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
129
159
encryptProp := boardBuildProperties .ContainsKey ("build.keys.encrypt_key" )
130
160
// we verify that all the properties for the secure boot keys are defined or none of them is defined.
131
161
if ! (keychainProp == signProp && signProp == encryptProp ) {
132
- return nil , fmt .Errorf (tr ("Firmware encryption/signing requires all the following properties to be defined: %s" , "build.keys.keychain, build.keys.sign_key, build.keys.encrypt_key" ))
162
+ return fmt .Errorf (tr ("Firmware encryption/signing requires all the following properties to be defined: %s" , "build.keys.keychain, build.keys.sign_key, build.keys.encrypt_key" ))
133
163
}
134
164
135
165
// Generate or retrieve build path
@@ -138,15 +168,15 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
138
168
buildPath = paths .New (req .GetBuildPath ()).Canonical ()
139
169
if in , _ := buildPath .IsInsideDir (sk .FullPath ); in && buildPath .IsDir () {
140
170
if sk .AdditionalFiles , err = removeBuildFromSketchFiles (sk .AdditionalFiles , buildPath ); err != nil {
141
- return nil , err
171
+ return err
142
172
}
143
173
}
144
174
}
145
175
if buildPath == nil {
146
176
buildPath = sk .DefaultBuildPath ()
147
177
}
148
178
if err = buildPath .MkdirAll (); err != nil {
149
- return nil , & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build directory" ), Cause : err }
179
+ return & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build directory" ), Cause : err }
150
180
}
151
181
buildcache .New (buildPath .Parent ()).GetOrCreate (buildPath .Base ())
152
182
// cache is purged after compilation to not remove entries that might be required
@@ -158,16 +188,16 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
158
188
} else {
159
189
buildCachePath , err := paths .New (req .GetBuildCachePath ()).Abs ()
160
190
if err != nil {
161
- return nil , & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build cache directory" ), Cause : err }
191
+ return & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build cache directory" ), Cause : err }
162
192
}
163
193
if err := buildCachePath .MkdirAll (); err != nil {
164
- return nil , & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build cache directory" ), Cause : err }
194
+ return & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build cache directory" ), Cause : err }
165
195
}
166
196
coreBuildCachePath = buildCachePath .Join ("core" )
167
197
}
168
198
169
199
if _ , err := pme .FindToolsRequiredForBuild (targetPlatform , buildPlatform ); err != nil {
170
- return nil , err
200
+ return err
171
201
}
172
202
173
203
actualPlatform := buildPlatform
@@ -179,7 +209,25 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
179
209
libsManager = lm
180
210
}
181
211
212
+ outStream := feedStreamTo (func (data []byte ) {
213
+ syncSend .Send (& rpc.CompileResponse {
214
+ Message : & rpc.CompileResponse_OutStream {OutStream : data },
215
+ })
216
+ })
217
+ defer outStream .Close ()
218
+ errStream := feedStreamTo (func (data []byte ) {
219
+ syncSend .Send (& rpc.CompileResponse {
220
+ Message : & rpc.CompileResponse_ErrStream {ErrStream : data },
221
+ })
222
+ })
223
+ defer errStream .Close ()
224
+ progressCB := func (p * rpc.TaskProgress ) {
225
+ syncSend .Send (& rpc.CompileResponse {
226
+ Message : & rpc.CompileResponse_Progress {Progress : p },
227
+ })
228
+ }
182
229
sketchBuilder , err := builder .NewBuilder (
230
+ ctx ,
183
231
sk ,
184
232
boardBuildProperties ,
185
233
buildPath ,
@@ -204,14 +252,14 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
204
252
)
205
253
if err != nil {
206
254
if strings .Contains (err .Error (), "invalid build properties" ) {
207
- return nil , & cmderrors.InvalidArgumentError {Message : tr ("Invalid build properties" ), Cause : err }
255
+ return & cmderrors.InvalidArgumentError {Message : tr ("Invalid build properties" ), Cause : err }
208
256
}
209
257
if errors .Is (err , builder .ErrSketchCannotBeLocatedInBuildPath ) {
210
- return r , & cmderrors.CompileFailedError {
258
+ return & cmderrors.CompileFailedError {
211
259
Message : tr ("Sketch cannot be located in build path. Please specify a different build path" ),
212
260
}
213
261
}
214
- return r , & cmderrors.CompileFailedError {Message : err .Error ()}
262
+ return & cmderrors.CompileFailedError {Message : err .Error ()}
215
263
}
216
264
217
265
defer func () {
@@ -241,18 +289,18 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
241
289
242
290
// Just get build properties and exit
243
291
if req .GetShowProperties () {
244
- return r , nil
292
+ return nil
245
293
}
246
294
247
295
if req .GetPreprocess () {
248
296
// Just output preprocessed source code and exit
249
297
preprocessedSketch , err := sketchBuilder .Preprocess ()
250
298
if err != nil {
251
299
err = & cmderrors.CompileFailedError {Message : err .Error ()}
252
- return r , err
300
+ return err
253
301
}
254
302
_ , err = outStream .Write (preprocessedSketch )
255
- return r , err
303
+ return err
256
304
}
257
305
258
306
defer func () {
@@ -294,7 +342,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
294
342
}
295
343
296
344
if err := sketchBuilder .Build (); err != nil {
297
- return r , & cmderrors.CompileFailedError {Message : err .Error ()}
345
+ return & cmderrors.CompileFailedError {Message : err .Error ()}
298
346
}
299
347
300
348
// If the export directory is set we assume you want to export the binaries
@@ -306,9 +354,8 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
306
354
exportBinaries = false
307
355
}
308
356
if exportBinaries {
309
- err := sketchBuilder .RunRecipe ("recipe.hooks.savehex.presavehex" , ".pattern" , false )
310
- if err != nil {
311
- return r , err
357
+ if err := sketchBuilder .RunRecipe ("recipe.hooks.savehex.presavehex" , ".pattern" , false ); err != nil {
358
+ return err
312
359
}
313
360
314
361
exportPath := paths .New (req .GetExportDir ())
@@ -322,38 +369,36 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
322
369
if ! buildPath .EqualsTo (exportPath ) {
323
370
logrus .WithField ("path" , exportPath ).Trace ("Saving sketch to export path." )
324
371
if err := exportPath .MkdirAll (); err != nil {
325
- return r , & cmderrors.PermissionDeniedError {Message : tr ("Error creating output dir" ), Cause : err }
372
+ return & cmderrors.PermissionDeniedError {Message : tr ("Error creating output dir" ), Cause : err }
326
373
}
327
374
328
375
baseName , ok := sketchBuilder .GetBuildProperties ().GetOk ("build.project_name" ) // == "sketch.ino"
329
376
if ! ok {
330
- return r , & cmderrors.MissingPlatformPropertyError {Property : "build.project_name" }
377
+ return & cmderrors.MissingPlatformPropertyError {Property : "build.project_name" }
331
378
}
332
379
buildFiles , err := sketchBuilder .GetBuildPath ().ReadDir ()
333
380
if err != nil {
334
- return r , & cmderrors.PermissionDeniedError {Message : tr ("Error reading build directory" ), Cause : err }
381
+ return & cmderrors.PermissionDeniedError {Message : tr ("Error reading build directory" ), Cause : err }
335
382
}
336
383
buildFiles .FilterPrefix (baseName )
337
384
for _ , buildFile := range buildFiles {
338
385
exportedFile := exportPath .Join (buildFile .Base ())
339
386
logrus .WithField ("src" , buildFile ).WithField ("dest" , exportedFile ).Trace ("Copying artifact." )
340
387
if err = buildFile .CopyTo (exportedFile ); err != nil {
341
- return r , & cmderrors.PermissionDeniedError {Message : tr ("Error copying output file %s" , buildFile ), Cause : err }
388
+ return & cmderrors.PermissionDeniedError {Message : tr ("Error copying output file %s" , buildFile ), Cause : err }
342
389
}
343
390
}
344
391
}
345
392
346
- err = sketchBuilder .RunRecipe ("recipe.hooks.savehex.postsavehex" , ".pattern" , false )
347
- if err != nil {
348
- return r , err
393
+ if err = sketchBuilder .RunRecipe ("recipe.hooks.savehex.postsavehex" , ".pattern" , false ); err != nil {
394
+ return err
349
395
}
350
396
}
351
397
352
398
r .ExecutableSectionsSize = sketchBuilder .ExecutableSectionsSize ().ToRPCExecutableSectionSizeArray ()
353
399
354
400
logrus .Tracef ("Compile %s for %s successful" , sk .Name , fqbnIn )
355
-
356
- return r , nil
401
+ return nil
357
402
}
358
403
359
404
// maybePurgeBuildCache runs the build files cache purge if the policy conditions are met.
0 commit comments