Skip to content

Commit 4fbcfc1

Browse files
committed
arduifine
1 parent 1bd9945 commit 4fbcfc1

File tree

13 files changed

+128
-31
lines changed

13 files changed

+128
-31
lines changed

docs/sketch-build-process.md

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ compiler:
2727
rare cases, prototype generation may fail for some functions. To work around this, you can provide your own prototypes
2828
for these functions.
2929
- `#line` directives are added to make warning or error messages reflect the original sketch layout.
30+
- Special and optional sketch variables named ARDUIFINE and ARDUINOGLOBAL are parsed, and their content is used to
31+
provide more arguments to the compiler commands. Those arguments are used for every compiled source file, including
32+
the core, internal and external libraries. Their content is displayed in the message area.
3033

3134
No pre-processing is done to files in a sketch with any extension other than .ino or .pde. Additionally, .h files in the
3235
sketch are not automatically #included from the main sketch file. Further, if you want to call functions defined in a .c

i18n/data/en.po

+28-24
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ msgstr "%s is not managed by package manager"
6161
msgid "%s must be installed."
6262
msgstr "%s must be installed."
6363

64-
#: legacy/builder/builder_utils/utils.go:530
64+
#: legacy/builder/builder_utils/utils.go:533
6565
#: legacy/builder/ctags_runner.go:41
6666
msgid "%s pattern is missing"
6767
msgstr "%s pattern is missing"
@@ -110,6 +110,10 @@ msgstr "ARCH"
110110
msgid "ARDUINO COMMAND LINE MANUAL"
111111
msgstr "ARDUINO COMMAND LINE MANUAL"
112112

113+
#: legacy/builder/phases/libraries_builder.go:48
114+
msgid "Additional compiler options provided by user sketch: {0}"
115+
msgstr "Additional compiler options provided by user sketch: {0}"
116+
113117
#: cli/usage.go:32
114118
msgid "Additional help topics:"
115119
msgstr "Additional help topics:"
@@ -349,7 +353,7 @@ msgstr "Check dependencies status for the specified library."
349353
msgid "Checking lib install prerequisites"
350354
msgstr "Checking lib install prerequisites"
351355

352-
#: legacy/builder/builder_utils/utils.go:280
356+
#: legacy/builder/builder_utils/utils.go:283
353357
msgid "Checking previous results for {0} (result = {1}, dep = {2})"
354358
msgstr "Checking previous results for {0} (result = {1}, dep = {2})"
355359

@@ -391,7 +395,7 @@ msgstr "Compiling core..."
391395
msgid "Compiling libraries..."
392396
msgstr "Compiling libraries..."
393397

394-
#: legacy/builder/phases/libraries_builder.go:135
398+
#: legacy/builder/phases/libraries_builder.go:139
395399
msgid "Compiling library \"{0}\""
396400
msgstr "Compiling library \"{0}\""
397401

@@ -525,7 +529,7 @@ msgstr "Deletes a settings key and all its sub keys."
525529
msgid "Dependencies: %s"
526530
msgstr "Dependencies: %s"
527531

528-
#: legacy/builder/builder_utils/utils.go:358
532+
#: legacy/builder/builder_utils/utils.go:361
529533
msgid "Depfile is about different file: {0}"
530534
msgstr "Depfile is about different file: {0}"
531535

@@ -794,7 +798,7 @@ msgstr "Error getting libraries info: %v"
794798
msgid "Error getting port settings details: %s"
795799
msgstr "Error getting port settings details: %s"
796800

797-
#: legacy/builder/types/context.go:239
801+
#: legacy/builder/types/context.go:244
798802
msgid "Error in FQBN: %s"
799803
msgstr "Error in FQBN: %s"
800804

@@ -1059,7 +1063,7 @@ msgstr "Failed to listen on TCP port: %[1]s. Unexpected error: %[2]v"
10591063
msgid "Failed to listen on TCP port: %s. Address already in use."
10601064
msgstr "Failed to listen on TCP port: %s. Address already in use."
10611065

1062-
#: legacy/builder/builder_utils/utils.go:380
1066+
#: legacy/builder/builder_utils/utils.go:383
10631067
msgid "Failed to read: {0}"
10641068
msgstr "Failed to read: {0}"
10651069

@@ -1358,7 +1362,7 @@ msgstr "Library installed"
13581362
msgid "Library name"
13591363
msgstr "Library name"
13601364

1361-
#: legacy/builder/phases/libraries_builder.go:91
1365+
#: legacy/builder/phases/libraries_builder.go:95
13621366
msgid "Library {0} has been declared precompiled:"
13631367
msgstr "Library {0} has been declared precompiled:"
13641368

@@ -1511,7 +1515,7 @@ msgstr "New version"
15111515
msgid "No boards found."
15121516
msgstr "No boards found."
15131517

1514-
#: legacy/builder/builder_utils/utils.go:351
1518+
#: legacy/builder/builder_utils/utils.go:354
15151519
msgid "No colon in first line of depfile"
15161520
msgstr "No colon in first line of depfile"
15171521

@@ -1563,13 +1567,13 @@ msgstr "No valid dependencies solution found"
15631567
msgid "Not enough memory; see %s for tips on reducing your footprint."
15641568
msgstr "Not enough memory; see %s for tips on reducing your footprint."
15651569

1566-
#: legacy/builder/builder_utils/utils.go:284
1570+
#: legacy/builder/builder_utils/utils.go:287
15671571
msgid "Not found: nil"
15681572
msgstr "Not found: nil"
15691573

1570-
#: legacy/builder/builder_utils/utils.go:300
1571-
#: legacy/builder/builder_utils/utils.go:313
1572-
#: legacy/builder/builder_utils/utils.go:387
1574+
#: legacy/builder/builder_utils/utils.go:303
1575+
#: legacy/builder/builder_utils/utils.go:316
1576+
#: legacy/builder/builder_utils/utils.go:390
15731577
msgid "Not found: {0}"
15741578
msgstr "Not found: {0}"
15751579

@@ -1745,8 +1749,8 @@ msgstr "Port closed:"
17451749
msgid "Port monitor error"
17461750
msgstr "Port monitor error"
17471751

1748-
#: legacy/builder/phases/libraries_builder.go:101
1749-
#: legacy/builder/phases/libraries_builder.go:109
1752+
#: legacy/builder/phases/libraries_builder.go:105
1753+
#: legacy/builder/phases/libraries_builder.go:113
17501754
msgid "Precompiled library in \"{0}\" not found"
17511755
msgstr "Precompiled library in \"{0}\" not found"
17521756

@@ -2004,11 +2008,11 @@ msgstr "Skip linking of final executable."
20042008
msgid "Skipping 1200-bps touch reset: no serial port selected!"
20052009
msgstr "Skipping 1200-bps touch reset: no serial port selected!"
20062010

2007-
#: legacy/builder/builder_utils/utils.go:476
2011+
#: legacy/builder/builder_utils/utils.go:479
20082012
msgid "Skipping archive creation of: {0}"
20092013
msgstr "Skipping archive creation of: {0}"
20102014

2011-
#: legacy/builder/builder_utils/utils.go:269
2015+
#: legacy/builder/builder_utils/utils.go:272
20122016
msgid "Skipping compile of: {0}"
20132017
msgstr "Skipping compile of: {0}"
20142018

@@ -2069,7 +2073,7 @@ msgstr "The key '%[1]v' is not a list of items, can't remove from it.\n"
20692073
msgid "The output format for the logs, can be: %s"
20702074
msgstr "The output format for the logs, can be: %s"
20712075

2072-
#: legacy/builder/phases/libraries_builder.go:151
2076+
#: legacy/builder/phases/libraries_builder.go:155
20732077
msgid "The platform does not support '{0}' for precompiled libraries."
20742078
msgstr "The platform does not support '{0}' for precompiled libraries."
20752079

@@ -2333,13 +2337,13 @@ msgstr "Using library {0} in folder: {1} {2}"
23332337
msgid "Using precompiled core: {0}"
23342338
msgstr "Using precompiled core: {0}"
23352339

2336-
#: legacy/builder/phases/libraries_builder.go:98
2337-
#: legacy/builder/phases/libraries_builder.go:106
2340+
#: legacy/builder/phases/libraries_builder.go:102
2341+
#: legacy/builder/phases/libraries_builder.go:110
23382342
msgid "Using precompiled library in {0}"
23392343
msgstr "Using precompiled library in {0}"
23402344

2341-
#: legacy/builder/builder_utils/utils.go:267
2342-
#: legacy/builder/builder_utils/utils.go:499
2345+
#: legacy/builder/builder_utils/utils.go:270
2346+
#: legacy/builder/builder_utils/utils.go:502
23432347
msgid "Using previously compiled file: {0}"
23442348
msgstr "Using previously compiled file: {0}"
23452349

@@ -3429,9 +3433,9 @@ msgstr "wrong format in server response"
34293433
msgid "{0} invalid, rebuilding all"
34303434
msgstr "{0} invalid, rebuilding all"
34313435

3432-
#: legacy/builder/builder_utils/utils.go:323
3433-
#: legacy/builder/builder_utils/utils.go:329
3434-
#: legacy/builder/builder_utils/utils.go:393
3436+
#: legacy/builder/builder_utils/utils.go:326
3437+
#: legacy/builder/builder_utils/utils.go:332
3438+
#: legacy/builder/builder_utils/utils.go:396
34353439
msgid "{0} newer than {1}"
34363440
msgstr "{0} newer than {1}"
34373441

legacy/builder/builder_utils/utils.go

+3
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ func compileFileWithRecipe(ctx *types.Context, sourcePath *paths.Path, source *p
232232
properties := buildProperties.Clone()
233233
properties.Set(constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS, properties.Get(constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS+"."+ctx.WarningsLevel))
234234
properties.Set(constants.BUILD_PROPERTIES_INCLUDES, strings.Join(includes, constants.SPACE))
235+
if len(ctx.Arduifines) > 0 {
236+
properties.Set(constants.BUILD_PROPERTIES_INCLUDES, properties.Get(constants.BUILD_PROPERTIES_INCLUDES) + " " + ctx.Arduifines + " ")
237+
}
235238
properties.SetPath(constants.BUILD_PROPERTIES_SOURCE_FILE, source)
236239
relativeSource, err := sourcePath.RelTo(source)
237240
if err != nil {

legacy/builder/ctags/ctags_parser.go

+45-3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const KIND_FUNCTION = "function"
3232
const TEMPLATE = "template"
3333
const STATIC = "static"
3434
const EXTERN = "extern \"C\""
35+
const ARDUIFINE = "ARDUIFINE"
36+
const ARDUINOGLOBAL = "ARDUINOGLOBAL"
3537

3638
var KNOWN_TAG_KINDS = map[string]bool{
3739
"prototype": true,
@@ -43,14 +45,21 @@ type CTagsParser struct {
4345
mainFile *paths.Path
4446
}
4547

46-
func (p *CTagsParser) Parse(ctagsOutput string, mainFile *paths.Path) []*types.CTag {
48+
func (p *CTagsParser) Parse(ctagsOutput string, mainFile *paths.Path) ([]*types.CTag, string) {
49+
Arduifines := ""
4750
rows := strings.Split(ctagsOutput, "\n")
4851
rows = removeEmpty(rows)
4952

5053
p.mainFile = mainFile
5154

5255
for _, row := range rows {
53-
p.tags = append(p.tags, parseTag(row))
56+
if strings.Index(row, " "+ARDUINOGLOBAL) != -1 {
57+
Arduifines += encloseForCmdLine(extractCtagsDoubleQuotedString(row, ARDUINOGLOBAL))
58+
} else if strings.Index(row, " "+ARDUIFINE) != -1 {
59+
Arduifines += encloseForCmdLine(toCompilerCmdLine(extractCtagsDoubleQuotedString(row, ARDUIFINE)))
60+
} else {
61+
p.tags = append(p.tags, parseTag(row))
62+
}
5463
}
5564

5665
p.skipTagsWhere(tagIsUnknown)
@@ -60,7 +69,7 @@ func (p *CTagsParser) Parse(ctagsOutput string, mainFile *paths.Path) []*types.C
6069
p.skipDuplicates()
6170
p.skipTagsWhere(p.prototypeAndCodeDontMatch)
6271

63-
return p.tags
72+
return p.tags, Arduifines
6473
}
6574

6675
func (p *CTagsParser) addPrototypes() {
@@ -238,3 +247,36 @@ func removeEmpty(rows []string) []string {
238247

239248
return newRows
240249
}
250+
251+
func extractCtagsDoubleQuotedString (row string, directive string) string {
252+
first := strings.Index(row, "\"");
253+
last := strings.LastIndex(row, "\";$/;\""); // <- $/;" is a ctag addition
254+
if (first <= 0) || (last <= 0) || (first + 1 >= last) {
255+
//print("\nERROR: malformed \"" + directive + "\" global directive\n\n")
256+
return ""
257+
}
258+
return strings.Replace(strings.Replace(row[first+1 : last], "\\\\", "\\", -1), "\\\"", "\"", -1)
259+
}
260+
261+
func toCompilerCmdLine (define string) string {
262+
// transforms ` A = "B C" ` to `-DA="B C"`
263+
// transforms ` A ` to `-DA`
264+
elts := strings.SplitAfterN(define, "=", 2)
265+
ret := ""
266+
eltsLength := len(elts)
267+
if eltsLength > 0 {
268+
equalsLength := eltsLength - 1
269+
ret += "-D"+strings.TrimSpace(elts[0][:len(elts[0])-equalsLength])
270+
if equalsLength > 0 {
271+
ret += "="+strings.TrimSpace(elts[1])
272+
}
273+
}
274+
return ret
275+
}
276+
277+
func encloseForCmdLine (str string) string {
278+
if len(str) > 0 {
279+
return " \""+str+"\" "
280+
}
281+
return ""
282+
}

legacy/builder/ctags/ctags_parser_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ func produceTags(t *testing.T, filename string) []*types.CTag {
3030
require.NoError(t, err)
3131

3232
parser := CTagsParser{}
33-
return parser.Parse(string(bytes), nil)
33+
tags, Arduifines := parser.Parse(string(bytes), nil)
34+
_ = Arduifines
35+
return tags
3436
}
3537

3638
func TestCTagsParserShouldListPrototypes(t *testing.T) {

legacy/builder/ctags_runner.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func (s *CTagsRunner) Run(ctx *types.Context) error {
5656

5757
parser := &ctags.CTagsParser{}
5858

59-
ctx.CTagsOfPreprocessedSource = parser.Parse(ctx.CTagsOutput, ctx.Sketch.MainFile)
59+
ctx.CTagsOfPreprocessedSource, ctx.Arduifines = parser.Parse(ctx.CTagsOutput, ctx.Sketch.MainFile)
6060
parser.FixCLinkageTagsDeclarations(ctx.CTagsOfPreprocessedSource)
6161

6262
protos, line := parser.GeneratePrototypes()

legacy/builder/phases/libraries_builder.go

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ func (s *LibrariesBuilder) Run(ctx *types.Context) error {
4444
return errors.WithStack(err)
4545
}
4646

47+
if len(ctx.Arduifines) > 0 {
48+
ctx.GetLogger().Println(constants.LOG_LEVEL_DEBUG, tr("Additional compiler options provided by user sketch: {0}"), ctx.Arduifines)
49+
}
50+
4751
objectFiles, err := compileLibraries(ctx, libs, librariesBuildPath, buildProperties, includes)
4852
if err != nil {
4953
return errors.WithStack(err)

legacy/builder/test/builder_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,25 @@ func prepareBuilderTestContext(t *testing.T, sketchPath *paths.Path, fqbn string
4343
}
4444
}
4545

46+
func TestBuilderArduifine(t *testing.T) {
47+
DownloadCoresAndToolsAndLibraries(t)
48+
49+
ctx := prepareBuilderTestContext(t, paths.New("sketch_arduifine", "sketch_arduifine.ino"), "arduino:avr:uno")
50+
ctx.DebugLevel = 10
51+
52+
buildPath := SetupBuildPath(t, ctx)
53+
defer buildPath.RemoveAll()
54+
55+
// Run builder
56+
command := builder.Builder{}
57+
err := command.Run(ctx)
58+
NoError(t, err)
59+
60+
exist, err := buildPath.Join("sketch_arduifine.ino.hex").ExistCheck()
61+
NoError(t, err)
62+
require.True(t, exist)
63+
}
64+
4665
func TestBuilderEmptySketch(t *testing.T) {
4766
DownloadCoresAndToolsAndLibraries(t)
4867

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
#include <lib4arduifine.h>
3+
4+
#if MYVERSION == 1337
5+
#pragma message "arduifine: MYVERSION is correctly defined"
6+
#else
7+
#error arduifine: MYVERSION is not correctly defined
8+
#endif

legacy/builder/test/libraries/lib4arduifine/lib4arduifine.h

Whitespace-only changes.

legacy/builder/test/libraries_loader_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func TestLoadLibrariesAVR(t *testing.T) {
6666
require.True(t, Abs(t, paths.New("libraries")).EquivalentTo(librariesFolders[2].Path))
6767

6868
libs := extractLibraries(ctx)
69-
require.Equal(t, 24, len(libs))
69+
require.Equal(t, 25, len(libs))
7070

7171
sort.Sort(ByLibraryName(libs))
7272

@@ -176,7 +176,7 @@ func TestLoadLibrariesSAM(t *testing.T) {
176176
require.True(t, Abs(t, paths.New("libraries")).EquivalentTo(librariesFolders[2].Path))
177177

178178
libraries := extractLibraries(ctx)
179-
require.Equal(t, 22, len(libraries))
179+
require.Equal(t, 23, len(libraries))
180180

181181
sort.Sort(ByLibraryName(libraries))
182182

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
#include <lib4arduifine.h>
3+
4+
const char* ARDUIFINEtest = "MYVERSION = 1337";
5+
6+
void setup() {}
7+
void loop() {}

legacy/builder/types/context.go

+5
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,11 @@ type Context struct {
177177
// The provided source data is used instead of reading it from disk.
178178
// The keys of the map are paths relative to sketch folder.
179179
SourceOverride map[string]string
180+
181+
// compiler options from ctags extraction
182+
// example: 'char ARDUIFINExxx = "MYLIB_BUFFER_LEN = 1234";'
183+
// example: 'char ARDUINOGLOBALyyy = "-DMYLIB_BUFFER2_LEN=1234 -free -fipa-pta";'
184+
Arduifines string
180185
}
181186

182187
// ExecutableSectionSize represents a section of the executable output file

0 commit comments

Comments
 (0)