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 *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 := utils.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 *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 := utils.LibraryToSourceFolder(newlyImportedLibrary)
			for _, sourceFolder := range sourceFolders {
				foldersWithSources.Push(sourceFolder)
			}
		}
	}

	context[constants.CTX_IMPORTED_LIBRARIES] = importedLibraries

	buildProperties := context[constants.CTX_BUILD_PROPERTIES].(map[string]string)
	verbose := context[constants.CTX_VERBOSE].(bool)
	includeFolders := resolveIncludeFolders(newlyImportedLibraries, buildProperties, verbose)
	context[constants.CTX_INCLUDE_FOLDERS] = includeFolders

	return nil
}