@@ -18,48 +18,50 @@ package phases
18
18
import (
19
19
"encoding/json"
20
20
"fmt"
21
+ "io"
21
22
"regexp"
22
23
"strconv"
23
24
25
+ "github.com/arduino/arduino-cli/arduino/builder"
24
26
"github.com/arduino/arduino-cli/arduino/builder/utils"
25
- "github.com/arduino/arduino-cli/legacy/builder/types"
26
27
"github.com/arduino/go-properties-orderedmap"
27
28
"github.com/pkg/errors"
28
29
)
29
30
30
- type Sizer struct {
31
- SketchError bool
32
- }
33
-
34
- func (s * Sizer ) Run (ctx * types.Context ) error {
35
- if ctx .OnlyUpdateCompilationDatabase {
36
- return nil
31
+ func Sizer (
32
+ onlyUpdateCompilationDatabase , sketchError , verbose bool ,
33
+ buildProperties * properties.Map ,
34
+ stdoutWriter , stderrWriter io.Writer ,
35
+ printInfoFn , printWarnFn func (msg string ),
36
+ warningsLevel string ,
37
+ ) (builder.ExecutablesFileSections , error ) {
38
+ if onlyUpdateCompilationDatabase || sketchError {
39
+ return nil , nil
37
40
}
38
- if s .SketchError {
39
- return nil
40
- }
41
-
42
- buildProperties := ctx .BuildProperties
43
41
44
42
if buildProperties .ContainsKey ("recipe.advanced_size.pattern" ) {
45
- return checkSizeAdvanced (ctx , buildProperties )
43
+ return checkSizeAdvanced (buildProperties , verbose , stdoutWriter , stderrWriter , printInfoFn , printWarnFn )
46
44
}
47
45
48
- return checkSize (ctx , buildProperties )
46
+ return checkSize (buildProperties , verbose , stdoutWriter , stderrWriter , printInfoFn , printWarnFn , warningsLevel )
49
47
}
50
48
51
- func checkSizeAdvanced (ctx * types.Context , properties * properties.Map ) error {
52
- command , err := utils .PrepareCommandForRecipe (properties , "recipe.advanced_size.pattern" , false )
49
+ func checkSizeAdvanced (buildProperties * properties.Map ,
50
+ verbose bool ,
51
+ stdoutWriter , stderrWriter io.Writer ,
52
+ printInfoFn , printWarnFn func (msg string ),
53
+ ) (builder.ExecutablesFileSections , error ) {
54
+ command , err := utils .PrepareCommandForRecipe (buildProperties , "recipe.advanced_size.pattern" , false )
53
55
if err != nil {
54
- return errors .New (tr ("Error while determining sketch size: %s" , err ))
56
+ return nil , errors .New (tr ("Error while determining sketch size: %s" , err ))
55
57
}
56
58
57
- verboseInfo , out , _ , err := utils .ExecCommand (ctx . Verbose , ctx . Stdout , ctx . Stderr , command , utils .Capture /* stdout */ , utils .Show /* stderr */ )
58
- if ctx . Verbose {
59
- ctx . Info (string (verboseInfo ))
59
+ verboseInfo , out , _ , err := utils .ExecCommand (verbose , stdoutWriter , stderrWriter , command , utils .Capture /* stdout */ , utils .Show /* stderr */ )
60
+ if verbose {
61
+ printInfoFn (string (verboseInfo ))
60
62
}
61
63
if err != nil {
62
- return errors .New (tr ("Error while determining sketch size: %s" , err ))
64
+ return nil , errors .New (tr ("Error while determining sketch size: %s" , err ))
63
65
}
64
66
65
67
type AdvancedSizerResponse struct {
@@ -69,7 +71,7 @@ func checkSizeAdvanced(ctx *types.Context, properties *properties.Map) error {
69
71
// likely be printed in red. Errors will stop build/upload.
70
72
Severity string `json:"severity"`
71
73
// Sections are the sections sizes for machine readable use
72
- Sections []types .ExecutableSectionSize `json:"sections"`
74
+ Sections []builder .ExecutableSectionSize `json:"sections"`
73
75
// ErrorMessage is a one line error message like:
74
76
// "text section exceeds available space in board"
75
77
// it must be set when Severity is "error"
@@ -78,118 +80,127 @@ func checkSizeAdvanced(ctx *types.Context, properties *properties.Map) error {
78
80
79
81
var resp AdvancedSizerResponse
80
82
if err := json .Unmarshal (out , & resp ); err != nil {
81
- return errors .New (tr ("Error while determining sketch size: %s" , err ))
83
+ return nil , errors .New (tr ("Error while determining sketch size: %s" , err ))
82
84
}
83
85
84
- ctx . ExecutableSectionsSize = resp .Sections
86
+ executableSectionsSize : = resp .Sections
85
87
switch resp .Severity {
86
88
case "error" :
87
- ctx . Warn (resp .Output )
88
- return errors .New (resp .ErrorMessage )
89
+ printWarnFn (resp .Output )
90
+ return executableSectionsSize , errors .New (resp .ErrorMessage )
89
91
case "warning" :
90
- ctx . Warn (resp .Output )
92
+ printWarnFn (resp .Output )
91
93
case "info" :
92
- ctx . Info (resp .Output )
94
+ printInfoFn (resp .Output )
93
95
default :
94
- return fmt .Errorf ("invalid '%s' severity from sketch sizer: it must be 'error', 'warning' or 'info'" , resp .Severity )
96
+ return executableSectionsSize , fmt .Errorf ("invalid '%s' severity from sketch sizer: it must be 'error', 'warning' or 'info'" , resp .Severity )
95
97
}
96
- return nil
98
+ return executableSectionsSize , nil
97
99
}
98
100
99
- func checkSize (ctx * types.Context , buildProperties * properties.Map ) error {
101
+ func checkSize (buildProperties * properties.Map ,
102
+ verbose bool ,
103
+ stdoutWriter , stderrWriter io.Writer ,
104
+ printInfoFn , printWarnFn func (msg string ),
105
+ warningsLevel string ,
106
+ ) (builder.ExecutablesFileSections , error ) {
100
107
properties := buildProperties .Clone ()
101
- properties .Set ("compiler.warning_flags" , properties .Get ("compiler.warning_flags." + ctx . WarningsLevel ))
108
+ properties .Set ("compiler.warning_flags" , properties .Get ("compiler.warning_flags." + warningsLevel ))
102
109
103
110
maxTextSizeString := properties .Get ("upload.maximum_size" )
104
111
maxDataSizeString := properties .Get ("upload.maximum_data_size" )
105
112
106
113
if maxTextSizeString == "" {
107
- return nil
114
+ return nil , nil
108
115
}
109
116
110
117
maxTextSize , err := strconv .Atoi (maxTextSizeString )
111
118
if err != nil {
112
- return err
119
+ return nil , err
113
120
}
114
121
115
122
maxDataSize := - 1
116
123
if maxDataSizeString != "" {
117
124
maxDataSize , err = strconv .Atoi (maxDataSizeString )
118
125
if err != nil {
119
- return err
126
+ return nil , err
120
127
}
121
128
}
122
129
123
- textSize , dataSize , _ , err := execSizeRecipe (ctx , properties )
130
+ textSize , dataSize , _ , err := execSizeRecipe (properties , verbose , stdoutWriter , stderrWriter , printInfoFn )
124
131
if err != nil {
125
- ctx . Warn (tr ("Couldn't determine program size" ))
126
- return nil
132
+ printWarnFn (tr ("Couldn't determine program size" ))
133
+ return nil , nil
127
134
}
128
135
129
- ctx . Info (tr ("Sketch uses %[1]s bytes (%[3]s%%) of program storage space. Maximum is %[2]s bytes." ,
136
+ printInfoFn (tr ("Sketch uses %[1]s bytes (%[3]s%%) of program storage space. Maximum is %[2]s bytes." ,
130
137
strconv .Itoa (textSize ),
131
138
strconv .Itoa (maxTextSize ),
132
139
strconv .Itoa (textSize * 100 / maxTextSize )))
133
140
if dataSize >= 0 {
134
141
if maxDataSize > 0 {
135
- ctx . Info (tr ("Global variables use %[1]s bytes (%[3]s%%) of dynamic memory, leaving %[4]s bytes for local variables. Maximum is %[2]s bytes." ,
142
+ printInfoFn (tr ("Global variables use %[1]s bytes (%[3]s%%) of dynamic memory, leaving %[4]s bytes for local variables. Maximum is %[2]s bytes." ,
136
143
strconv .Itoa (dataSize ),
137
144
strconv .Itoa (maxDataSize ),
138
145
strconv .Itoa (dataSize * 100 / maxDataSize ),
139
146
strconv .Itoa (maxDataSize - dataSize )))
140
147
} else {
141
- ctx . Info (tr ("Global variables use %[1]s bytes of dynamic memory." , strconv .Itoa (dataSize )))
148
+ printInfoFn (tr ("Global variables use %[1]s bytes of dynamic memory." , strconv .Itoa (dataSize )))
142
149
}
143
150
}
144
151
145
- ctx . ExecutableSectionsSize = []types .ExecutableSectionSize {
152
+ executableSectionsSize : = []builder .ExecutableSectionSize {
146
153
{
147
154
Name : "text" ,
148
155
Size : textSize ,
149
156
MaxSize : maxTextSize ,
150
157
},
151
158
}
152
159
if maxDataSize > 0 {
153
- ctx . ExecutableSectionsSize = append (ctx . ExecutableSectionsSize , types .ExecutableSectionSize {
160
+ executableSectionsSize = append (executableSectionsSize , builder .ExecutableSectionSize {
154
161
Name : "data" ,
155
162
Size : dataSize ,
156
163
MaxSize : maxDataSize ,
157
164
})
158
165
}
159
166
160
167
if textSize > maxTextSize {
161
- ctx . Warn (tr ("Sketch too big; see %[1]s for tips on reducing it." , "https://support.arduino.cc/hc/en-us/articles/360013825179" ))
162
- return errors .New (tr ("text section exceeds available space in board" ))
168
+ printWarnFn (tr ("Sketch too big; see %[1]s for tips on reducing it." , "https://support.arduino.cc/hc/en-us/articles/360013825179" ))
169
+ return executableSectionsSize , errors .New (tr ("text section exceeds available space in board" ))
163
170
}
164
171
165
172
if maxDataSize > 0 && dataSize > maxDataSize {
166
- ctx . Warn (tr ("Not enough memory; see %[1]s for tips on reducing your footprint." , "https://support.arduino.cc/hc/en-us/articles/360013825179" ))
167
- return errors .New (tr ("data section exceeds available space in board" ))
173
+ printWarnFn (tr ("Not enough memory; see %[1]s for tips on reducing your footprint." , "https://support.arduino.cc/hc/en-us/articles/360013825179" ))
174
+ return executableSectionsSize , errors .New (tr ("data section exceeds available space in board" ))
168
175
}
169
176
170
177
if w := properties .Get ("build.warn_data_percentage" ); w != "" {
171
178
warnDataPercentage , err := strconv .Atoi (w )
172
179
if err != nil {
173
- return err
180
+ return executableSectionsSize , err
174
181
}
175
182
if maxDataSize > 0 && dataSize > maxDataSize * warnDataPercentage / 100 {
176
- ctx . Warn (tr ("Low memory available, stability problems may occur." ))
183
+ printWarnFn (tr ("Low memory available, stability problems may occur." ))
177
184
}
178
185
}
179
186
180
- return nil
187
+ return executableSectionsSize , nil
181
188
}
182
189
183
- func execSizeRecipe (ctx * types.Context , properties * properties.Map ) (textSize int , dataSize int , eepromSize int , resErr error ) {
190
+ func execSizeRecipe (properties * properties.Map ,
191
+ verbose bool ,
192
+ stdoutWriter , stderrWriter io.Writer ,
193
+ printInfoFn func (msg string ),
194
+ ) (textSize int , dataSize int , eepromSize int , resErr error ) {
184
195
command , err := utils .PrepareCommandForRecipe (properties , "recipe.size.pattern" , false )
185
196
if err != nil {
186
197
resErr = fmt .Errorf (tr ("Error while determining sketch size: %s" ), err )
187
198
return
188
199
}
189
200
190
- verboseInfo , out , _ , err := utils .ExecCommand (ctx . Verbose , ctx . Stdout , ctx . Stderr , command , utils .Capture /* stdout */ , utils .Show /* stderr */ )
191
- if ctx . Verbose {
192
- ctx . Info (string (verboseInfo ))
201
+ verboseInfo , out , _ , err := utils .ExecCommand (verbose , stdoutWriter , stderrWriter , command , utils .Capture /* stdout */ , utils .Show /* stderr */ )
202
+ if verbose {
203
+ printInfoFn (string (verboseInfo ))
193
204
}
194
205
if err != nil {
195
206
resErr = fmt .Errorf (tr ("Error while determining sketch size: %s" ), err )
0 commit comments