func (s *CreateBuildOptionsMap) Run(context map[string]interface{}) error {
	buildOptions := make(map[string]string)

	for _, key := range []string{constants.CTX_HARDWARE_FOLDERS, constants.CTX_TOOLS_FOLDERS, constants.CTX_LIBRARIES_FOLDERS, constants.CTX_FQBN, constants.CTX_SKETCH_LOCATION, constants.CTX_BUILD_PROPERTIES_RUNTIME_IDE_VERSION} {
		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
}
Example #2
0
func (s *CTagsRunner) Run(context map[string]interface{}) error {
	buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string)
	ctagsTargetFileName := context[constants.CTX_CTAGS_TEMP_FILE_NAME].(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[constants.BUILD_PROPERTIES_SOURCE_FILE] = ctagsTargetFileName

	pattern := properties[constants.BUILD_PROPERTIES_PATTERN]
	if pattern == constants.EMPTY_STRING {
		return utils.Errorf(context, constants.MSG_PATTERN_MISSING, constants.CTAGS)
	}

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

	verbose := context[constants.CTX_VERBOSE].(bool)
	if verbose {
		fmt.Println(commandLine)
	}

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

	context[constants.CTX_CTAGS_OUTPUT] = string(sourceBytes)

	return nil
}
func (s *HardwareLoader) Run(context map[string]interface{}) error {
	mainHardwarePlatformTxt := make(map[string]string)

	packages := make(map[string]*types.Package)

	folders := context[constants.CTX_HARDWARE_FOLDERS].([]string)
	folders, err := utils.AbsolutizePaths(folders)
	if err != nil {
		return utils.WrapError(err)
	}

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

		if len(mainHardwarePlatformTxt) == 0 {
			mainHardwarePlatformTxt, err = props.SafeLoad(filepath.Join(folder, constants.FILE_PLATFORM_TXT))
			if err != nil {
				return utils.WrapError(err)
			}
		}
		hardwarePlatformTxt, err := props.SafeLoad(filepath.Join(folder, constants.FILE_PLATFORM_TXT))
		if err != nil {
			return utils.WrapError(err)
		}
		hardwarePlatformTxt = utils.MergeMapsOfStrings(make(map[string]string), mainHardwarePlatformTxt, hardwarePlatformTxt)

		subfolders, err := utils.ReadDirFiltered(folder, utils.FilterDirs)
		if err != nil {
			return utils.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, hardwarePlatformTxt)
			if err != nil {
				return utils.WrapError(err)
			}
			packages[packageId] = targetPackage
		}
	}

	context[constants.CTX_HARDWARE] = packages

	return nil
}
func (s *CoanRunner) Run(context map[string]interface{}) error {
	source := context[constants.CTX_SOURCE].(string)
	source += "\n"
	verbose := context[constants.CTX_VERBOSE].(bool)

	preprocPath := context[constants.CTX_PREPROC_PATH].(string)
	err := utils.EnsureFolderExists(preprocPath)
	if err != nil {
		return utils.WrapError(err)
	}

	coanTargetFileName := filepath.Join(preprocPath, constants.FILE_COAN_TARGET)
	err = utils.WriteFile(coanTargetFileName, source)
	if err != nil {
		return utils.WrapError(err)
	}

	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]
	if pattern == constants.EMPTY_STRING {
		return utils.Errorf(context, constants.MSG_PATTERN_MISSING, constants.COAN)
	}

	logger := context[constants.CTX_LOGGER].(i18n.Logger)
	commandLine := properties.ExpandPropsInString(pattern)
	command, err := utils.PrepareCommandFilteredArgs(commandLine, filterAllowedArg, logger)

	if verbose {
		fmt.Println(commandLine)
	}

	sourceBytes, _ := command.Output()

	context[constants.CTX_SOURCE] = string(sourceBytes)

	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 *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 *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
}
func (s *TargetBoardResolver) Run(context map[string]interface{}) error {
	fqbn := context[constants.CTX_FQBN].(string)

	fqbnParts := strings.Split(fqbn, ":")
	targetPackageName := fqbnParts[0]
	targetPlatformName := fqbnParts[1]
	targetBoardName := fqbnParts[2]

	packages := context[constants.CTX_HARDWARE].(*types.Packages)

	targetPackage := packages.Packages[targetPackageName]
	if targetPackage == nil {
		return utils.Errorf(context, constants.MSG_PACKAGE_UNKNOWN, targetPackageName)
	}

	targetPlatform := targetPackage.Platforms[targetPlatformName]
	if targetPlatform == nil {
		return utils.Errorf(context, constants.MSG_PLATFORM_UNKNOWN, targetPlatformName, targetPackageName)
	}

	targetBoard := targetPlatform.Boards[targetBoardName]
	if targetBoard == nil {
		return utils.Errorf(context, constants.MSG_BOARD_UNKNOWN, targetBoardName, targetPlatformName, targetPackageName)
	}

	context[constants.CTX_TARGET_PACKAGE] = targetPackage
	context[constants.CTX_TARGET_PLATFORM] = targetPlatform
	context[constants.CTX_TARGET_BOARD] = 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 utils.Errorf(context, 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
	}

	context[constants.CTX_BUILD_CORE] = core
	context[constants.CTX_ACTUAL_PLATFORM] = actualPlatform

	return nil
}