@@ -38,36 +38,62 @@ 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 )
68
+
43
69
exportBinaries := configuration .Settings .GetBool ("sketch.always_export_binaries" )
44
70
if e := req .ExportBinaries ; e != nil {
45
71
exportBinaries = * e
46
72
}
47
73
48
74
pme , release , err := instances .GetPackageManagerExplorer (req .GetInstance ())
49
75
if err != nil {
50
- return nil , err
76
+ return err
51
77
}
52
78
defer release ()
53
79
54
80
if pme .Dirty () {
55
- return nil , & cmderrors.InstanceNeedsReinitialization {}
81
+ return & cmderrors.InstanceNeedsReinitialization {}
56
82
}
57
83
58
84
lm , err := instances .GetLibraryManager (req .GetInstance ())
59
85
if err != nil {
60
- return nil , err
86
+ return err
61
87
}
62
88
63
89
logrus .Tracef ("Compile %s for %s started" , req .GetSketchPath (), req .GetFqbn ())
64
90
if req .GetSketchPath () == "" {
65
- return nil , & cmderrors.MissingSketchPathError {}
91
+ return & cmderrors.MissingSketchPathError {}
66
92
}
67
93
sketchPath := paths .New (req .GetSketchPath ())
68
94
sk , err := sketch .New (sketchPath )
69
95
if err != nil {
70
- return nil , & cmderrors.CantOpenSketchError {Cause : err }
96
+ return & cmderrors.CantOpenSketchError {Cause : err }
71
97
}
72
98
73
99
fqbnIn := req .GetFqbn ()
@@ -79,25 +105,30 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
79
105
}
80
106
}
81
107
if fqbnIn == "" {
82
- return nil , & cmderrors.MissingFQBNError {}
108
+ return & cmderrors.MissingFQBNError {}
83
109
}
84
110
85
111
fqbn , err := cores .ParseFQBN (fqbnIn )
86
112
if err != nil {
87
- return nil , & cmderrors.InvalidFQBNError {Cause : err }
113
+ return & cmderrors.InvalidFQBNError {Cause : err }
88
114
}
89
115
_ , targetPlatform , targetBoard , boardBuildProperties , buildPlatform , err := pme .ResolveFQBN (fqbn )
90
116
if err != nil {
91
117
if targetPlatform == nil {
92
- return nil , & cmderrors.PlatformNotFoundError {
118
+ return & cmderrors.PlatformNotFoundError {
93
119
Platform : fmt .Sprintf ("%s:%s" , fqbn .Package , fqbn .PlatformArch ),
94
120
Cause : fmt .Errorf (tr ("platform not installed" )),
95
121
}
96
122
}
97
- return nil , & cmderrors.InvalidFQBNError {Cause : err }
123
+ return & cmderrors.InvalidFQBNError {Cause : err }
98
124
}
99
125
100
- r = & rpc.BuilderResult {}
126
+ r := & rpc.BuilderResult {}
127
+ defer func () {
128
+ syncSend .Send (& rpc.CompileResponse {
129
+ Message : & rpc.CompileResponse_Result {Result : r },
130
+ })
131
+ }()
101
132
r .BoardPlatform = targetPlatform .ToRPCPlatformReference ()
102
133
r .BuildPlatform = buildPlatform .ToRPCPlatformReference ()
103
134
@@ -120,7 +151,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
120
151
encryptProp := boardBuildProperties .ContainsKey ("build.keys.encrypt_key" )
121
152
// we verify that all the properties for the secure boot keys are defined or none of them is defined.
122
153
if ! (keychainProp == signProp && signProp == encryptProp ) {
123
- 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" ))
154
+ 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" ))
124
155
}
125
156
126
157
// Generate or retrieve build path
@@ -129,15 +160,15 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
129
160
buildPath = paths .New (req .GetBuildPath ()).Canonical ()
130
161
if in , _ := buildPath .IsInsideDir (sk .FullPath ); in && buildPath .IsDir () {
131
162
if sk .AdditionalFiles , err = removeBuildFromSketchFiles (sk .AdditionalFiles , buildPath ); err != nil {
132
- return nil , err
163
+ return err
133
164
}
134
165
}
135
166
}
136
167
if buildPath == nil {
137
168
buildPath = sk .DefaultBuildPath ()
138
169
}
139
170
if err = buildPath .MkdirAll (); err != nil {
140
- return nil , & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build directory" ), Cause : err }
171
+ return & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build directory" ), Cause : err }
141
172
}
142
173
buildcache .New (buildPath .Parent ()).GetOrCreate (buildPath .Base ())
143
174
// cache is purged after compilation to not remove entries that might be required
@@ -149,16 +180,16 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
149
180
} else {
150
181
buildCachePath , err := paths .New (req .GetBuildCachePath ()).Abs ()
151
182
if err != nil {
152
- return nil , & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build cache directory" ), Cause : err }
183
+ return & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build cache directory" ), Cause : err }
153
184
}
154
185
if err := buildCachePath .MkdirAll (); err != nil {
155
- return nil , & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build cache directory" ), Cause : err }
186
+ return & cmderrors.PermissionDeniedError {Message : tr ("Cannot create build cache directory" ), Cause : err }
156
187
}
157
188
coreBuildCachePath = buildCachePath .Join ("core" )
158
189
}
159
190
160
191
if _ , err := pme .FindToolsRequiredForBuild (targetPlatform , buildPlatform ); err != nil {
161
- return nil , err
192
+ return err
162
193
}
163
194
164
195
actualPlatform := buildPlatform
@@ -170,7 +201,25 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
170
201
libsManager = lm
171
202
}
172
203
204
+ outStream := feedStreamTo (func (data []byte ) {
205
+ syncSend .Send (& rpc.CompileResponse {
206
+ Message : & rpc.CompileResponse_OutStream {OutStream : data },
207
+ })
208
+ })
209
+ defer outStream .Close ()
210
+ errStream := feedStreamTo (func (data []byte ) {
211
+ syncSend .Send (& rpc.CompileResponse {
212
+ Message : & rpc.CompileResponse_ErrStream {ErrStream : data },
213
+ })
214
+ })
215
+ defer errStream .Close ()
216
+ progressCB := func (p * rpc.TaskProgress ) {
217
+ syncSend .Send (& rpc.CompileResponse {
218
+ Message : & rpc.CompileResponse_Progress {Progress : p },
219
+ })
220
+ }
173
221
sketchBuilder , err := builder .NewBuilder (
222
+ ctx ,
174
223
sk ,
175
224
boardBuildProperties ,
176
225
buildPath ,
@@ -195,14 +244,14 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
195
244
)
196
245
if err != nil {
197
246
if strings .Contains (err .Error (), "invalid build properties" ) {
198
- return nil , & cmderrors.InvalidArgumentError {Message : tr ("Invalid build properties" ), Cause : err }
247
+ return & cmderrors.InvalidArgumentError {Message : tr ("Invalid build properties" ), Cause : err }
199
248
}
200
249
if errors .Is (err , builder .ErrSketchCannotBeLocatedInBuildPath ) {
201
- return r , & cmderrors.CompileFailedError {
250
+ return & cmderrors.CompileFailedError {
202
251
Message : tr ("Sketch cannot be located in build path. Please specify a different build path" ),
203
252
}
204
253
}
205
- return r , & cmderrors.CompileFailedError {Message : err .Error ()}
254
+ return & cmderrors.CompileFailedError {Message : err .Error ()}
206
255
}
207
256
208
257
defer func () {
@@ -232,18 +281,18 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
232
281
233
282
// Just get build properties and exit
234
283
if req .GetShowProperties () {
235
- return r , nil
284
+ return nil
236
285
}
237
286
238
287
if req .GetPreprocess () {
239
288
// Just output preprocessed source code and exit
240
289
preprocessedSketch , err := sketchBuilder .Preprocess ()
241
290
if err != nil {
242
291
err = & cmderrors.CompileFailedError {Message : err .Error ()}
243
- return r , err
292
+ return err
244
293
}
245
294
_ , err = outStream .Write (preprocessedSketch )
246
- return r , err
295
+ return err
247
296
}
248
297
249
298
defer func () {
@@ -285,7 +334,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
285
334
}
286
335
287
336
if err := sketchBuilder .Build (); err != nil {
288
- return r , & cmderrors.CompileFailedError {Message : err .Error ()}
337
+ return & cmderrors.CompileFailedError {Message : err .Error ()}
289
338
}
290
339
291
340
// If the export directory is set we assume you want to export the binaries
@@ -297,9 +346,8 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
297
346
exportBinaries = false
298
347
}
299
348
if exportBinaries {
300
- err := sketchBuilder .RunRecipe ("recipe.hooks.savehex.presavehex" , ".pattern" , false )
301
- if err != nil {
302
- return r , err
349
+ if err := sketchBuilder .RunRecipe ("recipe.hooks.savehex.presavehex" , ".pattern" , false ); err != nil {
350
+ return err
303
351
}
304
352
305
353
exportPath := paths .New (req .GetExportDir ())
@@ -313,38 +361,36 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
313
361
if ! buildPath .EqualsTo (exportPath ) {
314
362
logrus .WithField ("path" , exportPath ).Trace ("Saving sketch to export path." )
315
363
if err := exportPath .MkdirAll (); err != nil {
316
- return r , & cmderrors.PermissionDeniedError {Message : tr ("Error creating output dir" ), Cause : err }
364
+ return & cmderrors.PermissionDeniedError {Message : tr ("Error creating output dir" ), Cause : err }
317
365
}
318
366
319
367
baseName , ok := sketchBuilder .GetBuildProperties ().GetOk ("build.project_name" ) // == "sketch.ino"
320
368
if ! ok {
321
- return r , & cmderrors.MissingPlatformPropertyError {Property : "build.project_name" }
369
+ return & cmderrors.MissingPlatformPropertyError {Property : "build.project_name" }
322
370
}
323
371
buildFiles , err := sketchBuilder .GetBuildPath ().ReadDir ()
324
372
if err != nil {
325
- return r , & cmderrors.PermissionDeniedError {Message : tr ("Error reading build directory" ), Cause : err }
373
+ return & cmderrors.PermissionDeniedError {Message : tr ("Error reading build directory" ), Cause : err }
326
374
}
327
375
buildFiles .FilterPrefix (baseName )
328
376
for _ , buildFile := range buildFiles {
329
377
exportedFile := exportPath .Join (buildFile .Base ())
330
378
logrus .WithField ("src" , buildFile ).WithField ("dest" , exportedFile ).Trace ("Copying artifact." )
331
379
if err = buildFile .CopyTo (exportedFile ); err != nil {
332
- return r , & cmderrors.PermissionDeniedError {Message : tr ("Error copying output file %s" , buildFile ), Cause : err }
380
+ return & cmderrors.PermissionDeniedError {Message : tr ("Error copying output file %s" , buildFile ), Cause : err }
333
381
}
334
382
}
335
383
}
336
384
337
- err = sketchBuilder .RunRecipe ("recipe.hooks.savehex.postsavehex" , ".pattern" , false )
338
- if err != nil {
339
- return r , err
385
+ if err = sketchBuilder .RunRecipe ("recipe.hooks.savehex.postsavehex" , ".pattern" , false ); err != nil {
386
+ return err
340
387
}
341
388
}
342
389
343
390
r .ExecutableSectionsSize = sketchBuilder .ExecutableSectionsSize ().ToRPCExecutableSectionSizeArray ()
344
391
345
392
logrus .Tracef ("Compile %s for %s successful" , sk .Name , fqbnIn )
346
-
347
- return r , nil
393
+ return nil
348
394
}
349
395
350
396
// maybePurgeBuildCache runs the build files cache purge if the policy conditions are met.
0 commit comments