Skip to content

Commit

Permalink
arduifine
Browse files Browse the repository at this point in the history
  • Loading branch information
d-a-v committed Oct 14, 2021
1 parent 1bd9945 commit 4fbcfc1
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 31 deletions.
3 changes: 3 additions & 0 deletions docs/sketch-build-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ compiler:
rare cases, prototype generation may fail for some functions. To work around this, you can provide your own prototypes
for these functions.
- `#line` directives are added to make warning or error messages reflect the original sketch layout.
- Special and optional sketch variables named ARDUIFINE and ARDUINOGLOBAL are parsed, and their content is used to
provide more arguments to the compiler commands. Those arguments are used for every compiled source file, including
the core, internal and external libraries. Their content is displayed in the message area.

No pre-processing is done to files in a sketch with any extension other than .ino or .pde. Additionally, .h files in the
sketch are not automatically #included from the main sketch file. Further, if you want to call functions defined in a .c
Expand Down
52 changes: 28 additions & 24 deletions i18n/data/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ msgstr "%s is not managed by package manager"
msgid "%s must be installed."
msgstr "%s must be installed."

#: legacy/builder/builder_utils/utils.go:530
#: legacy/builder/builder_utils/utils.go:533
#: legacy/builder/ctags_runner.go:41
msgid "%s pattern is missing"
msgstr "%s pattern is missing"
Expand Down Expand Up @@ -110,6 +110,10 @@ msgstr "ARCH"
msgid "ARDUINO COMMAND LINE MANUAL"
msgstr "ARDUINO COMMAND LINE MANUAL"

#: legacy/builder/phases/libraries_builder.go:48
msgid "Additional compiler options provided by user sketch: {0}"
msgstr "Additional compiler options provided by user sketch: {0}"

#: cli/usage.go:32
msgid "Additional help topics:"
msgstr "Additional help topics:"
Expand Down Expand Up @@ -349,7 +353,7 @@ msgstr "Check dependencies status for the specified library."
msgid "Checking lib install prerequisites"
msgstr "Checking lib install prerequisites"

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

Expand Down Expand Up @@ -391,7 +395,7 @@ msgstr "Compiling core..."
msgid "Compiling libraries..."
msgstr "Compiling libraries..."

#: legacy/builder/phases/libraries_builder.go:135
#: legacy/builder/phases/libraries_builder.go:139
msgid "Compiling library \"{0}\""
msgstr "Compiling library \"{0}\""

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

#: legacy/builder/builder_utils/utils.go:358
#: legacy/builder/builder_utils/utils.go:361
msgid "Depfile is about different file: {0}"
msgstr "Depfile is about different file: {0}"

Expand Down Expand Up @@ -794,7 +798,7 @@ msgstr "Error getting libraries info: %v"
msgid "Error getting port settings details: %s"
msgstr "Error getting port settings details: %s"

#: legacy/builder/types/context.go:239
#: legacy/builder/types/context.go:244
msgid "Error in FQBN: %s"
msgstr "Error in FQBN: %s"

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

#: legacy/builder/builder_utils/utils.go:380
#: legacy/builder/builder_utils/utils.go:383
msgid "Failed to read: {0}"
msgstr "Failed to read: {0}"

Expand Down Expand Up @@ -1358,7 +1362,7 @@ msgstr "Library installed"
msgid "Library name"
msgstr "Library name"

#: legacy/builder/phases/libraries_builder.go:91
#: legacy/builder/phases/libraries_builder.go:95
msgid "Library {0} has been declared precompiled:"
msgstr "Library {0} has been declared precompiled:"

Expand Down Expand Up @@ -1511,7 +1515,7 @@ msgstr "New version"
msgid "No boards found."
msgstr "No boards found."

#: legacy/builder/builder_utils/utils.go:351
#: legacy/builder/builder_utils/utils.go:354
msgid "No colon in first line of depfile"
msgstr "No colon in first line of depfile"

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

#: legacy/builder/builder_utils/utils.go:284
#: legacy/builder/builder_utils/utils.go:287
msgid "Not found: nil"
msgstr "Not found: nil"

#: legacy/builder/builder_utils/utils.go:300
#: legacy/builder/builder_utils/utils.go:313
#: legacy/builder/builder_utils/utils.go:387
#: legacy/builder/builder_utils/utils.go:303
#: legacy/builder/builder_utils/utils.go:316
#: legacy/builder/builder_utils/utils.go:390
msgid "Not found: {0}"
msgstr "Not found: {0}"

Expand Down Expand Up @@ -1745,8 +1749,8 @@ msgstr "Port closed:"
msgid "Port monitor error"
msgstr "Port monitor error"

#: legacy/builder/phases/libraries_builder.go:101
#: legacy/builder/phases/libraries_builder.go:109
#: legacy/builder/phases/libraries_builder.go:105
#: legacy/builder/phases/libraries_builder.go:113
msgid "Precompiled library in \"{0}\" not found"
msgstr "Precompiled library in \"{0}\" not found"

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

#: legacy/builder/builder_utils/utils.go:476
#: legacy/builder/builder_utils/utils.go:479
msgid "Skipping archive creation of: {0}"
msgstr "Skipping archive creation of: {0}"

#: legacy/builder/builder_utils/utils.go:269
#: legacy/builder/builder_utils/utils.go:272
msgid "Skipping compile of: {0}"
msgstr "Skipping compile of: {0}"

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

#: legacy/builder/phases/libraries_builder.go:151
#: legacy/builder/phases/libraries_builder.go:155
msgid "The platform does not support '{0}' for precompiled libraries."
msgstr "The platform does not support '{0}' for precompiled libraries."

Expand Down Expand Up @@ -2333,13 +2337,13 @@ msgstr "Using library {0} in folder: {1} {2}"
msgid "Using precompiled core: {0}"
msgstr "Using precompiled core: {0}"

#: legacy/builder/phases/libraries_builder.go:98
#: legacy/builder/phases/libraries_builder.go:106
#: legacy/builder/phases/libraries_builder.go:102
#: legacy/builder/phases/libraries_builder.go:110
msgid "Using precompiled library in {0}"
msgstr "Using precompiled library in {0}"

#: legacy/builder/builder_utils/utils.go:267
#: legacy/builder/builder_utils/utils.go:499
#: legacy/builder/builder_utils/utils.go:270
#: legacy/builder/builder_utils/utils.go:502
msgid "Using previously compiled file: {0}"
msgstr "Using previously compiled file: {0}"

Expand Down Expand Up @@ -3429,9 +3433,9 @@ msgstr "wrong format in server response"
msgid "{0} invalid, rebuilding all"
msgstr "{0} invalid, rebuilding all"

#: legacy/builder/builder_utils/utils.go:323
#: legacy/builder/builder_utils/utils.go:329
#: legacy/builder/builder_utils/utils.go:393
#: legacy/builder/builder_utils/utils.go:326
#: legacy/builder/builder_utils/utils.go:332
#: legacy/builder/builder_utils/utils.go:396
msgid "{0} newer than {1}"
msgstr "{0} newer than {1}"

3 changes: 3 additions & 0 deletions legacy/builder/builder_utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ func compileFileWithRecipe(ctx *types.Context, sourcePath *paths.Path, source *p
properties := buildProperties.Clone()
properties.Set(constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS, properties.Get(constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS+"."+ctx.WarningsLevel))
properties.Set(constants.BUILD_PROPERTIES_INCLUDES, strings.Join(includes, constants.SPACE))
if len(ctx.Arduifines) > 0 {
properties.Set(constants.BUILD_PROPERTIES_INCLUDES, properties.Get(constants.BUILD_PROPERTIES_INCLUDES) + " " + ctx.Arduifines + " ")
}
properties.SetPath(constants.BUILD_PROPERTIES_SOURCE_FILE, source)
relativeSource, err := sourcePath.RelTo(source)
if err != nil {
Expand Down
48 changes: 45 additions & 3 deletions legacy/builder/ctags/ctags_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ const KIND_FUNCTION = "function"
const TEMPLATE = "template"
const STATIC = "static"
const EXTERN = "extern \"C\""
const ARDUIFINE = "ARDUIFINE"
const ARDUINOGLOBAL = "ARDUINOGLOBAL"

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

func (p *CTagsParser) Parse(ctagsOutput string, mainFile *paths.Path) []*types.CTag {
func (p *CTagsParser) Parse(ctagsOutput string, mainFile *paths.Path) ([]*types.CTag, string) {
Arduifines := ""
rows := strings.Split(ctagsOutput, "\n")
rows = removeEmpty(rows)

p.mainFile = mainFile

for _, row := range rows {
p.tags = append(p.tags, parseTag(row))
if strings.Index(row, " "+ARDUINOGLOBAL) != -1 {
Arduifines += encloseForCmdLine(extractCtagsDoubleQuotedString(row, ARDUINOGLOBAL))
} else if strings.Index(row, " "+ARDUIFINE) != -1 {
Arduifines += encloseForCmdLine(toCompilerCmdLine(extractCtagsDoubleQuotedString(row, ARDUIFINE)))
} else {
p.tags = append(p.tags, parseTag(row))
}
}

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

return p.tags
return p.tags, Arduifines
}

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

return newRows
}

func extractCtagsDoubleQuotedString (row string, directive string) string {
first := strings.Index(row, "\"");
last := strings.LastIndex(row, "\";$/;\""); // <- $/;" is a ctag addition
if (first <= 0) || (last <= 0) || (first + 1 >= last) {
//print("\nERROR: malformed \"" + directive + "\" global directive\n\n")
return ""
}
return strings.Replace(strings.Replace(row[first+1 : last], "\\\\", "\\", -1), "\\\"", "\"", -1)
}

func toCompilerCmdLine (define string) string {
// transforms ` A = "B C" ` to `-DA="B C"`
// transforms ` A ` to `-DA`
elts := strings.SplitAfterN(define, "=", 2)
ret := ""
eltsLength := len(elts)
if eltsLength > 0 {
equalsLength := eltsLength - 1
ret += "-D"+strings.TrimSpace(elts[0][:len(elts[0])-equalsLength])
if equalsLength > 0 {
ret += "="+strings.TrimSpace(elts[1])
}
}
return ret
}

func encloseForCmdLine (str string) string {
if len(str) > 0 {
return " \""+str+"\" "
}
return ""
}
4 changes: 3 additions & 1 deletion legacy/builder/ctags/ctags_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ func produceTags(t *testing.T, filename string) []*types.CTag {
require.NoError(t, err)

parser := CTagsParser{}
return parser.Parse(string(bytes), nil)
tags, Arduifines := parser.Parse(string(bytes), nil)
_ = Arduifines
return tags
}

func TestCTagsParserShouldListPrototypes(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion legacy/builder/ctags_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (s *CTagsRunner) Run(ctx *types.Context) error {

parser := &ctags.CTagsParser{}

ctx.CTagsOfPreprocessedSource = parser.Parse(ctx.CTagsOutput, ctx.Sketch.MainFile)
ctx.CTagsOfPreprocessedSource, ctx.Arduifines = parser.Parse(ctx.CTagsOutput, ctx.Sketch.MainFile)
parser.FixCLinkageTagsDeclarations(ctx.CTagsOfPreprocessedSource)

protos, line := parser.GeneratePrototypes()
Expand Down
4 changes: 4 additions & 0 deletions legacy/builder/phases/libraries_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ func (s *LibrariesBuilder) Run(ctx *types.Context) error {
return errors.WithStack(err)
}

if len(ctx.Arduifines) > 0 {
ctx.GetLogger().Println(constants.LOG_LEVEL_DEBUG, tr("Additional compiler options provided by user sketch: {0}"), ctx.Arduifines)
}

objectFiles, err := compileLibraries(ctx, libs, librariesBuildPath, buildProperties, includes)
if err != nil {
return errors.WithStack(err)
Expand Down
19 changes: 19 additions & 0 deletions legacy/builder/test/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,25 @@ func prepareBuilderTestContext(t *testing.T, sketchPath *paths.Path, fqbn string
}
}

func TestBuilderArduifine(t *testing.T) {
DownloadCoresAndToolsAndLibraries(t)

ctx := prepareBuilderTestContext(t, paths.New("sketch_arduifine", "sketch_arduifine.ino"), "arduino:avr:uno")
ctx.DebugLevel = 10

buildPath := SetupBuildPath(t, ctx)
defer buildPath.RemoveAll()

// Run builder
command := builder.Builder{}
err := command.Run(ctx)
NoError(t, err)

exist, err := buildPath.Join("sketch_arduifine.ino.hex").ExistCheck()
NoError(t, err)
require.True(t, exist)
}

func TestBuilderEmptySketch(t *testing.T) {
DownloadCoresAndToolsAndLibraries(t)

Expand Down
8 changes: 8 additions & 0 deletions legacy/builder/test/libraries/lib4arduifine/lib4arduifine.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

#include <lib4arduifine.h>

#if MYVERSION == 1337
#pragma message "arduifine: MYVERSION is correctly defined"
#else
#error arduifine: MYVERSION is not correctly defined
#endif
Empty file.
4 changes: 2 additions & 2 deletions legacy/builder/test/libraries_loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TestLoadLibrariesAVR(t *testing.T) {
require.True(t, Abs(t, paths.New("libraries")).EquivalentTo(librariesFolders[2].Path))

libs := extractLibraries(ctx)
require.Equal(t, 24, len(libs))
require.Equal(t, 25, len(libs))

sort.Sort(ByLibraryName(libs))

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

libraries := extractLibraries(ctx)
require.Equal(t, 22, len(libraries))
require.Equal(t, 23, len(libraries))

sort.Sort(ByLibraryName(libraries))

Expand Down
7 changes: 7 additions & 0 deletions legacy/builder/test/sketch_arduifine/sketch_arduifine.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

#include <lib4arduifine.h>

const char* ARDUIFINEtest = "MYVERSION = 1337";

void setup() {}
void loop() {}
5 changes: 5 additions & 0 deletions legacy/builder/types/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ type Context struct {
// The provided source data is used instead of reading it from disk.
// The keys of the map are paths relative to sketch folder.
SourceOverride map[string]string

// compiler options from ctags extraction
// example: 'char ARDUIFINExxx = "MYLIB_BUFFER_LEN = 1234";'
// example: 'char ARDUINOGLOBALyyy = "-DMYLIB_BUFFER2_LEN=1234 -free -fipa-pta";'
Arduifines string
}

// ExecutableSectionSize represents a section of the executable output file
Expand Down

0 comments on commit 4fbcfc1

Please sign in to comment.