16
16
package builder_utils
17
17
18
18
import (
19
+ "bytes"
19
20
"fmt"
21
+ "io"
20
22
"os"
21
23
"path/filepath"
22
24
"runtime"
23
25
"strings"
24
26
"sync"
25
27
28
+ "github.com/arduino/arduino-cli/arduino/builder"
26
29
bUtils "github.com/arduino/arduino-cli/arduino/builder/utils"
27
30
"github.com/arduino/arduino-cli/arduino/globals"
28
31
"github.com/arduino/arduino-cli/executils"
29
32
"github.com/arduino/arduino-cli/i18n"
30
33
"github.com/arduino/arduino-cli/legacy/builder/constants"
31
34
"github.com/arduino/arduino-cli/legacy/builder/types"
32
35
"github.com/arduino/arduino-cli/legacy/builder/utils"
36
+ rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
33
37
"github.com/arduino/go-paths-helper"
34
38
"github.com/arduino/go-properties-orderedmap"
35
39
"github.com/pkg/errors"
@@ -63,15 +67,81 @@ func DirContentIsOlderThan(dir *paths.Path, target *paths.Path, extensions ...st
63
67
return true , nil
64
68
}
65
69
66
- func CompileFiles (ctx * types.Context , sourceDir * paths.Path , buildPath * paths.Path , buildProperties * properties.Map , includes []string ) (paths.PathList , error ) {
67
- return compileFiles (ctx , sourceDir , false , buildPath , buildProperties , includes )
70
+ func CompileFiles (
71
+ sourceDir , buildPath * paths.Path ,
72
+ buildProperties * properties.Map ,
73
+ includes []string ,
74
+ onlyUpdateCompilationDatabase bool ,
75
+ compilationDatabase * builder.CompilationDatabase ,
76
+ jobs int ,
77
+ verbose bool ,
78
+ warningsLevel string ,
79
+ stdoutWriter , stderrWriter io.Writer ,
80
+ verboseInfoFn func (msg string ),
81
+ verboseStdoutFn , verboseStderrFn func (data []byte ),
82
+ progress * types.ProgressStruct , progressCB rpc.TaskProgressCB ,
83
+ ) (paths.PathList , error ) {
84
+ return compileFiles (
85
+ onlyUpdateCompilationDatabase ,
86
+ compilationDatabase ,
87
+ jobs ,
88
+ sourceDir ,
89
+ false ,
90
+ buildPath , buildProperties , includes ,
91
+ verbose ,
92
+ warningsLevel ,
93
+ stdoutWriter , stderrWriter ,
94
+ verboseInfoFn , verboseStdoutFn , verboseStderrFn ,
95
+ progress , progressCB ,
96
+ )
68
97
}
69
98
70
- func CompileFilesRecursive (ctx * types.Context , sourceDir * paths.Path , buildPath * paths.Path , buildProperties * properties.Map , includes []string ) (paths.PathList , error ) {
71
- return compileFiles (ctx , sourceDir , true , buildPath , buildProperties , includes )
99
+ func CompileFilesRecursive (
100
+ sourceDir , buildPath * paths.Path ,
101
+ buildProperties * properties.Map ,
102
+ includes []string ,
103
+ onlyUpdateCompilationDatabase bool ,
104
+ compilationDatabase * builder.CompilationDatabase ,
105
+ jobs int ,
106
+ verbose bool ,
107
+ warningsLevel string ,
108
+ stdoutWriter , stderrWriter io.Writer ,
109
+ verboseInfoFn func (msg string ),
110
+ verboseStdoutFn , verboseStderrFn func (data []byte ),
111
+ progress * types.ProgressStruct , progressCB rpc.TaskProgressCB ,
112
+ ) (paths.PathList , error ) {
113
+ return compileFiles (
114
+ onlyUpdateCompilationDatabase ,
115
+ compilationDatabase ,
116
+ jobs ,
117
+ sourceDir ,
118
+ true ,
119
+ buildPath , buildProperties , includes ,
120
+ verbose ,
121
+ warningsLevel ,
122
+ stdoutWriter , stderrWriter ,
123
+ verboseInfoFn , verboseStdoutFn , verboseStderrFn ,
124
+ progress , progressCB ,
125
+ )
72
126
}
73
127
74
- func compileFiles (ctx * types.Context , sourceDir * paths.Path , recurse bool , buildPath * paths.Path , buildProperties * properties.Map , includes []string ) (paths.PathList , error ) {
128
+ func compileFiles (
129
+ onlyUpdateCompilationDatabase bool ,
130
+ compilationDatabase * builder.CompilationDatabase ,
131
+ jobs int ,
132
+ sourceDir * paths.Path ,
133
+ recurse bool ,
134
+ buildPath * paths.Path ,
135
+ buildProperties * properties.Map ,
136
+ includes []string ,
137
+ verbose bool ,
138
+ warningsLevel string ,
139
+ stdoutWriter , stderrWriter io.Writer ,
140
+ verboseInfoFn func (msg string ),
141
+ verboseStdoutFn , verboseStderrFn func (data []byte ),
142
+ progress * types.ProgressStruct ,
143
+ progressCB rpc.TaskProgressCB ,
144
+ ) (paths.PathList , error ) {
75
145
validExtensions := []string {}
76
146
for ext := range globals .SourceFilesValidExtensions {
77
147
validExtensions = append (validExtensions , ext )
@@ -82,8 +152,8 @@ func compileFiles(ctx *types.Context, sourceDir *paths.Path, recurse bool, build
82
152
return nil , err
83
153
}
84
154
85
- ctx . Progress .AddSubSteps (len (sources ))
86
- defer ctx . Progress .RemoveSubSteps ()
155
+ progress .AddSubSteps (len (sources ))
156
+ defer progress .RemoveSubSteps ()
87
157
88
158
objectFiles := paths .NewPathList ()
89
159
var objectFilesMux sync.Mutex
@@ -99,7 +169,19 @@ func compileFiles(ctx *types.Context, sourceDir *paths.Path, recurse bool, build
99
169
if ! buildProperties .ContainsKey (recipe ) {
100
170
recipe = fmt .Sprintf ("recipe%s.o.pattern" , globals .SourceFilesValidExtensions [source .Ext ()])
101
171
}
102
- objectFile , err := compileFileWithRecipe (ctx , sourceDir , source , buildPath , buildProperties , includes , recipe )
172
+ objectFile , verboseInfo , verboseStdout , stderr , err := compileFileWithRecipe (
173
+ stdoutWriter , stderrWriter ,
174
+ warningsLevel ,
175
+ compilationDatabase ,
176
+ verbose ,
177
+ onlyUpdateCompilationDatabase ,
178
+ sourceDir , source , buildPath , buildProperties , includes , recipe ,
179
+ )
180
+ if verbose {
181
+ verboseStdoutFn (verboseStdout )
182
+ verboseInfoFn (string (verboseInfo ))
183
+ }
184
+ verboseStderrFn (stderr )
103
185
if err != nil {
104
186
errorsMux .Lock ()
105
187
errorsList = append (errorsList , err )
@@ -113,7 +195,6 @@ func compileFiles(ctx *types.Context, sourceDir *paths.Path, recurse bool, build
113
195
114
196
// Spawn jobs runners
115
197
var wg sync.WaitGroup
116
- jobs := ctx .Jobs
117
198
if jobs == 0 {
118
199
jobs = runtime .NumCPU ()
119
200
}
@@ -137,8 +218,14 @@ func compileFiles(ctx *types.Context, sourceDir *paths.Path, recurse bool, build
137
218
}
138
219
queue <- source
139
220
140
- ctx .Progress .CompleteStep ()
141
- ctx .PushProgress ()
221
+ progress .CompleteStep ()
222
+ // PushProgress
223
+ if progressCB != nil {
224
+ progressCB (& rpc.TaskProgress {
225
+ Percent : progress .Progress ,
226
+ Completed : progress .Progress >= 100.0 ,
227
+ })
228
+ }
142
229
}
143
230
close (queue )
144
231
wg .Wait ()
@@ -150,68 +237,87 @@ func compileFiles(ctx *types.Context, sourceDir *paths.Path, recurse bool, build
150
237
return objectFiles , nil
151
238
}
152
239
153
- func compileFileWithRecipe (ctx * types.Context , sourcePath * paths.Path , source * paths.Path , buildPath * paths.Path , buildProperties * properties.Map , includes []string , recipe string ) (* paths.Path , error ) {
240
+ func compileFileWithRecipe (
241
+ stdoutWriter , stderrWriter io.Writer ,
242
+ warningsLevel string ,
243
+ compilationDatabase * builder.CompilationDatabase ,
244
+ verbose , onlyUpdateCompilationDatabase bool ,
245
+ sourcePath * paths.Path ,
246
+ source * paths.Path ,
247
+ buildPath * paths.Path ,
248
+ buildProperties * properties.Map ,
249
+ includes []string ,
250
+ recipe string ,
251
+ ) (* paths.Path , []byte , []byte , []byte , error ) {
252
+ verboseStdout , verboseInfo , errOut := & bytes.Buffer {}, & bytes.Buffer {}, & bytes.Buffer {}
253
+
154
254
properties := buildProperties .Clone ()
155
- properties .Set (constants .BUILD_PROPERTIES_COMPILER_WARNING_FLAGS , properties .Get (constants .BUILD_PROPERTIES_COMPILER_WARNING_FLAGS + "." + ctx . WarningsLevel ))
255
+ properties .Set (constants .BUILD_PROPERTIES_COMPILER_WARNING_FLAGS , properties .Get (constants .BUILD_PROPERTIES_COMPILER_WARNING_FLAGS + "." + warningsLevel ))
156
256
properties .Set (constants .BUILD_PROPERTIES_INCLUDES , strings .Join (includes , constants .SPACE ))
157
257
properties .SetPath ("source_file" , source )
158
258
relativeSource , err := sourcePath .RelTo (source )
159
259
if err != nil {
160
- return nil , errors .WithStack (err )
260
+ return nil , nil , nil , nil , errors .WithStack (err )
161
261
}
162
262
depsFile := buildPath .Join (relativeSource .String () + ".d" )
163
263
objectFile := buildPath .Join (relativeSource .String () + ".o" )
164
264
165
265
properties .SetPath (constants .BUILD_PROPERTIES_OBJECT_FILE , objectFile )
166
266
err = objectFile .Parent ().MkdirAll ()
167
267
if err != nil {
168
- return nil , errors .WithStack (err )
268
+ return nil , nil , nil , nil , errors .WithStack (err )
169
269
}
170
270
171
271
objIsUpToDate , err := bUtils .ObjFileIsUpToDate (source , objectFile , depsFile )
172
272
if err != nil {
173
- return nil , errors .WithStack (err )
273
+ return nil , nil , nil , nil , errors .WithStack (err )
174
274
}
175
275
176
276
command , err := PrepareCommandForRecipe (properties , recipe , false )
177
277
if err != nil {
178
- return nil , errors .WithStack (err )
278
+ return nil , nil , nil , nil , errors .WithStack (err )
179
279
}
180
- if ctx . CompilationDatabase != nil {
181
- ctx . CompilationDatabase .Add (source , command )
280
+ if compilationDatabase != nil {
281
+ compilationDatabase .Add (source , command )
182
282
}
183
- if ! objIsUpToDate && ! ctx . OnlyUpdateCompilationDatabase {
283
+ if ! objIsUpToDate && ! onlyUpdateCompilationDatabase {
184
284
// Since this compile could be multithreaded, we first capture the command output
185
- stdout , stderr , err := utils .ExecCommand (ctx , command , utils .Capture , utils .Capture )
285
+ info , stdout , stderr , err := utils .ExecCommand (verbose , stdoutWriter , stderrWriter , command , utils .Capture , utils .Capture )
186
286
// and transfer all at once at the end...
187
- if ctx .Verbose {
188
- ctx .WriteStdout (stdout )
287
+ if verbose {
288
+ verboseInfo .Write (info )
289
+ verboseStdout .Write (stdout )
189
290
}
190
- ctx . WriteStderr (stderr )
291
+ errOut . Write (stderr )
191
292
192
293
// ...and then return the error
193
294
if err != nil {
194
- return nil , errors .WithStack (err )
295
+ return nil , verboseInfo . Bytes (), verboseStdout . Bytes (), errOut . Bytes (), errors .WithStack (err )
195
296
}
196
- } else if ctx . Verbose {
297
+ } else if verbose {
197
298
if objIsUpToDate {
198
- ctx . Info (tr ("Using previously compiled file: %[1]s" , objectFile ))
299
+ verboseInfo . WriteString (tr ("Using previously compiled file: %[1]s" , objectFile ))
199
300
} else {
200
- ctx . Info (tr ("Skipping compile of: %[1]s" , objectFile ))
301
+ verboseInfo . WriteString (tr ("Skipping compile of: %[1]s" , objectFile ))
201
302
}
202
303
}
203
304
204
- return objectFile , nil
305
+ return objectFile , verboseInfo . Bytes (), verboseStdout . Bytes (), errOut . Bytes (), nil
205
306
}
206
307
207
- func ArchiveCompiledFiles (ctx * types.Context , buildPath * paths.Path , archiveFile * paths.Path , objectFilesToArchive paths.PathList , buildProperties * properties.Map ) (* paths.Path , error ) {
308
+ func ArchiveCompiledFiles (
309
+ buildPath * paths.Path , archiveFile * paths.Path , objectFilesToArchive paths.PathList , buildProperties * properties.Map ,
310
+ onlyUpdateCompilationDatabase , verbose bool ,
311
+ stdoutWriter , stderrWriter io.Writer ,
312
+ ) (* paths.Path , []byte , error ) {
313
+ verboseInfobuf := & bytes.Buffer {}
208
314
archiveFilePath := buildPath .JoinPath (archiveFile )
209
315
210
- if ctx . OnlyUpdateCompilationDatabase {
211
- if ctx . Verbose {
212
- ctx . Info (tr ("Skipping archive creation of: %[1]s" , archiveFilePath ))
316
+ if onlyUpdateCompilationDatabase {
317
+ if verbose {
318
+ verboseInfobuf . WriteString (tr ("Skipping archive creation of: %[1]s" , archiveFilePath ))
213
319
}
214
- return archiveFilePath , nil
320
+ return archiveFilePath , verboseInfobuf . Bytes (), nil
215
321
}
216
322
217
323
if archiveFileStat , err := archiveFilePath .Stat (); err == nil {
@@ -228,13 +334,13 @@ func ArchiveCompiledFiles(ctx *types.Context, buildPath *paths.Path, archiveFile
228
334
// something changed, rebuild the core archive
229
335
if rebuildArchive {
230
336
if err := archiveFilePath .Remove (); err != nil {
231
- return nil , errors .WithStack (err )
337
+ return nil , nil , errors .WithStack (err )
232
338
}
233
339
} else {
234
- if ctx . Verbose {
235
- ctx . Info (tr ("Using previously compiled file: %[1]s" , archiveFilePath ))
340
+ if verbose {
341
+ verboseInfobuf . WriteString (tr ("Using previously compiled file: %[1]s" , archiveFilePath ))
236
342
}
237
- return archiveFilePath , nil
343
+ return archiveFilePath , verboseInfobuf . Bytes (), nil
238
344
}
239
345
}
240
346
@@ -246,16 +352,19 @@ func ArchiveCompiledFiles(ctx *types.Context, buildPath *paths.Path, archiveFile
246
352
247
353
command , err := PrepareCommandForRecipe (properties , constants .RECIPE_AR_PATTERN , false )
248
354
if err != nil {
249
- return nil , errors .WithStack (err )
355
+ return nil , verboseInfobuf . Bytes (), errors .WithStack (err )
250
356
}
251
357
252
- _ , _ , err = utils .ExecCommand (ctx , command , utils .ShowIfVerbose /* stdout */ , utils .Show /* stderr */ )
358
+ verboseInfo , _ , _ , err := utils .ExecCommand (verbose , stdoutWriter , stderrWriter , command , utils .ShowIfVerbose /* stdout */ , utils .Show /* stderr */ )
359
+ if verbose {
360
+ verboseInfobuf .WriteString (string (verboseInfo ))
361
+ }
253
362
if err != nil {
254
- return nil , errors .WithStack (err )
363
+ return nil , verboseInfobuf . Bytes (), errors .WithStack (err )
255
364
}
256
365
}
257
366
258
- return archiveFilePath , nil
367
+ return archiveFilePath , verboseInfobuf . Bytes (), nil
259
368
}
260
369
261
370
const COMMANDLINE_LIMIT = 30000
0 commit comments