func (s *FailIfImportedLibraryIsWrong) Run(ctx *types.Context) error {
	if len(ctx.ImportedLibraries) == 0 {
		return nil
	}

	logger := ctx.GetLogger()

	for _, library := range ctx.ImportedLibraries {
		if !library.IsLegacy {
			if stat, err := os.Stat(filepath.Join(library.Folder, constants.LIBRARY_FOLDER_ARCH)); err == nil && stat.IsDir() {
				return i18n.ErrorfWithLogger(logger, constants.MSG_ARCH_FOLDER_NOT_SUPPORTED)
			}
			for _, propName := range LIBRARY_MANDATORY_PROPERTIES {
				if _, ok := library.Properties[propName]; !ok {
					return i18n.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 i18n.ErrorfWithLogger(logger, constants.MSG_LIBRARY_CAN_USE_SRC_AND_UTILITY_FOLDERS, library.Folder)
				}
			}
		}
	}

	return nil
}
예제 #2
0
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, i18n.ErrorfWithLogger(logger, constants.MSG_PATTERN_MISSING, recipe)
	}

	var err error
	commandLine := properties.ExpandPropsInString(pattern)
	if removeUnsetProperties {
		commandLine, err = props.DeleteUnexpandedPropsFromString(commandLine)
		if err != nil {
			return nil, i18n.WrapError(err)
		}
	}

	command, err := utils.PrepareCommand(commandLine, logger)
	if err != nil {
		return nil, i18n.WrapError(err)
	}

	if echoCommandLine {
		fmt.Println(commandLine)
	}

	return command, nil
}
예제 #3
0
func (s *CTagsRunner) Run(ctx *types.Context) error {
	buildProperties := ctx.BuildProperties
	ctagsTargetFilePath := ctx.CTagsTargetFile
	logger := ctx.GetLogger()

	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]
	if pattern == constants.EMPTY_STRING {
		return i18n.ErrorfWithLogger(logger, constants.MSG_PATTERN_MISSING, constants.CTAGS)
	}

	commandLine := properties.ExpandPropsInString(pattern)
	command, err := utils.PrepareCommand(commandLine, logger)
	if err != nil {
		return i18n.WrapError(err)
	}

	verbose := ctx.Verbose
	if verbose {
		fmt.Println(commandLine)
	}

	sourceBytes, err := command.Output()
	if err != nil {
		return i18n.WrapError(err)
	}

	ctx.CTagsOutput = string(sourceBytes)

	return nil
}
예제 #4
0
func makeSketch(sketchLocation string, allSketchFilePaths []string, logger i18n.Logger) (*types.Sketch, error) {
	sketchFilesMap := make(map[string]types.SketchFile)
	for _, sketchFilePath := range allSketchFilePaths {
		source, err := ioutil.ReadFile(sketchFilePath)
		if err != nil {
			return nil, i18n.WrapError(err)
		}
		sketchFilesMap[sketchFilePath] = types.SketchFile{Name: sketchFilePath, Source: string(source)}
	}

	mainFile := sketchFilesMap[sketchLocation]
	delete(sketchFilesMap, sketchLocation)

	additionalFiles := []types.SketchFile{}
	otherSketchFiles := []types.SketchFile{}
	mainFileDir := filepath.Dir(mainFile.Name)
	for _, sketchFile := range sketchFilesMap {
		ext := strings.ToLower(filepath.Ext(sketchFile.Name))
		if MAIN_FILE_VALID_EXTENSIONS[ext] {
			if filepath.Dir(sketchFile.Name) == mainFileDir {
				otherSketchFiles = append(otherSketchFiles, sketchFile)
			}
		} else if ADDITIONAL_FILE_VALID_EXTENSIONS[ext] {
			additionalFiles = append(additionalFiles, sketchFile)
		} else {
			return nil, i18n.ErrorfWithLogger(logger, constants.MSG_UNKNOWN_SKETCH_EXT, sketchFile.Name)
		}
	}

	sort.Sort(types.SketchFileSortByName(additionalFiles))
	sort.Sort(types.SketchFileSortByName(otherSketchFiles))

	return &types.Sketch{MainFile: mainFile, OtherSketchFiles: otherSketchFiles, AdditionalFiles: additionalFiles}, nil
}
예제 #5
0
func (s *HardwareLoader) Run(ctx *types.Context) error {
	logger := ctx.GetLogger()

	packages := &types.Packages{}
	packages.Packages = make(map[string]*types.Package)
	packages.Properties = make(map[string]string)

	folders := ctx.HardwareFolders
	folders, err := utils.AbsolutizePaths(folders)
	if err != nil {
		return i18n.WrapError(err)
	}

	for _, folder := range folders {
		stat, err := os.Stat(folder)
		if err != nil {
			return i18n.WrapError(err)
		}
		if !stat.IsDir() {
			return i18n.ErrorfWithLogger(logger, constants.MSG_MUST_BE_A_FOLDER, folder)
		}

		hardwarePlatformTxt, err := props.SafeLoad(filepath.Join(folder, constants.FILE_PLATFORM_TXT), logger)
		if err != nil {
			return i18n.WrapError(err)
		}
		packages.Properties.Merge(hardwarePlatformTxt)

		subfolders, err := utils.ReadDirFiltered(folder, utils.FilterDirs)
		if err != nil {
			return i18n.WrapError(err)
		}
		subfolders = utils.FilterOutFoldersByNames(subfolders, constants.FOLDER_TOOLS)

		for _, subfolder := range subfolders {
			subfolderPath := filepath.Join(folder, subfolder.Name())
			packageId := subfolder.Name()

			if _, err := os.Stat(filepath.Join(subfolderPath, constants.FOLDER_HARDWARE)); err == nil {
				subfolderPath = filepath.Join(subfolderPath, constants.FOLDER_HARDWARE)
			}

			targetPackage := getOrCreatePackage(packages, packageId)
			err = loadPackage(targetPackage, subfolderPath, logger)
			if err != nil {
				return i18n.WrapError(err)
			}
			packages.Packages[packageId] = targetPackage
		}
	}

	ctx.Hardware = packages

	return nil
}
예제 #6
0
func LoadFromSlice(lines []string, logger i18n.Logger) (Map, error) {
	properties := make(Map)

	for _, line := range lines {
		err := properties.loadSingleLine(line)
		if err != nil {
			return nil, i18n.ErrorfWithLogger(logger, constants.MSG_WRONG_PROPERTIES, line)
		}
	}

	return properties, nil
}
예제 #7
0
func (s *SketchLoader) Run(ctx *types.Context) error {
	if ctx.SketchLocation == "" {
		return nil
	}

	sketchLocation := ctx.SketchLocation

	sketchLocation, err := filepath.Abs(sketchLocation)
	if err != nil {
		return i18n.WrapError(err)
	}
	mainSketchStat, err := os.Stat(sketchLocation)
	if err != nil {
		return i18n.WrapError(err)
	}
	if mainSketchStat.IsDir() {
		sketchLocation = filepath.Join(sketchLocation, mainSketchStat.Name()+".ino")
	}

	ctx.SketchLocation = sketchLocation

	allSketchFilePaths, err := collectAllSketchFiles(filepath.Dir(sketchLocation))
	if err != nil {
		return i18n.WrapError(err)
	}

	logger := ctx.GetLogger()

	if !utils.SliceContains(allSketchFilePaths, sketchLocation) {
		return i18n.ErrorfWithLogger(logger, constants.MSG_CANT_FIND_SKETCH_IN_PATH, sketchLocation, filepath.Dir(sketchLocation))
	}

	sketch, err := makeSketch(sketchLocation, allSketchFilePaths, logger)
	if err != nil {
		return i18n.WrapError(err)
	}

	ctx.SketchLocation = sketchLocation
	ctx.Sketch = sketch

	return nil
}
예제 #8
0
func Load(filepath string, logger i18n.Logger) (Map, error) {
	bytes, err := ioutil.ReadFile(filepath)
	if err != nil {
		return nil, err
	}

	text := string(bytes)
	text = strings.Replace(text, "\r\n", "\n", -1)
	text = strings.Replace(text, "\r", "\n", -1)

	properties := make(Map)

	for _, line := range strings.Split(text, "\n") {
		err := properties.loadSingleLine(line)
		if err != nil {
			return nil, i18n.ErrorfWithLogger(logger, constants.MSG_WRONG_PROPERTIES_FILE, line, filepath)
		}
	}

	return properties, nil
}
func (s *FailIfBuildPathEqualsSketchPath) Run(ctx *types.Context) error {
	if ctx.BuildPath == "" || ctx.SketchLocation == "" {
		return nil
	}

	buildPath, err := filepath.Abs(ctx.BuildPath)
	if err != nil {
		return i18n.WrapError(err)
	}

	sketchPath, err := filepath.Abs(ctx.SketchLocation)
	if err != nil {
		return i18n.WrapError(err)
	}
	sketchPath = filepath.Dir(sketchPath)

	if buildPath == sketchPath {
		return i18n.ErrorfWithLogger(ctx.GetLogger(), constants.MSG_SKETCH_CANT_BE_IN_BUILDPATH)
	}

	return nil
}
func (s *TargetBoardResolver) Run(ctx *types.Context) error {
	logger := ctx.GetLogger()

	fqbn := ctx.FQBN

	fqbnParts := strings.Split(fqbn, ":")
	if len(fqbnParts) < 3 {
		return i18n.ErrorfWithLogger(logger, constants.MSG_FQBN_INVALID, fqbn)
	}
	targetPackageName := fqbnParts[0]
	targetPlatformName := fqbnParts[1]
	targetBoardName := fqbnParts[2]

	packages := ctx.Hardware

	targetPackage := packages.Packages[targetPackageName]
	if targetPackage == nil {
		return i18n.ErrorfWithLogger(logger, constants.MSG_PACKAGE_UNKNOWN, targetPackageName)
	}

	targetPlatform := targetPackage.Platforms[targetPlatformName]
	if targetPlatform == nil {
		return i18n.ErrorfWithLogger(logger, constants.MSG_PLATFORM_UNKNOWN, targetPlatformName, targetPackageName)
	}

	targetBoard := targetPlatform.Boards[targetBoardName]
	if targetBoard == nil {
		return i18n.ErrorfWithLogger(logger, constants.MSG_BOARD_UNKNOWN, targetBoardName, targetPlatformName, targetPackageName)
	}

	ctx.TargetPackage = targetPackage
	ctx.TargetPlatform = targetPlatform
	ctx.TargetBoard = targetBoard

	if len(fqbnParts) > 3 {
		addAdditionalPropertiesToTargetBoard(targetBoard, fqbnParts[3])
	}

	core := targetBoard.Properties[constants.BUILD_PROPERTIES_BUILD_CORE]
	if core == constants.EMPTY_STRING {
		core = DEFAULT_BUILD_CORE
	}

	var corePlatform *types.Platform
	coreParts := strings.Split(core, ":")
	if len(coreParts) > 1 {
		core = coreParts[1]
		if packages.Packages[coreParts[0]] == nil {
			return i18n.ErrorfWithLogger(logger, constants.MSG_MISSING_CORE_FOR_BOARD, coreParts[0])

		}
		corePlatform = packages.Packages[coreParts[0]].Platforms[targetPlatform.PlatformId]
	}

	var actualPlatform *types.Platform
	if corePlatform != nil {
		actualPlatform = corePlatform
	} else {
		actualPlatform = targetPlatform
	}

	ctx.BuildCore = core
	ctx.ActualPlatform = actualPlatform

	return nil
}