func (s *IncludesToIncludeFolders) Run(context map[string]interface{}) error { if !utils.MapHas(context, constants.CTX_LIBRARIES) { return nil } includes := context[constants.CTX_INCLUDES].([]string) headerToLibraries := context[constants.CTX_HEADER_TO_LIBRARIES].(map[string][]*types.Library) debugLevel := utils.DebugLevel(context) logger := context[constants.CTX_LOGGER].(i18n.Logger) platform := context[constants.CTX_TARGET_PLATFORM].(*types.Platform) actualPlatform := context[constants.CTX_ACTUAL_PLATFORM].(*types.Platform) var previousImportedLibraries []*types.Library if utils.MapHas(context, constants.CTX_IMPORTED_LIBRARIES) { previousImportedLibraries = context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library) } importedLibraries, err := resolveLibraries(includes, headerToLibraries, previousImportedLibraries, []*types.Platform{actualPlatform, platform}, debugLevel, logger) if err != nil { return utils.WrapError(err) } context[constants.CTX_IMPORTED_LIBRARIES] = importedLibraries buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) verbose := context[constants.CTX_VERBOSE].(bool) includeFolders := resolveIncludeFolders(importedLibraries, buildProperties, verbose) context[constants.CTX_INCLUDE_FOLDERS] = includeFolders return nil }
func (s *AddAdditionalEntriesToContext) Run(context map[string]interface{}) error { if utils.MapHas(context, constants.CTX_BUILD_PATH) { buildPath := context[constants.CTX_BUILD_PATH].(string) preprocPath, err := filepath.Abs(filepath.Join(buildPath, constants.FOLDER_PREPROC)) if err != nil { return utils.WrapError(err) } sketchBuildPath, err := filepath.Abs(filepath.Join(buildPath, constants.FOLDER_SKETCH)) if err != nil { return utils.WrapError(err) } librariesBuildPath, err := filepath.Abs(filepath.Join(buildPath, constants.FOLDER_LIBRARIES)) if err != nil { return utils.WrapError(err) } coreBuildPath, err := filepath.Abs(filepath.Join(buildPath, constants.FOLDER_CORE)) if err != nil { return utils.WrapError(err) } context[constants.CTX_PREPROC_PATH] = preprocPath context[constants.CTX_SKETCH_BUILD_PATH] = sketchBuildPath context[constants.CTX_LIBRARIES_BUILD_PATH] = librariesBuildPath context[constants.CTX_CORE_BUILD_PATH] = coreBuildPath } if !utils.MapHas(context, constants.CTX_WARNINGS_LEVEL) { context[constants.CTX_WARNINGS_LEVEL] = DEFAULT_WARNINGS_LEVEL } if !utils.MapHas(context, constants.CTX_VERBOSE) { context[constants.CTX_VERBOSE] = false } if !utils.MapHas(context, constants.CTX_DEBUG_LEVEL) { context[constants.CTX_DEBUG_LEVEL] = DEFAULT_DEBUG_LEVEL } if !utils.MapHas(context, constants.CTX_LIBRARY_DISCOVERY_RECURSION_DEPTH) { context[constants.CTX_LIBRARY_DISCOVERY_RECURSION_DEPTH] = DEFAULT_LIBRARY_DISCOVERY_RECURSION_DEPTH } sourceFiles := &types.UniqueStringQueue{} context[constants.CTX_COLLECTED_SOURCE_FILES_QUEUE] = sourceFiles foldersWithSources := &types.UniqueSourceFolderQueue{} context[constants.CTX_FOLDERS_WITH_SOURCES_QUEUE] = foldersWithSources context[constants.CTX_LIBRARY_RESOLUTION_RESULTS] = make(map[string]types.LibraryResolutionResult) return nil }
func (s *ContainerFindIncludes) Run(context map[string]interface{}) error { err := runCommand(context, &IncludesToIncludeFolders{}) if err != nil { return utils.WrapError(err) } sketch := context[constants.CTX_SKETCH].(*types.Sketch) sketchBuildPath := context[constants.CTX_SKETCH_BUILD_PATH].(string) wheelSpins := context[constants.CTX_LIBRARY_DISCOVERY_RECURSION_DEPTH].(int) for i := 0; i < wheelSpins; i++ { commands := []types.Command{ &IncludesFinderWithGCC{SourceFile: filepath.Join(sketchBuildPath, filepath.Base(sketch.MainFile.Name)+".cpp")}, &GCCMinusMOutputParser{}, &IncludesToIncludeFolders{}, } for _, command := range commands { err := runCommand(context, command) if err != nil { return utils.WrapError(err) } } } foldersWithSources := context[constants.CTX_FOLDERS_WITH_SOURCES_QUEUE].(*types.UniqueSourceFolderQueue) 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) for _, sourceFolder := range sourceFolders { foldersWithSources.Push(sourceFolder) } } } err = runCommand(context, &CollectAllSourceFilesFromFoldersWithSources{}) if err != nil { return utils.WrapError(err) } sourceFiles := context[constants.CTX_COLLECTED_SOURCE_FILES_QUEUE].(*types.UniqueStringQueue) for !sourceFiles.Empty() { commands := []types.Command{ &IncludesFinderWithGCC{SourceFile: sourceFiles.Pop().(string)}, &GCCMinusMOutputParser{}, &IncludesToIncludeFolders{}, &CollectAllSourceFilesFromFoldersWithSources{}, } for _, command := range commands { err := runCommand(context, command) if err != nil { return utils.WrapError(err) } } } return nil }
func (s *PrototypesAdder) Run(context map[string]interface{}) error { source := context[constants.CTX_SOURCE].(string) sourceRows := strings.Split(source, "\n") if !utils.MapHas(context, constants.CTX_FIRST_FUNCTION_AT_LINE) { return nil } firstFunctionLine := context[constants.CTX_FIRST_FUNCTION_AT_LINE].(int) if firstFunctionOutsideOfSource(firstFunctionLine, sourceRows) { return nil } firstFunctionChar := len(strings.Join(sourceRows[:firstFunctionLine-1], "\n")) + 1 if firstFunctionLine > 1 { firstFunctionLine -= context[constants.CTX_LINE_OFFSET].(int) } prototypeSection := composePrototypeSection(firstFunctionLine, context[constants.CTX_PROTOTYPES].([]string)) context[constants.CTX_PROTOTYPE_SECTION] = prototypeSection source = source[:firstFunctionChar] + prototypeSection + source[firstFunctionChar:] includeSection := composeIncludeArduinoSection() context[constants.CTX_INCLUDE_SECTION] = includeSection source = includeSection + source context[constants.CTX_SOURCE] = source return nil }
func (s *SetupHumanLoggerIfMissing) Run(context map[string]interface{}) error { if !utils.MapHas(context, constants.CTX_LOGGER) { context[constants.CTX_LOGGER] = i18n.HumanLogger{} } return nil }
func (s *RewriteHardwareKeys) Run(context map[string]interface{}) error { if !utils.MapHas(context, constants.CTX_PLATFORM_KEYS_REWRITE) { return nil } packages := context[constants.CTX_HARDWARE].(*types.Packages) platformKeysRewrite := context[constants.CTX_PLATFORM_KEYS_REWRITE].(types.PlatforKeysRewrite) hardwareRewriteResults := context[constants.CTX_HARDWARE_REWRITE_RESULTS].(map[*types.Platform][]types.PlatforKeyRewrite) for _, aPackage := range packages.Packages { for _, platform := range aPackage.Platforms { if platform.Properties[constants.REWRITING] != constants.REWRITING_DISABLED { for _, rewrite := range platformKeysRewrite.Rewrites { if platform.Properties[rewrite.Key] != constants.EMPTY_STRING && platform.Properties[rewrite.Key] == rewrite.OldValue { platform.Properties[rewrite.Key] = rewrite.NewValue appliedRewrites := rewritesAppliedToPlatform(platform, hardwareRewriteResults) appliedRewrites = append(appliedRewrites, rewrite) hardwareRewriteResults[platform] = appliedRewrites } } } } } return nil }
func (s *PrintUsedLibrariesIfVerbose) Run(context map[string]interface{}) error { verbose := context[constants.CTX_VERBOSE].(bool) logger := context[constants.CTX_LOGGER].(i18n.Logger) if !verbose || !utils.MapHas(context, constants.CTX_IMPORTED_LIBRARIES) { return nil } importedLibraries := context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library) for _, library := range importedLibraries { legacy := constants.EMPTY_STRING if library.IsLegacy { legacy = constants.MSG_LIB_LEGACY } if library.Version == constants.EMPTY_STRING { logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_USING_LIBRARY, library.Name, library.Folder, legacy) } else { logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_USING_LIBRARY_AT_VERSION, library.Name, library.Version, library.Folder, legacy) } } time.Sleep(100 * time.Millisecond) return nil }
func (s *WipeoutBuildPathIfBuildOptionsChanged) Run(context map[string]interface{}) error { 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) if buildOptionsJson == previousBuildOptionsJson { return nil } logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_BUILD_OPTIONS_CHANGED) buildPath := context[constants.CTX_BUILD_PATH].(string) files, err := gohasissues.ReadDir(buildPath) if err != nil { return utils.WrapError(err) } for _, file := range files { os.RemoveAll(filepath.Join(buildPath, file.Name())) } return nil }
func (s *IncludesFinderWithRegExp) Run(context map[string]interface{}) error { source := context[s.ContextField].(string) matches := INCLUDE_REGEXP.FindAllStringSubmatch(source, -1) includes := []string{} for _, match := range matches { includes = append(includes, strings.TrimSpace(match[1])) } if len(includes) == 0 { include := findIncludesForOldCompilers(source) if include != "" { includes = append(includes, include) } } context[constants.CTX_INCLUDES_JUST_FOUND] = includes if !utils.MapHas(context, constants.CTX_INCLUDES) { context[constants.CTX_INCLUDES] = includes return nil } context[constants.CTX_INCLUDES] = utils.AddStringsToStringsSet(context[constants.CTX_INCLUDES].([]string), includes) return nil }
func (s *RewriteHardwareKeys) Run(context map[string]interface{}) error { if !utils.MapHas(context, constants.CTX_PLATFORM_KEYS_REWRITE) { return nil } hardware := context[constants.CTX_HARDWARE].(map[string]*types.Package) platformKeysRewrite := context[constants.CTX_PLATFORM_KEYS_REWRITE].(types.PlatforKeysRewrite) logger := context[constants.CTX_LOGGER].(i18n.Logger) warn := utils.DebugLevel(context) > 0 for _, aPackage := range hardware { for _, platform := range aPackage.Platforms { if platform.Properties[constants.REWRITING] != constants.REWRITING_DISABLED { for _, rewrite := range platformKeysRewrite.Rewrites { if platform.Properties[rewrite.Key] != constants.EMPTY_STRING && platform.Properties[rewrite.Key] == rewrite.OldValue { platform.Properties[rewrite.Key] = rewrite.NewValue if warn { logger.Fprintln(os.Stderr, constants.MSG_WARNING_PLATFORM_OLD_VALUES, platform.Properties[constants.PLATFORM_NAME], rewrite.Key+"="+rewrite.OldValue, rewrite.Key+"="+rewrite.NewValue) } } } } } } return nil }
func (s *IncludesFinderWithGCC) Run(context map[string]interface{}) error { 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) includesParams := constants.EMPTY_STRING if utils.MapHas(context, constants.CTX_INCLUDE_FOLDERS) { includes := context[constants.CTX_INCLUDE_FOLDERS].([]string) includes = utils.Map(includes, utils.WrapWithHyphenI) includesParams = strings.Join(includes, " ") } properties := buildProperties.Clone() properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = s.SourceFile properties[constants.BUILD_PROPERTIES_INCLUDES] = includesParams builder_utils.RemoveHyphenMDDFlagFromGCCCommandLine(properties) output, err := builder_utils.ExecRecipe(properties, constants.RECIPE_PREPROC_INCLUDES, true, verbose, false, logger) if err != nil { return utils.WrapError(err) } context[constants.CTX_GCC_MINUS_M_OUTPUT] = string(output) return nil }
func (s *GCCMinusMOutputParser) Run(context map[string]interface{}) error { output := context[constants.CTX_GCC_MINUS_M_OUTPUT].(string) rows := strings.Split(output, "\n") includes := make([]string, 0) if len(rows) > 2 { for _, row := range rows[2:] { if !strings.HasPrefix(row, constants.SPACE) { row = strings.TrimSpace(row) if row != constants.EMPTY_STRING { row = strings.TrimSuffix(row, ":") row = strings.Replace(row, "\\ ", " ", -1) includes = append(includes, row) } } } } if !utils.MapHas(context, constants.CTX_INCLUDES) { context[constants.CTX_INCLUDES] = includes return nil } previousIncludes := utils.SliceToMapStringBool(context[constants.CTX_INCLUDES].([]string), true) currentIncludes := utils.SliceToMapStringBool(includes, true) mergedIncludes := utils.MergeMapsOfStringBool(previousIncludes, currentIncludes) context[constants.CTX_INCLUDES] = utils.KeysOfMapOfStringBool(mergedIncludes) return nil }
func (s *FailIfImportedLibraryIsWrong) Run(context map[string]interface{}) error { if !utils.MapHas(context, constants.CTX_IMPORTED_LIBRARIES) { return nil } logger := context[constants.CTX_LOGGER].(i18n.Logger) importedLibraries := context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library) for _, library := range importedLibraries { if !library.IsLegacy { if stat, err := os.Stat(filepath.Join(library.Folder, constants.LIBRARY_FOLDER_ARCH)); err == nil && stat.IsDir() { return utils.ErrorfWithLogger(logger, constants.MSG_ARCH_FOLDER_NOT_SUPPORTED) } for _, propName := range LIBRARY_MANDATORY_PROPERTIES { if _, ok := library.Properties[propName]; !ok { return utils.ErrorfWithLogger(logger, constants.MSG_PROP_IN_LIBRARY, propName, library.Folder) } } if library.Layout == types.LIBRARY_RECURSIVE { if stat, err := os.Stat(filepath.Join(library.Folder, constants.LIBRARY_FOLDER_UTILITY)); err == nil && stat.IsDir() { return utils.ErrorfWithLogger(logger, constants.MSG_LIBRARY_CAN_USE_SRC_AND_UTILITY_FOLDERS, library.Folder) } } } } return nil }
func (s *GCCMinusMOutputParser) Run(context map[string]interface{}) error { output := context[constants.CTX_GCC_MINUS_M_OUTPUT].(string) rows := strings.Split(output, "\n") includes := make([]string, 0) if len(rows) > 2 { for _, row := range rows[2:] { if !strings.HasPrefix(row, constants.SPACE) { row = strings.TrimSpace(row) if row != constants.EMPTY_STRING { row = strings.TrimSuffix(row, ":") row = strings.Replace(row, "\\ ", " ", -1) includes = append(includes, row) } } } } if !utils.MapHas(context, constants.CTX_INCLUDES) { context[constants.CTX_INCLUDES] = includes return nil } context[constants.CTX_INCLUDES] = utils.AddStringsToStringsSet(context[constants.CTX_INCLUDES].([]string), includes) return nil }
func (s *LoadVIDPIDSpecificProperties) Run(context map[string]interface{}) error { if !utils.MapHas(context, constants.CTX_VIDPID) { return nil } vidPid := context[constants.CTX_VIDPID].(string) vidPid = strings.ToLower(vidPid) vidPidParts := strings.Split(vidPid, "_") vid := vidPidParts[0] pid := vidPidParts[1] buildProperties := context[constants.CTX_BUILD_PROPERTIES].(props.PropertiesMap) VIDPIDIndex, err := findVIDPIDIndex(buildProperties, vid, pid) if err != nil { return utils.WrapError(err) } if VIDPIDIndex < 0 { return nil } vidPidSpecificProperties := buildProperties.SubTree(constants.BUILD_PROPERTIES_VID).SubTree(strconv.Itoa(VIDPIDIndex)) buildProperties.Merge(vidPidSpecificProperties) return nil }
func (s *IncludesFinderWithGCC) Run(context map[string]interface{}) error { buildProperties := utils.GetMapStringStringOrDefault(context, constants.CTX_BUILD_PROPERTIES) sketch := context[constants.CTX_SKETCH].(*types.Sketch) sketchBuildPath := context[constants.CTX_SKETCH_BUILD_PATH].(string) verbose := context[constants.CTX_VERBOSE].(bool) logger := context[constants.CTX_LOGGER].(i18n.Logger) includesParams := "" if utils.MapHas(context, constants.CTX_INCLUDE_FOLDERS) { includes := context[constants.CTX_INCLUDE_FOLDERS].([]string) includes = utils.Map(includes, utils.WrapWithHyphenI) includesParams = strings.Join(includes, " ") } properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties) properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = filepath.Join(sketchBuildPath, filepath.Base(sketch.MainFile.Name)+".cpp") properties[constants.BUILD_PROPERTIES_INCLUDES] = includesParams builder_utils.RemoveHyphenMDDFlagFromGCCCommandLine(properties) output, err := builder_utils.ExecRecipe(properties, constants.RECIPE_PREPROC_INCLUDES, true, verbose, false, logger) if err != nil { return utils.WrapError(err) } context[constants.CTX_GCC_MINUS_M_OUTPUT] = string(output) return nil }
func (s *AddAdditionalEntriesToContext) Run(context map[string]interface{}) error { if utils.MapHas(context, constants.CTX_BUILD_PATH) { buildPath := context[constants.CTX_BUILD_PATH].(string) preprocPath, err := filepath.Abs(filepath.Join(buildPath, constants.FOLDER_PREPROC)) if err != nil { return utils.WrapError(err) } sketchBuildPath, err := filepath.Abs(filepath.Join(buildPath, constants.FOLDER_SKETCH)) if err != nil { return utils.WrapError(err) } librariesBuildPath, err := filepath.Abs(filepath.Join(buildPath, constants.FOLDER_LIBRARIES)) if err != nil { return utils.WrapError(err) } coreBuildPath, err := filepath.Abs(filepath.Join(buildPath, constants.FOLDER_CORE)) if err != nil { return utils.WrapError(err) } context[constants.CTX_PREPROC_PATH] = preprocPath context[constants.CTX_SKETCH_BUILD_PATH] = sketchBuildPath context[constants.CTX_LIBRARIES_BUILD_PATH] = librariesBuildPath context[constants.CTX_CORE_BUILD_PATH] = coreBuildPath } if !utils.MapHas(context, constants.CTX_WARNINGS_LEVEL) { context[constants.CTX_WARNINGS_LEVEL] = DEFAULT_WARNINGS_LEVEL } if !utils.MapHas(context, constants.CTX_VERBOSE) { context[constants.CTX_VERBOSE] = false } if !utils.MapHas(context, constants.CTX_DEBUG_LEVEL) { context[constants.CTX_DEBUG_LEVEL] = DEFAULT_DEBUG_LEVEL } if !utils.MapHas(context, constants.CTX_LIBRARY_DISCOVERY_RECURSION_DEPTH) { context[constants.CTX_LIBRARY_DISCOVERY_RECURSION_DEPTH] = DEFAULT_LIBRARY_DISCOVERY_RECURSION_DEPTH } return nil }
func (s *IncludesToIncludeFolders) Run(context map[string]interface{}) error { includes := []string{} if utils.MapHas(context, constants.CTX_INCLUDES) { includes = context[constants.CTX_INCLUDES].([]string) } headerToLibraries := make(map[string][]*types.Library) if utils.MapHas(context, constants.CTX_HEADER_TO_LIBRARIES) { headerToLibraries = context[constants.CTX_HEADER_TO_LIBRARIES].(map[string][]*types.Library) } platform := context[constants.CTX_TARGET_PLATFORM].(*types.Platform) actualPlatform := context[constants.CTX_ACTUAL_PLATFORM].(*types.Platform) libraryResolutionResults := context[constants.CTX_LIBRARY_RESOLUTION_RESULTS].(map[string]types.LibraryResolutionResult) importedLibraries := []*types.Library{} if utils.MapHas(context, constants.CTX_IMPORTED_LIBRARIES) { importedLibraries = context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library) } newlyImportedLibraries, err := resolveLibraries(includes, headerToLibraries, importedLibraries, []*types.Platform{actualPlatform, platform}, libraryResolutionResults) if err != nil { return utils.WrapError(err) } foldersWithSources := context[constants.CTX_FOLDERS_WITH_SOURCES_QUEUE].(*types.UniqueSourceFolderQueue) for _, newlyImportedLibrary := range newlyImportedLibraries { if !sliceContainsLibrary(importedLibraries, newlyImportedLibrary) { importedLibraries = append(importedLibraries, newlyImportedLibrary) sourceFolders := types.LibraryToSourceFolder(newlyImportedLibrary) for _, sourceFolder := range sourceFolders { foldersWithSources.Push(sourceFolder) } } } context[constants.CTX_IMPORTED_LIBRARIES] = importedLibraries 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 return nil }
func TestLoadPreviousBuildOptionsMapMissingFile(t *testing.T) { context := make(map[string]interface{}) buildPath := SetupBuildPath(t, context) defer os.RemoveAll(buildPath) command := builder.LoadPreviousBuildOptionsMap{} err := command.Run(context) NoError(t, err) require.False(t, utils.MapHas(context, constants.CTX_BUILD_OPTIONS_PREVIOUS_JSON)) }
func (s *FailIfBuildPathEqualsSketchPath) Run(context map[string]interface{}) error { if !utils.MapHas(context, constants.CTX_BUILD_PATH) || !utils.MapHas(context, constants.CTX_SKETCH_LOCATION) { return nil } buildPath, err := filepath.Abs(context[constants.CTX_BUILD_PATH].(string)) if err != nil { return utils.WrapError(err) } sketchPath, err := filepath.Abs(context[constants.CTX_SKETCH_LOCATION].(string)) if err != nil { return utils.WrapError(err) } sketchPath = filepath.Dir(sketchPath) if buildPath == sketchPath { return utils.Errorf(context, constants.MSG_SKETCH_CANT_BE_IN_BUILDPATH) } return nil }
func (s *SetCustomBuildProperties) Run(context map[string]interface{}) error { if !utils.MapHas(context, constants.CTX_CUSTOM_BUILD_PROPERTIES) { return nil } buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string) customBuildProperties := props.LoadFromSlice(context[constants.CTX_CUSTOM_BUILD_PROPERTIES].([]string)) for key, value := range customBuildProperties { buildProperties[key] = value } return nil }
func (s *ContainerFindIncludes) Run(context map[string]interface{}) error { err := runCommand(context, &IncludesToIncludeFolders{}) if err != nil { return utils.WrapError(err) } sketchBuildPath := context[constants.CTX_SKETCH_BUILD_PATH].(string) sketch := context[constants.CTX_SKETCH].(*types.Sketch) err = findIncludesUntilDone(context, filepath.Join(sketchBuildPath, filepath.Base(sketch.MainFile.Name)+".cpp")) if err != nil { return utils.WrapError(err) } foldersWithSources := context[constants.CTX_FOLDERS_WITH_SOURCES_QUEUE].(*types.UniqueSourceFolderQueue) 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 := types.LibraryToSourceFolder(library) for _, sourceFolder := range sourceFolders { foldersWithSources.Push(sourceFolder) } } } err = runCommand(context, &CollectAllSourceFilesFromFoldersWithSources{}) if err != nil { return utils.WrapError(err) } sourceFilePaths := context[constants.CTX_COLLECTED_SOURCE_FILES_QUEUE].(*types.UniqueStringQueue) for !sourceFilePaths.Empty() { err = findIncludesUntilDone(context, sourceFilePaths.Pop().(string)) if err != nil { return utils.WrapError(err) } err := runCommand(context, &CollectAllSourceFilesFromFoldersWithSources{}) if err != nil { return utils.WrapError(err) } } err = runCommand(context, &FailIfImportedLibraryIsWrong{}) if err != nil { return utils.WrapError(err) } return nil }
func (s *SetCustomBuildProperties) Run(context map[string]interface{}) error { if !utils.MapHas(context, constants.CTX_CUSTOM_BUILD_PROPERTIES) { return nil } logger := context[constants.CTX_LOGGER].(i18n.Logger) 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) } for key, value := range customBuildProperties { buildProperties[key] = value } return nil }
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) { return nil } firstFunctionLine := context[constants.CTX_LINE_WHERE_TO_INSERT_PROTOTYPES].(int) if isFirstFunctionOutsideOfSource(firstFunctionLine, sourceRows) { return nil } 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 }
func (s *CreateBuildOptionsMap) Run(context map[string]interface{}) error { buildOptions := make(map[string]string) buildOptionsMapKeys := []string{ constants.CTX_HARDWARE_FOLDERS, constants.CTX_TOOLS_FOLDERS, constants.CTX_BUILT_IN_LIBRARIES_FOLDERS, constants.CTX_OTHER_LIBRARIES_FOLDERS, constants.CTX_FQBN, constants.CTX_SKETCH_LOCATION, constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION, constants.CTX_CUSTOM_BUILD_PROPERTIES, } for _, key := range buildOptionsMapKeys { if utils.MapHas(context, key) { originalValue := context[key] value := constants.EMPTY_STRING kindOfValue := reflect.TypeOf(originalValue).Kind() if kindOfValue == reflect.Slice { value = strings.Join(originalValue.([]string), ",") } else if kindOfValue == reflect.String { value = originalValue.(string) } else { return utils.Errorf(context, constants.MSG_UNHANDLED_TYPE_IN_CONTEXT, kindOfValue.String(), key) } buildOptions[key] = value } } context[constants.CTX_BUILD_OPTIONS] = buildOptions bytes, err := json.MarshalIndent(buildOptions, "", " ") if err != nil { return utils.WrapError(err) } context[constants.CTX_BUILD_OPTIONS_JSON] = string(bytes) return nil }
func (s *SketchLoader) Run(context map[string]interface{}) error { if !utils.MapHas(context, constants.CTX_SKETCH_LOCATION) { return nil } sketchLocation := context[constants.CTX_SKETCH_LOCATION].(string) sketchLocation, err := filepath.Abs(sketchLocation) if err != nil { return utils.WrapError(err) } mainSketchStat, err := os.Stat(sketchLocation) if err != nil { return utils.WrapError(err) } if mainSketchStat.IsDir() { sketchLocation = filepath.Join(sketchLocation, mainSketchStat.Name()+".ino") } context[constants.CTX_SKETCH_LOCATION] = sketchLocation allSketchFilePaths, err := collectAllSketchFiles(filepath.Dir(sketchLocation)) if err != nil { return utils.WrapError(err) } if !utils.SliceContains(allSketchFilePaths, sketchLocation) { return utils.Errorf(context, constants.MSG_CANT_FIND_SKETCH_IN_PATH, sketchLocation, filepath.Dir(sketchLocation)) } logger := context[constants.CTX_LOGGER].(i18n.Logger) sketch, err := makeSketch(sketchLocation, allSketchFilePaths, logger) if err != nil { return utils.WrapError(err) } context[constants.CTX_SKETCH_LOCATION] = sketchLocation context[constants.CTX_SKETCH] = sketch return nil }
func (s *PrototypesAdder) Run(context map[string]interface{}) error { source := context[constants.CTX_SOURCE].(string) sourceRows := strings.Split(source, "\n") if !utils.MapHas(context, constants.CTX_LINE_WHERE_TO_INSERT_PROTOTYPES) { return nil } firstFunctionLine := context[constants.CTX_LINE_WHERE_TO_INSERT_PROTOTYPES].(int) if firstFunctionOutsideOfSource(firstFunctionLine, sourceRows) { return nil } firstFunctionChar := len(strings.Join(sourceRows[:firstFunctionLine+context[constants.CTX_LINE_OFFSET].(int)-1], "\n")) + 1 prototypeSection := composePrototypeSection(firstFunctionLine, context[constants.CTX_PROTOTYPES].([]*types.Prototype)) context[constants.CTX_PROTOTYPE_SECTION] = prototypeSection source = source[:firstFunctionChar] + prototypeSection + source[firstFunctionChar:] context[constants.CTX_SOURCE] = source return nil }
func (s *GenerateBuildPathIfMissing) Run(context map[string]interface{}) error { if utils.MapHas(context, constants.CTX_BUILD_PATH) && context[constants.CTX_BUILD_PATH].(string) != constants.EMPTY_STRING { return nil } sketchLocation := context[constants.CTX_SKETCH_LOCATION].(string) md5sum := utils.MD5Sum([]byte(sketchLocation)) buildPath := filepath.Join(os.TempDir(), "arduino-sketch-"+strings.ToUpper(md5sum)) _, err := os.Stat(buildPath) if err != nil && !os.IsNotExist(err) { return utils.WrapError(err) } if utils.DebugLevel(context) > 5 { logger := context[constants.CTX_LOGGER].(i18n.Logger) logger.Fprintln(os.Stdout, constants.LOG_LEVEL_WARN, constants.MSG_SETTING_BUILD_PATH, buildPath) } context[constants.CTX_BUILD_PATH] = buildPath return nil }
func (s *LibrariesLoader) Run(context map[string]interface{}) error { sortedLibrariesFolders := []string{} builtInLibrariesFolders := []string{} if utils.MapHas(context, constants.CTX_BUILT_IN_LIBRARIES_FOLDERS) { builtInLibrariesFolders = context[constants.CTX_BUILT_IN_LIBRARIES_FOLDERS].([]string) } builtInLibrariesFolders, err := utils.AbsolutizePaths(builtInLibrariesFolders) if err != nil { return utils.WrapError(err) } sortedLibrariesFolders = utils.AppendIfNotPresent(sortedLibrariesFolders, builtInLibrariesFolders...) platform := context[constants.CTX_TARGET_PLATFORM].(*types.Platform) debugLevel := utils.DebugLevel(context) logger := context[constants.CTX_LOGGER].(i18n.Logger) actualPlatform := context[constants.CTX_ACTUAL_PLATFORM].(*types.Platform) if actualPlatform != platform { sortedLibrariesFolders = appendPathToLibrariesFolders(sortedLibrariesFolders, filepath.Join(actualPlatform.Folder, constants.FOLDER_LIBRARIES)) } sortedLibrariesFolders = appendPathToLibrariesFolders(sortedLibrariesFolders, filepath.Join(platform.Folder, constants.FOLDER_LIBRARIES)) librariesFolders := []string{} if utils.MapHas(context, constants.CTX_OTHER_LIBRARIES_FOLDERS) { librariesFolders = context[constants.CTX_OTHER_LIBRARIES_FOLDERS].([]string) } librariesFolders, err = utils.AbsolutizePaths(librariesFolders) if err != nil { return utils.WrapError(err) } sortedLibrariesFolders = utils.AppendIfNotPresent(sortedLibrariesFolders, librariesFolders...) context[constants.CTX_LIBRARIES_FOLDERS] = sortedLibrariesFolders var libraries []*types.Library for _, libraryFolder := range sortedLibrariesFolders { subFolders, err := utils.ReadDirFiltered(libraryFolder, utils.FilterDirs) if err != nil { return utils.WrapError(err) } for _, subFolder := range subFolders { library, err := makeLibrary(filepath.Join(libraryFolder, subFolder.Name()), debugLevel, logger) if err != nil { return utils.WrapError(err) } libraries = append(libraries, library) } } context[constants.CTX_LIBRARIES] = libraries headerToLibraries := make(map[string][]*types.Library) for _, library := range libraries { headers, err := utils.ReadDirFiltered(library.SrcFolder, utils.FilterFilesWithExtension(".h")) if err != nil { return utils.WrapError(err) } for _, header := range headers { headerFileName := header.Name() headerToLibraries[headerFileName] = append(headerToLibraries[headerFileName], library) } } context[constants.CTX_HEADER_TO_LIBRARIES] = headerToLibraries return nil }
func (s *SetupBuildProperties) Run(context map[string]interface{}) error { packages := context[constants.CTX_HARDWARE].(map[string]*types.Package) targetPlatform := context[constants.CTX_TARGET_PLATFORM].(*types.Platform) 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) if utils.MapHas(context, constants.CTX_BUILD_PATH) { buildProperties[constants.BUILD_PROPERTIES_BUILD_PATH] = context[constants.CTX_BUILD_PATH].(string) } if utils.MapHas(context, constants.CTX_SKETCH) { buildProperties[constants.BUILD_PROPERTIES_BUILD_PROJECT_NAME] = filepath.Base(context[constants.CTX_SKETCH].(*types.Sketch).MainFile.Name) } buildProperties[constants.BUILD_PROPERTIES_BUILD_ARCH] = strings.ToUpper(targetPlatform.PlatformId) if buildProperties[constants.BUILD_PROPERTIES_COMPILER_PATH] == constants.EMPTY_STRING { return utils.Errorf(context, constants.MSG_MISSING_COMPILER_PATH) } buildProperties[constants.BUILD_PROPERTIES_BUILD_CORE] = context[constants.CTX_BUILD_CORE].(string) buildProperties[constants.BUILD_PROPERTIES_BUILD_CORE_PATH] = filepath.Join(actualPlatform.Folder, constants.FOLDER_CORES, buildProperties[constants.BUILD_PROPERTIES_BUILD_CORE]) buildProperties[constants.BUILD_PROPERTIES_BUILD_SYSTEM_PATH] = filepath.Join(actualPlatform.Folder, constants.FOLDER_SYSTEM) buildProperties[constants.BUILD_PROPERTIES_RUNTIME_PLATFORM_PATH] = actualPlatform.Folder buildProperties[constants.BUILD_PROPERTIES_RUNTIME_HARDWARE_PATH] = filepath.Join(actualPlatform.Folder, "..") buildProperties[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION].(string) buildProperties[constants.IDE_VERSION] = context[constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION].(string) buildProperties[constants.BUILD_PROPERTIES_RUNTIME_OS] = utils.PrettyOSName() variant := buildProperties[constants.BUILD_PROPERTIES_BUILD_VARIANT] if variant == constants.EMPTY_STRING { buildProperties[constants.BUILD_PROPERTIES_BUILD_VARIANT_PATH] = constants.EMPTY_STRING } else { var variantPlatform *types.Platform variantParts := strings.Split(variant, ":") if len(variantParts) > 1 { variantPlatform = packages[variantParts[0]].Platforms[targetPlatform.PlatformId] variant = variantParts[1] } else { variantPlatform = targetPlatform } buildProperties[constants.BUILD_PROPERTIES_BUILD_VARIANT_PATH] = filepath.Join(variantPlatform.Folder, constants.FOLDER_VARIANTS, variant) } tools := context[constants.CTX_TOOLS].([]*types.Tool) for _, tool := range tools { buildProperties[constants.BUILD_PROPERTIES_RUNTIME_TOOLS_PREFIX+tool.Name+constants.BUILD_PROPERTIES_RUNTIME_TOOLS_SUFFIX] = tool.Folder buildProperties[constants.BUILD_PROPERTIES_RUNTIME_TOOLS_PREFIX+tool.Name+"-"+tool.Version+constants.BUILD_PROPERTIES_RUNTIME_TOOLS_SUFFIX] = tool.Folder } if !utils.MapStringStringHas(buildProperties, constants.BUILD_PROPERTIES_SOFTWARE) { buildProperties[constants.BUILD_PROPERTIES_SOFTWARE] = DEFAULT_SOFTWARE } if utils.MapHas(context, constants.CTX_SKETCH_LOCATION) { sourcePath, err := filepath.Abs(context[constants.CTX_SKETCH_LOCATION].(string)) if err != nil { return err } buildProperties[constants.BUILD_PROPERTIES_SOURCE_PATH] = sourcePath } context[constants.CTX_BUILD_PROPERTIES] = buildProperties return nil }