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 *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 compileCore(buildPath string, buildProperties map[string]string, verbose bool, warningsLevel string, logger i18n.Logger) (string, error) { coreFolder := buildProperties[constants.BUILD_PROPERTIES_BUILD_CORE_PATH] variantFolder := buildProperties[constants.BUILD_PROPERTIES_BUILD_VARIANT_PATH] var includes []string includes = append(includes, coreFolder) if variantFolder != constants.EMPTY_STRING { includes = append(includes, variantFolder) } includes = utils.Map(includes, utils.WrapWithHyphenI) var err error var variantObjectFiles []string if variantFolder != constants.EMPTY_STRING { variantObjectFiles, err = builder_utils.CompileFiles(variantObjectFiles, variantFolder, true, buildPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return "", utils.WrapError(err) } } coreObjectFiles, err := builder_utils.CompileFiles([]string{}, coreFolder, true, buildPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return "", utils.WrapError(err) } objectFiles := append(coreObjectFiles, variantObjectFiles...) archiveFile, err := builder_utils.ArchiveCompiledFiles(buildPath, "core.a", objectFiles, buildProperties, verbose, logger) if err != nil { return "", utils.WrapError(err) } return archiveFile, nil }
func (s *SketchBuilder) Run(ctx *types.Context) error { sketchBuildPath := ctx.SketchBuildPath buildProperties := ctx.BuildProperties includes := ctx.IncludeFolders includes = utils.Map(includes, utils.WrapWithHyphenI) verbose := ctx.Verbose warningsLevel := ctx.WarningsLevel logger := ctx.GetLogger() err := utils.EnsureFolderExists(sketchBuildPath) if err != nil { return i18n.WrapError(err) } var objectFiles []string objectFiles, err = builder_utils.CompileFiles(objectFiles, sketchBuildPath, false, sketchBuildPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return i18n.WrapError(err) } // The "src/" subdirectory of a sketch is compiled recursively sketchSrcPath := filepath.Join(sketchBuildPath, constants.SKETCH_FOLDER_SRC) if info, err := os.Stat(sketchSrcPath); err == nil && info.IsDir() { objectFiles, err = builder_utils.CompileFiles(objectFiles, sketchSrcPath, true, sketchSrcPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return i18n.WrapError(err) } } ctx.SketchObjectFiles = objectFiles return nil }
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) if err != nil { return nil, "", utils.WrapError(err) } targetFilePath = filepath.Join(preprocPath, targetFilePath) } 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 includes := context[constants.CTX_INCLUDE_FOLDERS].([]string) includes = utils.Map(includes, utils.WrapWithHyphenI) properties[constants.BUILD_PROPERTIES_INCLUDES] = strings.Join(includes, constants.SPACE) builder_utils.RemoveHyphenMDDFlagFromGCCCommandLine(properties) return properties, targetFilePath, nil }
func TestMapTrimSpace(t *testing.T) { value := "hello, world , how are,you? " parts := utils.Map(strings.Split(value, ","), utils.TrimSpace) require.Equal(t, 4, len(parts)) require.Equal(t, "hello", parts[0]) require.Equal(t, "world", parts[1]) require.Equal(t, "how are", parts[2]) require.Equal(t, "you?", parts[3]) }
func addAdditionalPropertiesToTargetBoard(board *types.Board, options string) { optionsParts := strings.Split(options, ",") optionsParts = utils.Map(optionsParts, utils.TrimSpace) for _, optionPart := range optionsParts { parts := strings.Split(optionPart, "=") parts = utils.Map(parts, utils.TrimSpace) key := parts[0] value := parts[1] if key != constants.EMPTY_STRING && value != constants.EMPTY_STRING { menu := board.Properties.SubTree(constants.BOARD_PROPERTIES_MENU) if len(menu) == 0 { return } propertiesOfKey := menu.SubTree(key) if len(propertiesOfKey) == 0 { return } propertiesOfKeyValue := propertiesOfKey.SubTree(value) board.Properties.Merge(propertiesOfKeyValue) } } }
func compileCore(buildPath string, buildProperties map[string]string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) { var objectFiles []string coreFolder := buildProperties[constants.BUILD_PROPERTIES_BUILD_CORE_PATH] variantFolder := buildProperties[constants.BUILD_PROPERTIES_BUILD_VARIANT_PATH] var includes []string includes = append(includes, coreFolder) if variantFolder != constants.EMPTY_STRING { includes = append(includes, variantFolder) } includes = utils.Map(includes, utils.WrapWithHyphenI) var err error if variantFolder != constants.EMPTY_STRING { objectFiles, err = builder_utils.CompileFiles(objectFiles, variantFolder, true, buildPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return nil, utils.WrapError(err) } } coreObjectFiles, err := builder_utils.CompileFiles([]string{}, coreFolder, true, buildPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return nil, utils.WrapError(err) } coreArchiveFilePath := filepath.Join(buildPath, "core.a") if _, err := os.Stat(coreArchiveFilePath); err == nil { err = os.Remove(coreArchiveFilePath) if err != nil { return nil, utils.WrapError(err) } } for _, coreObjectFile := range coreObjectFiles { properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties) properties[constants.BUILD_PROPERTIES_INCLUDES] = strings.Join(includes, constants.SPACE) properties[constants.BUILD_PROPERTIES_ARCHIVE_FILE] = filepath.Base(coreArchiveFilePath) properties[constants.BUILD_PROPERTIES_OBJECT_FILE] = coreObjectFile _, err := builder_utils.ExecRecipe(properties, "recipe.ar.pattern", false, verbose, verbose, logger) if err != nil { return nil, utils.WrapError(err) } } return objectFiles, nil }
func link(objectFiles []string, coreDotARelPath string, coreArchiveFilePath string, buildProperties properties.Map, verbose bool, warningsLevel string, logger i18n.Logger) error { optRelax := addRelaxTrickIfATMEGA2560(buildProperties) objectFiles = utils.Map(objectFiles, wrapWithDoubleQuotes) objectFileList := strings.Join(objectFiles, constants.SPACE) 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 properties[constants.BUILD_PROPERTIES_ARCHIVE_FILE_PATH] = coreArchiveFilePath properties[constants.BUILD_PROPERTIES_OBJECT_FILES] = objectFileList _, err := builder_utils.ExecRecipe(properties, constants.RECIPE_C_COMBINE_PATTERN, false, verbose, verbose, logger) return err }
func link(objectFiles []string, buildProperties map[string]string, verbose bool, warningsLevel string, logger i18n.Logger) error { optRelax := constants.EMPTY_STRING if buildProperties[constants.BUILD_PROPERTIES_BUILD_MCU] == "atmega2560" { optRelax = ",--relax" } objectFiles = utils.Map(objectFiles, wrapWithDoubleQuotes) objectFileList := strings.Join(objectFiles, constants.SPACE) properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties) properties["compiler.c.elf.flags"] = properties["compiler.c.elf.flags"] + optRelax properties["compiler.warning_flags"] = properties["compiler.warning_flags."+warningsLevel] properties[constants.BUILD_PROPERTIES_ARCHIVE_FILE] = "core.a" properties[constants.BUILD_PROPERTIES_OBJECT_FILES] = objectFileList _, err := builder_utils.ExecRecipe(properties, "recipe.c.combine.pattern", false, verbose, verbose, logger) return err }
func prepareGCCPreprocRecipeProperties(ctx *types.Context, sourceFilePath string, targetFilePath string, includes []string) (properties.Map, string, error) { if targetFilePath != utils.NULLFile() { preprocPath := ctx.PreprocPath err := utils.EnsureFolderExists(preprocPath) if err != nil { return nil, "", i18n.WrapError(err) } targetFilePath = filepath.Join(preprocPath, targetFilePath) } properties := ctx.BuildProperties.Clone() properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = sourceFilePath properties[constants.BUILD_PROPERTIES_PREPROCESSED_FILE_PATH] = targetFilePath includes = utils.Map(includes, utils.WrapWithHyphenI) properties[constants.BUILD_PROPERTIES_INCLUDES] = strings.Join(includes, constants.SPACE) builder_utils.RemoveHyphenMDDFlagFromGCCCommandLine(properties) return properties, targetFilePath, nil }
func prepareGCCPreprocRecipeProperties(context map[string]interface{}, sourceFilePath string, targetFileName string) (map[string]string, string, error) { preprocPath := context[constants.CTX_PREPROC_PATH].(string) err := utils.EnsureFolderExists(preprocPath) if err != nil { return nil, "", utils.WrapError(err) } targetFilePath := filepath.Join(preprocPath, targetFileName) buildProperties := utils.GetMapStringStringOrDefault(context, constants.CTX_BUILD_PROPERTIES) properties := utils.MergeMapsOfStrings(make(map[string]string), buildProperties) properties[constants.BUILD_PROPERTIES_SOURCE_FILE] = sourceFilePath properties[constants.BUILD_PROPERTIES_PREPROCESSED_FILE_PATH] = targetFilePath includes := context[constants.CTX_INCLUDE_FOLDERS].([]string) includes = utils.Map(includes, utils.WrapWithHyphenI) properties[constants.BUILD_PROPERTIES_INCLUDES] = strings.Join(includes, constants.SPACE) builder_utils.RemoveHyphenMDDFlagFromGCCCommandLine(properties) return properties, targetFilePath, nil }
func (s *LibrariesBuilder) Run(ctx *types.Context) error { librariesBuildPath := ctx.LibrariesBuildPath buildProperties := ctx.BuildProperties includes := ctx.IncludeFolders includes = utils.Map(includes, utils.WrapWithHyphenI) libraries := ctx.ImportedLibraries verbose := ctx.Verbose warningsLevel := ctx.WarningsLevel logger := ctx.GetLogger() err := utils.EnsureFolderExists(librariesBuildPath) if err != nil { return i18n.WrapError(err) } objectFiles, err := compileLibraries(libraries, librariesBuildPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return i18n.WrapError(err) } ctx.LibrariesObjectFiles = objectFiles return nil }
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) includes := context[constants.CTX_INCLUDE_FOLDERS].([]string) includes = utils.Map(includes, utils.WrapWithHyphenI) verbose := context[constants.CTX_VERBOSE].(bool) warningsLevel := context[constants.CTX_WARNINGS_LEVEL].(string) logger := context[constants.CTX_LOGGER].(i18n.Logger) err := os.MkdirAll(sketchBuildPath, os.FileMode(0755)) if err != nil { return utils.WrapError(err) } var objectFiles []string objectFiles, err = builder_utils.CompileFiles(objectFiles, sketchBuildPath, false, sketchBuildPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return utils.WrapError(err) } context[constants.CTX_OBJECT_FILES_SKETCH] = objectFiles return nil }
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) includes := context[constants.CTX_INCLUDE_FOLDERS].([]string) includes = utils.Map(includes, utils.WrapWithHyphenI) libraries := context[constants.CTX_IMPORTED_LIBRARIES].([]*types.Library) verbose := context[constants.CTX_VERBOSE].(bool) warningsLevel := context[constants.CTX_WARNINGS_LEVEL].(string) logger := context[constants.CTX_LOGGER].(i18n.Logger) err := utils.EnsureFolderExists(librariesBuildPath) if err != nil { return utils.WrapError(err) } objectFiles, err := compileLibraries(libraries, librariesBuildPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return utils.WrapError(err) } context[constants.CTX_OBJECT_FILES_LIBRARIES] = objectFiles return nil }
func (s *SketchBuilder) Run(ctx *types.Context) error { sketchBuildPath := ctx.SketchBuildPath buildProperties := ctx.BuildProperties includes := ctx.IncludeFolders includes = utils.Map(includes, utils.WrapWithHyphenI) verbose := ctx.Verbose warningsLevel := ctx.WarningsLevel logger := ctx.GetLogger() err := utils.EnsureFolderExists(sketchBuildPath) if err != nil { return i18n.WrapError(err) } var objectFiles []string objectFiles, err = builder_utils.CompileFiles(objectFiles, sketchBuildPath, true, sketchBuildPath, buildProperties, includes, verbose, warningsLevel, logger) if err != nil { return i18n.WrapError(err) } ctx.SketchObjectFiles = objectFiles return nil }
func ObjFileIsUpToDate(sourceFile, objectFile, dependencyFile string) (bool, error) { sourceFile = filepath.Clean(sourceFile) objectFile = filepath.Clean(objectFile) dependencyFile = filepath.Clean(dependencyFile) sourceFileStat, err := os.Stat(sourceFile) if err != nil { return false, i18n.WrapError(err) } objectFileStat, err := os.Stat(objectFile) if err != nil { if os.IsNotExist(err) { return false, nil } else { return false, i18n.WrapError(err) } } dependencyFileStat, err := os.Stat(dependencyFile) if err != nil { if os.IsNotExist(err) { return false, nil } else { return false, i18n.WrapError(err) } } if sourceFileStat.ModTime().After(objectFileStat.ModTime()) { return false, nil } if sourceFileStat.ModTime().After(dependencyFileStat.ModTime()) { return false, nil } rows, err := utils.ReadFileToRows(dependencyFile) if err != nil { return false, i18n.WrapError(err) } rows = utils.Map(rows, removeEndingBackSlash) rows = utils.Map(rows, strings.TrimSpace) rows = utils.Map(rows, unescapeDep) rows = utils.Filter(rows, nonEmptyString) if len(rows) == 0 { return true, nil } firstRow := rows[0] if !strings.HasSuffix(firstRow, ":") { return false, nil } objFileInDepFile := firstRow[:len(firstRow)-1] if objFileInDepFile != objectFile { return false, nil } rows = rows[1:] for _, row := range rows { depStat, err := os.Stat(row) if err != nil && !os.IsNotExist(err) { // There is probably a parsing error of the dep file // Ignore the error and trigger a full rebuild anyway return false, nil } if os.IsNotExist(err) { return false, nil } if depStat.ModTime().After(objectFileStat.ModTime()) { return false, nil } } return true, nil }