Skip to content

Commit 0802e27

Browse files
committed
Move size calculation from Java IDE
1 parent a07ea16 commit 0802e27

File tree

3 files changed

+204
-0
lines changed

3 files changed

+204
-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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ const MSG_PROP_IN_LIBRARY = "Missing '{0}' from library in {1}"
170170
const MSG_RUNNING_COMMAND = "Ts: {0} - Running: {1}"
171171
const MSG_RUNNING_RECIPE = "Running recipe: {0}"
172172
const MSG_SETTING_BUILD_PATH = "Setting build path to {0}"
173+
const MSG_SIZER_TEXT_FULL = "Sketch uses {0} bytes ({2}%%) of program storage space. Maximum is {1} bytes."
174+
const MSG_SIZER_DATA_FULL = "Global variables use {0} bytes ({2}%%) of dynamic memory, leaving {3} bytes for local variables. Maximum is {1} bytes."
175+
const MSG_SIZER_DATA = "Global variables use {0} bytes of dynamic memory."
176+
const MSG_SIZER_TEXT_TOO_BIG = "Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it."
177+
const MSG_SIZER_DATA_TOO_BIG = "Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint."
178+
const MSG_SIZER_LOW_MEMORY = "Low memory available, stability problems may occur."
179+
const MSG_SIZER_ERROR_NO_RULE = "Couldn't determine program size"
173180
const MSG_SKETCH_CANT_BE_IN_BUILDPATH = "Sketch cannot be located in build path. Please specify a different build path"
174181
const MSG_SKIPPING_TAG_ALREADY_DEFINED = "Skipping tag {0} because prototype is already defined"
175182
const MSG_SKIPPING_TAG_BECAUSE_HAS_FIELD = "Skipping tag {0} because it has field {0}"
@@ -197,14 +204,21 @@ const PLATFORM_REWRITE_NEW = "new"
197204
const PLATFORM_REWRITE_OLD = "old"
198205
const PLATFORM_URL = "url"
199206
const PLATFORM_VERSION = "version"
207+
const PROPERTY_WARN_DATA_PERCENT = "build.warn_data_percentage"
208+
const PROPERTY_UPLOAD_MAX_SIZE = "upload.maximum_size"
209+
const PROPERTY_UPLOAD_MAX_DATA_SIZE = "upload.maximum_data_size"
200210
const PROGRAMMER_NAME = "name"
201211
const RECIPE_AR_PATTERN = "recipe.ar.pattern"
202212
const RECIPE_C_COMBINE_PATTERN = "recipe.c.combine.pattern"
203213
const RECIPE_C_PATTERN = "recipe.c.o.pattern"
204214
const RECIPE_CPP_PATTERN = "recipe.cpp.o.pattern"
215+
const RECIPE_SIZE_PATTERN = "recipe.size.pattern"
205216
const RECIPE_PREPROC_INCLUDES = "recipe.preproc.includes"
206217
const RECIPE_PREPROC_MACROS = "recipe.preproc.macros"
207218
const RECIPE_S_PATTERN = "recipe.S.o.pattern"
219+
const RECIPE_SIZE_REGEXP = "recipe.size.regex"
220+
const RECIPE_SIZE_REGEXP_DATA = "recipe.size.regex.data"
221+
const RECIPE_SIZE_REGEXP_EEPROM = "recipe.size.regex.eeprom"
208222
const REWRITING_DISABLED = "disabled"
209223
const REWRITING = "rewriting"
210224
const SPACE = " "
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
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+
"regexp"
35+
"strconv"
36+
37+
"arduino.cc/builder/builder_utils"
38+
"arduino.cc/builder/constants"
39+
"arduino.cc/builder/i18n"
40+
"arduino.cc/builder/types"
41+
"arduino.cc/properties"
42+
)
43+
44+
type Sizer struct{}
45+
46+
func (s *Sizer) Run(ctx *types.Context) error {
47+
buildProperties := ctx.BuildProperties
48+
verbose := ctx.Verbose
49+
warningsLevel := ctx.WarningsLevel
50+
logger := ctx.GetLogger()
51+
52+
err := checkSize(buildProperties, verbose, warningsLevel, logger)
53+
if err != nil {
54+
return i18n.WrapError(err)
55+
}
56+
57+
return nil
58+
}
59+
60+
func checkSize(buildProperties properties.Map, verbose bool, warningsLevel string, logger i18n.Logger) error {
61+
62+
properties := buildProperties.Clone()
63+
properties[constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS] = properties[constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS+"."+warningsLevel]
64+
65+
maxTextSizeString := properties[constants.PROPERTY_UPLOAD_MAX_SIZE]
66+
maxDataSizeString := properties[constants.PROPERTY_UPLOAD_MAX_DATA_SIZE]
67+
68+
if maxTextSizeString == "" {
69+
return nil
70+
}
71+
72+
maxTextSize, err := strconv.Atoi(maxTextSizeString)
73+
if err != nil {
74+
return err
75+
}
76+
77+
maxDataSize := -1
78+
if maxDataSizeString != "" {
79+
maxDataSize, err = strconv.Atoi(maxDataSizeString)
80+
if err != nil {
81+
return err
82+
}
83+
}
84+
85+
textSize, dataSize, _, err := execSizeReceipe(properties, logger)
86+
if err != nil {
87+
logger.Println(constants.LOG_LEVEL_WARN, constants.MSG_SIZER_ERROR_NO_RULE)
88+
return nil
89+
}
90+
91+
logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_SIZER_TEXT_FULL, strconv.Itoa(textSize), strconv.Itoa(maxTextSize), strconv.Itoa(textSize*100/maxTextSize))
92+
if dataSize >= 0 {
93+
if maxDataSize > 0 {
94+
logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_SIZER_DATA_FULL, strconv.Itoa(dataSize), strconv.Itoa(maxDataSize), strconv.Itoa(dataSize*100/maxDataSize), strconv.Itoa(maxDataSize-dataSize))
95+
} else {
96+
logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_SIZER_DATA, strconv.Itoa(dataSize))
97+
}
98+
}
99+
100+
if textSize > maxTextSize {
101+
logger.Println(constants.LOG_LEVEL_ERROR, constants.MSG_SIZER_TEXT_TOO_BIG)
102+
return errors.New("")
103+
}
104+
105+
if maxDataSize > 0 && dataSize > maxDataSize {
106+
logger.Println(constants.LOG_LEVEL_ERROR, constants.MSG_SIZER_DATA_TOO_BIG)
107+
return errors.New("")
108+
}
109+
110+
if properties[constants.PROPERTY_WARN_DATA_PERCENT] != "" {
111+
warnDataPercentage, err := strconv.Atoi(properties[constants.PROPERTY_WARN_DATA_PERCENT])
112+
if err != nil {
113+
return err
114+
}
115+
if maxDataSize > 0 && dataSize > maxDataSize*warnDataPercentage/100 {
116+
logger.Println(constants.LOG_LEVEL_WARN, constants.MSG_SIZER_LOW_MEMORY)
117+
}
118+
}
119+
120+
return nil
121+
}
122+
123+
func execSizeReceipe(properties properties.Map, logger i18n.Logger) (textSize int, dataSize int, eepromSize int, resErr error) {
124+
out, err := builder_utils.ExecRecipe(properties, constants.RECIPE_SIZE_PATTERN, false, false, false, logger)
125+
if err != nil {
126+
resErr = errors.New("Error while determining sketch size: " + err.Error())
127+
return
128+
}
129+
130+
// force multiline match prepending "(?m)" to the actual regexp
131+
// return an error if RECIPE_SIZE_REGEXP doesn't exist
132+
133+
if len(properties[constants.RECIPE_SIZE_REGEXP]) > 0 {
134+
textRegexp, err := regexp.Compile("(?m)" + properties[constants.RECIPE_SIZE_REGEXP])
135+
if err != nil {
136+
resErr = errors.New("Invalid size regexp: " + err.Error())
137+
return
138+
}
139+
result := textRegexp.FindAllSubmatch(out, -1)
140+
for _, b := range result {
141+
for _, c := range b {
142+
if res, err := strconv.Atoi(string(c)); err == nil {
143+
textSize += res
144+
}
145+
}
146+
}
147+
} else {
148+
resErr = errors.New("Missing size regexp")
149+
return
150+
}
151+
152+
if len(properties[constants.RECIPE_SIZE_REGEXP_DATA]) > 0 {
153+
dataRegexp, err := regexp.Compile("(?m)" + properties[constants.RECIPE_SIZE_REGEXP_DATA])
154+
if err != nil {
155+
resErr = errors.New("Invalid data size regexp: " + err.Error())
156+
return
157+
}
158+
result := dataRegexp.FindAllSubmatch(out, -1)
159+
for _, b := range result {
160+
for _, c := range b {
161+
if res, err := strconv.Atoi(string(c)); err == nil {
162+
dataSize += res
163+
}
164+
}
165+
}
166+
} else {
167+
dataSize = -1
168+
}
169+
170+
if len(properties[constants.RECIPE_SIZE_REGEXP_EEPROM]) > 0 {
171+
eepromRegexp, err := regexp.Compile("(?m)" + properties[constants.RECIPE_SIZE_REGEXP_EEPROM])
172+
if err != nil {
173+
resErr = errors.New("Invalid eeprom size regexp: " + err.Error())
174+
return
175+
}
176+
result := eepromRegexp.FindAllSubmatch(out, -1)
177+
for _, b := range result {
178+
for _, c := range b {
179+
if res, err := strconv.Atoi(string(c)); err == nil {
180+
eepromSize += res
181+
}
182+
}
183+
}
184+
} else {
185+
eepromSize = -1
186+
}
187+
return
188+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy