Skip to content

Commit ee529d3

Browse files
committed
Adding support for sketch-specific build properties
Tests for existence of a build_props.txt file in the sketch directory. If present reads properties similar to those found in the hardware and board files, allowing the user to easily customise the build for a specific sketch. Most useful when containing lines similar to compiler.c.extra_flags=-D NDEBUG compiler.cpp.extra_flags=-D NDEBUG -D MYLIBRARY_BUFSIZE=100 which enables the user to have macros defined for all compilation units, including libraries. Signed-off-by: Steve Marple <[email protected]>
1 parent a25b7e8 commit ee529d3

12 files changed

+269
-9
lines changed

Diff for: main.go

+9
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,15 @@ func main() {
293293
context[constants.CTX_LOGGER] = i18n.HumanLogger{}
294294
}
295295

296+
sketchBuildOptions, err := builder.GetSketchBuildProperties(context)
297+
if err != nil {
298+
printError(err, printStackTrace)
299+
defer os.Exit(1)
300+
return
301+
}
302+
context[constants.CTX_SKETCH_BUILD_PROPERTIES] = sketchBuildOptions
303+
304+
296305
if compile {
297306
err = builder.RunBuilder(context)
298307
} else if dumpPrefs {

Diff for: src/arduino.cc/builder/constants/constants.go

+2
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ const CTX_PROTOTYPES_OF_PREPROC_SOURCE = "prototypesOfPreprocSource"
114114
const CTX_PROTOTYPES_OF_SOURCE = "prototypesOfSource"
115115
const CTX_PROTOTYPES = "prototypes"
116116
const CTX_SKETCH_BUILD_PATH = "sketchBuildPath"
117+
const CTX_SKETCH_BUILD_PROPERTIES = "sketchBuildProperties"
117118
const CTX_SKETCH_LOCATION = "sketchLocation"
118119
const CTX_SKETCH = "sketch"
119120
const CTX_SOURCE = "source"
@@ -245,6 +246,7 @@ const RECIPE_PREPROC_MACROS = "recipe.preproc.macros"
245246
const RECIPE_S_PATTERN = "recipe.S.o.pattern"
246247
const REWRITING_DISABLED = "disabled"
247248
const REWRITING = "rewriting"
249+
const SKETCH_BUILD_OPTIONS_TXT = "build_props.txt"
248250
const SPACE = " "
249251
const TOOL_NAME = "name"
250252
const TOOL_URL = "url"

Diff for: src/arduino.cc/builder/container_setup.go

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ func (s *ContainerSetupHardwareToolsLibsSketchAndProps) Run(context map[string]i
5050
&SketchLoader{},
5151
&SetupBuildProperties{},
5252
&LoadVIDPIDSpecificProperties{},
53+
&SetSketchBuildProperties{},
5354
&SetCustomBuildProperties{},
5455
&AddMissingBuildPropertiesFromParentPlatformTxtFiles{},
5556
}

Diff for: src/arduino.cc/builder/create_build_options_map.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -40,32 +40,31 @@ import (
4040
type CreateBuildOptionsMap struct{}
4141

4242
func (s *CreateBuildOptionsMap) Run(context map[string]interface{}) error {
43-
buildOptions := make(map[string]string)
44-
43+
buildOptions := make(map[string]interface{})
4544
buildOptionsMapKeys := []string{
4645
constants.CTX_HARDWARE_FOLDERS,
4746
constants.CTX_TOOLS_FOLDERS,
4847
constants.CTX_LIBRARIES_FOLDERS,
4948
constants.CTX_FQBN,
5049
constants.CTX_SKETCH_LOCATION,
5150
constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION,
51+
constants.CTX_SKETCH_BUILD_PROPERTIES,
5252
constants.CTX_CUSTOM_BUILD_PROPERTIES,
5353
}
5454

5555
for _, key := range buildOptionsMapKeys {
5656
if utils.MapHas(context, key) {
5757
originalValue := context[key]
58-
value := constants.EMPTY_STRING
5958
kindOfValue := reflect.TypeOf(originalValue).Kind()
6059
if kindOfValue == reflect.Slice {
61-
value = strings.Join(originalValue.([]string), ",")
60+
buildOptions[key] = strings.Join(originalValue.([]string), ",")
6261
} else if kindOfValue == reflect.String {
63-
value = originalValue.(string)
62+
buildOptions[key] = originalValue.(string)
63+
} else if kindOfValue == reflect.TypeOf(make(map[string]string)).Kind() {
64+
buildOptions[key] = originalValue
6465
} else {
6566
return utils.Errorf(context, constants.MSG_UNHANDLED_TYPE_IN_CONTEXT, kindOfValue.String(), key)
6667
}
67-
68-
buildOptions[key] = value
6968
}
7069
}
7170

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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 2015 Steve Marple
28+
*/
29+
30+
package builder
31+
32+
import (
33+
"arduino.cc/builder/constants"
34+
"arduino.cc/builder/props"
35+
"github.com/go-errors/errors"
36+
"os"
37+
"path/filepath"
38+
)
39+
40+
func GetSketchBuildPropertiesFilename(context map[string]interface{}) (string, error) {
41+
sketchLocation, ok := context[constants.CTX_SKETCH_LOCATION].(string)
42+
if !ok {
43+
return "", errors.New("Unknown sketch location")
44+
}
45+
46+
filename := filepath.Join(filepath.Dir(sketchLocation), constants.SKETCH_BUILD_OPTIONS_TXT)
47+
return filename, nil
48+
}
49+
50+
51+
func GetSketchBuildProperties(context map[string]interface{}) (map[string]string, error) {
52+
filename, err := GetSketchBuildPropertiesFilename(context)
53+
if err != nil {
54+
return nil, err
55+
}
56+
_, err = os.Stat(filename)
57+
if err == nil {
58+
return props.SafeLoad(filename)
59+
}
60+
return make(map[string]string), nil
61+
}
62+
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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 2015 Steve Marple
28+
*/
29+
30+
package builder
31+
32+
import (
33+
"arduino.cc/builder/constants"
34+
"arduino.cc/builder/utils"
35+
)
36+
37+
type SetSketchBuildProperties struct{}
38+
39+
func (s *SetSketchBuildProperties) Run(context map[string]interface{}) error {
40+
if !utils.MapHas(context, constants.CTX_SKETCH_BUILD_PROPERTIES) {
41+
return nil
42+
}
43+
44+
buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string)
45+
46+
sketchBuildProperties := context[constants.CTX_SKETCH_BUILD_PROPERTIES].(map[string]string)
47+
for key, value := range sketchBuildProperties {
48+
buildProperties[key] = value
49+
}
50+
51+
return nil
52+
}

Diff for: src/arduino.cc/builder/test/create_build_options_map_test.go

+16-2
Original file line numberDiff line numberDiff line change
@@ -48,26 +48,40 @@ func TestCreateBuildOptionsMap(t *testing.T) {
4848
context[constants.CTX_SKETCH_LOCATION] = "sketchLocation"
4949
context[constants.CTX_VERBOSE] = true
5050
context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = "ideVersion"
51+
context[constants.CTX_SKETCH_BUILD_PROPERTIES] = map[string]string{
52+
"compiler.c.extra_flags": "-D NDEBUG",
53+
"compiler.cpp.extra_flags": "-D HOSTNAME=\"www.example.com\"",
54+
}
5155
context[constants.CTX_DEBUG_LEVEL] = 5
5256

5357
create := builder.CreateBuildOptionsMap{}
5458
err := create.Run(context)
5559
NoError(t, err)
5660

57-
buildOptions := context[constants.CTX_BUILD_OPTIONS].(map[string]string)
58-
require.Equal(t, 6, len(utils.KeysOfMapOfString(buildOptions)))
61+
buildOptions := context[constants.CTX_BUILD_OPTIONS].(map[string]interface{})
62+
require.Equal(t, 7, len(utils.KeysOfMapOfStringInterface(buildOptions)))
5963
require.Equal(t, "hardware,hardware2", buildOptions[constants.CTX_HARDWARE_FOLDERS])
6064
require.Equal(t, "tools", buildOptions[constants.CTX_TOOLS_FOLDERS])
6165
require.Equal(t, "libraries", buildOptions[constants.CTX_LIBRARIES_FOLDERS])
6266
require.Equal(t, "fqbn", buildOptions[constants.CTX_FQBN])
6367
require.Equal(t, "sketchLocation", buildOptions[constants.CTX_SKETCH_LOCATION])
6468
require.Equal(t, "ideVersion", buildOptions[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION])
6569

70+
sketchBuildProps := map[string]string{
71+
"compiler.c.extra_flags": "-D NDEBUG",
72+
"compiler.cpp.extra_flags": "-D HOSTNAME=\"www.example.com\"",
73+
}
74+
require.Equal(t, sketchBuildProps, buildOptions[constants.CTX_SKETCH_BUILD_PROPERTIES])
75+
6676
require.Equal(t, "{\n"+
6777
" \"fqbn\": \"fqbn\",\n"+
6878
" \"hardwareFolders\": \"hardware,hardware2\",\n"+
6979
" \"librariesFolders\": \"libraries\",\n"+
7080
" \"runtime.ide.version\": \"ideVersion\",\n"+
81+
" \"sketchBuildProperties\": {\n" +
82+
" \"compiler.c.extra_flags\": \"-D NDEBUG\",\n"+
83+
" \"compiler.cpp.extra_flags\": \"-D HOSTNAME=\\\"www.example.com\\\"\"\n"+
84+
" },\n"+
7185
" \"sketchLocation\": \"sketchLocation\",\n"+
7286
" \"toolsFolders\": \"tools\"\n"+
7387
"}", context[constants.CTX_BUILD_OPTIONS_JSON].(string))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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 2015 Steve Marple
28+
*/
29+
30+
package test
31+
32+
import (
33+
"arduino.cc/builder"
34+
"arduino.cc/builder/constants"
35+
"github.com/stretchr/testify/require"
36+
"path/filepath"
37+
"testing"
38+
)
39+
40+
func TestSketchWithNoBuildProps(t *testing.T) {
41+
var err error
42+
context := make(map[string]interface{})
43+
44+
context[constants.CTX_BUILD_PATH] = "buildPath"
45+
context[constants.CTX_HARDWARE_FOLDERS] = []string{"hardware"}
46+
context[constants.CTX_TOOLS_FOLDERS] = []string{"tools"}
47+
context[constants.CTX_LIBRARIES_FOLDERS] = []string{"libraries"}
48+
context[constants.CTX_FQBN] = "fqbn"
49+
context[constants.CTX_SKETCH_LOCATION] = filepath.Join("sketch_no_props", "sketch.ino")
50+
51+
context[constants.CTX_VERBOSE] = true
52+
context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = "ideVersion"
53+
context[constants.CTX_SKETCH_BUILD_PROPERTIES], err = builder.GetSketchBuildProperties(context)
54+
NoError(t, err)
55+
56+
context[constants.CTX_DEBUG_LEVEL] = 5
57+
58+
create := builder.CreateBuildOptionsMap{}
59+
err = create.Run(context)
60+
NoError(t, err)
61+
62+
buildOptions := context[constants.CTX_BUILD_OPTIONS].(map[string]interface{})
63+
sketchBuildProps := make(map[string]string)
64+
require.Equal(t, sketchBuildProps, buildOptions[constants.CTX_SKETCH_BUILD_PROPERTIES])
65+
}
66+
67+
func TestSketchWithBuildProps(t *testing.T) {
68+
var err error
69+
context := make(map[string]interface{})
70+
71+
context[constants.CTX_BUILD_PATH] = "buildPath"
72+
context[constants.CTX_HARDWARE_FOLDERS] = []string{"hardware"}
73+
context[constants.CTX_TOOLS_FOLDERS] = []string{"tools"}
74+
context[constants.CTX_LIBRARIES_FOLDERS] = []string{"libraries"}
75+
context[constants.CTX_FQBN] = "fqbn"
76+
context[constants.CTX_SKETCH_LOCATION] = filepath.Join("sketch_with_props", "sketch.ino")
77+
78+
context[constants.CTX_VERBOSE] = true
79+
context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = "ideVersion"
80+
context[constants.CTX_SKETCH_BUILD_PROPERTIES], err = builder.GetSketchBuildProperties(context)
81+
NoError(t, err)
82+
83+
context[constants.CTX_DEBUG_LEVEL] = 5
84+
85+
create := builder.CreateBuildOptionsMap{}
86+
err = create.Run(context)
87+
NoError(t, err)
88+
89+
buildOptions := context[constants.CTX_BUILD_OPTIONS].(map[string]interface{})
90+
sketchBuildProps := make(map[string]string)
91+
sketchBuildProps["compiler.c.extra_flags"] = "-D NDEBUG"
92+
sketchBuildProps["compiler.cpp.extra_flags"] = "-D NDEBUG -D TESTLIBRARY_BUFSIZE=100 -D ARDUINO_URL=\"https://www.arduino.cc/\""
93+
94+
require.Equal(t, sketchBuildProps, buildOptions[constants.CTX_SKETCH_BUILD_PROPERTIES])
95+
96+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
void setup() {
2+
3+
}
4+
5+
void loop() {
6+
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
compiler.c.extra_flags=-D NDEBUG
2+
compiler.cpp.extra_flags=-D NDEBUG -D TESTLIBRARY_BUFSIZE=100 -D ARDUINO_URL="https://www.arduino.cc/"
3+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
void setup() {
2+
3+
}
4+
5+
void loop() {
6+
7+
}

Diff for: src/arduino.cc/builder/utils/utils.go

+8
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ func KeysOfMapOfStringBool(input map[string]bool) []string {
6060
return keys
6161
}
6262

63+
func KeysOfMapOfStringInterface(input map[string]interface{}) []string {
64+
var keys []string
65+
for key, _ := range input {
66+
keys = append(keys, key)
67+
}
68+
return keys
69+
}
70+
6371
func MergeMapsOfStrings(target map[string]string, sources ...map[string]string) map[string]string {
6472
for _, source := range sources {
6573
for key, value := range source {

0 commit comments

Comments
 (0)