Skip to content

Commit 7fdae39

Browse files
committed
Move size calculation from Java IDE
1 parent a07ea16 commit 7fdae39

File tree

3 files changed

+163
-0
lines changed

3 files changed

+163
-0
lines changed

src/arduino.cc/builder/builder.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ func (s *Builder) Run(ctx *types.Context) error {
116116
&RecipeByPrefixSuffixRunner{Prefix: "recipe.objcopy.", Suffix: constants.HOOKS_PATTERN_SUFFIX},
117117
&RecipeByPrefixSuffixRunner{Prefix: constants.HOOKS_OBJCOPY_POSTOBJCOPY, Suffix: constants.HOOKS_PATTERN_SUFFIX},
118118

119+
&phases.Sizer{},
120+
119121
&MergeSketchWithBootloader{},
120122

121123
&RecipeByPrefixSuffixRunner{Prefix: constants.HOOKS_POSTBUILD, Suffix: constants.HOOKS_PATTERN_SUFFIX},

src/arduino.cc/builder/constants/constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ const RECIPE_AR_PATTERN = "recipe.ar.pattern"
202202
const RECIPE_C_COMBINE_PATTERN = "recipe.c.combine.pattern"
203203
const RECIPE_C_PATTERN = "recipe.c.o.pattern"
204204
const RECIPE_CPP_PATTERN = "recipe.cpp.o.pattern"
205+
const RECIPE_SIZE_PATTERN = "recipe.size.pattern"
205206
const RECIPE_PREPROC_INCLUDES = "recipe.preproc.includes"
206207
const RECIPE_PREPROC_MACROS = "recipe.preproc.macros"
207208
const RECIPE_S_PATTERN = "recipe.S.o.pattern"
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* This file is part of Arduino Builder.
3+
*
4+
* Arduino Builder is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*
18+
* As a special exception, you may use this file as part of a free software
19+
* library without restriction. Specifically, if other files instantiate
20+
* templates or use macros or inline functions from this file, or you compile
21+
* this file and link it with other files to produce an executable, this
22+
* file does not by itself cause the resulting executable to be covered by
23+
* the GNU General Public License. This exception does not however
24+
* invalidate any other reasons why the executable file might be covered by
25+
* the GNU General Public License.
26+
*
27+
* Copyright 2016 Arduino LLC (http://www.arduino.cc/)
28+
*/
29+
30+
package phases
31+
32+
import (
33+
"errors"
34+
"os"
35+
"regexp"
36+
"strconv"
37+
38+
"arduino.cc/builder/builder_utils"
39+
"arduino.cc/builder/constants"
40+
"arduino.cc/builder/i18n"
41+
"arduino.cc/builder/types"
42+
"arduino.cc/properties"
43+
)
44+
45+
type Sizer struct{}
46+
47+
func (s *Sizer) Run(ctx *types.Context) error {
48+
buildProperties := ctx.BuildProperties
49+
verbose := ctx.Verbose
50+
warningsLevel := ctx.WarningsLevel
51+
logger := ctx.GetLogger()
52+
53+
err := checkSize(buildProperties, verbose, warningsLevel, logger)
54+
if err != nil {
55+
return i18n.WrapError(err)
56+
}
57+
58+
return nil
59+
}
60+
61+
func checkSize(buildProperties properties.Map, verbose bool, warningsLevel string, logger i18n.Logger) error {
62+
63+
properties := buildProperties.Clone()
64+
properties[constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS] = properties[constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS+"."+warningsLevel]
65+
66+
maxTextSizeString := properties["upload.maximum_size"]
67+
maxDataSizeString := properties["upload.maximum_data_size"]
68+
69+
if maxTextSizeString == "" {
70+
return nil
71+
}
72+
73+
logLevel := constants.LOG_LEVEL_INFO
74+
75+
maxTextSize, _ := strconv.Atoi(maxTextSizeString)
76+
maxDataSize := -1
77+
78+
if maxDataSizeString != "" {
79+
maxDataSize, _ = strconv.Atoi(maxDataSizeString)
80+
}
81+
82+
var textSize, dataSize, eepromSize int
83+
84+
err := execSizeReceipe(properties, logger, &textSize, &dataSize, &eepromSize)
85+
if err != nil {
86+
return err
87+
}
88+
89+
logger.Fprintln(os.Stdout, logLevel, "Sketch uses {0} bytes ({2}%%) of program storage space. Maximum is {1} bytes.", strconv.Itoa(textSize), strconv.Itoa(maxTextSize), strconv.Itoa(textSize*100/maxTextSize))
90+
if dataSize > 0 {
91+
if maxDataSize > 0 {
92+
logger.Fprintln(os.Stdout, logLevel, "Global variables use {0} bytes ({2}%%) of dynamic memory, leaving {3} bytes for local variables. Maximum is {1} bytes.", strconv.Itoa(dataSize), strconv.Itoa(maxDataSize), strconv.Itoa(dataSize*100/maxDataSize), strconv.Itoa(maxDataSize-dataSize))
93+
} else {
94+
logger.Fprintln(os.Stdout, logLevel, "Global variables use {0} bytes of dynamic memory.", strconv.Itoa(dataSize))
95+
}
96+
}
97+
98+
if textSize > maxTextSize {
99+
return errors.New("Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it.")
100+
}
101+
102+
if maxDataSize > 0 && dataSize > maxDataSize {
103+
return errors.New("Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint.")
104+
}
105+
106+
if properties["build.warn_data_percentage"] != "" {
107+
warnDataPercentage, _ := strconv.Atoi(properties["build.warn_data_percentage"])
108+
if maxDataSize > 0 && dataSize > maxDataSize*warnDataPercentage/100 {
109+
logger.Fprintln(os.Stdout, logLevel, "Low memory available, stability problems may occur.")
110+
}
111+
}
112+
113+
return nil
114+
}
115+
116+
func execSizeReceipe(properties properties.Map, logger i18n.Logger, textSize *int, dataSize *int, eepromSize *int) error {
117+
118+
out, err := builder_utils.ExecRecipe(properties, constants.RECIPE_SIZE_PATTERN, false, false, false, logger)
119+
120+
if err != nil {
121+
return errors.New("Couldn't determine program size: {0}")
122+
}
123+
124+
// force multiline match prepending "(?m)" to the actual regexp
125+
126+
if len(properties["recipe.size.regex"]) > 0 {
127+
textRegexp := regexp.MustCompile("(?m)" + properties["recipe.size.regex"])
128+
result := textRegexp.FindAllSubmatch(out, -1)
129+
for _, b := range result {
130+
for _, c := range b {
131+
res, _ := strconv.Atoi(string(c))
132+
*textSize += res
133+
}
134+
}
135+
}
136+
137+
if len(properties["recipe.size.regex.data"]) > 0 {
138+
dataRegexp := regexp.MustCompile("(?m)" + properties["recipe.size.regex.data"])
139+
result := dataRegexp.FindAllSubmatch(out, -1)
140+
for _, b := range result {
141+
for _, c := range b {
142+
res, _ := strconv.Atoi(string(c))
143+
*dataSize += res
144+
}
145+
}
146+
}
147+
148+
if len(properties["recipe.size.regex.eeprom"]) > 0 {
149+
eepromRegexp := regexp.MustCompile("(?m)" + properties["recipe.size.regex.eeprom"])
150+
result := eepromRegexp.FindAllSubmatch(out, -1)
151+
for _, b := range result {
152+
for _, c := range b {
153+
res, _ := strconv.Atoi(string(c))
154+
*eepromSize += res
155+
}
156+
}
157+
}
158+
159+
return nil
160+
}

0 commit comments

Comments
 (0)