Skip to content

Commit 6e8b3bd

Browse files
authored
Merge branch 'master' into problematic_multiline
2 parents db95d14 + 4a09bad commit 6e8b3bd

27 files changed

+608
-231
lines changed

src/arduino.cc/arduino-builder/main.go

+23-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import (
4949
"github.com/go-errors/errors"
5050
)
5151

52-
const VERSION = "1.3.22"
52+
const VERSION = "1.3.25"
5353

5454
const FLAG_ACTION_COMPILE = "compile"
5555
const FLAG_ACTION_PREPROCESS = "preprocess"
@@ -64,6 +64,7 @@ const FLAG_FQBN = "fqbn"
6464
const FLAG_IDE_VERSION = "ide-version"
6565
const FLAG_CORE_API_VERSION = "core-api-version"
6666
const FLAG_BUILD_PATH = "build-path"
67+
const FLAG_BUILD_CACHE = "build-cache"
6768
const FLAG_VERBOSE = "verbose"
6869
const FLAG_QUIET = "quiet"
6970
const FLAG_DEBUG_LEVEL = "debug-level"
@@ -126,6 +127,7 @@ var fqbnFlag *string
126127
var coreAPIVersionFlag *string
127128
var ideVersionFlag *string
128129
var buildPathFlag *string
130+
var buildCachePathFlag *string
129131
var verboseFlag *bool
130132
var quietFlag *bool
131133
var debugLevelFlag *int
@@ -148,6 +150,7 @@ func init() {
148150
coreAPIVersionFlag = flag.String(FLAG_CORE_API_VERSION, "10600", "version of core APIs (used to populate ARDUINO #define)")
149151
ideVersionFlag = flag.String(FLAG_IDE_VERSION, "10600", "[deprecated] use '"+FLAG_CORE_API_VERSION+"' instead")
150152
buildPathFlag = flag.String(FLAG_BUILD_PATH, "", "build path")
153+
buildCachePathFlag = flag.String(FLAG_BUILD_CACHE, "", "builds of 'core.a' are saved into this folder to be cached and reused")
151154
verboseFlag = flag.Bool(FLAG_VERBOSE, false, "if 'true' prints lots of stuff")
152155
quietFlag = flag.Bool(FLAG_QUIET, false, "if 'true' doesn't print any warnings or progress or whatever")
153156
debugLevelFlag = flag.Int(FLAG_DEBUG_LEVEL, builder.DEFAULT_DEBUG_LEVEL, "Turns on debugging messages. The higher, the chattier")
@@ -256,6 +259,25 @@ func main() {
256259
}
257260
ctx.BuildPath = buildPath
258261

262+
// FLAG_BUILD_CACHE
263+
buildCachePath, err := gohasissues.Unquote(*buildCachePathFlag)
264+
if err != nil {
265+
printCompleteError(err)
266+
}
267+
if buildCachePath != "" {
268+
_, err := os.Stat(buildCachePath)
269+
if err != nil {
270+
fmt.Fprintln(os.Stderr, err)
271+
os.Exit(1)
272+
}
273+
274+
err = utils.EnsureFolderExists(buildCachePath)
275+
if err != nil {
276+
printCompleteError(err)
277+
}
278+
}
279+
ctx.BuildCachePath = buildCachePath
280+
259281
// FLAG_VID_PID
260282
if *vidPidFlag != "" {
261283
ctx.USBVidPid = *vidPidFlag

src/arduino.cc/builder/add_additional_entries_to_context.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@
3030
package builder
3131

3232
import (
33+
"path/filepath"
34+
3335
"arduino.cc/builder/constants"
3436
"arduino.cc/builder/i18n"
3537
"arduino.cc/builder/types"
36-
"path/filepath"
3738
)
3839

3940
type AddAdditionalEntriesToContext struct{}
@@ -64,6 +65,15 @@ func (s *AddAdditionalEntriesToContext) Run(ctx *types.Context) error {
6465
ctx.CoreBuildPath = coreBuildPath
6566
}
6667

68+
if ctx.BuildCachePath != "" {
69+
coreBuildCachePath, err := filepath.Abs(filepath.Join(ctx.BuildCachePath, constants.FOLDER_CORE))
70+
if err != nil {
71+
return i18n.WrapError(err)
72+
}
73+
74+
ctx.CoreBuildCachePath = coreBuildCachePath
75+
}
76+
6777
if ctx.WarningsLevel == "" {
6878
ctx.WarningsLevel = DEFAULT_WARNINGS_LEVEL
6979
}

src/arduino.cc/builder/builder_utils/utils.go

+107
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ package builder_utils
3232
import (
3333
"bytes"
3434
"fmt"
35+
"io"
3536
"os"
3637
"os/exec"
3738
"path/filepath"
@@ -116,6 +117,34 @@ func findFilesInFolder(sourcePath string, extension string, recurse bool) ([]str
116117
return sources, nil
117118
}
118119

120+
func findAllFilesInFolder(sourcePath string, recurse bool) ([]string, error) {
121+
files, err := utils.ReadDirFiltered(sourcePath, utils.FilterFiles())
122+
if err != nil {
123+
return nil, i18n.WrapError(err)
124+
}
125+
var sources []string
126+
for _, file := range files {
127+
sources = append(sources, filepath.Join(sourcePath, file.Name()))
128+
}
129+
130+
if recurse {
131+
folders, err := utils.ReadDirFiltered(sourcePath, utils.FilterDirs)
132+
if err != nil {
133+
return nil, i18n.WrapError(err)
134+
}
135+
136+
for _, folder := range folders {
137+
otherSources, err := findAllFilesInFolder(filepath.Join(sourcePath, folder.Name()), recurse)
138+
if err != nil {
139+
return nil, i18n.WrapError(err)
140+
}
141+
sources = append(sources, otherSources...)
142+
}
143+
}
144+
145+
return sources, nil
146+
}
147+
119148
func compileFilesWithRecipe(objectFiles []string, sourcePath string, sources []string, buildPath string, buildProperties properties.Map, includes []string, recipe string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) {
120149
for _, source := range sources {
121150
objectFile, err := compileFileWithRecipe(sourcePath, source, buildPath, buildProperties, includes, recipe, verbose, warningsLevel, logger)
@@ -258,6 +287,28 @@ func nonEmptyString(s string) bool {
258287
return s != constants.EMPTY_STRING
259288
}
260289

290+
func CoreOrReferencedCoreHasChanged(corePath, targetCorePath, targetFile string) bool {
291+
292+
targetFileStat, err := os.Stat(targetFile)
293+
if err == nil {
294+
files, err := findAllFilesInFolder(corePath, true)
295+
if err != nil {
296+
return true
297+
}
298+
for _, file := range files {
299+
fileStat, err := os.Stat(file)
300+
if err != nil || fileStat.ModTime().After(targetFileStat.ModTime()) {
301+
return true
302+
}
303+
}
304+
if targetCorePath != constants.EMPTY_STRING && !strings.EqualFold(corePath, targetCorePath) {
305+
return CoreOrReferencedCoreHasChanged(targetCorePath, constants.EMPTY_STRING, targetFile)
306+
}
307+
return false
308+
}
309+
return true
310+
}
311+
261312
func ArchiveCompiledFiles(buildPath string, archiveFile string, objectFiles []string, buildProperties properties.Map, verbose bool, logger i18n.Logger) (string, error) {
262313
archiveFilePath := filepath.Join(buildPath, archiveFile)
263314

@@ -366,3 +417,59 @@ func ExecRecipeCollectStdErr(buildProperties properties.Map, recipe string, remo
366417
func RemoveHyphenMDDFlagFromGCCCommandLine(buildProperties properties.Map) {
367418
buildProperties[constants.BUILD_PROPERTIES_COMPILER_CPP_FLAGS] = strings.Replace(buildProperties[constants.BUILD_PROPERTIES_COMPILER_CPP_FLAGS], "-MMD", "", -1)
368419
}
420+
421+
// CopyFile copies the contents of the file named src to the file named
422+
// by dst. The file will be created if it does not already exist. If the
423+
// destination file exists, all it's contents will be replaced by the contents
424+
// of the source file. The file mode will be copied from the source and
425+
// the copied data is synced/flushed to stable storage.
426+
func CopyFile(src, dst string) (err error) {
427+
in, err := os.Open(src)
428+
if err != nil {
429+
return
430+
}
431+
defer in.Close()
432+
433+
out, err := os.Create(dst)
434+
if err != nil {
435+
return
436+
}
437+
defer func() {
438+
if e := out.Close(); e != nil {
439+
err = e
440+
}
441+
}()
442+
443+
_, err = io.Copy(out, in)
444+
if err != nil {
445+
return
446+
}
447+
448+
err = out.Sync()
449+
if err != nil {
450+
return
451+
}
452+
453+
si, err := os.Stat(src)
454+
if err != nil {
455+
return
456+
}
457+
err = os.Chmod(dst, si.Mode())
458+
if err != nil {
459+
return
460+
}
461+
462+
return
463+
}
464+
465+
// GetCachedCoreArchiveFileName returns the filename to be used to store
466+
// the global cached core.a.
467+
func GetCachedCoreArchiveFileName(fqbn, coreFolder string) string {
468+
fqbnToUnderscore := strings.Replace(fqbn, ":", "_", -1)
469+
fqbnToUnderscore = strings.Replace(fqbnToUnderscore, "=", "_", -1)
470+
if absCoreFolder, err := filepath.Abs(coreFolder); err == nil {
471+
coreFolder = absCoreFolder
472+
} // silently continue if absolute path can't be detected
473+
hash := utils.MD5Sum([]byte(coreFolder))
474+
return "core_" + fqbnToUnderscore + "_" + hash + ".a"
475+
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const BUILD_PROPERTIES_EXTRA_TIME_DST = "extra.time.dst"
5555
const BUILD_PROPERTIES_EXTRA_TIME_LOCAL = "extra.time.local"
5656
const BUILD_PROPERTIES_EXTRA_TIME_UTC = "extra.time.utc"
5757
const BUILD_PROPERTIES_EXTRA_TIME_ZONE = "extra.time.zone"
58+
const BUILD_PROPERTIES_FQBN = "build.fqbn"
5859
const BUILD_PROPERTIES_INCLUDES = "includes"
5960
const BUILD_PROPERTIES_OBJECT_FILE = "object_file"
6061
const BUILD_PROPERTIES_OBJECT_FILES = "object_files"

src/arduino.cc/builder/ctags/ctags_parser.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,16 @@ var KNOWN_TAG_KINDS = map[string]bool{
5151
}
5252

5353
type CTagsParser struct {
54-
tags []*types.CTag
54+
tags []*types.CTag
55+
mainFile string
5556
}
5657

57-
func (p *CTagsParser) Parse(ctagsOutput string) []*types.CTag {
58+
func (p *CTagsParser) Parse(ctagsOutput string, mainFile string) []*types.CTag {
5859
rows := strings.Split(ctagsOutput, "\n")
5960
rows = removeEmpty(rows)
6061

62+
p.mainFile = mainFile
63+
6164
for _, row := range rows {
6265
p.tags = append(p.tags, parseTag(row))
6366
}
@@ -199,7 +202,6 @@ func parseTag(row string) *types.CTag {
199202

200203
parts = parts[2:]
201204

202-
signature := ""
203205
returntype := ""
204206
for _, part := range parts {
205207
if strings.Contains(part, ":") {
@@ -216,7 +218,7 @@ func parseTag(row string) *types.CTag {
216218
case "typeref":
217219
tag.Typeref = value
218220
case "signature":
219-
signature = value
221+
tag.Signature = value
220222
case "returntype":
221223
returntype = value
222224
case "class":
@@ -228,7 +230,7 @@ func parseTag(row string) *types.CTag {
228230
}
229231
}
230232
}
231-
tag.Prototype = returntype + " " + tag.FunctionName + signature + ";"
233+
tag.Prototype = returntype + " " + tag.FunctionName + tag.Signature + ";"
232234

233235
if strings.Contains(row, "/^") && strings.Contains(row, "$/;") {
234236
tag.Code = row[strings.Index(row, "/^")+2 : strings.Index(row, "$/;")]

src/arduino.cc/builder/ctags/ctags_parser_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func produceTags(t *testing.T, filename string) []*types.CTag {
4444
require.NoError(t, err)
4545

4646
parser := CTagsParser{}
47-
return parser.Parse(string(bytes))
47+
return parser.Parse(string(bytes), "")
4848
}
4949

5050
func TestCTagsParserShouldListPrototypes(t *testing.T) {

src/arduino.cc/builder/ctags/ctags_to_prototypes.go

+19-13
Original file line numberDiff line numberDiff line change
@@ -48,45 +48,51 @@ func (p *CTagsParser) findLineWhereToInsertPrototypes() int {
4848
} else {
4949
return firstFunctionPointerAsArgument
5050
}
51-
} else if firstFunctionLine == -1 {
51+
} else if firstFunctionLine != -1 {
52+
return firstFunctionLine
53+
} else if firstFunctionPointerAsArgument != -1 {
5254
return firstFunctionPointerAsArgument
5355
} else {
54-
return firstFunctionLine
56+
return 0
5557
}
5658
}
5759

5860
func (p *CTagsParser) firstFunctionPointerUsedAsArgument() int {
59-
functionNames := p.collectFunctionNames()
61+
functionTags := p.collectFunctions()
6062
for _, tag := range p.tags {
61-
if functionNameUsedAsFunctionPointerIn(tag, functionNames) {
63+
if functionNameUsedAsFunctionPointerIn(tag, functionTags) {
6264
return tag.Line
6365
}
6466
}
6567
return -1
6668
}
6769

68-
func functionNameUsedAsFunctionPointerIn(tag *types.CTag, functionNames []string) bool {
69-
for _, functionName := range functionNames {
70-
if strings.Index(tag.Code, "&"+functionName) != -1 {
70+
func functionNameUsedAsFunctionPointerIn(tag *types.CTag, functionTags []*types.CTag) bool {
71+
for _, functionTag := range functionTags {
72+
if tag.Line != functionTag.Line && strings.Index(tag.Code, "&"+functionTag.FunctionName) != -1 {
73+
return true
74+
}
75+
if tag.Line != functionTag.Line && strings.Index(tag.Code, functionTag.FunctionName) != -1 &&
76+
(functionTag.Signature == "(void)" || functionTag.Signature == "()") {
7177
return true
7278
}
7379
}
7480
return false
7581
}
7682

77-
func (p *CTagsParser) collectFunctionNames() []string {
78-
names := []string{}
83+
func (p *CTagsParser) collectFunctions() []*types.CTag {
84+
functionTags := []*types.CTag{}
7985
for _, tag := range p.tags {
80-
if tag.Kind == KIND_FUNCTION {
81-
names = append(names, tag.FunctionName)
86+
if tag.Kind == KIND_FUNCTION && !tag.SkipMe {
87+
functionTags = append(functionTags, tag)
8288
}
8389
}
84-
return names
90+
return functionTags
8591
}
8692

8793
func (p *CTagsParser) firstFunctionAtLine() int {
8894
for _, tag := range p.tags {
89-
if !tagIsUnknown(tag) && isHandled(tag) && tag.Kind == KIND_FUNCTION {
95+
if !tagIsUnknown(tag) && isHandled(tag) && tag.Kind == KIND_FUNCTION && tag.Filename == p.mainFile {
9096
return tag.Line
9197
}
9298
}

0 commit comments

Comments
 (0)