diff --git a/README.md b/README.md index 457fd27d..453fb958 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ This tool generates function prototypes and gathers library paths, providing `gc * `-debug-level`: Optional, defaults to "5". Used for debugging. Set it to 10 when submitting an issue. -* `-ide-version`: Optional, defaults to "10600". The version of the Arduino IDE which is using this tool. +* `-core-api-version`: Optional, defaults to "10600". The version of the Arduino IDE which is using this tool. * `-logger`: Optional, can be "human" or "machine". Defaults to "human". If "machine", messages emitted will be in a format which the Arduino IDE understands and that it uses for I18N. @@ -48,16 +48,18 @@ Final mandatory parameter is the sketch to compile (of course). Every time you run this tool, it will create a `build.options.json` file in build path. It's used to understand if build options (such as hardware folders, fqbn and so on) were changed when compiling the same sketch. If they changed, the whole build path is wiped out. If they didn't change, previous compiled files will be reused if the corresponding source files didn't change as well. You can save this file locally and use it instead of specifying `-hardware`, `-tools`, `-libraries`, `-fqbn`, `-pref` and `-ide-version`. - + ### Using it for continuously verify your libraries or cores See [Doing continuous integration with arduino builder](https://github.com/arduino/arduino-builder/wiki/Doing-continuous-integration-with-arduino-builder/). - + ### Building from source - + You need [Go 1.4.3](https://golang.org/dl/#go1.4.3). -Repo root contains script `setup_go_env_vars`. Use it as is or as a template for setting up Go environment variables. +Repo root contains the script `setup_go_env_vars`. Use it as is or as a template for setting up Go environment variables. + +To install `codereview/patch` you have to install [Mercurial](https://www.mercurial-scm.org/) first. Once done, run the following commands: @@ -75,17 +77,17 @@ go build In order to run the tests, type: ``` -go test -v ./src/arduino.cc/builder/test/... +go test -timeout 60m -v ./src/arduino.cc/builder/test/... ``` In jenkins, use ``` -go test -v ./src/arduino.cc/builder/test/... | bin/go-junit-report > report.xml +go test -timeout 60m -v ./src/arduino.cc/builder/test/... | bin/go-junit-report > report.xml ``` ### License and Copyright -`arduino-builder` is licensed under General Public License version 2, as published bythe Free Software Foundation. See [LICENSE.txt](LICENSE.txt). +`arduino-builder` is licensed under General Public License version 2, as published by the Free Software Foundation. See [LICENSE.txt](LICENSE.txt). Copyright (C) 2015 Arduino LLC and contributors diff --git a/main.go b/main.go index c5b81082..bcbade65 100644 --- a/main.go +++ b/main.go @@ -31,23 +31,24 @@ package main import ( - "arduino.cc/builder" - "arduino.cc/builder/constants" - "arduino.cc/builder/gohasissues" - "arduino.cc/builder/i18n" - "arduino.cc/builder/utils" "encoding/json" "flag" "fmt" - "github.com/go-errors/errors" "io/ioutil" "os" "os/exec" "strings" "syscall" + + "arduino.cc/builder" + "arduino.cc/builder/constants" + "arduino.cc/builder/gohasissues" + "arduino.cc/builder/i18n" + "arduino.cc/builder/utils" + "github.com/go-errors/errors" ) -const VERSION = "1.3.9" +const VERSION = "1.3.15" const FLAG_ACTION_COMPILE = "compile" const FLAG_ACTION_PREPROCESS = "preprocess" @@ -60,6 +61,7 @@ const FLAG_LIBRARIES = "libraries" const FLAG_PREFS = "prefs" const FLAG_FQBN = "fqbn" const FLAG_IDE_VERSION = "ide-version" +const FLAG_CORE_API_VERSION = "core-api-version" const FLAG_BUILD_PATH = "build-path" const FLAG_VERBOSE = "verbose" const FLAG_QUIET = "quiet" @@ -107,6 +109,7 @@ var librariesBuiltInFoldersFlag slice var librariesFoldersFlag slice var customBuildPropertiesFlag slice var fqbnFlag *string +var coreAPIVersionFlag *string var ideVersionFlag *string var buildPathFlag *string var verboseFlag *bool @@ -128,7 +131,8 @@ func init() { flag.Var(&librariesFoldersFlag, FLAG_LIBRARIES, "Specify a 'libraries' folder. Can be added multiple times for specifying multiple 'libraries' folders") flag.Var(&customBuildPropertiesFlag, FLAG_PREFS, "Specify a custom preference. Can be added multiple times for specifying multiple custom preferences") fqbnFlag = flag.String(FLAG_FQBN, "", "fully qualified board name") - ideVersionFlag = flag.String(FLAG_IDE_VERSION, "10600", "fake IDE version") + coreAPIVersionFlag = flag.String(FLAG_CORE_API_VERSION, "10600", "version of core APIs (used to populate ARDUINO #define)") + ideVersionFlag = flag.String(FLAG_IDE_VERSION, "10600", "[deprecated] use '"+FLAG_CORE_API_VERSION+"' instead") buildPathFlag = flag.String(FLAG_BUILD_PATH, "", "build path") verboseFlag = flag.Bool(FLAG_VERBOSE, false, "if 'true' prints lots of stuff") quietFlag = flag.Bool(FLAG_QUIET, false, "if 'true' doesn't print any warnings or progress or whatever") @@ -273,13 +277,18 @@ func main() { context[constants.CTX_VERBOSE] = *verboseFlag - ideVersion := "" + coreAPIVersion := "" if utils.MapStringStringHas(buildOptions, constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION) { - ideVersion = buildOptions[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] + coreAPIVersion = buildOptions[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] } else { - ideVersion = *ideVersionFlag + // if deprecated 'ideVersionFlag' has been used... + if *coreAPIVersionFlag == "10600" && *ideVersionFlag != "10600" { + coreAPIVersion = *ideVersionFlag + } else { + coreAPIVersion = *coreAPIVersionFlag + } } - context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = ideVersion + context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = coreAPIVersion if *warningsLevelFlag != "" { context[constants.CTX_WARNINGS_LEVEL] = *warningsLevelFlag diff --git a/src/arduino.cc/builder/add_missing_build_properties_from_parent_platform_txt_files.go b/src/arduino.cc/builder/add_missing_build_properties_from_parent_platform_txt_files.go index 0c613515..bf268070 100644 --- a/src/arduino.cc/builder/add_missing_build_properties_from_parent_platform_txt_files.go +++ b/src/arduino.cc/builder/add_missing_build_properties_from_parent_platform_txt_files.go @@ -31,8 +31,8 @@ package builder import ( "arduino.cc/builder/constants" + "arduino.cc/builder/props" "arduino.cc/builder/types" - "arduino.cc/builder/utils" ) type AddMissingBuildPropertiesFromParentPlatformTxtFiles struct{} @@ -40,11 +40,13 @@ type AddMissingBuildPropertiesFromParentPlatformTxtFiles struct{} func (s *AddMissingBuildPropertiesFromParentPlatformTxtFiles) Run(context map[string]interface{}) error { packages := context[constants.CTX_HARDWARE].(*types.Packages) targetPackage := context[constants.CTX_TARGET_PACKAGE].(*types.Package) - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) - buildProperties = utils.MergeMapsOfStrings(make(map[string]string), packages.Properties, targetPackage.Properties, buildProperties) + newBuildProperties := packages.Properties.Clone() + newBuildProperties.Merge(targetPackage.Properties) + newBuildProperties.Merge(buildProperties) - context[constants.CTX_BUILD_PROPERTIES] = buildProperties + context[constants.CTX_BUILD_PROPERTIES] = newBuildProperties return nil } diff --git a/src/arduino.cc/builder/builder_utils/utils.go b/src/arduino.cc/builder/builder_utils/utils.go index 18ab284e..9d0dc06d 100644 --- a/src/arduino.cc/builder/builder_utils/utils.go +++ b/src/arduino.cc/builder/builder_utils/utils.go @@ -42,7 +42,7 @@ import ( "strings" ) -func CompileFilesRecursive(objectFiles []string, sourcePath string, buildPath string, buildProperties map[string]string, includes []string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { +func CompileFilesRecursive(objectFiles []string, sourcePath string, buildPath string, buildProperties props.PropertiesMap, includes []string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { objectFiles, err := CompileFiles(objectFiles, sourcePath, false, buildPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return nil, utils.WrapError(err) @@ -63,7 +63,7 @@ func CompileFilesRecursive(objectFiles []string, sourcePath string, buildPath st return objectFiles, nil } -func CompileFiles(objectFiles []string, sourcePath string, recurse bool, buildPath string, buildProperties map[string]string, includes []string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { +func CompileFiles(objectFiles []string, sourcePath string, recurse bool, buildPath string, buildProperties props.PropertiesMap, includes []string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { objectFiles, err := compileFilesWithExtensionWithRecipe(objectFiles, sourcePath, recurse, buildPath, buildProperties, includes, ".S", constants.RECIPE_S_PATTERN, verbose, warningsLevel, logger) if err != nil { return nil, utils.WrapError(err) @@ -79,7 +79,7 @@ func CompileFiles(objectFiles []string, sourcePath string, recurse bool, buildPa return objectFiles, nil } -func compileFilesWithExtensionWithRecipe(objectFiles []string, sourcePath string, recurse bool, buildPath string, buildProperties map[string]string, includes []string, extension string, recipe string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { +func compileFilesWithExtensionWithRecipe(objectFiles []string, sourcePath string, recurse bool, buildPath string, buildProperties props.PropertiesMap, includes []string, extension string, recipe string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { sources, err := findFilesInFolder(sourcePath, extension, recurse) if err != nil { return nil, utils.WrapError(err) @@ -115,7 +115,7 @@ func findFilesInFolder(sourcePath string, extension string, recurse bool) ([]str return sources, nil } -func compileFilesWithRecipe(objectFiles []string, sourcePath string, sources []string, buildPath string, buildProperties map[string]string, includes []string, recipe string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { +func compileFilesWithRecipe(objectFiles []string, sourcePath string, sources []string, buildPath string, buildProperties props.PropertiesMap, includes []string, recipe string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { for _, source := range sources { objectFile, err := compileFileWithRecipe(sourcePath, source, buildPath, buildProperties, includes, recipe, verbose, warningsLevel, logger) if err != nil { @@ -127,8 +127,8 @@ func compileFilesWithRecipe(objectFiles []string, sourcePath string, sources []s return objectFiles, nil } -func compileFileWithRecipe(sourcePath string, source string, buildPath string, buildProperties map[string]string, includes []string, recipe string, verbose bool, warningsLevel string, logger i18n.Logger) (string, error) { - properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties) +func compileFileWithRecipe(sourcePath string, source string, buildPath string, buildProperties props.PropertiesMap, includes []string, recipe string, verbose bool, warningsLevel string, logger i18n.Logger) (string, error) { + properties := buildProperties.Clone() properties[constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS] = properties[constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS+"."+warningsLevel] properties[constants.BUILD_PROPERTIES_INCLUDES] = strings.Join(includes, constants.SPACE) properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = source @@ -255,7 +255,7 @@ func nonEmptyString(s string) bool { return s != constants.EMPTY_STRING } -func ArchiveCompiledFiles(buildPath string, archiveFile string, objectFiles []string, buildProperties map[string]string, verbose bool, logger i18n.Logger) (string, error) { +func ArchiveCompiledFiles(buildPath string, archiveFile string, objectFiles []string, buildProperties props.PropertiesMap, verbose bool, logger i18n.Logger) (string, error) { archiveFilePath := filepath.Join(buildPath, archiveFile) if _, err := os.Stat(archiveFilePath); err == nil { err = os.Remove(archiveFilePath) @@ -265,7 +265,7 @@ func ArchiveCompiledFiles(buildPath string, archiveFile string, objectFiles []st } for _, objectFile := range objectFiles { - properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties) + properties := buildProperties.Clone() properties[constants.BUILD_PROPERTIES_ARCHIVE_FILE] = filepath.Base(archiveFilePath) properties[constants.BUILD_PROPERTIES_ARCHIVE_FILE_PATH] = archiveFilePath properties[constants.BUILD_PROPERTIES_OBJECT_FILE] = objectFile @@ -279,7 +279,7 @@ func ArchiveCompiledFiles(buildPath string, archiveFile string, objectFiles []st return archiveFilePath, nil } -func ExecRecipe(properties map[string]string, recipe string, removeUnsetProperties bool, echoCommandLine bool, echoOutput bool, logger i18n.Logger) ([]byte, error) { +func ExecRecipe(properties props.PropertiesMap, recipe string, removeUnsetProperties bool, echoCommandLine bool, echoOutput bool, logger i18n.Logger) ([]byte, error) { command, err := PrepareCommandForRecipe(properties, recipe, removeUnsetProperties, echoCommandLine, echoOutput, logger) if err != nil { return nil, utils.WrapError(err) @@ -300,14 +300,14 @@ func ExecRecipe(properties map[string]string, recipe string, removeUnsetProperti return bytes, utils.WrapError(err) } -func PrepareCommandForRecipe(properties map[string]string, recipe string, removeUnsetProperties bool, echoCommandLine bool, echoOutput bool, logger i18n.Logger) (*exec.Cmd, error) { +func PrepareCommandForRecipe(properties props.PropertiesMap, recipe string, removeUnsetProperties bool, echoCommandLine bool, echoOutput bool, logger i18n.Logger) (*exec.Cmd, error) { pattern := properties[recipe] if pattern == constants.EMPTY_STRING { return nil, utils.ErrorfWithLogger(logger, constants.MSG_PATTERN_MISSING, recipe) } var err error - commandLine := props.ExpandPropsInString(properties, pattern) + commandLine := properties.ExpandPropsInString(pattern) if removeUnsetProperties { commandLine, err = props.DeleteUnexpandedPropsFromString(commandLine) if err != nil { @@ -327,7 +327,7 @@ func PrepareCommandForRecipe(properties map[string]string, recipe string, remove return command, nil } -func ExecRecipeCollectStdErr(properties map[string]string, recipe string, removeUnsetProperties bool, echoCommandLine bool, echoOutput bool, logger i18n.Logger) (string, error) { +func ExecRecipeCollectStdErr(properties props.PropertiesMap, recipe string, removeUnsetProperties bool, echoCommandLine bool, echoOutput bool, logger i18n.Logger) (string, error) { command, err := PrepareCommandForRecipe(properties, recipe, removeUnsetProperties, echoCommandLine, echoOutput, logger) if err != nil { return "", utils.WrapError(err) @@ -339,6 +339,6 @@ func ExecRecipeCollectStdErr(properties map[string]string, recipe string, remove return string(buffer.Bytes()), nil } -func RemoveHyphenMDDFlagFromGCCCommandLine(properties map[string]string) { +func RemoveHyphenMDDFlagFromGCCCommandLine(properties props.PropertiesMap) { properties[constants.BUILD_PROPERTIES_COMPILER_CPP_FLAGS] = strings.Replace(properties[constants.BUILD_PROPERTIES_COMPILER_CPP_FLAGS], "-MMD", "", -1) } diff --git a/src/arduino.cc/builder/coan_runner.go b/src/arduino.cc/builder/coan_runner.go index f4630621..01420d2f 100644 --- a/src/arduino.cc/builder/coan_runner.go +++ b/src/arduino.cc/builder/coan_runner.go @@ -60,8 +60,9 @@ func (s *CoanRunner) Run(context map[string]interface{}) error { return utils.WrapError(err) } - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) - properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties, props.SubTree(props.SubTree(buildProperties, constants.BUILD_PROPERTIES_TOOLS_KEY), constants.COAN)) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) + properties := buildProperties.Clone() + properties.Merge(buildProperties.SubTree(constants.BUILD_PROPERTIES_TOOLS_KEY).SubTree(constants.COAN)) properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = coanTargetFileName pattern := properties[constants.BUILD_PROPERTIES_PATTERN] @@ -70,7 +71,7 @@ func (s *CoanRunner) Run(context map[string]interface{}) error { } logger := context[constants.CTX_LOGGER].(i18n.Logger) - commandLine := props.ExpandPropsInString(properties, pattern) + commandLine := properties.ExpandPropsInString(pattern) command, err := utils.PrepareCommandFilteredArgs(commandLine, filterAllowedArg, logger) if verbose { diff --git a/src/arduino.cc/builder/collect_ctags_from_sketch_files.go b/src/arduino.cc/builder/collect_ctags_from_sketch_files.go index a836c4d3..471f3411 100644 --- a/src/arduino.cc/builder/collect_ctags_from_sketch_files.go +++ b/src/arduino.cc/builder/collect_ctags_from_sketch_files.go @@ -42,9 +42,9 @@ func (s *CollectCTagsFromSketchFiles) Run(context map[string]interface{}) error sketch := context[constants.CTX_SKETCH].(*types.Sketch) sketchFileNames := collectSketchFileNamesFrom(sketch) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + allCtags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) ctagsOfSketch := []*types.CTag{} - for _, ctag := range ctags { + for _, ctag := range allCtags { if utils.SliceContains(sketchFileNames, strings.Replace(ctag.Filename, "\\\\", "\\", -1)) { ctagsOfSketch = append(ctagsOfSketch, ctag) } diff --git a/src/arduino.cc/builder/constants/constants.go b/src/arduino.cc/builder/constants/constants.go index d80d232c..078ac08d 100644 --- a/src/arduino.cc/builder/constants/constants.go +++ b/src/arduino.cc/builder/constants/constants.go @@ -92,6 +92,7 @@ const CTX_CTAGS_OUTPUT = "ctagsOutput" const CTX_CTAGS_TEMP_FILE_PATH = "ctagsTempFilePath" const CTX_CUSTOM_BUILD_PROPERTIES = "customBuildProperties" const CTX_DEBUG_LEVEL = "debugLevel" +const CTX_DEBUG_PREPROCESSOR = "debugPreprocessor" const CTX_FILE_PATH_TO_READ = "filePathToRead" const CTX_FOLDERS_WITH_SOURCES_QUEUE = "foldersWithSourcesQueue" const CTX_FQBN = "fqbn" @@ -218,7 +219,7 @@ const MSG_LIBRARIES_USED = " Used: {0}" const MSG_LIBRARY_CAN_USE_SRC_AND_UTILITY_FOLDERS = "Library can't use both 'src' and 'utility' folders. Double check {0}" const MSG_LIBRARY_INCOMPATIBLE_ARCH = "WARNING: library {0} claims to run on {1} architecture(s) and may be incompatible with your current board which runs on {2} architecture(s)." const MSG_LOOKING_FOR_RECIPES = "Looking for recipes like {0}*{1}" -const MSG_MISSING_BUILD_BOARD = "Board {0}:{1}:{2} doesn''t define a ''build.board'' preference. Auto-set to: {3}" +const MSG_MISSING_BUILD_BOARD = "Warning: Board {0}:{1}:{2} doesn''t define a ''build.board'' preference. Auto-set to: {3}" const MSG_MISSING_CORE_FOR_BOARD = "Selected board depends on '{0}' core (not installed)." const MSG_MUST_BE_A_FOLDER = "{0} must be a folder" const MSG_PACKAGE_UNKNOWN = "{0}: Unknown package" diff --git a/src/arduino.cc/builder/container_add_prototypes.go b/src/arduino.cc/builder/container_add_prototypes.go index 427a3056..6c337af9 100644 --- a/src/arduino.cc/builder/container_add_prototypes.go +++ b/src/arduino.cc/builder/container_add_prototypes.go @@ -31,6 +31,7 @@ package builder import ( "arduino.cc/builder/constants" + "arduino.cc/builder/ctags" "arduino.cc/builder/types" "arduino.cc/builder/utils" ) @@ -42,10 +43,10 @@ func (s *ContainerAddPrototypes) Run(context map[string]interface{}) error { &GCCPreprocRunner{TargetFileName: constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E}, &ReadFileAndStoreInContext{TargetField: constants.CTX_GCC_MINUS_E_SOURCE}, &CTagsTargetFileSaver{SourceField: constants.CTX_GCC_MINUS_E_SOURCE, TargetFileName: constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E}, - &CTagsRunner{}, - &CTagsParser{}, + &ctags.CTagsRunner{}, + &ctags.CTagsParser{}, &CollectCTagsFromSketchFiles{}, - &CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, &PrototypesAdder{}, &SketchSaver{}, } diff --git a/src/arduino.cc/builder/container_find_includes.go b/src/arduino.cc/builder/container_find_includes.go index 35408f21..ae6a2396 100644 --- a/src/arduino.cc/builder/container_find_includes.go +++ b/src/arduino.cc/builder/container_find_includes.go @@ -55,7 +55,7 @@ func (s *ContainerFindIncludes) Run(context map[string]interface{}) error { foldersWithSources.Push(types.SourceFolder{Folder: context[constants.CTX_SKETCH_BUILD_PATH].(string), Recurse: true}) if utils.MapHas(context, constants.CTX_IMPORTED_LIBRARIES) { for _, library := range context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library) { - sourceFolders := utils.LibraryToSourceFolder(library) + sourceFolders := types.LibraryToSourceFolder(library) for _, sourceFolder := range sourceFolders { foldersWithSources.Push(sourceFolder) } diff --git a/src/arduino.cc/builder/ctags_parser.go b/src/arduino.cc/builder/ctags/ctags_parser.go similarity index 83% rename from src/arduino.cc/builder/ctags_parser.go rename to src/arduino.cc/builder/ctags/ctags_parser.go index 09a01d51..c301c1c5 100644 --- a/src/arduino.cc/builder/ctags_parser.go +++ b/src/arduino.cc/builder/ctags/ctags_parser.go @@ -27,7 +27,7 @@ * Copyright 2015 Arduino LLC (http://www.arduino.cc/) */ -package builder +package ctags import ( "arduino.cc/builder/constants" @@ -38,6 +38,7 @@ import ( "runtime" "strconv" "strings" + "bufio" ) const KIND_PROTOTYPE = "prototype" @@ -47,6 +48,7 @@ const KIND_FUNCTION = "function" const TEMPLATE = "template" const STATIC = "static" +const EXTERN = "extern \"C\"" var KNOWN_TAG_KINDS = map[string]bool{ "prototype": true, @@ -67,7 +69,6 @@ func (s *CTagsParser) Run(context map[string]interface{}) error { skipTagsWhere(tags, tagIsUnknown, context) skipTagsWhere(tags, tagIsUnhandled, context) - skipTagsWhere(tags, signatureContainsDefaultArg, context) addPrototypes(tags) removeDefinedProtypes(tags, context) removeDuplicate(tags) @@ -87,7 +88,7 @@ func addPrototypes(tags []*types.CTag) { } func addPrototype(tag *types.CTag) { - if strings.Index(tag.Returntype, TEMPLATE) == 0 || strings.Index(tag.Code, TEMPLATE) == 0 { + if strings.Index(tag.Prototype, TEMPLATE) == 0 || strings.Index(tag.Code, TEMPLATE) == 0 { code := tag.Code if strings.Contains(code, "{") { code = code[:strings.Index(code, "{")] @@ -98,12 +99,13 @@ func addPrototype(tag *types.CTag) { return } - tag.Prototype = tag.Returntype + " " + tag.FunctionName + tag.Signature + ";" - tag.PrototypeModifiers = "" if strings.Index(tag.Code, STATIC+" ") != -1 { tag.PrototypeModifiers = tag.PrototypeModifiers + " " + STATIC } + if strings.Index(tag.Code, EXTERN+" ") != -1 { + tag.PrototypeModifiers = tag.PrototypeModifiers + " " + EXTERN + } tag.PrototypeModifiers = strings.TrimSpace(tag.PrototypeModifiers) } @@ -151,16 +153,41 @@ func skipTagsWhere(tags []*types.CTag, skipFunc skipFuncType, context map[string } } -func signatureContainsDefaultArg(tag *types.CTag) bool { - return strings.Contains(tag.Signature, "=") -} - func prototypeAndCodeDontMatch(tag *types.CTag) bool { if tag.SkipMe { return true } code := removeSpacesAndTabs(tag.Code) + + // original code is multi-line, which tags doesn't have - could we find this code in the + // original source file, for purposes of checking here? + if strings.Index(code, ")") == -1 { + file, err := os.Open(tag.Filename) + if err == nil { + defer file.Close() + + scanner := bufio.NewScanner(file) + line := 1 + + // skip lines until we get to the start of this tag + for scanner.Scan() && line < tag.Line { + line++; + } + + // read up to 10 lines in search of a closing paren + newcode := scanner.Text() + for scanner.Scan() && line < (tag.Line + 10) && strings.Index(newcode, ")") == -1 { + newcode += scanner.Text() + } + + // don't bother replacing the code text if we haven't found a closing paren + if strings.Index(newcode, ")") != -1 { + code = removeSpacesAndTabs(newcode) + } + } + } + prototype := removeSpacesAndTabs(tag.Prototype) prototype = removeTralingSemicolon(prototype) @@ -207,6 +234,8 @@ func parseTag(row string) *types.CTag { parts = parts[2:] + signature := "" + returntype := "" for _, part := range parts { if strings.Contains(part, ":") { colon := strings.Index(part, ":") @@ -222,9 +251,9 @@ func parseTag(row string) *types.CTag { case "typeref": tag.Typeref = value case "signature": - tag.Signature = value + signature = value case "returntype": - tag.Returntype = value + returntype = value case "class": tag.Class = value case "struct": @@ -234,6 +263,7 @@ func parseTag(row string) *types.CTag { } } } + tag.Prototype = returntype + " " + tag.FunctionName + signature + ";" if strings.Contains(row, "/^") && strings.Contains(row, "$/;") { tag.Code = row[strings.Index(row, "/^")+2 : strings.Index(row, "$/;")] diff --git a/src/arduino.cc/builder/ctags_runner.go b/src/arduino.cc/builder/ctags/ctags_runner.go similarity index 87% rename from src/arduino.cc/builder/ctags_runner.go rename to src/arduino.cc/builder/ctags/ctags_runner.go index 20c9eb7c..4a603fd9 100644 --- a/src/arduino.cc/builder/ctags_runner.go +++ b/src/arduino.cc/builder/ctags/ctags_runner.go @@ -27,7 +27,7 @@ * Copyright 2015 Arduino LLC (http://www.arduino.cc/) */ -package builder +package ctags import ( "arduino.cc/builder/constants" @@ -40,11 +40,12 @@ import ( type CTagsRunner struct{} func (s *CTagsRunner) Run(context map[string]interface{}) error { - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) ctagsTargetFilePath := context[constants.CTX_CTAGS_TEMP_FILE_PATH].(string) logger := context[constants.CTX_LOGGER].(i18n.Logger) - properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties, props.SubTree(props.SubTree(buildProperties, constants.BUILD_PROPERTIES_TOOLS_KEY), constants.CTAGS)) + properties := buildProperties.Clone() + properties.Merge(buildProperties.SubTree(constants.BUILD_PROPERTIES_TOOLS_KEY).SubTree(constants.CTAGS)) properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = ctagsTargetFilePath pattern := properties[constants.BUILD_PROPERTIES_PATTERN] @@ -52,7 +53,7 @@ func (s *CTagsRunner) Run(context map[string]interface{}) error { return utils.Errorf(context, constants.MSG_PATTERN_MISSING, constants.CTAGS) } - commandLine := props.ExpandPropsInString(properties, pattern) + commandLine := properties.ExpandPropsInString(pattern) command, err := utils.PrepareCommand(commandLine, logger) if err != nil { return utils.WrapError(err) diff --git a/src/arduino.cc/builder/ctags_to_prototypes.go b/src/arduino.cc/builder/ctags/ctags_to_prototypes.go similarity index 98% rename from src/arduino.cc/builder/ctags_to_prototypes.go rename to src/arduino.cc/builder/ctags/ctags_to_prototypes.go index d8cde83b..73e05482 100644 --- a/src/arduino.cc/builder/ctags_to_prototypes.go +++ b/src/arduino.cc/builder/ctags/ctags_to_prototypes.go @@ -27,7 +27,7 @@ * Copyright 2015 Arduino LLC (http://www.arduino.cc/) */ -package builder +package ctags import ( "arduino.cc/builder/constants" @@ -108,6 +108,9 @@ func firstFunctionAtLine(tags []*types.CTag) int { func toPrototypes(tags []*types.CTag) []*types.Prototype { prototypes := []*types.Prototype{} for _, tag := range tags { + if strings.TrimSpace(tag.Prototype) == "" { + continue + } if !tag.SkipMe { prototype := &types.Prototype{ FunctionName: tag.FunctionName, diff --git a/src/arduino.cc/builder/dump_build_properties.go b/src/arduino.cc/builder/dump_build_properties.go index 08a5f850..41db23f2 100644 --- a/src/arduino.cc/builder/dump_build_properties.go +++ b/src/arduino.cc/builder/dump_build_properties.go @@ -31,6 +31,7 @@ package builder import ( "arduino.cc/builder/constants" + "arduino.cc/builder/props" "arduino.cc/builder/utils" "fmt" "sort" @@ -39,7 +40,7 @@ import ( type DumpBuildProperties struct{} func (s *DumpBuildProperties) Run(context map[string]interface{}) error { - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) keys := utils.KeysOfMapOfString(buildProperties) sort.Strings(keys) diff --git a/src/arduino.cc/builder/gcc_preproc_runner.go b/src/arduino.cc/builder/gcc_preproc_runner.go index 5c5b87d1..19f599c3 100644 --- a/src/arduino.cc/builder/gcc_preproc_runner.go +++ b/src/arduino.cc/builder/gcc_preproc_runner.go @@ -33,6 +33,7 @@ import ( "arduino.cc/builder/builder_utils" "arduino.cc/builder/constants" "arduino.cc/builder/i18n" + "arduino.cc/builder/props" "arduino.cc/builder/types" "arduino.cc/builder/utils" "path/filepath" @@ -51,6 +52,11 @@ func (s *GCCPreprocRunner) Run(context map[string]interface{}) error { return utils.WrapError(err) } + if properties[constants.RECIPE_PREPROC_MACROS] == constants.EMPTY_STRING { + //generate PREPROC_MACROS from RECIPE_CPP_PATTERN + properties[constants.RECIPE_PREPROC_MACROS] = GeneratePreprocPatternFromCompile(properties[constants.RECIPE_CPP_PATTERN]) + } + verbose := context[constants.CTX_VERBOSE].(bool) logger := context[constants.CTX_LOGGER].(i18n.Logger) _, err = builder_utils.ExecRecipe(properties, constants.RECIPE_PREPROC_MACROS, true, verbose, false, logger) @@ -76,6 +82,12 @@ func (s *GCCPreprocRunnerForDiscoveringIncludes) Run(context map[string]interfac verbose := context[constants.CTX_VERBOSE].(bool) logger := context[constants.CTX_LOGGER].(i18n.Logger) + + if properties[constants.RECIPE_PREPROC_MACROS] == constants.EMPTY_STRING { + //generate PREPROC_MACROS from RECIPE_CPP_PATTERN + properties[constants.RECIPE_PREPROC_MACROS] = GeneratePreprocPatternFromCompile(properties[constants.RECIPE_CPP_PATTERN]) + } + stderr, err := builder_utils.ExecRecipeCollectStdErr(properties, constants.RECIPE_PREPROC_MACROS, true, verbose, false, logger) if err != nil { return utils.WrapError(err) @@ -86,7 +98,7 @@ func (s *GCCPreprocRunnerForDiscoveringIncludes) Run(context map[string]interfac return nil } -func prepareGCCPreprocRecipeProperties(context map[string]interface{}, sourceFilePath string, targetFilePath string) (map[string]string, string, error) { +func prepareGCCPreprocRecipeProperties(context map[string]interface{}, sourceFilePath string, targetFilePath string) (props.PropertiesMap, string, error) { if targetFilePath != utils.NULLFile() { preprocPath := context[constants.CTX_PREPROC_PATH].(string) err := utils.EnsureFolderExists(preprocPath) @@ -96,8 +108,10 @@ func prepareGCCPreprocRecipeProperties(context map[string]interface{}, sourceFil targetFilePath = filepath.Join(preprocPath, targetFilePath) } - buildProperties := utils.GetMapStringStringOrDefault(context, constants.CTX_BUILD_PROPERTIES) - properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties) + properties := make(props.PropertiesMap) + if p, ok := context[constants.CTX_BUILD_PROPERTIES]; ok { + properties = p.(props.PropertiesMap).Clone() + } properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = sourceFilePath properties[constants.BUILD_PROPERTIES_PREPROCESSED_FILE_PATH] = targetFilePath @@ -109,3 +123,12 @@ func prepareGCCPreprocRecipeProperties(context map[string]interface{}, sourceFil return properties, targetFilePath, nil } + +func GeneratePreprocPatternFromCompile(compilePattern string) string { + // add {preproc.macros.flags} + // replace "{object_file}" with "{preprocessed_file_path}" + returnString := compilePattern + returnString = strings.Replace(returnString, "{compiler.cpp.flags}", "{compiler.cpp.flags} {preproc.macros.flags}", 1) + returnString = strings.Replace(returnString, "{object_file}", "{preprocessed_file_path}", 1) + return returnString +} diff --git a/src/arduino.cc/builder/hardware/platform.txt b/src/arduino.cc/builder/hardware/platform.txt index 8adc28a3..87d8b64a 100644 --- a/src/arduino.cc/builder/hardware/platform.txt +++ b/src/arduino.cc/builder/hardware/platform.txt @@ -8,9 +8,9 @@ tools.ctags.pattern="{cmd.path}" -u --language-force=c++ -f - --c++-kinds=svpf - tools.avrdude.path={runtime.tools.avrdude.path} preproc.includes.flags=-w -x c++ -M -MG -MP -preproc.includes.compatibility_flags={build.mbed_api_include} {build.nRF51822_api_include} {build.ble_api_include} {compiler.libsam.c.flags} {compiler.arm.cmsis.path} {build.variant_system_include} -recipe.preproc.includes="{compiler.path}{compiler.cpp.cmd}" {preproc.includes.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {preproc.includes.compatibility_flags} {includes} "{source_file}" +#preproc.includes.compatibility_flags={build.mbed_api_include} {build.nRF51822_api_include} {build.ble_api_include} {compiler.libsam.c.flags} {compiler.arm.cmsis.path} {build.variant_system_include} +#recipe.preproc.includes="{compiler.path}{compiler.cpp.cmd}" {preproc.includes.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {preproc.includes.compatibility_flags} {includes} "{source_file}" preproc.macros.flags=-w -x c++ -E -CC -preproc.macros.compatibility_flags={build.mbed_api_include} {build.nRF51822_api_include} {build.ble_api_include} {compiler.libsam.c.flags} {compiler.arm.cmsis.path} {build.variant_system_include} -recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} {preproc.macros.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {preproc.macros.compatibility_flags} {includes} "{source_file}" -o "{preprocessed_file_path}" +#preproc.macros.compatibility_flags={build.mbed_api_include} {build.nRF51822_api_include} {build.ble_api_include} {compiler.libsam.c.flags} {compiler.arm.cmsis.path} {build.variant_system_include} +#recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} {preproc.macros.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {preproc.macros.compatibility_flags} {includes} "{source_file}" -o "{preprocessed_file_path}" diff --git a/src/arduino.cc/builder/hardware_loader.go b/src/arduino.cc/builder/hardware_loader.go index 87428166..29dce302 100644 --- a/src/arduino.cc/builder/hardware_loader.go +++ b/src/arduino.cc/builder/hardware_loader.go @@ -67,7 +67,7 @@ func (s *HardwareLoader) Run(context map[string]interface{}) error { if err != nil { return utils.WrapError(err) } - packages.Properties = utils.MergeMapsOfStrings(packages.Properties, hardwarePlatformTxt) + packages.Properties.Merge(hardwarePlatformTxt) subfolders, err := utils.ReadDirFiltered(folder, utils.FilterDirs) if err != nil { @@ -115,7 +115,7 @@ func loadPackage(targetPackage *types.Package, folder string, logger i18n.Logger if err != nil { return utils.WrapError(err) } - targetPackage.Properties = utils.MergeMapsOfStrings(targetPackage.Properties, packagePlatformTxt) + targetPackage.Properties.Merge(packagePlatformTxt) subfolders, err := utils.ReadDirFiltered(folder, utils.FilterDirs) if err != nil { @@ -161,7 +161,7 @@ func getOrCreatePlatform(platforms map[string]*types.Platform, platformId string targetPlatform.PlatformId = platformId targetPlatform.Boards = make(map[string]*types.Board) targetPlatform.Properties = make(map[string]string) - targetPlatform.Programmers = make(map[string]map[string]string) + targetPlatform.Programmers = make(map[string]props.PropertiesMap) return &targetPlatform } @@ -195,13 +195,15 @@ func loadPlatform(targetPlatform *types.Platform, packageId string, folder strin return utils.WrapError(err) } - targetPlatform.Properties = utils.MergeMapsOfStrings(make(map[string]string), targetPlatform.Properties, platformTxt, localPlatformProperties) + targetPlatform.Properties = targetPlatform.Properties.Clone() + targetPlatform.Properties.Merge(platformTxt) + targetPlatform.Properties.Merge(localPlatformProperties) programmersProperties, err := props.SafeLoad(filepath.Join(folder, constants.FILE_PROGRAMMERS_TXT), logger) if err != nil { return utils.WrapError(err) } - targetPlatform.Programmers = utils.MergeMapsOfMapsOfStrings(make(map[string]map[string]string), targetPlatform.Programmers, props.FirstLevelOf(programmersProperties)) + targetPlatform.Programmers = props.MergeMapsOfProperties(make(map[string]props.PropertiesMap), targetPlatform.Programmers, programmersProperties.FirstLevelOf()) return nil } @@ -227,15 +229,15 @@ func loadBoards(boards map[string]*types.Board, packageId string, platformId str return utils.WrapError(err) } - properties = utils.MergeMapsOfStrings(properties, localProperties) + properties = properties.Merge(localProperties) - propertiesByBoardId := props.FirstLevelOf(properties) + propertiesByBoardId := properties.FirstLevelOf() delete(propertiesByBoardId, constants.BOARD_PROPERTIES_MENU) for boardId, properties := range propertiesByBoardId { properties[constants.ID] = boardId board := getOrCreateBoard(boards, boardId) - board.Properties = utils.MergeMapsOfStrings(board.Properties, properties) + board.Properties.Merge(properties) boards[boardId] = board } @@ -249,7 +251,7 @@ func getOrCreateBoard(boards map[string]*types.Board, boardId string) *types.Boa board := types.Board{} board.BoardId = boardId - board.Properties = make(map[string]string) + board.Properties = make(props.PropertiesMap) return &board } diff --git a/src/arduino.cc/builder/includes_finder_with_gcc.go b/src/arduino.cc/builder/includes_finder_with_gcc.go index e633e632..55648e76 100644 --- a/src/arduino.cc/builder/includes_finder_with_gcc.go +++ b/src/arduino.cc/builder/includes_finder_with_gcc.go @@ -33,6 +33,7 @@ import ( "arduino.cc/builder/builder_utils" "arduino.cc/builder/constants" "arduino.cc/builder/i18n" + "arduino.cc/builder/props" "arduino.cc/builder/utils" "strings" ) @@ -42,7 +43,10 @@ type IncludesFinderWithGCC struct { } func (s *IncludesFinderWithGCC) Run(context map[string]interface{}) error { - buildProperties := utils.GetMapStringStringOrDefault(context, constants.CTX_BUILD_PROPERTIES) + buildProperties := make(props.PropertiesMap) + if p, ok := context[constants.CTX_BUILD_PROPERTIES]; ok { + buildProperties = p.(props.PropertiesMap).Clone() + } verbose := context[constants.CTX_VERBOSE].(bool) logger := context[constants.CTX_LOGGER].(i18n.Logger) @@ -53,11 +57,16 @@ func (s *IncludesFinderWithGCC) Run(context map[string]interface{}) error { includesParams = strings.Join(includes, " ") } - properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties) + properties := buildProperties.Clone() properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = s.SourceFile properties[constants.BUILD_PROPERTIES_INCLUDES] = includesParams builder_utils.RemoveHyphenMDDFlagFromGCCCommandLine(properties) + if properties[constants.RECIPE_PREPROC_INCLUDES] == "" { + //generate RECIPE_PREPROC_INCLUDES from RECIPE_CPP_PATTERN + properties[constants.RECIPE_PREPROC_INCLUDES] = GeneratePreprocIncludePatternFromCompile(properties[constants.RECIPE_CPP_PATTERN]) + } + output, err := builder_utils.ExecRecipe(properties, constants.RECIPE_PREPROC_INCLUDES, true, verbose, false, logger) if err != nil { return utils.WrapError(err) @@ -67,3 +76,12 @@ func (s *IncludesFinderWithGCC) Run(context map[string]interface{}) error { return nil } + +func GeneratePreprocIncludePatternFromCompile(compilePattern string) string { + // add {preproc.includes.flags} + // remove -o "{object_file}" + returnString := compilePattern + returnString = strings.Replace(returnString, "{compiler.cpp.flags}", "{compiler.cpp.flags} {preproc.includes.flags}", 1) + returnString = strings.Replace(returnString, "-o {object_file}", "", 1) + return returnString +} diff --git a/src/arduino.cc/builder/includes_to_include_folders.go b/src/arduino.cc/builder/includes_to_include_folders.go index 29bbea78..9760fb64 100644 --- a/src/arduino.cc/builder/includes_to_include_folders.go +++ b/src/arduino.cc/builder/includes_to_include_folders.go @@ -31,6 +31,7 @@ package builder import ( "arduino.cc/builder/constants" + "arduino.cc/builder/props" "arduino.cc/builder/types" "arduino.cc/builder/utils" "path/filepath" @@ -67,7 +68,7 @@ func (s *IncludesToIncludeFolders) Run(context map[string]interface{}) error { for _, newlyImportedLibrary := range newlyImportedLibraries { if !sliceContainsLibrary(importedLibraries, newlyImportedLibrary) { importedLibraries = append(importedLibraries, newlyImportedLibrary) - sourceFolders := utils.LibraryToSourceFolder(newlyImportedLibrary) + sourceFolders := types.LibraryToSourceFolder(newlyImportedLibrary) for _, sourceFolder := range sourceFolders { foldersWithSources.Push(sourceFolder) } @@ -76,7 +77,7 @@ func (s *IncludesToIncludeFolders) Run(context map[string]interface{}) error { context[constants.CTX_IMPORTED_LIBRARIES] = importedLibraries - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) verbose := context[constants.CTX_VERBOSE].(bool) includeFolders := resolveIncludeFolders(newlyImportedLibraries, buildProperties, verbose) context[constants.CTX_INCLUDE_FOLDERS] = includeFolders @@ -84,7 +85,7 @@ func (s *IncludesToIncludeFolders) Run(context map[string]interface{}) error { return nil } -func resolveIncludeFolders(importedLibraries []*types.Library, buildProperties map[string]string, verbose bool) []string { +func resolveIncludeFolders(importedLibraries []*types.Library, buildProperties props.PropertiesMap, verbose bool) []string { var includeFolders []string includeFolders = append(includeFolders, buildProperties[constants.BUILD_PROPERTIES_BUILD_CORE_PATH]) if buildProperties[constants.BUILD_PROPERTIES_BUILD_VARIANT_PATH] != constants.EMPTY_STRING { @@ -139,8 +140,8 @@ func resolveLibrary(header string, headerToLibraries map[string][]*types.Library var library *types.Library for _, platform := range platforms { - if platform != nil && library == nil { - library = findBestLibraryWithHeader(header, librariesCompatibleWithPlatform(libraries, platform)) + if platform != nil { + library = findBestLibraryWithHeader(header, librariesCompatibleWithPlatform(libraries, platform, true)) } } @@ -149,6 +150,12 @@ func resolveLibrary(header string, headerToLibraries map[string][]*types.Library } if library == nil { + // reorder libraries to promote fully compatible ones + for _, platform := range platforms { + if platform != nil { + libraries = append(librariesCompatibleWithPlatform(libraries, platform, false), libraries...) + } + } library = libraries[0] } @@ -217,21 +224,34 @@ func findLibraryIn(libraries []*types.Library, library *types.Library) *types.Li return nil } -func libraryCompatibleWithPlatform(library *types.Library, platform *types.Platform) bool { +func libraryCompatibleWithPlatform(library *types.Library, platform *types.Platform) (bool, bool) { if len(library.Archs) == 0 { - return true + return true, true + } + if utils.SliceContains(library.Archs, constants.LIBRARY_ALL_ARCHS) { + return true, true } + return utils.SliceContains(library.Archs, platform.PlatformId), false +} + +func libraryCompatibleWithAllPlatforms(library *types.Library) bool { if utils.SliceContains(library.Archs, constants.LIBRARY_ALL_ARCHS) { return true } - return utils.SliceContains(library.Archs, platform.PlatformId) + return false } -func librariesCompatibleWithPlatform(libraries []*types.Library, platform *types.Platform) []*types.Library { +func librariesCompatibleWithPlatform(libraries []*types.Library, platform *types.Platform, reorder bool) []*types.Library { var compatibleLibraries []*types.Library for _, library := range libraries { - if libraryCompatibleWithPlatform(library, platform) { - compatibleLibraries = append(compatibleLibraries, library) + compatible, generic := libraryCompatibleWithPlatform(library, platform) + if compatible { + if !generic && len(compatibleLibraries) != 0 && libraryCompatibleWithAllPlatforms(compatibleLibraries[0]) && reorder == true { + //priority inversion + compatibleLibraries = append([]*types.Library{library}, compatibleLibraries...) + } else { + compatibleLibraries = append(compatibleLibraries, library) + } } } diff --git a/src/arduino.cc/builder/load_vid_pid_specific_properties.go b/src/arduino.cc/builder/load_vid_pid_specific_properties.go index 41ecf1bc..3f7ccd2d 100644 --- a/src/arduino.cc/builder/load_vid_pid_specific_properties.go +++ b/src/arduino.cc/builder/load_vid_pid_specific_properties.go @@ -50,7 +50,7 @@ func (s *LoadVIDPIDSpecificProperties) Run(context map[string]interface{}) error vid := vidPidParts[0] pid := vidPidParts[1] - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) VIDPIDIndex, err := findVIDPIDIndex(buildProperties, vid, pid) if err != nil { return utils.WrapError(err) @@ -59,14 +59,14 @@ func (s *LoadVIDPIDSpecificProperties) Run(context map[string]interface{}) error return nil } - vidPidSpecificProperties := props.SubTree(props.SubTree(buildProperties, constants.BUILD_PROPERTIES_VID), strconv.Itoa(VIDPIDIndex)) - utils.MergeMapsOfStrings(buildProperties, vidPidSpecificProperties) + vidPidSpecificProperties := buildProperties.SubTree(constants.BUILD_PROPERTIES_VID).SubTree(strconv.Itoa(VIDPIDIndex)) + buildProperties.Merge(vidPidSpecificProperties) return nil } -func findVIDPIDIndex(buildProperties map[string]string, vid, pid string) (int, error) { - for key, value := range props.SubTree(buildProperties, constants.BUILD_PROPERTIES_VID) { +func findVIDPIDIndex(buildProperties props.PropertiesMap, vid, pid string) (int, error) { + for key, value := range buildProperties.SubTree(constants.BUILD_PROPERTIES_VID) { if !strings.Contains(key, ".") { if vid == strings.ToLower(value) && pid == strings.ToLower(buildProperties[constants.BUILD_PROPERTIES_PID+"."+key]) { return strconv.Atoi(key) diff --git a/src/arduino.cc/builder/merge_sketch_with_bootloader.go b/src/arduino.cc/builder/merge_sketch_with_bootloader.go index 0d73afc4..85c5d015 100644 --- a/src/arduino.cc/builder/merge_sketch_with_bootloader.go +++ b/src/arduino.cc/builder/merge_sketch_with_bootloader.go @@ -43,7 +43,7 @@ import ( type MergeSketchWithBootloader struct{} func (s *MergeSketchWithBootloader) Run(context map[string]interface{}) error { - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) if !utils.MapStringStringHas(buildProperties, constants.BUILD_PROPERTIES_BOOTLOADER_NOBLINK) && !utils.MapStringStringHas(buildProperties, constants.BUILD_PROPERTIES_BOOTLOADER_FILE) { return nil } @@ -71,7 +71,7 @@ func (s *MergeSketchWithBootloader) Run(context map[string]interface{}) error { } else { bootloader = buildProperties[constants.BUILD_PROPERTIES_BOOTLOADER_FILE] } - bootloader = props.ExpandPropsInString(buildProperties, bootloader) + bootloader = buildProperties.ExpandPropsInString(bootloader) bootloaderPath := filepath.Join(buildProperties[constants.BUILD_PROPERTIES_RUNTIME_PLATFORM_PATH], constants.FOLDER_BOOTLOADERS, bootloader) if _, err := os.Stat(bootloaderPath); err != nil { @@ -86,6 +86,48 @@ func (s *MergeSketchWithBootloader) Run(context map[string]interface{}) error { return err } +func hexLineOnlyContainsFF(line string) bool { + //:206FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 + if len(line) <= 11 { + return false + } + byteArray := []byte(line) + for _, char := range byteArray[9:(len(byteArray) - 2)] { + if char != 'F' { + return false + } + } + return true +} + +func extractActualBootloader(bootloader []string) []string { + + var realBootloader []string + + // skip until we find a line full of FFFFFF (except address and checksum) + for i, row := range bootloader { + if hexLineOnlyContainsFF(row) { + realBootloader = bootloader[i:len(bootloader)] + break + } + } + + // drop all "empty" lines + for i, row := range realBootloader { + if !hexLineOnlyContainsFF(row) { + realBootloader = realBootloader[i:len(realBootloader)] + break + } + } + + if len(realBootloader) == 0 { + // we didn't find any line full of FFFF, thus it's a standalone bootloader + realBootloader = bootloader + } + + return realBootloader +} + func merge(builtSketchPath, bootloaderPath, mergedSketchPath string) error { sketch, err := utils.ReadFileToRows(builtSketchPath) if err != nil { @@ -98,7 +140,9 @@ func merge(builtSketchPath, bootloaderPath, mergedSketchPath string) error { return utils.WrapError(err) } - for _, row := range bootloader { + realBootloader := extractActualBootloader(bootloader) + + for _, row := range realBootloader { sketch = append(sketch, row) } diff --git a/src/arduino.cc/builder/phases/core_builder.go b/src/arduino.cc/builder/phases/core_builder.go index cf1c761d..d1b8cc9b 100644 --- a/src/arduino.cc/builder/phases/core_builder.go +++ b/src/arduino.cc/builder/phases/core_builder.go @@ -33,6 +33,7 @@ import ( "arduino.cc/builder/builder_utils" "arduino.cc/builder/constants" "arduino.cc/builder/i18n" + "arduino.cc/builder/props" "arduino.cc/builder/utils" ) @@ -40,7 +41,7 @@ type CoreBuilder struct{} func (s *CoreBuilder) Run(context map[string]interface{}) error { coreBuildPath := context[constants.CTX_CORE_BUILD_PATH].(string) - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) verbose := context[constants.CTX_VERBOSE].(bool) warningsLevel := context[constants.CTX_WARNINGS_LEVEL].(string) logger := context[constants.CTX_LOGGER].(i18n.Logger) @@ -61,7 +62,7 @@ func (s *CoreBuilder) Run(context map[string]interface{}) error { return nil } -func compileCore(buildPath string, buildProperties map[string]string, verbose bool, warningsLevel string, logger i18n.Logger) (string, []string, error) { +func compileCore(buildPath string, buildProperties props.PropertiesMap, verbose bool, warningsLevel string, logger i18n.Logger) (string, []string, error) { coreFolder := buildProperties[constants.BUILD_PROPERTIES_BUILD_CORE_PATH] variantFolder := buildProperties[constants.BUILD_PROPERTIES_BUILD_VARIANT_PATH] diff --git a/src/arduino.cc/builder/phases/libraries_builder.go b/src/arduino.cc/builder/phases/libraries_builder.go index bb01f8e8..a26f5b2a 100644 --- a/src/arduino.cc/builder/phases/libraries_builder.go +++ b/src/arduino.cc/builder/phases/libraries_builder.go @@ -33,6 +33,7 @@ import ( "arduino.cc/builder/builder_utils" "arduino.cc/builder/constants" "arduino.cc/builder/i18n" + "arduino.cc/builder/props" "arduino.cc/builder/types" "arduino.cc/builder/utils" "os" @@ -43,7 +44,7 @@ type LibrariesBuilder struct{} func (s *LibrariesBuilder) Run(context map[string]interface{}) error { librariesBuildPath := context[constants.CTX_LIBRARIES_BUILD_PATH].(string) - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) includes := context[constants.CTX_INCLUDE_FOLDERS].([]string) includes = utils.Map(includes, utils.WrapWithHyphenI) libraries := context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library) @@ -66,7 +67,7 @@ func (s *LibrariesBuilder) Run(context map[string]interface{}) error { return nil } -func compileLibraries(libraries []*types.Library, buildPath string, buildProperties map[string]string, includes []string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { +func compileLibraries(libraries []*types.Library, buildPath string, buildProperties props.PropertiesMap, includes []string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { objectFiles := []string{} for _, library := range libraries { libraryObjectFiles, err := compileLibrary(library, buildPath, buildProperties, includes, verbose, warningsLevel, logger) @@ -80,7 +81,7 @@ func compileLibraries(libraries []*types.Library, buildPath string, buildPropert } -func compileLibrary(library *types.Library, buildPath string, buildProperties map[string]string, includes []string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { +func compileLibrary(library *types.Library, buildPath string, buildProperties props.PropertiesMap, includes []string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { libraryBuildPath := filepath.Join(buildPath, library.Name) err := utils.EnsureFolderExists(libraryBuildPath) diff --git a/src/arduino.cc/builder/phases/linker.go b/src/arduino.cc/builder/phases/linker.go index 7b9fd319..d2530d31 100644 --- a/src/arduino.cc/builder/phases/linker.go +++ b/src/arduino.cc/builder/phases/linker.go @@ -33,6 +33,7 @@ import ( "arduino.cc/builder/builder_utils" "arduino.cc/builder/constants" "arduino.cc/builder/i18n" + "arduino.cc/builder/props" "arduino.cc/builder/utils" "path/filepath" "strings" @@ -57,7 +58,7 @@ func (s *Linker) Run(context map[string]interface{}) error { return utils.WrapError(err) } - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) verbose := context[constants.CTX_VERBOSE].(bool) warningsLevel := context[constants.CTX_WARNINGS_LEVEL].(string) logger := context[constants.CTX_LOGGER].(i18n.Logger) @@ -70,13 +71,13 @@ func (s *Linker) Run(context map[string]interface{}) error { return nil } -func link(objectFiles []string, coreDotARelPath string, coreArchiveFilePath string, buildProperties map[string]string, verbose bool, warningsLevel string, logger i18n.Logger) error { +func link(objectFiles []string, coreDotARelPath string, coreArchiveFilePath string, buildProperties props.PropertiesMap, verbose bool, warningsLevel string, logger i18n.Logger) error { optRelax := addRelaxTrickIfATMEGA2560(buildProperties) objectFiles = utils.Map(objectFiles, wrapWithDoubleQuotes) objectFileList := strings.Join(objectFiles, constants.SPACE) - properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties) + properties := buildProperties.Clone() properties[constants.BUILD_PROPERTIES_COMPILER_C_ELF_FLAGS] = properties[constants.BUILD_PROPERTIES_COMPILER_C_ELF_FLAGS] + optRelax properties[constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS] = properties[constants.BUILD_PROPERTIES_COMPILER_WARNING_FLAGS+"."+warningsLevel] properties[constants.BUILD_PROPERTIES_ARCHIVE_FILE] = coreDotARelPath @@ -91,7 +92,7 @@ func wrapWithDoubleQuotes(value string) string { return "\"" + value + "\"" } -func addRelaxTrickIfATMEGA2560(buildProperties map[string]string) string { +func addRelaxTrickIfATMEGA2560(buildProperties props.PropertiesMap) string { if buildProperties[constants.BUILD_PROPERTIES_BUILD_MCU] == "atmega2560" { return ",--relax" } diff --git a/src/arduino.cc/builder/phases/sketch_builder.go b/src/arduino.cc/builder/phases/sketch_builder.go index 27d26d59..cf9befe7 100644 --- a/src/arduino.cc/builder/phases/sketch_builder.go +++ b/src/arduino.cc/builder/phases/sketch_builder.go @@ -33,6 +33,7 @@ import ( "arduino.cc/builder/builder_utils" "arduino.cc/builder/constants" "arduino.cc/builder/i18n" + "arduino.cc/builder/props" "arduino.cc/builder/utils" ) @@ -40,7 +41,7 @@ type SketchBuilder struct{} func (s *SketchBuilder) Run(context map[string]interface{}) error { sketchBuildPath := context[constants.CTX_SKETCH_BUILD_PATH].(string) - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) includes := context[constants.CTX_INCLUDE_FOLDERS].([]string) includes = utils.Map(includes, utils.WrapWithHyphenI) verbose := context[constants.CTX_VERBOSE].(bool) diff --git a/src/arduino.cc/builder/props/properties.go b/src/arduino.cc/builder/props/properties.go index 9cfa01ad..68ef4861 100644 --- a/src/arduino.cc/builder/props/properties.go +++ b/src/arduino.cc/builder/props/properties.go @@ -41,6 +41,8 @@ import ( "strings" ) +type PropertiesMap map[string]string + var OSNAME string func init() { @@ -56,7 +58,7 @@ func init() { } } -func Load(filepath string, logger i18n.Logger) (map[string]string, error) { +func Load(filepath string, logger i18n.Logger) (PropertiesMap, error) { bytes, err := ioutil.ReadFile(filepath) if err != nil { return nil, utils.WrapError(err) @@ -66,10 +68,10 @@ func Load(filepath string, logger i18n.Logger) (map[string]string, error) { text = strings.Replace(text, "\r\n", "\n", -1) text = strings.Replace(text, "\r", "\n", -1) - properties := make(map[string]string) + properties := make(PropertiesMap) for _, line := range strings.Split(text, "\n") { - err := loadSingleLine(properties, line) + err := properties.loadSingleLine(line) if err != nil { return nil, utils.ErrorfWithLogger(logger, constants.MSG_WRONG_PROPERTIES_FILE, line, filepath) } @@ -78,11 +80,11 @@ func Load(filepath string, logger i18n.Logger) (map[string]string, error) { return properties, nil } -func LoadFromSlice(lines []string, logger i18n.Logger) (map[string]string, error) { - properties := make(map[string]string) +func LoadFromSlice(lines []string, logger i18n.Logger) (PropertiesMap, error) { + properties := make(PropertiesMap) for _, line := range lines { - err := loadSingleLine(properties, line) + err := properties.loadSingleLine(line) if err != nil { return nil, utils.ErrorfWithLogger(logger, constants.MSG_WRONG_PROPERTIES, line) } @@ -91,7 +93,7 @@ func LoadFromSlice(lines []string, logger i18n.Logger) (map[string]string, error return properties, nil } -func loadSingleLine(properties map[string]string, line string) error { +func (properties PropertiesMap) loadSingleLine(line string) error { line = strings.TrimSpace(line) if len(line) > 0 && line[0] != '#' { @@ -109,10 +111,10 @@ func loadSingleLine(properties map[string]string, line string) error { return nil } -func SafeLoad(filepath string, logger i18n.Logger) (map[string]string, error) { +func SafeLoad(filepath string, logger i18n.Logger) (PropertiesMap, error) { _, err := os.Stat(filepath) if os.IsNotExist(err) { - return make(map[string]string), nil + return make(PropertiesMap), nil } properties, err := Load(filepath, logger) @@ -122,26 +124,26 @@ func SafeLoad(filepath string, logger i18n.Logger) (map[string]string, error) { return properties, nil } -func FirstLevelOf(aMap map[string]string) map[string]map[string]string { - newMap := make(map[string]map[string]string) +func (aMap PropertiesMap) FirstLevelOf() map[string]PropertiesMap { + newMap := make(map[string]PropertiesMap) for key, value := range aMap { if strings.Index(key, ".") == -1 { continue } keyParts := strings.SplitN(key, ".", 2) if newMap[keyParts[0]] == nil { - newMap[keyParts[0]] = make(map[string]string) + newMap[keyParts[0]] = make(PropertiesMap) } newMap[keyParts[0]][keyParts[1]] = value } return newMap } -func SubTree(aMap map[string]string, key string) map[string]string { - return FirstLevelOf(aMap)[key] +func (aMap PropertiesMap) SubTree(key string) PropertiesMap { + return aMap.FirstLevelOf()[key] } -func ExpandPropsInString(aMap map[string]string, str string) string { +func (aMap PropertiesMap) ExpandPropsInString(str string) string { replaced := true for i := 0; i < 10 && replaced; i++ { replaced = false @@ -154,6 +156,30 @@ func ExpandPropsInString(aMap map[string]string, str string) string { return str } +func (target PropertiesMap) Merge(sources ...PropertiesMap) PropertiesMap { + for _, source := range sources { + for key, value := range source { + target[key] = value + } + } + return target +} + +func (aMap PropertiesMap) Clone() PropertiesMap { + newMap := make(PropertiesMap) + newMap.Merge(aMap) + return newMap +} + +func MergeMapsOfProperties(target map[string]PropertiesMap, sources ...map[string]PropertiesMap) map[string]PropertiesMap { + for _, source := range sources { + for key, value := range source { + target[key] = value + } + } + return target +} + func DeleteUnexpandedPropsFromString(str string) (string, error) { rxp, err := regexp.Compile("\\{.+?\\}") if err != nil { diff --git a/src/arduino.cc/builder/prototypes_adder.go b/src/arduino.cc/builder/prototypes_adder.go index fe58c8b5..5fa95c65 100644 --- a/src/arduino.cc/builder/prototypes_adder.go +++ b/src/arduino.cc/builder/prototypes_adder.go @@ -33,6 +33,7 @@ import ( "arduino.cc/builder/constants" "arduino.cc/builder/types" "arduino.cc/builder/utils" + "fmt" "strconv" "strings" ) @@ -40,7 +41,12 @@ import ( type PrototypesAdder struct{} func (s *PrototypesAdder) Run(context map[string]interface{}) error { + debugOutput := context[constants.CTX_DEBUG_PREPROCESSOR] != nil source := context[constants.CTX_SOURCE].(string) + + source = strings.Replace(source, "\r\n", "\n", -1) + source = strings.Replace(source, "\r", "\n", -1) + sourceRows := strings.Split(source, "\n") if !utils.MapHas(context, constants.CTX_LINE_WHERE_TO_INSERT_PROTOTYPES) { @@ -48,15 +54,31 @@ func (s *PrototypesAdder) Run(context map[string]interface{}) error { } firstFunctionLine := context[constants.CTX_LINE_WHERE_TO_INSERT_PROTOTYPES].(int) - if firstFunctionOutsideOfSource(firstFunctionLine, sourceRows) { + if isFirstFunctionOutsideOfSource(firstFunctionLine, sourceRows) { return nil } - firstFunctionChar := len(strings.Join(sourceRows[:firstFunctionLine+context[constants.CTX_LINE_OFFSET].(int)-1], "\n")) + 1 + insertionLine := firstFunctionLine + context[constants.CTX_LINE_OFFSET].(int) - 1 + firstFunctionChar := len(strings.Join(sourceRows[:insertionLine], "\n")) + 1 prototypeSection := composePrototypeSection(firstFunctionLine, context[constants.CTX_PROTOTYPES].([]*types.Prototype)) context[constants.CTX_PROTOTYPE_SECTION] = prototypeSection source = source[:firstFunctionChar] + prototypeSection + source[firstFunctionChar:] + if debugOutput { + fmt.Println("#PREPROCESSED SOURCE") + prototypesRows := strings.Split(prototypeSection, "\n") + prototypesRows = prototypesRows[:len(prototypesRows)-1] + for i := 0; i < len(sourceRows)+len(prototypesRows); i++ { + if i < insertionLine { + fmt.Printf(" |%s\n", sourceRows[i]) + } else if i < insertionLine+len(prototypesRows) { + fmt.Printf("PRO|%s\n", prototypesRows[i-insertionLine]) + } else { + fmt.Printf(" |%s\n", sourceRows[i-len(prototypesRows)]) + } + } + fmt.Println("#END OF PREPROCESSED SOURCE") + } context[constants.CTX_SOURCE] = source return nil @@ -70,6 +92,7 @@ func composePrototypeSection(line int, prototypes []*types.Prototype) string { str := joinPrototypes(prototypes) str += "\n#line " str += strconv.Itoa(line) + str += " \"" + prototypes[0].File + "\"" str += "\n" return str @@ -78,6 +101,9 @@ func composePrototypeSection(line int, prototypes []*types.Prototype) string { func joinPrototypes(prototypes []*types.Prototype) string { prototypesSlice := []string{} for _, proto := range prototypes { + if signatureContainsaDefaultArg(proto) { + continue + } prototypesSlice = append(prototypesSlice, "#line "+strconv.Itoa(proto.Line)+" \""+proto.File+"\"") prototypeParts := []string{} if proto.Modifiers != "" { @@ -89,6 +115,10 @@ func joinPrototypes(prototypes []*types.Prototype) string { return strings.Join(prototypesSlice, "\n") } -func firstFunctionOutsideOfSource(firstFunctionLine int, sourceRows []string) bool { +func signatureContainsaDefaultArg(proto *types.Prototype) bool { + return strings.Contains(proto.Prototype, "=") +} + +func isFirstFunctionOutsideOfSource(firstFunctionLine int, sourceRows []string) bool { return firstFunctionLine > len(sourceRows)-1 } diff --git a/src/arduino.cc/builder/recipe_runner.go b/src/arduino.cc/builder/recipe_runner.go index 05d3920d..8e656bd7 100644 --- a/src/arduino.cc/builder/recipe_runner.go +++ b/src/arduino.cc/builder/recipe_runner.go @@ -33,6 +33,7 @@ import ( "arduino.cc/builder/builder_utils" "arduino.cc/builder/constants" "arduino.cc/builder/i18n" + "arduino.cc/builder/props" "arduino.cc/builder/utils" "os" "sort" @@ -50,12 +51,15 @@ func (s *RecipeByPrefixSuffixRunner) Run(context map[string]interface{}) error { logger.Fprintln(os.Stdout, constants.LOG_LEVEL_DEBUG, constants.MSG_LOOKING_FOR_RECIPES, s.Prefix, s.Suffix) } - buildProperties := utils.GetMapStringStringOrDefault(context, constants.CTX_BUILD_PROPERTIES) + buildProperties := make(props.PropertiesMap) + if p, ok := context[constants.CTX_BUILD_PROPERTIES]; ok { + buildProperties = p.(props.PropertiesMap).Clone() + } verbose := context[constants.CTX_VERBOSE].(bool) recipes := findRecipes(buildProperties, s.Prefix, s.Suffix) - properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties) + properties := buildProperties.Clone() for _, recipe := range recipes { if utils.DebugLevel(context) >= 10 { logger.Fprintln(os.Stdout, constants.LOG_LEVEL_DEBUG, constants.MSG_RUNNING_RECIPE, recipe) diff --git a/src/arduino.cc/builder/set_custom_build_properties.go b/src/arduino.cc/builder/set_custom_build_properties.go index d77a2098..ed908772 100644 --- a/src/arduino.cc/builder/set_custom_build_properties.go +++ b/src/arduino.cc/builder/set_custom_build_properties.go @@ -44,7 +44,7 @@ func (s *SetCustomBuildProperties) Run(context map[string]interface{}) error { } logger := context[constants.CTX_LOGGER].(i18n.Logger) - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) customBuildProperties, err := props.LoadFromSlice(context[constants.CTX_CUSTOM_BUILD_PROPERTIES].([]string), logger) if err != nil { return utils.WrapError(err) diff --git a/src/arduino.cc/builder/setup_build_properties.go b/src/arduino.cc/builder/setup_build_properties.go index 1c03cbec..7e9332f7 100644 --- a/src/arduino.cc/builder/setup_build_properties.go +++ b/src/arduino.cc/builder/setup_build_properties.go @@ -31,6 +31,7 @@ package builder import ( "arduino.cc/builder/constants" + "arduino.cc/builder/props" "arduino.cc/builder/types" "arduino.cc/builder/utils" "path/filepath" @@ -48,10 +49,10 @@ func (s *SetupBuildProperties) Run(context map[string]interface{}) error { actualPlatform := context[constants.CTX_ACTUAL_PLATFORM].(*types.Platform) targetBoard := context[constants.CTX_TARGET_BOARD].(*types.Board) - buildProperties := make(map[string]string) - utils.MergeMapsOfStrings(buildProperties, actualPlatform.Properties) - utils.MergeMapsOfStrings(buildProperties, targetPlatform.Properties) - utils.MergeMapsOfStrings(buildProperties, targetBoard.Properties) + buildProperties := make(props.PropertiesMap) + buildProperties.Merge(actualPlatform.Properties) + buildProperties.Merge(targetPlatform.Properties) + buildProperties.Merge(targetBoard.Properties) if utils.MapHas(context, constants.CTX_BUILD_PATH) { buildProperties[constants.BUILD_PROPERTIES_BUILD_PATH] = context[constants.CTX_BUILD_PATH].(string) diff --git a/src/arduino.cc/builder/sketch_source_merger.go b/src/arduino.cc/builder/sketch_source_merger.go index 1e99a57f..d4cc71a3 100644 --- a/src/arduino.cc/builder/sketch_source_merger.go +++ b/src/arduino.cc/builder/sketch_source_merger.go @@ -33,6 +33,7 @@ package builder import ( "arduino.cc/builder/constants" "arduino.cc/builder/types" + "regexp" "strings" ) @@ -42,8 +43,13 @@ func (s *SketchSourceMerger) Run(context map[string]interface{}) error { sketch := context[constants.CTX_SKETCH].(*types.Sketch) lineOffset := 0 - includeSection := composeIncludeArduinoSection() - lineOffset += 2 + includeSection := "" + if !sketchIncludesArduinoH(&sketch.MainFile) { + includeSection += "#include \n" + lineOffset++ + } + includeSection += "#line 1 \"" + strings.Replace((&sketch.MainFile).Name, "\\", "\\\\", -1) + "\"\n" + lineOffset++ context[constants.CTX_INCLUDE_SECTION] = includeSection source := includeSection @@ -59,6 +65,14 @@ func (s *SketchSourceMerger) Run(context map[string]interface{}) error { return nil } +func sketchIncludesArduinoH(sketch *types.SketchFile) bool { + if matched, err := regexp.MatchString("(?m)^\\s*#\\s*include\\s*[<\"]Arduino\\.h[>\"]", sketch.Source); err != nil { + panic(err) + } else { + return matched + } +} + func addSourceWrappedWithLineDirective(sketch *types.SketchFile) string { source := "#line 1 \"" + strings.Replace(sketch.Name, "\\", "\\\\", -1) + "\"\n" source += sketch.Source @@ -66,10 +80,3 @@ func addSourceWrappedWithLineDirective(sketch *types.SketchFile) string { return source } - -func composeIncludeArduinoSection() string { - str := "#include \n" - str += "#line 1\n" - - return str -} diff --git a/src/arduino.cc/builder/target_board_resolver.go b/src/arduino.cc/builder/target_board_resolver.go index fc67917d..c1c58c4a 100644 --- a/src/arduino.cc/builder/target_board_resolver.go +++ b/src/arduino.cc/builder/target_board_resolver.go @@ -31,7 +31,6 @@ package builder import ( "arduino.cc/builder/constants" - "arduino.cc/builder/props" "arduino.cc/builder/types" "arduino.cc/builder/utils" "strings" @@ -112,16 +111,16 @@ func addAdditionalPropertiesToTargetBoard(board *types.Board, options string) { key := parts[0] value := parts[1] if key != constants.EMPTY_STRING && value != constants.EMPTY_STRING { - menu := props.SubTree(board.Properties, constants.BOARD_PROPERTIES_MENU) + menu := board.Properties.SubTree(constants.BOARD_PROPERTIES_MENU) if len(menu) == 0 { return } - propertiesOfKey := props.SubTree(menu, key) + propertiesOfKey := menu.SubTree(key) if len(propertiesOfKey) == 0 { return } - propertiesOfKeyValue := props.SubTree(propertiesOfKey, value) - utils.MergeMapsOfStrings(board.Properties, propertiesOfKeyValue) + propertiesOfKeyValue := propertiesOfKey.SubTree(value) + board.Properties.Merge(propertiesOfKeyValue) } } } diff --git a/src/arduino.cc/builder/test/ctags_parser_test.go b/src/arduino.cc/builder/test/ctags_parser_test.go index cb6353dc..9f671308 100644 --- a/src/arduino.cc/builder/test/ctags_parser_test.go +++ b/src/arduino.cc/builder/test/ctags_parser_test.go @@ -30,8 +30,8 @@ package test import ( - "arduino.cc/builder" "arduino.cc/builder/constants" + "arduino.cc/builder/ctags" "arduino.cc/builder/types" "github.com/stretchr/testify/require" "io/ioutil" @@ -47,44 +47,44 @@ func TestCTagsParserShouldListPrototypes(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 8, len(ctags)) + require.Equal(t, 8, len(tags)) idx := 0 - require.Equal(t, "server", ctags[idx].FunctionName) - require.Equal(t, "variable", ctags[idx].Kind) - require.Equal(t, "/tmp/sketch7210316334309249705.cpp", ctags[idx].Filename) + require.Equal(t, "server", tags[idx].FunctionName) + require.Equal(t, "variable", tags[idx].Kind) + require.Equal(t, "/tmp/sketch7210316334309249705.cpp", tags[idx].Filename) idx++ - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "/tmp/sketch7210316334309249705.cpp", ctags[idx].Filename) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "/tmp/sketch7210316334309249705.cpp", tags[idx].Filename) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "/tmp/sketch7210316334309249705.cpp", ctags[idx].Filename) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "/tmp/sketch7210316334309249705.cpp", tags[idx].Filename) idx++ - require.Equal(t, "process", ctags[idx].FunctionName) - require.Equal(t, "prototype", ctags[idx].Kind) - require.Equal(t, "/tmp/sketch7210316334309249705.cpp", ctags[idx].Filename) + require.Equal(t, "process", tags[idx].FunctionName) + require.Equal(t, "prototype", tags[idx].Kind) + require.Equal(t, "/tmp/sketch7210316334309249705.cpp", tags[idx].Filename) idx++ - require.Equal(t, "process", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "/tmp/sketch7210316334309249705.cpp", ctags[idx].Filename) + require.Equal(t, "process", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "/tmp/sketch7210316334309249705.cpp", tags[idx].Filename) idx++ - require.Equal(t, "digitalCommand", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "/tmp/sketch7210316334309249705.cpp", ctags[idx].Filename) + require.Equal(t, "digitalCommand", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "/tmp/sketch7210316334309249705.cpp", tags[idx].Filename) idx++ - require.Equal(t, "analogCommand", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "/tmp/sketch7210316334309249705.cpp", ctags[idx].Filename) + require.Equal(t, "analogCommand", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "/tmp/sketch7210316334309249705.cpp", tags[idx].Filename) idx++ - require.Equal(t, "modeCommand", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "/tmp/sketch7210316334309249705.cpp", ctags[idx].Filename) + require.Equal(t, "modeCommand", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "/tmp/sketch7210316334309249705.cpp", tags[idx].Filename) } func TestCTagsParserShouldListTemplates(t *testing.T) { @@ -95,22 +95,24 @@ func TestCTagsParserShouldListTemplates(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 3, len(ctags)) + require.Equal(t, 3, len(tags)) idx := 0 - require.Equal(t, "minimum", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "(T a, T b)", ctags[idx].Signature) + require.Equal(t, "minimum", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "template T minimum (T a, T b);", tags[idx].Prototype) idx++ - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "void setup();", tags[idx].Prototype) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "void loop();", tags[idx].Prototype) } func TestCTagsParserShouldListTemplates2(t *testing.T) { @@ -121,26 +123,26 @@ func TestCTagsParserShouldListTemplates2(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 4, len(ctags)) + require.Equal(t, 4, len(tags)) idx := 0 - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "SRAM_writeAnything", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "(int ee, const T& value)", ctags[idx].Signature) + require.Equal(t, "SRAM_writeAnything", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "template int SRAM_writeAnything(int ee, const T& value);", tags[idx].Prototype) idx++ - require.Equal(t, "SRAM_readAnything", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "(int ee, T& value)", ctags[idx].Signature) + require.Equal(t, "SRAM_readAnything", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "template int SRAM_readAnything(int ee, T& value);", tags[idx].Prototype) } func TestCTagsParserShouldDealWithClasses(t *testing.T) { @@ -151,18 +153,18 @@ func TestCTagsParserShouldDealWithClasses(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 2, len(ctags)) + require.Equal(t, 2, len(tags)) idx := 0 - require.Equal(t, "SleepCycle", ctags[idx].FunctionName) - require.Equal(t, "prototype", ctags[idx].Kind) + require.Equal(t, "SleepCycle", tags[idx].FunctionName) + require.Equal(t, "prototype", tags[idx].Kind) idx++ - require.Equal(t, "SleepCycle", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "SleepCycle", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) } func TestCTagsParserShouldDealWithStructs(t *testing.T) { @@ -173,28 +175,28 @@ func TestCTagsParserShouldDealWithStructs(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 5, len(ctags)) + require.Equal(t, 5, len(tags)) idx := 0 - require.Equal(t, "A_NEW_TYPE", ctags[idx].FunctionName) - require.Equal(t, "struct", ctags[idx].Kind) + require.Equal(t, "A_NEW_TYPE", tags[idx].FunctionName) + require.Equal(t, "struct", tags[idx].Kind) idx++ - require.Equal(t, "foo", ctags[idx].FunctionName) - require.Equal(t, "variable", ctags[idx].Kind) - require.Equal(t, "struct:A_NEW_TYPE", ctags[idx].Typeref) + require.Equal(t, "foo", tags[idx].FunctionName) + require.Equal(t, "variable", tags[idx].Kind) + require.Equal(t, "struct:A_NEW_TYPE", tags[idx].Typeref) idx++ - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "dostuff", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "dostuff", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) } func TestCTagsParserShouldDealWithMacros(t *testing.T) { @@ -205,36 +207,36 @@ func TestCTagsParserShouldDealWithMacros(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 8, len(ctags)) + require.Equal(t, 8, len(tags)) idx := 0 - require.Equal(t, "DEBUG", ctags[idx].FunctionName) - require.Equal(t, "macro", ctags[idx].Kind) + require.Equal(t, "DEBUG", tags[idx].FunctionName) + require.Equal(t, "macro", tags[idx].Kind) idx++ - require.Equal(t, "DISABLED", ctags[idx].FunctionName) - require.Equal(t, "macro", ctags[idx].Kind) + require.Equal(t, "DISABLED", tags[idx].FunctionName) + require.Equal(t, "macro", tags[idx].Kind) idx++ - require.Equal(t, "hello", ctags[idx].FunctionName) - require.Equal(t, "variable", ctags[idx].Kind) + require.Equal(t, "hello", tags[idx].FunctionName) + require.Equal(t, "variable", tags[idx].Kind) idx++ - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "debug", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "debug", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "disabledIsDefined", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "disabledIsDefined", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "useMyType", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "useMyType", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) } func TestCTagsParserShouldDealFunctionWithDifferentSignatures(t *testing.T) { @@ -245,21 +247,21 @@ func TestCTagsParserShouldDealFunctionWithDifferentSignatures(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 3, len(ctags)) + require.Equal(t, 3, len(tags)) idx := 0 - require.Equal(t, "getBytes", ctags[idx].FunctionName) - require.Equal(t, "prototype", ctags[idx].Kind) + require.Equal(t, "getBytes", tags[idx].FunctionName) + require.Equal(t, "prototype", tags[idx].Kind) idx++ - require.Equal(t, "getBytes", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "getBytes", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "getBytes", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "getBytes", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) } func TestCTagsParserClassMembersAreFilteredOut(t *testing.T) { @@ -270,30 +272,30 @@ func TestCTagsParserClassMembersAreFilteredOut(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 5, len(ctags)) + require.Equal(t, 5, len(tags)) idx := 0 - require.Equal(t, "set_values", ctags[idx].FunctionName) - require.Equal(t, "prototype", ctags[idx].Kind) - require.Equal(t, "Rectangle", ctags[idx].Class) + require.Equal(t, "set_values", tags[idx].FunctionName) + require.Equal(t, "prototype", tags[idx].Kind) + require.Equal(t, "Rectangle", tags[idx].Class) idx++ - require.Equal(t, "area", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "Rectangle", ctags[idx].Class) + require.Equal(t, "area", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "Rectangle", tags[idx].Class) idx++ - require.Equal(t, "set_values", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "Rectangle", ctags[idx].Class) + require.Equal(t, "set_values", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "Rectangle", tags[idx].Class) idx++ - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) } func TestCTagsParserStructWithFunctions(t *testing.T) { @@ -304,38 +306,38 @@ func TestCTagsParserStructWithFunctions(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 8, len(ctags)) + require.Equal(t, 8, len(tags)) idx := 0 - require.Equal(t, "sensorData", ctags[idx].FunctionName) - require.Equal(t, "struct", ctags[idx].Kind) + require.Equal(t, "sensorData", tags[idx].FunctionName) + require.Equal(t, "struct", tags[idx].Kind) idx++ - require.Equal(t, "sensorData", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "sensorData", ctags[idx].Struct) + require.Equal(t, "sensorData", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "sensorData", tags[idx].Struct) idx++ - require.Equal(t, "sensorData", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "sensorData", ctags[idx].Struct) + require.Equal(t, "sensorData", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "sensorData", tags[idx].Struct) idx++ - require.Equal(t, "sensors", ctags[idx].FunctionName) - require.Equal(t, "variable", ctags[idx].Kind) + require.Equal(t, "sensors", tags[idx].FunctionName) + require.Equal(t, "variable", tags[idx].Kind) idx++ - require.Equal(t, "sensor1", ctags[idx].FunctionName) - require.Equal(t, "variable", ctags[idx].Kind) + require.Equal(t, "sensor1", tags[idx].FunctionName) + require.Equal(t, "variable", tags[idx].Kind) idx++ - require.Equal(t, "sensor2", ctags[idx].FunctionName) - require.Equal(t, "variable", ctags[idx].Kind) + require.Equal(t, "sensor2", tags[idx].FunctionName) + require.Equal(t, "variable", tags[idx].Kind) idx++ - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) } func TestCTagsParserDefaultArguments(t *testing.T) { @@ -346,22 +348,22 @@ func TestCTagsParserDefaultArguments(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 3, len(ctags)) + require.Equal(t, 3, len(tags)) idx := 0 - require.Equal(t, "test", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "(int x = 1)", ctags[idx].Signature) + require.Equal(t, "test", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "void test(int x = 1);", tags[idx].Prototype) idx++ - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) } func TestCTagsParserNamespace(t *testing.T) { @@ -372,22 +374,22 @@ func TestCTagsParserNamespace(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 3, len(ctags)) + require.Equal(t, 3, len(tags)) idx := 0 - require.Equal(t, "value", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "Test", ctags[idx].Namespace) + require.Equal(t, "value", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "Test", tags[idx].Namespace) idx++ - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) } func TestCTagsParserStatic(t *testing.T) { @@ -398,21 +400,21 @@ func TestCTagsParserStatic(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 3, len(ctags)) + require.Equal(t, 3, len(tags)) idx := 0 - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "doStuff", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "doStuff", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) } func TestCTagsParserFunctionPointer(t *testing.T) { @@ -423,24 +425,24 @@ func TestCTagsParserFunctionPointer(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 4, len(ctags)) + require.Equal(t, 4, len(tags)) idx := 0 - require.Equal(t, "t1Callback", ctags[idx].FunctionName) - require.Equal(t, "variable", ctags[idx].Kind) + require.Equal(t, "t1Callback", tags[idx].FunctionName) + require.Equal(t, "variable", tags[idx].Kind) idx++ - require.Equal(t, "t1Callback", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "t1Callback", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) } func TestCTagsParserFunctionPointers(t *testing.T) { @@ -451,28 +453,27 @@ func TestCTagsParserFunctionPointers(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) - ctagsParser := builder.CTagsParser{} + ctagsParser := ctags.CTagsParser{} ctagsParser.Run(context) - ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) + tags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*types.CTag) - require.Equal(t, 5, len(ctags)) + require.Equal(t, 5, len(tags)) idx := 0 - require.Equal(t, "setup", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "setup", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "loop", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "loop", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "func", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) + require.Equal(t, "func", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) idx++ - require.Equal(t, "funcArr", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "()", ctags[idx].Signature) + require.Equal(t, "funcArr", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "int funcArr();", tags[idx].Prototype) idx++ - require.Equal(t, "funcCombo", ctags[idx].FunctionName) - require.Equal(t, "function", ctags[idx].Kind) - require.Equal(t, "(void (*(&in)[5])(int))", ctags[idx].Signature) - + require.Equal(t, "funcCombo", tags[idx].FunctionName) + require.Equal(t, "function", tags[idx].Kind) + require.Equal(t, "void funcCombo(void (*(&in)[5])(int));", tags[idx].Prototype) } diff --git a/src/arduino.cc/builder/test/ctags_runner_test.go b/src/arduino.cc/builder/test/ctags_runner_test.go index 9abab566..8cb77b9e 100644 --- a/src/arduino.cc/builder/test/ctags_runner_test.go +++ b/src/arduino.cc/builder/test/ctags_runner_test.go @@ -32,6 +32,7 @@ package test import ( "arduino.cc/builder" "arduino.cc/builder/constants" + "arduino.cc/builder/ctags" "arduino.cc/builder/types" "github.com/stretchr/testify/require" "os" @@ -70,7 +71,7 @@ func TestCTagsRunner(t *testing.T) { &builder.PrintUsedLibrariesIfVerbose{}, &builder.WarnAboutArchIncompatibleLibraries{}, &builder.CTagsTargetFileSaver{SourceField: constants.CTX_SOURCE, TargetFileName: constants.FILE_CTAGS_TARGET}, - &builder.CTagsRunner{}, + &ctags.CTagsRunner{}, } for _, command := range commands { @@ -120,7 +121,7 @@ func TestCTagsRunnerSketchWithClass(t *testing.T) { &builder.PrintUsedLibrariesIfVerbose{}, &builder.WarnAboutArchIncompatibleLibraries{}, &builder.CTagsTargetFileSaver{SourceField: constants.CTX_SOURCE, TargetFileName: constants.FILE_CTAGS_TARGET}, - &builder.CTagsRunner{}, + &ctags.CTagsRunner{}, } for _, command := range commands { @@ -168,7 +169,7 @@ func TestCTagsRunnerSketchWithTypename(t *testing.T) { &builder.PrintUsedLibrariesIfVerbose{}, &builder.WarnAboutArchIncompatibleLibraries{}, &builder.CTagsTargetFileSaver{SourceField: constants.CTX_SOURCE, TargetFileName: constants.FILE_CTAGS_TARGET}, - &builder.CTagsRunner{}, + &ctags.CTagsRunner{}, } for _, command := range commands { @@ -215,7 +216,7 @@ func TestCTagsRunnerSketchWithNamespace(t *testing.T) { &builder.PrintUsedLibrariesIfVerbose{}, &builder.WarnAboutArchIncompatibleLibraries{}, &builder.CTagsTargetFileSaver{SourceField: constants.CTX_SOURCE, TargetFileName: constants.FILE_CTAGS_TARGET}, - &builder.CTagsRunner{}, + &ctags.CTagsRunner{}, } for _, command := range commands { @@ -230,3 +231,50 @@ func TestCTagsRunnerSketchWithNamespace(t *testing.T) { require.Equal(t, expectedOutput, strings.Replace(context[constants.CTX_CTAGS_OUTPUT].(string), "\r\n", "\n", -1)) } + +func TestCTagsRunnerSketchWithTemplates(t *testing.T) { + DownloadCoresAndToolsAndLibraries(t) + + context := make(map[string]interface{}) + + buildPath := SetupBuildPath(t, context) + defer os.RemoveAll(buildPath) + + sketchLocation := Abs(t, filepath.Join("sketch_with_templates_and_shift", "template_and_shift.cpp")) + context[constants.CTX_HARDWARE_FOLDERS] = []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"} + context[constants.CTX_TOOLS_FOLDERS] = []string{"downloaded_tools"} + context[constants.CTX_FQBN] = "arduino:avr:leonardo" + context[constants.CTX_SKETCH_LOCATION] = sketchLocation + context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = "10600" + context[constants.CTX_BUILT_IN_LIBRARIES_FOLDERS] = []string{"downloaded_libraries"} + context[constants.CTX_OTHER_LIBRARIES_FOLDERS] = []string{"libraries"} + context[constants.CTX_VERBOSE] = true + + commands := []types.Command{ + &builder.SetupHumanLoggerIfMissing{}, + + &builder.ContainerSetupHardwareToolsLibsSketchAndProps{}, + + &builder.ContainerMergeCopySketchFiles{}, + + &builder.ContainerFindIncludes{}, + + &builder.PrintUsedLibrariesIfVerbose{}, + &builder.WarnAboutArchIncompatibleLibraries{}, + &builder.CTagsTargetFileSaver{SourceField: constants.CTX_SOURCE, TargetFileName: constants.FILE_CTAGS_TARGET}, + &ctags.CTagsRunner{}, + } + + for _, command := range commands { + err := command.Run(context) + NoError(t, err) + } + + sketchLocation = strings.Replace(sketchLocation, "\\", "\\\\", -1) + expectedOutput := "printGyro\t" + sketchLocation + "\t/^void printGyro()$/;\"\tkind:function\tline:10\tsignature:()\treturntype:void\n" + + "bVar\t" + sketchLocation + "\t/^c< 8 > bVar;$/;\"\tkind:variable\tline:15\n" + + "aVar\t" + sketchLocation + "\t/^c< 1<<8 > aVar;$/;\"\tkind:variable\tline:16\n" + + "func\t" + sketchLocation + "\t/^template func( c< 1< & aParam) {$/;\"\tkind:function\tline:18\tsignature:( c< 1< & aParam)\treturntype:template\n" + + require.Equal(t, expectedOutput, strings.Replace(context[constants.CTX_CTAGS_OUTPUT].(string), "\r\n", "\n", -1)) +} diff --git a/src/arduino.cc/builder/test/ctags_to_prototypes_test.go b/src/arduino.cc/builder/test/ctags_to_prototypes_test.go index c0a4ed6c..29597646 100644 --- a/src/arduino.cc/builder/test/ctags_to_prototypes_test.go +++ b/src/arduino.cc/builder/test/ctags_to_prototypes_test.go @@ -30,8 +30,8 @@ package test import ( - "arduino.cc/builder" "arduino.cc/builder/constants" + "arduino.cc/builder/ctags" "arduino.cc/builder/types" "github.com/stretchr/testify/require" "io/ioutil" @@ -48,9 +48,9 @@ func TestCTagsToPrototypesShouldListPrototypes(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -81,9 +81,9 @@ func TestCTagsToPrototypesShouldListTemplates(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -112,9 +112,9 @@ func TestCTagsToPrototypesShouldListTemplates2(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -144,9 +144,9 @@ func TestCTagsToPrototypesShouldDealWithClasses(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -171,9 +171,9 @@ func TestCTagsToPrototypesShouldDealWithStructs(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -202,9 +202,9 @@ func TestCTagsToPrototypesShouldDealWithMacros(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -235,9 +235,9 @@ func TestCTagsToPrototypesShouldDealFunctionWithDifferentSignatures(t *testing.T context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -264,9 +264,9 @@ func TestCTagsToPrototypesClassMembersAreFilteredOut(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -294,9 +294,9 @@ func TestCTagsToPrototypesStructWithFunctions(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -324,9 +324,9 @@ func TestCTagsToPrototypesDefaultArguments(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -336,10 +336,11 @@ func TestCTagsToPrototypesDefaultArguments(t *testing.T) { prototypes := context[constants.CTX_PROTOTYPES].([]*types.Prototype) - require.Equal(t, 2, len(prototypes)) - require.Equal(t, "void setup();", prototypes[0].Prototype) - require.Equal(t, "/tmp/test179252494/preproc/ctags_target.cpp", prototypes[0].File) - require.Equal(t, "void loop();", prototypes[1].Prototype) + require.Equal(t, 3, len(prototypes)) + require.Equal(t, "void test(int x = 1);", prototypes[0].Prototype) + require.Equal(t, "void setup();", prototypes[1].Prototype) + require.Equal(t, "/tmp/test179252494/preproc/ctags_target.cpp", prototypes[1].File) + require.Equal(t, "void loop();", prototypes[2].Prototype) prototypeLine := context[constants.CTX_LINE_WHERE_TO_INSERT_PROTOTYPES].(int) require.Equal(t, 2, prototypeLine) @@ -354,9 +355,9 @@ func TestCTagsToPrototypesNamespace(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -384,9 +385,9 @@ func TestCTagsToPrototypesStatic(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -416,9 +417,9 @@ func TestCTagsToPrototypesFunctionPointer(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { @@ -447,9 +448,9 @@ func TestCTagsToPrototypesFunctionPointers(t *testing.T) { context[constants.CTX_CTAGS_OUTPUT] = string(bytes) commands := []types.Command{ - &builder.CTagsParser{}, + &ctags.CTagsParser{}, &CopyContextKeys{From: constants.CTX_CTAGS_OF_PREPROC_SOURCE, To: constants.CTX_COLLECTED_CTAGS}, - &builder.CTagsToPrototypes{}, + &ctags.CTagsToPrototypes{}, } for _, command := range commands { diff --git a/src/arduino.cc/builder/test/downloaded_libraries/.gitignore b/src/arduino.cc/builder/test/downloaded_libraries/.gitignore index 537e8c18..72e8ffc0 100644 --- a/src/arduino.cc/builder/test/downloaded_libraries/.gitignore +++ b/src/arduino.cc/builder/test/downloaded_libraries/.gitignore @@ -1,6 +1 @@ -A* -B* -C* -H* -P* -R* \ No newline at end of file +* diff --git a/src/arduino.cc/builder/test/eol_processing/sketch.ino b/src/arduino.cc/builder/test/eol_processing/sketch.ino new file mode 100644 index 00000000..9037a7fa --- /dev/null +++ b/src/arduino.cc/builder/test/eol_processing/sketch.ino @@ -0,0 +1 @@ +int led = 7; void setup() { } void loop() { } \ No newline at end of file diff --git a/src/arduino.cc/builder/test/hardware_loader_test.go b/src/arduino.cc/builder/test/hardware_loader_test.go index e0fec6e3..df530172 100644 --- a/src/arduino.cc/builder/test/hardware_loader_test.go +++ b/src/arduino.cc/builder/test/hardware_loader_test.go @@ -147,7 +147,6 @@ func TestLoadHardwareMixingUserHardwareFolder(t *testing.T) { require.Equal(t, "\"{cmd.path}\" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives \"{source_file}\"", packages.Properties["tools.ctags.pattern"]) require.Equal(t, "{runtime.tools.avrdude.path}", packages.Properties["tools.avrdude.path"]) require.Equal(t, "-w -x c++ -E -CC", packages.Properties["preproc.macros.flags"]) - require.Equal(t, "{build.mbed_api_include} {build.nRF51822_api_include} {build.ble_api_include} {compiler.libsam.c.flags} {compiler.arm.cmsis.path} {build.variant_system_include}", packages.Properties["preproc.macros.compatibility_flags"]) if runtime.GOOS != "windows" { require.NotNil(t, packages.Packages["my_symlinked_avr_platform"]) diff --git a/src/arduino.cc/builder/test/helper_tools_downloader.go b/src/arduino.cc/builder/test/helper_tools_downloader.go index 04e18c54..b9a6bfa9 100644 --- a/src/arduino.cc/builder/test/helper_tools_downloader.go +++ b/src/arduino.cc/builder/test/helper_tools_downloader.go @@ -110,13 +110,15 @@ func DownloadCoresAndToolsAndLibraries(t *testing.T) { OsUrl{Os: "x86_64-pc-linux-gnu", Url: "http://downloads.arduino.cc/tools/coan-5.2-x86_64-pc-linux-gnu.tar.bz2"}, OsUrl{Os: "i686-mingw32", Url: "http://downloads.arduino.cc/tools/coan-5.2-i686-mingw32.zip"}, OsUrl{Os: "x86_64-apple-darwin", Url: "http://downloads.arduino.cc/tools/coan-5.2-x86_64-apple-darwin.zip"}, + OsUrl{Os: "arm-linux-gnueabihf", Url: "http://downloads.arduino.cc/tools/coan-5.2-arm-linux-gnueabihf.tar.bz2"}, }}, - Tool{Name: "ctags", Version: "5.8-arduino5", + Tool{Name: "ctags", Version: "5.8-arduino10", OsUrls: []OsUrl{ - OsUrl{Os: "i686-pc-linux-gnu", Url: "http://downloads.arduino.cc/tools/ctags-5.8-arduino5-i686-pc-linux-gnu.tar.bz2"}, - OsUrl{Os: "x86_64-pc-linux-gnu", Url: "http://downloads.arduino.cc/tools/ctags-5.8-arduino5-x86_64-pc-linux-gnu.tar.bz2"}, - OsUrl{Os: "i686-mingw32", Url: "http://downloads.arduino.cc/tools/ctags-5.8-arduino5-i686-mingw32.zip"}, - OsUrl{Os: "x86_64-apple-darwin", Url: "http://downloads.arduino.cc/tools/ctags-5.8-arduino5-x86_64-apple-darwin.zip"}, + OsUrl{Os: "i686-pc-linux-gnu", Url: "http://downloads.arduino.cc/tools/ctags-5.8-arduino10-i686-pc-linux-gnu.tar.bz2"}, + OsUrl{Os: "x86_64-pc-linux-gnu", Url: "http://downloads.arduino.cc/tools/ctags-5.8-arduino10-x86_64-pc-linux-gnu.tar.bz2"}, + OsUrl{Os: "i686-mingw32", Url: "http://downloads.arduino.cc/tools/ctags-5.8-arduino10-i686-mingw32.zip"}, + OsUrl{Os: "x86_64-apple-darwin", Url: "http://downloads.arduino.cc/tools/ctags-5.8-arduino10-x86_64-apple-darwin.zip"}, + OsUrl{Os: "arm-linux-gnueabihf", Url: "http://downloads.arduino.cc/tools/ctags-5.8-arduino10-armv6-linux-gnueabihf.tar.bz2"}, }}, } @@ -134,7 +136,9 @@ func DownloadCoresAndToolsAndLibraries(t *testing.T) { Library{Name: "Adafruit PN532", Version: "1.0.0"}, Library{Name: "Bridge", Version: "1.1.0"}, Library{Name: "CapacitiveSensor", Version: "0.5.0", VersionInLibProperties: "0.5"}, + Library{Name: "Ethernet", Version: "1.1.1"}, Library{Name: "Robot IR Remote", Version: "1.0.2"}, + Library{Name: "FastLED", Version: "3.1.0"}, } download(t, cores, boardsManagerCores, boardsManagerRedBearCores, tools, toolsMultipleVersions, boardsManagerTools, boardsManagerRFduinoTools, libraries) @@ -192,7 +196,7 @@ func download(t *testing.T, cores, boardsManagerCores, boardsManagerRedBearCores err = downloadBoardsManagerTools(boardsManagerTools, index) NoError(t, err) - rfduinoIndex, err := downloadIndex("http://www.rfduino.com/package_rfduino_index.json") + rfduinoIndex, err := downloadIndex("http://downloads.arduino.cc/packages/test_package_rfduino_index.json") NoError(t, err) err = downloadBoardsManagerTools(boardsManagerRFduinoTools, rfduinoIndex) @@ -699,6 +703,8 @@ func translateGOOSGOARCHToPackageIndexValue() []string { return []string{"i686-mingw32"} case "darwin-amd64": return []string{"i386-apple-darwin11", "x86_64-apple-darwin"} + case "linux-arm": + return []string{"arm-linux-gnueabihf"} default: panic("Unknown OS: " + value) } diff --git a/src/arduino.cc/builder/test/includes_finder_with_gcc_test.go b/src/arduino.cc/builder/test/includes_finder_with_gcc_test.go index 7f2c3e11..1fc613bd 100644 --- a/src/arduino.cc/builder/test/includes_finder_with_gcc_test.go +++ b/src/arduino.cc/builder/test/includes_finder_with_gcc_test.go @@ -209,7 +209,7 @@ func TestIncludesFinderWithGCCSketchWithThatChecksIfSPIHasTransactions(t *testin require.Equal(t, "SPI", importedLibraries[0].Name) } -func TestIncludesFinderWithGCCSketchWithThatChecksIfSPIHasTransactionsAndIncludesMissingEthernet(t *testing.T) { +func TestIncludesFinderWithGCCSketchWithThatChecksIfSPIHasTransactionsAndIncludesMissingLib(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) context := make(map[string]interface{}) @@ -247,7 +247,7 @@ func TestIncludesFinderWithGCCSketchWithThatChecksIfSPIHasTransactionsAndInclude includes := context[constants.CTX_INCLUDES].([]string) require.Equal(t, 2, len(includes)) sort.Strings(includes) - require.Equal(t, "Ethernet.h", includes[0]) + require.Equal(t, "Inexistent.h", includes[0]) require.Equal(t, "SPI.h", includes[1]) importedLibraries := context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library) diff --git a/src/arduino.cc/builder/test/libraries_loader_test.go b/src/arduino.cc/builder/test/libraries_loader_test.go index 71b7e04a..c0ab45bf 100644 --- a/src/arduino.cc/builder/test/libraries_loader_test.go +++ b/src/arduino.cc/builder/test/libraries_loader_test.go @@ -69,7 +69,7 @@ func TestLoadLibrariesAVR(t *testing.T) { require.Equal(t, Abs(t, filepath.Join("libraries")), librariesFolders[2]) libraries := context[constants.CTX_LIBRARIES].([]*types.Library) - require.Equal(t, 18, len(libraries)) + require.Equal(t, 20, len(libraries)) sort.Sort(ByLibraryName(libraries)) @@ -107,8 +107,12 @@ func TestLoadLibrariesAVR(t *testing.T) { idx++ require.Equal(t, "EEPROM", libraries[idx].Name) idx++ + require.Equal(t, "Ethernet", libraries[idx].Name) + idx++ require.Equal(t, "FakeAudio", libraries[idx].Name) idx++ + require.Equal(t, "FastLED", libraries[idx].Name) + idx++ require.Equal(t, "HID", libraries[idx].Name) idx++ require.Equal(t, "IRremote", libraries[idx].Name) @@ -175,7 +179,7 @@ func TestLoadLibrariesSAM(t *testing.T) { require.Equal(t, Abs(t, filepath.Join("libraries")), librariesFolders[2]) libraries := context[constants.CTX_LIBRARIES].([]*types.Library) - require.Equal(t, 16, len(libraries)) + require.Equal(t, 18, len(libraries)) sort.Sort(ByLibraryName(libraries)) @@ -192,8 +196,12 @@ func TestLoadLibrariesSAM(t *testing.T) { idx++ require.Equal(t, "CapacitiveSensor", libraries[idx].Name) idx++ + require.Equal(t, "Ethernet", libraries[idx].Name) + idx++ require.Equal(t, "FakeAudio", libraries[idx].Name) idx++ + require.Equal(t, "FastLED", libraries[idx].Name) + idx++ require.Equal(t, "HID", libraries[idx].Name) idx++ require.Equal(t, "IRremote", libraries[idx].Name) diff --git a/src/arduino.cc/builder/test/load_vid_pid_specific_properties_test.go b/src/arduino.cc/builder/test/load_vid_pid_specific_properties_test.go index fee5d60c..f4ef6ff5 100644 --- a/src/arduino.cc/builder/test/load_vid_pid_specific_properties_test.go +++ b/src/arduino.cc/builder/test/load_vid_pid_specific_properties_test.go @@ -32,6 +32,7 @@ package test import ( "arduino.cc/builder" "arduino.cc/builder/constants" + "arduino.cc/builder/props" "arduino.cc/builder/types" "github.com/stretchr/testify/require" "os" @@ -63,7 +64,7 @@ func TestLoadVIDPIDSpecificPropertiesWhenNoVIDPIDAreProvided(t *testing.T) { NoError(t, err) } - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) require.Equal(t, "0x0037", buildProperties["pid.0"]) require.Equal(t, "\"Genuino Micro\"", buildProperties["vid.4.build.usb_product"]) @@ -95,7 +96,7 @@ func TestLoadVIDPIDSpecificProperties(t *testing.T) { NoError(t, err) } - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) require.Equal(t, "0x0037", buildProperties["pid.0"]) require.Equal(t, "\"Genuino Micro\"", buildProperties["vid.4.build.usb_product"]) diff --git a/src/arduino.cc/builder/test/merge_sketch_with_bootloader_test.go b/src/arduino.cc/builder/test/merge_sketch_with_bootloader_test.go index 8bfd4913..727ab5c9 100644 --- a/src/arduino.cc/builder/test/merge_sketch_with_bootloader_test.go +++ b/src/arduino.cc/builder/test/merge_sketch_with_bootloader_test.go @@ -32,6 +32,7 @@ package test import ( "arduino.cc/builder" "arduino.cc/builder/constants" + "arduino.cc/builder/props" "arduino.cc/builder/types" "arduino.cc/builder/utils" "github.com/stretchr/testify/require" @@ -154,7 +155,7 @@ func TestMergeSketchWithBootloaderWhenNoBootloaderAvailable(t *testing.T) { NoError(t, err) } - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) delete(buildProperties, constants.BUILD_PROPERTIES_BOOTLOADER_NOBLINK) delete(buildProperties, constants.BUILD_PROPERTIES_BOOTLOADER_FILE) diff --git a/src/arduino.cc/builder/test/properties_test.go b/src/arduino.cc/builder/test/properties_test.go index b79d31eb..5e9842ff 100644 --- a/src/arduino.cc/builder/test/properties_test.go +++ b/src/arduino.cc/builder/test/properties_test.go @@ -48,7 +48,7 @@ func TestPropertiesBoardsTxt(t *testing.T) { require.Equal(t, "32256", properties["ethernet.upload.maximum_size"]) require.Equal(t, "{build.usb_flags}", properties["robotMotor.build.extra_flags"]) - ethernet := props.SubTree(properties, "ethernet") + ethernet := properties.SubTree("ethernet") require.Equal(t, "Arduino Ethernet", ethernet[constants.LIBRARY_NAME]) } @@ -73,47 +73,47 @@ func TestPropertiesTestTxt(t *testing.T) { } func TestExpandPropsInString(t *testing.T) { - aMap := make(map[string]string) + aMap := make(props.PropertiesMap) aMap["key1"] = "42" aMap["key2"] = "{key1}" str := "{key1} == {key2} == true" - str = props.ExpandPropsInString(aMap, str) + str = aMap.ExpandPropsInString(str) require.Equal(t, "42 == 42 == true", str) } func TestExpandPropsInString2(t *testing.T) { - aMap := make(map[string]string) + aMap := make(props.PropertiesMap) aMap["key2"] = "{key2}" aMap["key1"] = "42" str := "{key1} == {key2} == true" - str = props.ExpandPropsInString(aMap, str) + str = aMap.ExpandPropsInString(str) require.Equal(t, "42 == {key2} == true", str) } func TestDeleteUnexpandedPropsFromString(t *testing.T) { - aMap := make(map[string]string) + aMap := make(props.PropertiesMap) aMap["key1"] = "42" aMap["key2"] = "{key1}" str := "{key1} == {key2} == {key3} == true" - str = props.ExpandPropsInString(aMap, str) + str = aMap.ExpandPropsInString(str) str, err := props.DeleteUnexpandedPropsFromString(str) NoError(t, err) require.Equal(t, "42 == 42 == == true", str) } func TestDeleteUnexpandedPropsFromString2(t *testing.T) { - aMap := make(map[string]string) + aMap := make(props.PropertiesMap) aMap["key2"] = "42" str := "{key1} == {key2} == {key3} == true" - str = props.ExpandPropsInString(aMap, str) + str = aMap.ExpandPropsInString(str) str, err := props.DeleteUnexpandedPropsFromString(str) NoError(t, err) require.Equal(t, " == 42 == == true", str) @@ -129,7 +129,7 @@ func TestPropertiesRedBeearLabBoardsTxt(t *testing.T) { require.Equal(t, "arduino:arduino", properties["blend.build.core"]) require.Equal(t, "0x2404", properties["blendmicro16.pid.0"]) - ethernet := props.SubTree(properties, "blend") + ethernet := properties.SubTree("blend") require.Equal(t, "arduino:arduino", ethernet[constants.BUILD_PROPERTIES_BUILD_CORE]) } diff --git a/src/arduino.cc/builder/test/prototypes_adder_test.go b/src/arduino.cc/builder/test/prototypes_adder_test.go index 0be24def..6976b289 100644 --- a/src/arduino.cc/builder/test/prototypes_adder_test.go +++ b/src/arduino.cc/builder/test/prototypes_adder_test.go @@ -82,8 +82,8 @@ func TestPrototypesAdderBridgeExample(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) - require.Equal(t, "#line 33 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 46 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 62 \""+absoluteSketchLocation+"\"\nvoid process(BridgeClient client);\n#line 82 \""+absoluteSketchLocation+"\"\nvoid digitalCommand(BridgeClient client);\n#line 109 \""+absoluteSketchLocation+"\"\nvoid analogCommand(BridgeClient client);\n#line 149 \""+absoluteSketchLocation+"\"\nvoid modeCommand(BridgeClient client);\n#line 33\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) + require.Equal(t, "#line 33 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 46 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 62 \""+absoluteSketchLocation+"\"\nvoid process(BridgeClient client);\n#line 82 \""+absoluteSketchLocation+"\"\nvoid digitalCommand(BridgeClient client);\n#line 109 \""+absoluteSketchLocation+"\"\nvoid analogCommand(BridgeClient client);\n#line 149 \""+absoluteSketchLocation+"\"\nvoid modeCommand(BridgeClient client);\n#line 33 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) } func TestPrototypesAdderSketchWithIfDef(t *testing.T) { @@ -370,7 +370,12 @@ func TestPrototypesAdderSketchWithStruct(t *testing.T) { } preprocessed := LoadAndInterpolate(t, filepath.Join("sketch8", "SketchWithStruct.preprocessed.txt"), context) - require.Equal(t, preprocessed, strings.Replace(context[constants.CTX_SOURCE].(string), "\r\n", "\n", -1)) + obtained := strings.Replace(context[constants.CTX_SOURCE].(string), "\r\n", "\n", -1) + // ctags based preprocessing removes the space after "dostuff", but this is still OK + // TODO: remove this exception when moving to a more powerful parser + preprocessed = strings.Replace(preprocessed, "void dostuff (A_NEW_TYPE * bar);", "void dostuff(A_NEW_TYPE * bar);", 1) + obtained = strings.Replace(obtained, "void dostuff (A_NEW_TYPE * bar);", "void dostuff(A_NEW_TYPE * bar);", 1) + require.Equal(t, preprocessed, obtained) } func TestPrototypesAdderSketchWithConfig(t *testing.T) { @@ -413,8 +418,8 @@ func TestPrototypesAdderSketchWithConfig(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) - require.Equal(t, "#line 13 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 17 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 13\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) + require.Equal(t, "#line 13 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 17 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 13 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) preprocessed := LoadAndInterpolate(t, filepath.Join("sketch_with_config", "sketch_with_config.preprocessed.txt"), context) require.Equal(t, preprocessed, strings.Replace(context[constants.CTX_SOURCE].(string), "\r\n", "\n", -1)) @@ -428,6 +433,9 @@ func TestPrototypesAdderSketchNoFunctionsTwoFiles(t *testing.T) { buildPath := SetupBuildPath(t, context) defer os.RemoveAll(buildPath) + sketchLocation := filepath.Join("sketch_no_functions_two_files", "main.ino") + absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + context[constants.CTX_HARDWARE_FOLDERS] = []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"} context[constants.CTX_TOOLS_FOLDERS] = []string{"downloaded_tools"} context[constants.CTX_FQBN] = "arduino:avr:leonardo" @@ -457,7 +465,7 @@ func TestPrototypesAdderSketchNoFunctionsTwoFiles(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) require.Nil(t, context[constants.CTX_PROTOTYPE_SECTION]) } @@ -469,6 +477,9 @@ func TestPrototypesAdderSketchNoFunctions(t *testing.T) { buildPath := SetupBuildPath(t, context) defer os.RemoveAll(buildPath) + sketchLocation := filepath.Join("sketch_no_functions", "main.ino") + absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + context[constants.CTX_HARDWARE_FOLDERS] = []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"} context[constants.CTX_TOOLS_FOLDERS] = []string{"downloaded_tools"} context[constants.CTX_FQBN] = "arduino:avr:leonardo" @@ -498,7 +509,7 @@ func TestPrototypesAdderSketchNoFunctions(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) require.Nil(t, context[constants.CTX_PROTOTYPE_SECTION]) } @@ -542,8 +553,8 @@ func TestPrototypesAdderSketchWithDefaultArgs(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) - require.Equal(t, "#line 4 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 7 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 1\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) + require.Equal(t, "#line 4 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 7 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) } func TestPrototypesAdderSketchWithInlineFunction(t *testing.T) { @@ -586,8 +597,19 @@ func TestPrototypesAdderSketchWithInlineFunction(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) - require.Equal(t, "#line 1 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 2 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 4 \""+absoluteSketchLocation+"\"\nshort unsigned int testInt();\n#line 8 \""+absoluteSketchLocation+"\"\nstatic int8_t testInline();\n#line 12 \""+absoluteSketchLocation+"\"\nuint8_t testAttribute();\n#line 1\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) + + expected := "#line 1 \"" + absoluteSketchLocation + "\"\nvoid setup();\n#line 2 \"" + absoluteSketchLocation + "\"\nvoid loop();\n#line 4 \"" + absoluteSketchLocation + "\"\nshort unsigned int testInt();\n#line 8 \"" + absoluteSketchLocation + "\"\nstatic int8_t testInline();\n#line 12 \"" + absoluteSketchLocation + "\"\n__attribute__((always_inline)) uint8_t testAttribute();\n#line 1 \"" + absoluteSketchLocation + "\"\n" + obtained := context[constants.CTX_PROTOTYPE_SECTION].(string) + // ctags based preprocessing removes "inline" but this is still OK + // TODO: remove this exception when moving to a more powerful parser + expected = strings.Replace(expected, "static inline int8_t testInline();", "static int8_t testInline();", -1) + obtained = strings.Replace(obtained, "static inline int8_t testInline();", "static int8_t testInline();", -1) + // ctags based preprocessing removes "__attribute__ ....." but this is still OK + // TODO: remove this exception when moving to a more powerful parser + expected = strings.Replace(expected, "__attribute__((always_inline)) uint8_t testAttribute();", "uint8_t testAttribute();", -1) + obtained = strings.Replace(obtained, "__attribute__((always_inline)) uint8_t testAttribute();", "uint8_t testAttribute();", -1) + require.Equal(t, expected, obtained) } func TestPrototypesAdderSketchWithFunctionSignatureInsideIFDEF(t *testing.T) { @@ -630,8 +652,8 @@ func TestPrototypesAdderSketchWithFunctionSignatureInsideIFDEF(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) - require.Equal(t, "#line 1 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 3 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 15 \""+absoluteSketchLocation+"\"\nint8_t adalight();\n#line 1\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) + require.Equal(t, "#line 1 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 3 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 15 \""+absoluteSketchLocation+"\"\nint8_t adalight();\n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) } func TestPrototypesAdderSketchWithUSBCON(t *testing.T) { @@ -674,8 +696,8 @@ func TestPrototypesAdderSketchWithUSBCON(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) - require.Equal(t, "#line 5 \""+absoluteSketchLocation+"\"\nvoid ciao();\n#line 10 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 15 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 5\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) + require.Equal(t, "#line 5 \""+absoluteSketchLocation+"\"\nvoid ciao();\n#line 10 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 15 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 5 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) } func TestPrototypesAdderSketchWithTypename(t *testing.T) { @@ -717,8 +739,14 @@ func TestPrototypesAdderSketchWithTypename(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) - require.Equal(t, "#line 6 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 10 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 6\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) + expected := "#line 6 \"" + absoluteSketchLocation + "\"\nvoid setup();\n#line 10 \"" + absoluteSketchLocation + "\"\nvoid loop();\n#line 12 \"" + absoluteSketchLocation + "\"\ntypename Foo::Bar func();\n#line 6 \"" + absoluteSketchLocation + "\"\n" + obtained := context[constants.CTX_PROTOTYPE_SECTION].(string) + // ctags based preprocessing ignores line with typename + // TODO: remove this exception when moving to a more powerful parser + expected = strings.Replace(expected, "#line 12 \""+absoluteSketchLocation+"\"\ntypename Foo::Bar func();\n", "", -1) + obtained = strings.Replace(obtained, "#line 12 \""+absoluteSketchLocation+"\"\ntypename Foo::Bar func();\n", "", -1) + require.Equal(t, expected, obtained) } func TestPrototypesAdderSketchWithIfDef2(t *testing.T) { @@ -761,8 +789,8 @@ func TestPrototypesAdderSketchWithIfDef2(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) - require.Equal(t, "#line 5 \""+absoluteSketchLocation+"\"\nvoid elseBranch();\n#line 9 \""+absoluteSketchLocation+"\"\nvoid f1();\n#line 10 \""+absoluteSketchLocation+"\"\nvoid f2();\n#line 12 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 14 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 5\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) + require.Equal(t, "#line 5 \""+absoluteSketchLocation+"\"\nvoid elseBranch();\n#line 9 \""+absoluteSketchLocation+"\"\nvoid f1();\n#line 10 \""+absoluteSketchLocation+"\"\nvoid f2();\n#line 12 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 14 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 5 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) expectedSource := LoadAndInterpolate(t, filepath.Join("sketch_with_ifdef", "sketch.preprocessed.txt"), context) require.Equal(t, expectedSource, strings.Replace(context[constants.CTX_SOURCE].(string), "\r\n", "\n", -1)) @@ -808,8 +836,8 @@ func TestPrototypesAdderSketchWithIfDef2SAM(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) - require.Equal(t, "#line 2 \""+absoluteSketchLocation+"\"\nvoid ifBranch();\n#line 9 \""+absoluteSketchLocation+"\"\nvoid f1();\n#line 10 \""+absoluteSketchLocation+"\"\nvoid f2();\n#line 12 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 14 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 2\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) + require.Equal(t, "#line 2 \""+absoluteSketchLocation+"\"\nvoid ifBranch();\n#line 9 \""+absoluteSketchLocation+"\"\nvoid f1();\n#line 10 \""+absoluteSketchLocation+"\"\nvoid f2();\n#line 12 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 14 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 2 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) expectedSource := LoadAndInterpolate(t, filepath.Join("sketch_with_ifdef", "sketch.preprocessed.SAM.txt"), context) require.Equal(t, expectedSource, strings.Replace(context[constants.CTX_SOURCE].(string), "\r\n", "\n", -1)) @@ -855,6 +883,47 @@ func TestPrototypesAdderSketchWithConst(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1\n", context[constants.CTX_INCLUDE_SECTION].(string)) - require.Equal(t, "#line 1 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 2 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 4 \""+absoluteSketchLocation+"\"\nconst __FlashStringHelper* test();\n#line 6 \""+absoluteSketchLocation+"\"\nconst int test3();\n#line 8 \""+absoluteSketchLocation+"\"\nvolatile __FlashStringHelper* test2();\n#line 10 \""+absoluteSketchLocation+"\"\nvolatile int test4();\n#line 1\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) + require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_INCLUDE_SECTION].(string)) + require.Equal(t, "#line 1 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 2 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 4 \""+absoluteSketchLocation+"\"\nconst __FlashStringHelper* test();\n#line 6 \""+absoluteSketchLocation+"\"\nconst int test3();\n#line 8 \""+absoluteSketchLocation+"\"\nvolatile __FlashStringHelper* test2();\n#line 10 \""+absoluteSketchLocation+"\"\nvolatile int test4();\n#line 1 \""+absoluteSketchLocation+"\"\n", context[constants.CTX_PROTOTYPE_SECTION].(string)) +} + +func TestPrototypesAdderSketchWithDosEol(t *testing.T) { + DownloadCoresAndToolsAndLibraries(t) + + context := make(map[string]interface{}) + + buildPath := SetupBuildPath(t, context) + defer os.RemoveAll(buildPath) + + sketchLocation := filepath.Join("eol_processing", "sketch.ino") + + context[constants.CTX_HARDWARE_FOLDERS] = []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"} + context[constants.CTX_TOOLS_FOLDERS] = []string{"downloaded_tools"} + context[constants.CTX_FQBN] = "arduino:avr:uno" + context[constants.CTX_SKETCH_LOCATION] = sketchLocation + context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = "10600" + context[constants.CTX_BUILT_IN_LIBRARIES_FOLDERS] = []string{"downloaded_libraries"} + context[constants.CTX_OTHER_LIBRARIES_FOLDERS] = []string{"libraries"} + context[constants.CTX_VERBOSE] = true + + commands := []types.Command{ + &builder.SetupHumanLoggerIfMissing{}, + + &builder.ContainerSetupHardwareToolsLibsSketchAndProps{}, + + &builder.ContainerMergeCopySketchFiles{}, + + &builder.ContainerFindIncludes{}, + + &builder.PrintUsedLibrariesIfVerbose{}, + &builder.WarnAboutArchIncompatibleLibraries{}, + + &builder.ContainerAddPrototypes{}, + } + + for _, command := range commands { + err := command.Run(context) + NoError(t, err) + } + // only requires no error as result } diff --git a/src/arduino.cc/builder/test/recipe_runner_test.go b/src/arduino.cc/builder/test/recipe_runner_test.go index 9eca7957..d4d51f64 100644 --- a/src/arduino.cc/builder/test/recipe_runner_test.go +++ b/src/arduino.cc/builder/test/recipe_runner_test.go @@ -32,6 +32,7 @@ package test import ( "arduino.cc/builder" "arduino.cc/builder/constants" + "arduino.cc/builder/props" "arduino.cc/builder/types" "github.com/stretchr/testify/require" "testing" @@ -43,7 +44,7 @@ import ( // So this test is pretty useless func TestRecipeRunner(t *testing.T) { context := make(map[string]interface{}) - buildProperties := make(map[string]string) + buildProperties := make(props.PropertiesMap) context[constants.CTX_BUILD_PROPERTIES] = buildProperties buildProperties["recipe.hooks.prebuild.1.pattern"] = "echo" diff --git a/src/arduino.cc/builder/test/setup_build_properties_test.go b/src/arduino.cc/builder/test/setup_build_properties_test.go index d63f87ec..b933f8a1 100644 --- a/src/arduino.cc/builder/test/setup_build_properties_test.go +++ b/src/arduino.cc/builder/test/setup_build_properties_test.go @@ -70,7 +70,7 @@ func TestSetupBuildProperties(t *testing.T) { NoError(t, err) } - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) require.Equal(t, "ARDUINO", buildProperties[constants.BUILD_PROPERTIES_SOFTWARE]) @@ -134,7 +134,7 @@ func TestSetupBuildPropertiesWithSomeCustomOverrides(t *testing.T) { NoError(t, err) } - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) require.Equal(t, "ARDUINO", buildProperties[constants.BUILD_PROPERTIES_SOFTWARE]) @@ -173,7 +173,7 @@ func TestSetupBuildPropertiesUserHardware(t *testing.T) { NoError(t, err) } - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) require.Equal(t, "ARDUINO", buildProperties[constants.BUILD_PROPERTIES_SOFTWARE]) @@ -207,7 +207,7 @@ func TestSetupBuildPropertiesWithMissingPropsFromParentPlatformTxtFiles(t *testi NoError(t, err) } - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) require.Equal(t, "ARDUINO", buildProperties[constants.BUILD_PROPERTIES_SOFTWARE]) @@ -217,7 +217,7 @@ func TestSetupBuildPropertiesWithMissingPropsFromParentPlatformTxtFiles(t *testi require.Equal(t, "\"{compiler.path}{compiler.c.cmd}\" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {includes} \"{source_file}\" -o \"{object_file}\"", buildProperties["recipe.c.o.pattern"]) require.Equal(t, "{path}/etc/avrdude.conf", buildProperties["tools.avrdude.config.path"]) - coanProps := props.SubTree(props.SubTree(buildProperties, constants.BUILD_PROPERTIES_TOOLS_KEY), constants.COAN) + coanProps := buildProperties.SubTree(constants.BUILD_PROPERTIES_TOOLS_KEY).SubTree(constants.COAN) require.Equal(t, "{path}/coan", coanProps["cmd.path"]) require.Equal(t, "\"{cmd.path}\" source -m -E -P -kb {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} \"{source_file}\"", coanProps[constants.BUILD_PROPERTIES_PATTERN]) diff --git a/src/arduino.cc/builder/test/sketch1/merged_sketch.txt b/src/arduino.cc/builder/test/sketch1/merged_sketch.txt index 362cfc82..38af5a38 100644 --- a/src/arduino.cc/builder/test/sketch1/merged_sketch.txt +++ b/src/arduino.cc/builder/test/sketch1/merged_sketch.txt @@ -1,5 +1,5 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void setup() { diff --git a/src/arduino.cc/builder/test/sketch10/sketch.ino b/src/arduino.cc/builder/test/sketch10/sketch.ino index e8935804..28c88524 100644 --- a/src/arduino.cc/builder/test/sketch10/sketch.ino +++ b/src/arduino.cc/builder/test/sketch10/sketch.ino @@ -2,4 +2,4 @@ #include void setup() {} -void main() {} +void loop() {} diff --git a/src/arduino.cc/builder/test/sketch11/sketch_fastleds.ino b/src/arduino.cc/builder/test/sketch11/sketch_fastleds.ino new file mode 100644 index 00000000..eba4f526 --- /dev/null +++ b/src/arduino.cc/builder/test/sketch11/sketch_fastleds.ino @@ -0,0 +1,27 @@ +#include "FastLED.h" + +#define DATA_PIN 7 +#define CLK_PIN 6 +#define LED_TYPE APA102 +#define COLOR_ORDER GRB +#define NUM_LEDS 79 +CRGB leds[NUM_LEDS]; + +#define BRIGHTNESS 96 +#define FRAMES_PER_SECOND 120 +void setup() { + + FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); +} + +void loop() { + +} + +typedef void (*SimplePatternList[])(); +//SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm }; +SimplePatternList gPatterns = {sinelon}; + +void sinelon() +{ +} \ No newline at end of file diff --git a/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.ino b/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.ino index 655c62ca..ddd7f3d4 100644 --- a/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.ino +++ b/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.ino @@ -1,7 +1,7 @@ #define DEBUG 1 #define DISABLED 0 -typedef MyType int; +typedef int MyType; #if DISABLED #include @@ -47,4 +47,4 @@ void disabledIsDefined() { int useMyType(MyType type) { -} \ No newline at end of file +} diff --git a/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.preprocessed.txt b/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.preprocessed.txt index cd473ce8..4c7c7545 100644 --- a/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.preprocessed.txt @@ -1,10 +1,10 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #define DEBUG 1 #define DISABLED 0 -typedef MyType int; +typedef int MyType; #if DISABLED #include @@ -26,7 +26,7 @@ void debug(); void disabledIsDefined(); #line 48 "{{EscapeBackSlashes .sketch.MainFile.Name}}" int useMyType(MyType type); -#line 16 +#line 16 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void setup() { // put your setup code here, to run once: @@ -62,3 +62,4 @@ void disabledIsDefined() { int useMyType(MyType type) { } + diff --git a/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt b/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt index 75f8b730..1f7492ad 100644 --- a/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt +++ b/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt @@ -1,10 +1,10 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #define DEBUG 1 #define DISABLED 0 -typedef MyType int; +typedef int MyType; @@ -52,3 +52,4 @@ int useMyType(MyType type) { } + diff --git a/src/arduino.cc/builder/test/sketch3/Baladuino.preprocessed.txt b/src/arduino.cc/builder/test/sketch3/Baladuino.preprocessed.txt index e11411d8..fd7fd313 100644 --- a/src/arduino.cc/builder/test/sketch3/Baladuino.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch3/Baladuino.preprocessed.txt @@ -1,5 +1,5 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" /* * The code is released under the GNU General Public License. @@ -92,7 +92,7 @@ WII Wii(&Btd); // The Wii library can communicate with Wiimotes and the Nunchuck void setup(); #line 204 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void loop(); -#line 88 +#line 88 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void setup() { /* Initialize UART */ Serial.begin(115200); diff --git a/src/arduino.cc/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt b/src/arduino.cc/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt index caa42958..b7cfb728 100644 --- a/src/arduino.cc/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt @@ -1,5 +1,5 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #include // required to send and receive AT commands from the GPRS Shield #include // required for I2C communication with the RTC @@ -81,7 +81,7 @@ void printTime(); void setup(); #line 334 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void loop(); -#line 39 +#line 39 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void setPowerStateTo( int newState ) { if( newState != 1 && newState != 0 ) { // tests for an invalid state. In this case no change is made to powerstate diff --git a/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.ino b/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.ino index bc8e6c34..65909275 100644 --- a/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.ino +++ b/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.ino @@ -9,7 +9,7 @@ void setup() } void loop() { - long total1 = cs_13_8.read(30); + long total1 = cs_13_8.capacitiveSensor(30); Serial.println(total1); delay(100); -} \ No newline at end of file +} diff --git a/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt b/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt index 8dcc3599..b29c05e7 100644 --- a/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt @@ -1,5 +1,5 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #include /* @@ -10,14 +10,15 @@ CapacitiveSensor cs_13_8 = CapacitiveSensor(13,8); void setup(); #line 10 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void loop(); -#line 6 +#line 6 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void setup() { Serial.begin(9600); } void loop() { - long total1 = cs_13_8.read(30); + long total1 = cs_13_8.capacitiveSensor(30); Serial.println(total1); delay(100); } + diff --git a/src/arduino.cc/builder/test/sketch6/LineContinuations.preprocessed.txt b/src/arduino.cc/builder/test/sketch6/LineContinuations.preprocessed.txt index 5742adcc..567d373c 100644 --- a/src/arduino.cc/builder/test/sketch6/LineContinuations.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch6/LineContinuations.preprocessed.txt @@ -1,5 +1,5 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" const char *foo = "\ hello \ @@ -11,7 +11,7 @@ world\n"; void setup(); #line 11 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void loop(); -#line 7 +#line 7 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void setup() { } diff --git a/src/arduino.cc/builder/test/sketch7/StringWithComment.preprocessed.txt b/src/arduino.cc/builder/test/sketch7/StringWithComment.preprocessed.txt index 9e6f2bcf..9700f3e2 100644 --- a/src/arduino.cc/builder/test/sketch7/StringWithComment.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch7/StringWithComment.preprocessed.txt @@ -1,11 +1,11 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void setup(); #line 10 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void loop(); -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void setup() { // put your setup code here, to run once: // "comment with a double quote diff --git a/src/arduino.cc/builder/test/sketch8/SketchWithStruct.preprocessed.txt b/src/arduino.cc/builder/test/sketch8/SketchWithStruct.preprocessed.txt index 8808f91e..cdfcd34e 100644 --- a/src/arduino.cc/builder/test/sketch8/SketchWithStruct.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch8/SketchWithStruct.preprocessed.txt @@ -1,5 +1,5 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" /* START CODE */ @@ -14,8 +14,8 @@ void setup(); #line 13 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void loop(); #line 17 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -void dostuff(A_NEW_TYPE * bar); -#line 9 +void dostuff (A_NEW_TYPE * bar); +#line 9 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void setup() { } diff --git a/src/arduino.cc/builder/test/sketch_that_checks_if_SPI_has_transactions_and_includes_missing_Ethernet/sketch.ino b/src/arduino.cc/builder/test/sketch_that_checks_if_SPI_has_transactions_and_includes_missing_Ethernet/sketch.ino index 1a2f81c1..68092faa 100644 --- a/src/arduino.cc/builder/test/sketch_that_checks_if_SPI_has_transactions_and_includes_missing_Ethernet/sketch.ino +++ b/src/arduino.cc/builder/test/sketch_that_checks_if_SPI_has_transactions_and_includes_missing_Ethernet/sketch.ino @@ -1,5 +1,5 @@ #include -#include +#include #if !defined(SPI_HAS_TRANSACTION) || !SPI_HAS_TRANSACTION #error "Where is my SPI_HAS_TRANSACTION!?!?" diff --git a/src/arduino.cc/builder/test/sketch_that_includes_arduino_h/sketch_that_includes_arduino_h.ino b/src/arduino.cc/builder/test/sketch_that_includes_arduino_h/sketch_that_includes_arduino_h.ino new file mode 100644 index 00000000..515d9fe5 --- /dev/null +++ b/src/arduino.cc/builder/test/sketch_that_includes_arduino_h/sketch_that_includes_arduino_h.ino @@ -0,0 +1,14 @@ +// Arduino.h should not be automatically included by the Arduino +// preprocessor before the explicit include line in this sketch. + +#if defined(HIGH) +#error Arduino.h seems to be automatically included +#endif + + # include + +void setup() { +} + +void loop() { +} diff --git a/src/arduino.cc/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt b/src/arduino.cc/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt index f706e579..89ddbf6f 100644 --- a/src/arduino.cc/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt @@ -1,5 +1,5 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #include "config.h" @@ -17,7 +17,7 @@ void setup(); #line 17 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void loop(); -#line 13 +#line 13 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void setup() { } diff --git a/src/arduino.cc/builder/test/sketch_with_enum_class/sketch_with_enum_class.ino b/src/arduino.cc/builder/test/sketch_with_enum_class/sketch_with_enum_class.ino new file mode 100644 index 00000000..54c3dfbb --- /dev/null +++ b/src/arduino.cc/builder/test/sketch_with_enum_class/sketch_with_enum_class.ino @@ -0,0 +1,19 @@ +void test() { + test2(); +} + +enum class MyEnum +{ + AValue = 0, + AnotherValue = 1 +}; + +void test2() { +} + +void setup() { +} + +void loop() { +} + diff --git a/src/arduino.cc/builder/test/sketch_with_externC/sketch_with_externC.ino b/src/arduino.cc/builder/test/sketch_with_externC/sketch_with_externC.ino new file mode 100644 index 00000000..8e6c53ea --- /dev/null +++ b/src/arduino.cc/builder/test/sketch_with_externC/sketch_with_externC.ino @@ -0,0 +1,11 @@ +void setup() { + // put your setup code here, to run once: + test(); +} + +void loop() { + // put your main code here, to run repeatedly: + +} + +extern "C" void test() {} \ No newline at end of file diff --git a/src/arduino.cc/builder/test/sketch_with_function_pointer/CallbackBug.h b/src/arduino.cc/builder/test/sketch_with_function_pointer/CallbackBug.h new file mode 100644 index 00000000..cc8ee18b --- /dev/null +++ b/src/arduino.cc/builder/test/sketch_with_function_pointer/CallbackBug.h @@ -0,0 +1,5 @@ +class Task { + public: + Task(void (*aCallback)()) {}; +}; + diff --git a/src/arduino.cc/builder/test/sketch_with_function_pointer/sketch.ino b/src/arduino.cc/builder/test/sketch_with_function_pointer/sketch.ino index a758f4e2..aa50e6e0 100644 --- a/src/arduino.cc/builder/test/sketch_with_function_pointer/sketch.ino +++ b/src/arduino.cc/builder/test/sketch_with_function_pointer/sketch.ino @@ -1,4 +1,5 @@ +#include "CallbackBug.h" Task t1(&t1Callback); void t1Callback() {} void setup() {} -void loop() {} \ No newline at end of file +void loop() {} diff --git a/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt b/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt index c483fd33..ae868905 100644 --- a/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt +++ b/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt @@ -1,5 +1,5 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #if __SAM3X8E__ #line 2 "{{EscapeBackSlashes .sketch.MainFile.Name}}" @@ -12,7 +12,7 @@ void f2(); void setup(); #line 14 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void loop(); -#line 2 +#line 2 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void ifBranch() { } #else diff --git a/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.txt b/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.txt index 9482b870..88778cd2 100644 --- a/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.txt @@ -1,5 +1,5 @@ #include -#line 1 +#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" #if __SAM3X8E__ void ifBranch() { @@ -15,7 +15,7 @@ void f2(); void setup(); #line 14 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void loop(); -#line 5 +#line 5 "{{EscapeBackSlashes .sketch.MainFile.Name}}" void elseBranch() { } #endif diff --git a/src/arduino.cc/builder/test/sketch_with_multiline_prototypes/sketch_with_multiline_prototypes.ino b/src/arduino.cc/builder/test/sketch_with_multiline_prototypes/sketch_with_multiline_prototypes.ino new file mode 100644 index 00000000..a4fdf58a --- /dev/null +++ b/src/arduino.cc/builder/test/sketch_with_multiline_prototypes/sketch_with_multiline_prototypes.ino @@ -0,0 +1,9 @@ +void setup() { myctagstestfunc(1,2,3,4); } + +void myctagstestfunc(int a, +int b, +int c, +int d) { } + +void loop() {} + diff --git a/src/arduino.cc/builder/test/sketch_with_static_asserts/sketch_with_static_asserts.ino b/src/arduino.cc/builder/test/sketch_with_static_asserts/sketch_with_static_asserts.ino new file mode 100644 index 00000000..4b5500dd --- /dev/null +++ b/src/arduino.cc/builder/test/sketch_with_static_asserts/sketch_with_static_asserts.ino @@ -0,0 +1,16 @@ +// https://github.com/arduino/arduino-builder/issues/68 + +const int a = 10; +const int b = 20; + +static_assert(a < b, "bar"); + +void setup() { + test(); +} + +void loop() { +} + +void test() { +} diff --git a/src/arduino.cc/builder/test/sketch_with_templates_and_shift/template_and_shift.cpp b/src/arduino.cc/builder/test/sketch_with_templates_and_shift/template_and_shift.cpp new file mode 100644 index 00000000..f4f1ece8 --- /dev/null +++ b/src/arduino.cc/builder/test/sketch_with_templates_and_shift/template_and_shift.cpp @@ -0,0 +1,19 @@ +template<> class FastPin<0> : public _ARMPIN<0, 10, 1 << 10, 0> {};; + +template<> class FastPin<0> : public _ARMPIN<0, 10, 1 < 10, 0> {};; + +template class OtherType> class NestedTemplateClass +{ + OtherType f; +}; + +void printGyro() +{ +} + +template class c {}; +c< 8 > bVar; +c< 1<<8 > aVar; + +template func( c< 1< & aParam) { +} diff --git a/src/arduino.cc/builder/test/try_build_of_problematic_sketch_test.go b/src/arduino.cc/builder/test/try_build_of_problematic_sketch_test.go new file mode 100644 index 00000000..37bfb131 --- /dev/null +++ b/src/arduino.cc/builder/test/try_build_of_problematic_sketch_test.go @@ -0,0 +1,245 @@ +/* + * This file is part of Arduino Builder. + * + * Arduino Builder is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + * + * Copyright 2015 Arduino LLC (http://www.arduino.cc/) + * Copyright 2015 Matthijs Kooijman + */ + +package test + +import ( + "arduino.cc/builder" + "arduino.cc/builder/constants" + "os" + "path/filepath" + "testing" +) + +func TestTryBuild001(t *testing.T) { + tryBuild(t, "sketch_with_inline_function", "sketch.ino") +} + +func TestTryBuild002(t *testing.T) { + tryBuild(t, "sketch_with_function_signature_inside_ifdef", "sketch.ino") +} + +func TestTryBuild003(t *testing.T) { + tryPreprocess(t, "sketch_no_functions", "main.ino") +} + +func TestTryBuild004(t *testing.T) { + tryBuild(t, "sketch_with_const", "sketch.ino") +} + +func TestTryBuild005(t *testing.T) { + tryBuild(t, "sketch_with_old_lib", "sketch.ino") +} + +func TestTryBuild006(t *testing.T) { + tryBuild(t, "sketch_with_macosx_garbage", "sketch.ino") +} + +func TestTryBuild007(t *testing.T) { + tryBuild(t, "sketch_with_config", "sketch_with_config.ino") +} + +// XXX: Failing sketch, typename not supported +//func TestTryBuild008(t *testing.T) { +// tryBuild(t, "sketch_with_typename", "sketch.ino") +//} + +func TestTryBuild009(t *testing.T) { + tryBuild(t, "sketch_with_usbcon", "sketch.ino") +} + +func TestTryBuild010(t *testing.T) { + tryBuild(t, "sketch_with_namespace", "sketch.ino") +} + +func TestTryBuild011(t *testing.T) { + tryBuild(t, "sketch_with_inline_function", "sketch.ino") +} + +func TestTryBuild012(t *testing.T) { + tryBuild(t, "sketch_with_default_args", "sketch.ino") +} + +func TestTryBuild013(t *testing.T) { + tryBuild(t, "sketch_with_class", "sketch.ino") +} + +func TestTryBuild014(t *testing.T) { + tryBuild(t, "sketch_with_backup_files", "sketch.ino") +} + +func TestTryBuild015(t *testing.T) { + tryBuild(t, "sketch_with_subfolders") +} + +// This is a sketch that fails to build on purpose +//func TestTryBuild016(t *testing.T) { +// tryBuild(t, "sketch_that_checks_if_SPI_has_transactions_and_includes_missing_Ethernet", "sketch.ino") +//} + +func TestTryBuild017(t *testing.T) { + tryPreprocess(t, "sketch_no_functions_two_files", "main.ino") +} + +func TestTryBuild018(t *testing.T) { + tryBuild(t, "sketch_that_checks_if_SPI_has_transactions", "sketch.ino") +} + +func TestTryBuild019(t *testing.T) { + tryBuild(t, "sketch_with_ifdef", "sketch.ino") +} + +func TestTryBuild020(t *testing.T) { + context := makeDefaultContext(t) + context[constants.CTX_OTHER_LIBRARIES_FOLDERS] = []string{"dependent_libraries", "libraries"} + tryPreprocessWithContext(t, context, "sketch_with_dependend_libraries", "sketch.ino") +} + +func TestTryBuild021(t *testing.T) { + tryBuild(t, "sketch_with_function_pointer", "sketch.ino") +} + +func TestTryBuild022(t *testing.T) { + context := makeDefaultContext(t) + context[constants.CTX_FQBN] = "arduino:samd:arduino_zero_native" + tryBuildWithContext(t, context, "sketch_usbhost", "sketch_usbhost.ino") +} + +func TestTryBuild023(t *testing.T) { + tryBuild(t, "sketch1", "sketch.ino") +} + +func TestTryBuild024(t *testing.T) { + tryBuild(t, "sketch2", "SketchWithIfDef.ino") +} + +// The library for this sketch is missing +//func TestTryBuild025(t *testing.T) { +// tryBuild(t, "sketch3", "Baladuino.ino") +//} + +func TestTryBuild026(t *testing.T) { + tryBuild(t, "sketch4", "CharWithEscapedDoubleQuote.ino") +} + +func TestTryBuild027(t *testing.T) { + tryBuild(t, "sketch5", "IncludeBetweenMultilineComment.ino") +} + +func TestTryBuild028(t *testing.T) { + tryBuild(t, "sketch6", "LineContinuations.ino") +} + +func TestTryBuild029(t *testing.T) { + tryBuild(t, "sketch7", "StringWithComment.ino") +} + +func TestTryBuild030(t *testing.T) { + tryBuild(t, "sketch8", "SketchWithStruct.ino") +} + +func TestTryBuild031(t *testing.T) { + tryBuild(t, "sketch9", "sketch.ino") +} + +func TestTryBuild032(t *testing.T) { + tryBuild(t, "sketch10", "sketch.ino") +} + +func TestTryBuild033(t *testing.T) { + tryBuild(t, "sketch_that_includes_arduino_h", "sketch_that_includes_arduino_h.ino") +} + +func TestTryBuild034(t *testing.T) { + tryBuild(t, "sketch_with_static_asserts", "sketch_with_static_asserts.ino") +} + +func TestTryBuild035(t *testing.T) { + tryBuild(t, "sketch_with_enum_class", "sketch_with_enum_class.ino") +} + +func TestTryBuild036(t *testing.T) { + context := makeDefaultContext(t) + context[constants.CTX_FQBN] = "arduino:samd:arduino_zero_native" + tryBuildWithContext(t, context, "sketch11", "sketch_fastleds.ino") +} + +func TestTryBuild037(t *testing.T) { + tryBuild(t, "sketch_with_externC", "sketch_with_externC.ino") +} + +func TestTryBuild038(t *testing.T) { + tryBuild(t, "sketch_with_multiline_prototypes", "sketch_with_multiline_prototypes.ino") +} + +func makeDefaultContext(t *testing.T) map[string]interface{} { + DownloadCoresAndToolsAndLibraries(t) + + context := make(map[string]interface{}) + buildPath := SetupBuildPath(t, context) + defer os.RemoveAll(buildPath) + + context[constants.CTX_HARDWARE_FOLDERS] = []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware", "downloaded_board_manager_stuff"} + context[constants.CTX_TOOLS_FOLDERS] = []string{"downloaded_tools", "downloaded_board_manager_stuff"} + context[constants.CTX_BUILT_IN_LIBRARIES_FOLDERS] = []string{"downloaded_libraries"} + context[constants.CTX_FQBN] = "arduino:avr:leonardo" + context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = "10607" + context[constants.CTX_OTHER_LIBRARIES_FOLDERS] = []string{"libraries"} + context[constants.CTX_VERBOSE] = true + context[constants.CTX_DEBUG_PREPROCESSOR] = true + + return context +} + +func tryBuild(t *testing.T, sketchPath ...string) { + context := makeDefaultContext(t) + tryBuildWithContext(t, context, sketchPath...) +} + +func tryBuildWithContext(t *testing.T, context map[string]interface{}, sketchPath ...string) { + sketchLocation := filepath.Join(sketchPath...) + context[constants.CTX_SKETCH_LOCATION] = sketchLocation + + err := builder.RunBuilder(context) + NoError(t, err, "Build error for "+sketchLocation) +} + +func tryPreprocess(t *testing.T, sketchPath ...string) { + context := makeDefaultContext(t) + tryPreprocessWithContext(t, context, sketchPath...) +} + +func tryPreprocessWithContext(t *testing.T, context map[string]interface{}, sketchPath ...string) { + sketchLocation := filepath.Join(sketchPath...) + context[constants.CTX_SKETCH_LOCATION] = sketchLocation + + err := builder.RunPreprocess(context) + NoError(t, err, "Build error for "+sketchLocation) +} diff --git a/src/arduino.cc/builder/types/types.go b/src/arduino.cc/builder/types/types.go index 57da8897..2eebaf8e 100644 --- a/src/arduino.cc/builder/types/types.go +++ b/src/arduino.cc/builder/types/types.go @@ -31,6 +31,8 @@ package types import ( "arduino.cc/builder/constants" + "arduino.cc/builder/props" + "path/filepath" "strconv" ) @@ -60,13 +62,13 @@ type Sketch struct { } type Packages struct { - Properties map[string]string + Properties props.PropertiesMap Packages map[string]*Package } type Package struct { PackageId string - Properties map[string]string + Properties props.PropertiesMap Platforms map[string]*Platform } @@ -75,13 +77,13 @@ type Platform struct { Folder string DefaultBoard *Board Boards map[string]*Board - Properties map[string]string - Programmers map[string]map[string]string + Properties props.PropertiesMap + Programmers map[string]props.PropertiesMap } type Board struct { BoardId string - Properties map[string]string + Properties props.PropertiesMap } type Tool struct { @@ -180,8 +182,6 @@ type CTag struct { FunctionName string Kind string Line int - Signature string - Returntype string Code string Class string Struct string @@ -194,3 +194,14 @@ type CTag struct { Function string PrototypeModifiers string } + +func LibraryToSourceFolder(library *Library) []SourceFolder { + sourceFolders := []SourceFolder{} + recurse := library.Layout == LIBRARY_RECURSIVE + sourceFolders = append(sourceFolders, SourceFolder{Folder: library.SrcFolder, Recurse: recurse}) + if library.Layout == LIBRARY_FLAT { + utility := filepath.Join(library.SrcFolder, constants.LIBRARY_FOLDER_UTILITY) + sourceFolders = append(sourceFolders, SourceFolder{Folder: utility, Recurse: false}) + } + return sourceFolders +} diff --git a/src/arduino.cc/builder/utils/utils.go b/src/arduino.cc/builder/utils/utils.go index 100598d3..068d212c 100644 --- a/src/arduino.cc/builder/utils/utils.go +++ b/src/arduino.cc/builder/utils/utils.go @@ -33,7 +33,6 @@ import ( "arduino.cc/builder/constants" "arduino.cc/builder/gohasissues" "arduino.cc/builder/i18n" - "arduino.cc/builder/types" "crypto/md5" "encoding/hex" "github.com/go-errors/errors" @@ -70,15 +69,6 @@ func KeysOfMapOfStringBool(input map[string]bool) []string { return keys } -func MergeMapsOfStrings(target map[string]string, sources ...map[string]string) map[string]string { - for _, source := range sources { - for key, value := range source { - target[key] = value - } - } - return target -} - func MergeMapsOfStringBool(target map[string]bool, sources ...map[string]bool) map[string]bool { for _, source := range sources { for key, value := range source { @@ -88,15 +78,6 @@ func MergeMapsOfStringBool(target map[string]bool, sources ...map[string]bool) m return target } -func MergeMapsOfMapsOfStrings(target map[string]map[string]string, sources ...map[string]map[string]string) map[string]map[string]string { - for _, source := range sources { - for key, value := range source { - target[key] = value - } - } - return target -} - func PrettyOSName() string { switch osName := runtime.GOOS; osName { case "darwin": @@ -327,14 +308,6 @@ func SliceToMapStringBool(keys []string, value bool) map[string]bool { return aMap } -func GetMapStringStringOrDefault(aMap map[string]interface{}, key string) map[string]string { - if MapHas(aMap, key) { - return aMap[key].(map[string]string) - } - - return make(map[string]string) -} - func AbsolutizePaths(files []string) ([]string, error) { for idx, file := range files { absFile, err := filepath.Abs(file) @@ -419,17 +392,6 @@ func AppendIfNotPresent(target []string, elements ...string) []string { return target } -func LibraryToSourceFolder(library *types.Library) []types.SourceFolder { - sourceFolders := []types.SourceFolder{} - recurse := library.Layout == types.LIBRARY_RECURSIVE - sourceFolders = append(sourceFolders, types.SourceFolder{Folder: library.SrcFolder, Recurse: recurse}) - if library.Layout == types.LIBRARY_FLAT { - utility := filepath.Join(library.SrcFolder, constants.LIBRARY_FOLDER_UTILITY) - sourceFolders = append(sourceFolders, types.SourceFolder{Folder: utility, Recurse: false}) - } - return sourceFolders -} - func AddStringsToStringsSet(accumulator []string, stringsToAdd []string) []string { previousStringsSet := SliceToMapStringBool(accumulator, true) stringsSetToAdd := SliceToMapStringBool(stringsToAdd, true) diff --git a/src/arduino.cc/builder/warn_about_arch_incompatible_libraries.go b/src/arduino.cc/builder/warn_about_arch_incompatible_libraries.go index 4cad2db7..8ca59447 100644 --- a/src/arduino.cc/builder/warn_about_arch_incompatible_libraries.go +++ b/src/arduino.cc/builder/warn_about_arch_incompatible_libraries.go @@ -32,6 +32,7 @@ package builder import ( "arduino.cc/builder/constants" "arduino.cc/builder/i18n" + "arduino.cc/builder/props" "arduino.cc/builder/types" "arduino.cc/builder/utils" "os" @@ -46,7 +47,7 @@ func (s *WarnAboutArchIncompatibleLibraries) Run(context map[string]interface{}) } targetPlatform := context[constants.CTX_TARGET_PLATFORM].(*types.Platform) - buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) + buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) logger := context[constants.CTX_LOGGER].(i18n.Logger) archs := []string{} diff --git a/src/arduino.cc/builder/wipeout_build_path_if_build_options_changed.go b/src/arduino.cc/builder/wipeout_build_path_if_build_options_changed.go index 71a30e01..a974164e 100644 --- a/src/arduino.cc/builder/wipeout_build_path_if_build_options_changed.go +++ b/src/arduino.cc/builder/wipeout_build_path_if_build_options_changed.go @@ -36,6 +36,7 @@ import ( "arduino.cc/builder/utils" "os" "path/filepath" + "regexp" ) type WipeoutBuildPathIfBuildOptionsChanged struct{} @@ -44,7 +45,6 @@ func (s *WipeoutBuildPathIfBuildOptionsChanged) Run(context map[string]interface if !utils.MapHas(context, constants.CTX_BUILD_OPTIONS_PREVIOUS_JSON) { return nil } - buildOptionsJson := context[constants.CTX_BUILD_OPTIONS_JSON].(string) previousBuildOptionsJson := context[constants.CTX_BUILD_OPTIONS_PREVIOUS_JSON].(string) logger := context[constants.CTX_LOGGER].(i18n.Logger) @@ -53,6 +53,15 @@ func (s *WipeoutBuildPathIfBuildOptionsChanged) Run(context map[string]interface return nil } + re := regexp.MustCompile("(?m)^.*" + constants.CTX_SKETCH_LOCATION + ".*$[\r\n]+") + buildOptionsJson = re.ReplaceAllString(buildOptionsJson, "") + previousBuildOptionsJson = re.ReplaceAllString(previousBuildOptionsJson, "") + + // if the only difference is the sketch path skip deleting everything + if buildOptionsJson == previousBuildOptionsJson { + return nil + } + logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_BUILD_OPTIONS_CHANGED) buildPath := context[constants.CTX_BUILD_PATH].(string)