Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 48be630

Browse files
committedSep 7, 2023
refactor Sizer in a function
1 parent 592f46e commit 48be630

File tree

4 files changed

+118
-86
lines changed

4 files changed

+118
-86
lines changed
 

‎arduino/builder/sizer.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package builder
2+
3+
import rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
4+
5+
// ExecutableSectionSize represents a section of the executable output file
6+
type ExecutableSectionSize struct {
7+
Name string `json:"name"`
8+
Size int `json:"size"`
9+
MaxSize int `json:"max_size"`
10+
}
11+
12+
// ExecutablesFileSections is an array of ExecutablesFileSection
13+
type ExecutablesFileSections []ExecutableSectionSize
14+
15+
// ToRPCExecutableSectionSizeArray transforms this array into a []*rpc.ExecutableSectionSize
16+
func (s ExecutablesFileSections) ToRPCExecutableSectionSizeArray() []*rpc.ExecutableSectionSize {
17+
res := []*rpc.ExecutableSectionSize{}
18+
for _, section := range s {
19+
res = append(res, &rpc.ExecutableSectionSize{
20+
Name: section.Name,
21+
Size: int64(section.Size),
22+
MaxSize: int64(section.MaxSize),
23+
})
24+
}
25+
return res
26+
}

‎legacy/builder/builder.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,24 @@ func (s *Builder) Run(ctx *types.Context) error {
204204

205205
&ExportProjectCMake{SketchError: mainErr != nil},
206206

207-
&phases.Sizer{SketchError: mainErr != nil},
207+
types.BareCommand(func(ctx *types.Context) error {
208+
executableSectionsSize, verboseInfoOut, infoOut, warnOut, err := phases.Sizer(
209+
mainErr != nil,
210+
ctx.OnlyUpdateCompilationDatabase,
211+
ctx.BuildProperties,
212+
ctx.Verbose,
213+
ctx.Stdout, ctx.Stderr,
214+
ctx.WarningsLevel,
215+
)
216+
ctx.ExecutableSectionsSize = executableSectionsSize
217+
if ctx.Verbose {
218+
ctx.Info(string(verboseInfoOut))
219+
}
220+
ctx.Info(string(infoOut))
221+
ctx.Warn(string(warnOut))
222+
223+
return err
224+
}),
208225
}
209226
for _, command := range commands {
210227
PrintRingNameIfDebug(ctx, command)

‎legacy/builder/phases/sizer.go

Lines changed: 73 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -16,50 +16,54 @@
1616
package phases
1717

1818
import (
19+
"bytes"
1920
"encoding/json"
2021
"fmt"
22+
"io"
2123
"regexp"
2224
"strconv"
2325

26+
"github.com/arduino/arduino-cli/arduino/builder"
2427
"github.com/arduino/arduino-cli/arduino/builder/utils"
25-
"github.com/arduino/arduino-cli/legacy/builder/types"
2628
"github.com/arduino/go-properties-orderedmap"
2729
"github.com/pkg/errors"
2830
)
2931

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
37-
}
38-
if s.SketchError {
39-
return nil
32+
func Sizer(
33+
sketchError, onlyUpdateCompilationDatabase bool,
34+
buildProperties *properties.Map,
35+
verbose bool,
36+
stdoutWriter, stderrWriter io.Writer,
37+
warningsLevel string,
38+
) (builder.ExecutablesFileSections, []byte, []byte, []byte, error) {
39+
if onlyUpdateCompilationDatabase || sketchError {
40+
return nil, nil, nil, nil, nil
4041
}
4142

42-
buildProperties := ctx.BuildProperties
43-
4443
if buildProperties.ContainsKey("recipe.advanced_size.pattern") {
45-
return checkSizeAdvanced(ctx, buildProperties)
44+
return checkSizeAdvanced(buildProperties, verbose, stdoutWriter, stderrWriter)
4645
}
4746

48-
return checkSize(ctx, buildProperties)
47+
return checkSize(buildProperties, verbose, stdoutWriter, stderrWriter, warningsLevel)
4948
}
5049

51-
func checkSizeAdvanced(ctx *types.Context, properties *properties.Map) error {
52-
command, err := utils.PrepareCommandForRecipe(properties, "recipe.advanced_size.pattern", false)
50+
func checkSizeAdvanced(
51+
buildProperties *properties.Map,
52+
verbose bool,
53+
stdoutWriter, stderrWriter io.Writer,
54+
) (builder.ExecutablesFileSections, []byte, []byte, []byte, error) {
55+
verboseInfoBuf, infoBuf, warnBuf := &bytes.Buffer{}, &bytes.Buffer{}, &bytes.Buffer{}
56+
command, err := utils.PrepareCommandForRecipe(buildProperties, "recipe.advanced_size.pattern", false)
5357
if err != nil {
54-
return errors.New(tr("Error while determining sketch size: %s", err))
58+
return nil, nil, nil, nil, errors.New(tr("Error while determining sketch size: %s", err))
5559
}
5660

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))
61+
verboseInfo, out, _, err := utils.ExecCommand(verbose, stdoutWriter, stderrWriter, command, utils.Capture /* stdout */, utils.Show /* stderr */)
62+
if verbose {
63+
verboseInfoBuf.WriteString(string(verboseInfo))
6064
}
6165
if err != nil {
62-
return errors.New(tr("Error while determining sketch size: %s", err))
66+
return nil, verboseInfoBuf.Bytes(), nil, nil, errors.New(tr("Error while determining sketch size: %s", err))
6367
}
6468

6569
type AdvancedSizerResponse struct {
@@ -69,7 +73,7 @@ func checkSizeAdvanced(ctx *types.Context, properties *properties.Map) error {
6973
// likely be printed in red. Errors will stop build/upload.
7074
Severity string `json:"severity"`
7175
// Sections are the sections sizes for machine readable use
72-
Sections []types.ExecutableSectionSize `json:"sections"`
76+
Sections []builder.ExecutableSectionSize `json:"sections"`
7377
// ErrorMessage is a one line error message like:
7478
// "text section exceeds available space in board"
7579
// it must be set when Severity is "error"
@@ -78,118 +82,126 @@ func checkSizeAdvanced(ctx *types.Context, properties *properties.Map) error {
7882

7983
var resp AdvancedSizerResponse
8084
if err := json.Unmarshal(out, &resp); err != nil {
81-
return errors.New(tr("Error while determining sketch size: %s", err))
85+
return nil, verboseInfoBuf.Bytes(), nil, nil, errors.New(tr("Error while determining sketch size: %s", err))
8286
}
83-
84-
ctx.ExecutableSectionsSize = resp.Sections
87+
executableSectionsSize := resp.Sections
8588
switch resp.Severity {
8689
case "error":
87-
ctx.Warn(resp.Output)
88-
return errors.New(resp.ErrorMessage)
90+
warnBuf.WriteString(resp.Output)
91+
return executableSectionsSize, verboseInfoBuf.Bytes(), nil, warnBuf.Bytes(), errors.New(resp.ErrorMessage)
8992
case "warning":
90-
ctx.Warn(resp.Output)
93+
warnBuf.WriteString(resp.Output)
9194
case "info":
92-
ctx.Info(resp.Output)
95+
infoBuf.WriteString(resp.Output)
9396
default:
94-
return fmt.Errorf("invalid '%s' severity from sketch sizer: it must be 'error', 'warning' or 'info'", resp.Severity)
97+
return executableSectionsSize, verboseInfoBuf.Bytes(), nil, nil, fmt.Errorf("invalid '%s' severity from sketch sizer: it must be 'error', 'warning' or 'info'", resp.Severity)
9598
}
96-
return nil
99+
return executableSectionsSize, verboseInfoBuf.Bytes(), infoBuf.Bytes(), warnBuf.Bytes(), nil
97100
}
98101

99-
func checkSize(ctx *types.Context, buildProperties *properties.Map) error {
102+
func checkSize(
103+
buildProperties *properties.Map,
104+
verbose bool,
105+
stdoutWriter, stderrWriter io.Writer,
106+
warningsLevel string,
107+
) (builder.ExecutablesFileSections, []byte, []byte, []byte, error) {
108+
infoBuf, warnBuf := &bytes.Buffer{}, &bytes.Buffer{}
100109
properties := buildProperties.Clone()
101-
properties.Set("compiler.warning_flags", properties.Get("compiler.warning_flags."+ctx.WarningsLevel))
110+
properties.Set("compiler.warning_flags", properties.Get("compiler.warning_flags."+warningsLevel))
102111

103112
maxTextSizeString := properties.Get("upload.maximum_size")
104113
maxDataSizeString := properties.Get("upload.maximum_data_size")
105114

106115
if maxTextSizeString == "" {
107-
return nil
116+
return nil, nil, nil, nil, nil
108117
}
109118

110119
maxTextSize, err := strconv.Atoi(maxTextSizeString)
111120
if err != nil {
112-
return err
121+
return nil, nil, nil, nil, err
113122
}
114123

115124
maxDataSize := -1
116125
if maxDataSizeString != "" {
117126
maxDataSize, err = strconv.Atoi(maxDataSizeString)
118127
if err != nil {
119-
return err
128+
return nil, nil, nil, nil, err
120129
}
121130
}
122131

123-
textSize, dataSize, _, err := execSizeRecipe(ctx, properties)
132+
textSize, dataSize, _, verboseInfoOut, err := execSizeRecipe(properties, verbose, stdoutWriter, stderrWriter)
124133
if err != nil {
125-
ctx.Warn(tr("Couldn't determine program size"))
126-
return nil
134+
infoBuf.WriteString(tr("Couldn't determine program size"))
135+
return nil, verboseInfoOut, infoBuf.Bytes(), nil, nil
127136
}
128137

129-
ctx.Info(tr("Sketch uses %[1]s bytes (%[3]s%%) of program storage space. Maximum is %[2]s bytes.",
138+
infoBuf.WriteString(tr("Sketch uses %[1]s bytes (%[3]s%%) of program storage space. Maximum is %[2]s bytes.",
130139
strconv.Itoa(textSize),
131140
strconv.Itoa(maxTextSize),
132141
strconv.Itoa(textSize*100/maxTextSize)))
133142
if dataSize >= 0 {
134143
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.",
144+
infoBuf.WriteString(tr("Global variables use %[1]s bytes (%[3]s%%) of dynamic memory, leaving %[4]s bytes for local variables. Maximum is %[2]s bytes.",
136145
strconv.Itoa(dataSize),
137146
strconv.Itoa(maxDataSize),
138147
strconv.Itoa(dataSize*100/maxDataSize),
139148
strconv.Itoa(maxDataSize-dataSize)))
140149
} else {
141-
ctx.Info(tr("Global variables use %[1]s bytes of dynamic memory.", strconv.Itoa(dataSize)))
150+
infoBuf.WriteString(tr("Global variables use %[1]s bytes of dynamic memory.", strconv.Itoa(dataSize)))
142151
}
143152
}
144-
145-
ctx.ExecutableSectionsSize = []types.ExecutableSectionSize{
153+
executableSectionsSize := []builder.ExecutableSectionSize{
146154
{
147155
Name: "text",
148156
Size: textSize,
149157
MaxSize: maxTextSize,
150158
},
151159
}
152160
if maxDataSize > 0 {
153-
ctx.ExecutableSectionsSize = append(ctx.ExecutableSectionsSize, types.ExecutableSectionSize{
161+
executableSectionsSize = append(executableSectionsSize, builder.ExecutableSectionSize{
154162
Name: "data",
155163
Size: dataSize,
156164
MaxSize: maxDataSize,
157165
})
158166
}
159167

160168
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"))
169+
warnBuf.WriteString(tr("Sketch too big; see %[1]s for tips on reducing it.", "https://support.arduino.cc/hc/en-us/articles/360013825179"))
170+
return executableSectionsSize, verboseInfoOut, infoBuf.Bytes(), warnBuf.Bytes(), errors.New(tr("text section exceeds available space in board"))
163171
}
164172

165173
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"))
174+
warnBuf.WriteString(tr("Not enough memory; see %[1]s for tips on reducing your footprint.", "https://support.arduino.cc/hc/en-us/articles/360013825179"))
175+
return executableSectionsSize, verboseInfoOut, infoBuf.Bytes(), warnBuf.Bytes(), errors.New(tr("data section exceeds available space in board"))
168176
}
169177

170178
if w := properties.Get("build.warn_data_percentage"); w != "" {
171179
warnDataPercentage, err := strconv.Atoi(w)
172180
if err != nil {
173-
return err
181+
return executableSectionsSize, verboseInfoOut, infoBuf.Bytes(), warnBuf.Bytes(), err
174182
}
175183
if maxDataSize > 0 && dataSize > maxDataSize*warnDataPercentage/100 {
176-
ctx.Warn(tr("Low memory available, stability problems may occur."))
184+
warnBuf.WriteString(tr("Low memory available, stability problems may occur."))
177185
}
178186
}
179187

180-
return nil
188+
return executableSectionsSize, verboseInfoOut, infoBuf.Bytes(), warnBuf.Bytes(), nil
181189
}
182190

183-
func execSizeRecipe(ctx *types.Context, properties *properties.Map) (textSize int, dataSize int, eepromSize int, resErr error) {
184-
command, err := utils.PrepareCommandForRecipe(properties, "recipe.size.pattern", false)
191+
func execSizeRecipe(
192+
buildProperties *properties.Map,
193+
verbose bool,
194+
stdoutWriter, stderrWriter io.Writer,
195+
) (textSize int, dataSize int, eepromSize int, verboseInfoOut []byte, resErr error) {
196+
command, err := utils.PrepareCommandForRecipe(buildProperties, "recipe.size.pattern", false)
185197
if err != nil {
186198
resErr = fmt.Errorf(tr("Error while determining sketch size: %s"), err)
187199
return
188200
}
189201

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))
202+
verboseInfo, out, _, err := utils.ExecCommand(verbose, stdoutWriter, stderrWriter, command, utils.Capture /* stdout */, utils.Show /* stderr */)
203+
if verbose {
204+
verboseInfoOut = verboseInfo
193205
}
194206
if err != nil {
195207
resErr = fmt.Errorf(tr("Error while determining sketch size: %s"), err)
@@ -199,7 +211,7 @@ func execSizeRecipe(ctx *types.Context, properties *properties.Map) (textSize in
199211
// force multiline match prepending "(?m)" to the actual regexp
200212
// return an error if RECIPE_SIZE_REGEXP doesn't exist
201213

202-
textSize, err = computeSize(properties.Get("recipe.size.regex"), out)
214+
textSize, err = computeSize(buildProperties.Get("recipe.size.regex"), out)
203215
if err != nil {
204216
resErr = fmt.Errorf(tr("Invalid size regexp: %s"), err)
205217
return
@@ -209,13 +221,13 @@ func execSizeRecipe(ctx *types.Context, properties *properties.Map) (textSize in
209221
return
210222
}
211223

212-
dataSize, err = computeSize(properties.Get("recipe.size.regex.data"), out)
224+
dataSize, err = computeSize(buildProperties.Get("recipe.size.regex.data"), out)
213225
if err != nil {
214226
resErr = fmt.Errorf(tr("Invalid data size regexp: %s"), err)
215227
return
216228
}
217229

218-
eepromSize, err = computeSize(properties.Get("recipe.size.regex.eeprom"), out)
230+
eepromSize, err = computeSize(buildProperties.Get("recipe.size.regex.eeprom"), out)
219231
if err != nil {
220232
resErr = fmt.Errorf(tr("Invalid eeprom size regexp: %s"), err)
221233
return

‎legacy/builder/types/context.go

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ type Context struct {
9393
stdLock sync.Mutex
9494

9595
// Sizer results
96-
ExecutableSectionsSize ExecutablesFileSections
96+
ExecutableSectionsSize builder.ExecutablesFileSections
9797

9898
// Compilation Database to build/update
9999
CompilationDatabase *builder.CompilationDatabase
@@ -106,29 +106,6 @@ type Context struct {
106106
SourceOverride map[string]string
107107
}
108108

109-
// ExecutableSectionSize represents a section of the executable output file
110-
type ExecutableSectionSize struct {
111-
Name string `json:"name"`
112-
Size int `json:"size"`
113-
MaxSize int `json:"max_size"`
114-
}
115-
116-
// ExecutablesFileSections is an array of ExecutablesFileSection
117-
type ExecutablesFileSections []ExecutableSectionSize
118-
119-
// ToRPCExecutableSectionSizeArray transforms this array into a []*rpc.ExecutableSectionSize
120-
func (s ExecutablesFileSections) ToRPCExecutableSectionSizeArray() []*rpc.ExecutableSectionSize {
121-
res := []*rpc.ExecutableSectionSize{}
122-
for _, section := range s {
123-
res = append(res, &rpc.ExecutableSectionSize{
124-
Name: section.Name,
125-
Size: int64(section.Size),
126-
MaxSize: int64(section.MaxSize),
127-
})
128-
}
129-
return res
130-
}
131-
132109
func (ctx *Context) ExtractBuildOptions() *properties.Map {
133110
opts := properties.NewMap()
134111
opts.Set("hardwareFolders", strings.Join(ctx.HardwareDirs.AsStrings(), ","))

0 commit comments

Comments
 (0)
Please sign in to comment.