Unverified Commit 5e01a2ea authored by Alessio Perugini's avatar Alessio Perugini Committed by GitHub

[skip-changelog] legacy: refactor (part 3) (#2302)

* refactor RecipeRunner in a function

* refactor CreateBuildOptionsMap in a function

* refactor LoadPreviousBuildOptionsMap in a function

* refactor StoreBuildOptionsMap in a function

* refactor WipeoutBuildPathIfBuildOptionsChanged in a function

* refactor ContainerBuildOptions in a function

* refactor MergeSketchWithBootloader in a function

* refactor PrintUsedLibrariesIfVerbose in a function

* refactor UnusedCompiledLibrariesRemover in a function

* refactor WarnAboutArchIncompatibleLibraries in a function

* refactor CreateMakeRule in a function

* move include finder with regex tests under detector

* move jobs properites in arduino/builder component

* remove sketch property from context

* apply CR suggestion
parent 65915d8a
......@@ -26,6 +26,9 @@ type Builder struct {
sketch *sketch.Sketch
buildProperties *properties.Map
// Parallel processes
jobs int
// core related
coreBuildCachePath *paths.Path
}
......@@ -37,6 +40,7 @@ func NewBuilder(
buildPath *paths.Path,
optimizeForDebug bool,
coreBuildCachePath *paths.Path,
jobs int,
) *Builder {
buildProperties := properties.NewMap()
if boardBuildProperties != nil {
......@@ -64,6 +68,7 @@ func NewBuilder(
sketch: sk,
buildProperties: buildProperties,
coreBuildCachePath: coreBuildCachePath,
jobs: jobs,
}
}
......@@ -71,3 +76,8 @@ func NewBuilder(
func (b *Builder) GetBuildProperties() *properties.Map {
return b.buildProperties
}
// Jobs number of parallel processes
func (b *Builder) Jobs() int {
return b.jobs
}
......@@ -13,7 +13,7 @@
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.
package test
package detector_test
import (
"testing"
......
......@@ -21,6 +21,7 @@ import (
"regexp"
"github.com/arduino/arduino-cli/arduino/builder/cpp"
"github.com/arduino/arduino-cli/arduino/sketch"
"github.com/arduino/arduino-cli/i18n"
"github.com/arduino/go-paths-helper"
......@@ -32,6 +33,11 @@ var (
tr = i18n.Tr
)
// Sketch fixdoc
func (b *Builder) Sketch() *sketch.Sketch {
return b.sketch
}
// PrepareSketchBuildPath copies the sketch source files in the build path.
// The .ino files are merged together to create a .cpp file (by the way, the
// .cpp file still needs to be Arduino-preprocessed to compile).
......
......@@ -48,7 +48,7 @@ func TestMergeSketchSources(t *testing.T) {
}
mergedSources := strings.ReplaceAll(string(mergedBytes), "%s", pathToGoldenSource)
b := NewBuilder(sk, nil, nil, false, nil)
b := NewBuilder(sk, nil, nil, false, nil, 0)
offset, source, err := b.sketchMergeSources(nil)
require.Nil(t, err)
require.Equal(t, 2, offset)
......@@ -61,7 +61,7 @@ func TestMergeSketchSourcesArduinoIncluded(t *testing.T) {
require.NotNil(t, sk)
// ensure not to include Arduino.h when it's already there
b := NewBuilder(sk, nil, nil, false, nil)
b := NewBuilder(sk, nil, nil, false, nil, 0)
_, source, err := b.sketchMergeSources(nil)
require.Nil(t, err)
require.Equal(t, 1, strings.Count(source, "<Arduino.h>"))
......@@ -76,7 +76,7 @@ func TestCopyAdditionalFiles(t *testing.T) {
sk1, err := sketch.New(paths.New("testdata", t.Name()))
require.Nil(t, err)
require.Equal(t, sk1.AdditionalFiles.Len(), 1)
b1 := NewBuilder(sk1, nil, nil, false, nil)
b1 := NewBuilder(sk1, nil, nil, false, nil, 0)
// copy the sketch over, create a fake main file we don't care about it
// but we need it for `SketchLoad` to succeed later
......
......@@ -169,7 +169,14 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
coreBuildCachePath = buildCachePath.Join("core")
}
sketchBuilder := bldr.NewBuilder(sk, boardBuildProperties, buildPath, req.GetOptimizeForDebug(), coreBuildCachePath)
sketchBuilder := bldr.NewBuilder(
sk,
boardBuildProperties,
buildPath,
req.GetOptimizeForDebug(),
coreBuildCachePath,
int(req.GetJobs()),
)
buildProperties := sketchBuilder.GetBuildProperties()
......@@ -197,7 +204,6 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
builderCtx.BuildProperties = buildProperties
builderCtx.CustomBuildProperties = customBuildPropertiesArgs
builderCtx.FQBN = fqbn
builderCtx.Sketch = sk
builderCtx.BuildPath = buildPath
builderCtx.ProgressCB = progressCB
......@@ -212,7 +218,6 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
)
builderCtx.Verbose = req.GetVerbose()
builderCtx.Jobs = int(req.GetJobs())
builderCtx.WarningsLevel = req.GetWarnings()
if builderCtx.WarningsLevel == "" {
......@@ -243,7 +248,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
builderCtx.LibrariesBuildPath = librariesBuildPath
builderCtx.CoreBuildPath = coreBuildPath
if builderCtx.BuildPath.Canonical().EqualsTo(builderCtx.Sketch.FullPath.Canonical()) {
if builderCtx.BuildPath.Canonical().EqualsTo(sk.FullPath.Canonical()) {
return r, &arduino.CompileFailedError{
Message: tr("Sketch cannot be located in build path. Please specify a different build path"),
}
......@@ -365,8 +370,13 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
exportBinaries = false
}
if exportBinaries {
presaveHex := builder.RecipeByPrefixSuffixRunner{Prefix: "recipe.hooks.savehex.presavehex", Suffix: ".pattern"}
if err := presaveHex.Run(builderCtx); err != nil {
err := builder.RecipeByPrefixSuffixRunner(
"recipe.hooks.savehex.presavehex", ".pattern", false,
builderCtx.OnlyUpdateCompilationDatabase, builderCtx.Verbose,
builderCtx.BuildProperties, builderCtx.Stdout, builderCtx.Stderr,
func(msg string) { builderCtx.Info(msg) },
)
if err != nil {
return r, err
}
......@@ -404,8 +414,13 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
}
}
postsaveHex := builder.RecipeByPrefixSuffixRunner{Prefix: "recipe.hooks.savehex.postsavehex", Suffix: ".pattern"}
if err := postsaveHex.Run(builderCtx); err != nil {
err = builder.RecipeByPrefixSuffixRunner(
"recipe.hooks.savehex.postsavehex", ".pattern", false,
builderCtx.OnlyUpdateCompilationDatabase, builderCtx.Verbose,
builderCtx.BuildProperties, builderCtx.Stdout, builderCtx.Stderr,
func(msg string) { builderCtx.Info(msg) },
)
if err != nil {
return r, err
}
}
......
This diff is collapsed.
......@@ -16,27 +16,45 @@
package builder
import (
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/arduino-cli/arduino/sketch"
"github.com/arduino/go-paths-helper"
properties "github.com/arduino/go-properties-orderedmap"
"github.com/pkg/errors"
)
type ContainerBuildOptions struct{}
func ContainerBuildOptions(
hardwareDirs, builtInToolsDirs, otherLibrariesDirs paths.PathList,
builtInLibrariesDirs, buildPath *paths.Path,
sketch *sketch.Sketch,
customBuildProperties []string,
fqbn string,
clean bool,
buildProperties *properties.Map,
) (string, string, string, error) {
buildOptionsJSON, err := CreateBuildOptionsMap(
hardwareDirs, builtInToolsDirs, otherLibrariesDirs,
builtInLibrariesDirs, sketch, customBuildProperties,
fqbn, buildProperties.Get("compiler.optimization_flags"),
)
if err != nil {
return "", "", "", errors.WithStack(err)
}
func (s *ContainerBuildOptions) Run(ctx *types.Context) error {
commands := []types.Command{
&CreateBuildOptionsMap{},
&LoadPreviousBuildOptionsMap{},
&WipeoutBuildPathIfBuildOptionsChanged{},
&StoreBuildOptionsMap{},
buildOptionsJSONPrevious, err := LoadPreviousBuildOptionsMap(buildPath)
if err != nil {
return "", "", "", errors.WithStack(err)
}
for _, command := range commands {
PrintRingNameIfDebug(ctx, command)
err := command.Run(ctx)
if err != nil {
return errors.WithStack(err)
}
infoOut, err := WipeoutBuildPathIfBuildOptionsChanged(
clean,
buildPath,
buildOptionsJSON,
buildOptionsJSONPrevious,
buildProperties,
)
if err != nil {
return "", "", "", errors.WithStack(err)
}
return nil
return buildOptionsJSON, buildOptionsJSONPrevious, infoOut, StoreBuildOptionsMap(buildPath, buildOptionsJSON)
}
......@@ -17,20 +17,47 @@ package builder
import (
"encoding/json"
"strings"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/arduino-cli/arduino/sketch"
"github.com/arduino/go-paths-helper"
properties "github.com/arduino/go-properties-orderedmap"
"github.com/pkg/errors"
)
type CreateBuildOptionsMap struct{}
func CreateBuildOptionsMap(
hardwareDirs, builtInToolsDirs, otherLibrariesDirs paths.PathList,
builtInLibrariesDirs *paths.Path,
sketch *sketch.Sketch,
customBuildProperties []string,
fqbn, compilerOptimizationFlags string,
) (string, error) {
opts := properties.NewMap()
opts.Set("hardwareFolders", strings.Join(hardwareDirs.AsStrings(), ","))
opts.Set("builtInToolsFolders", strings.Join(builtInToolsDirs.AsStrings(), ","))
if builtInLibrariesDirs != nil {
opts.Set("builtInLibrariesFolders", builtInLibrariesDirs.String())
}
opts.Set("otherLibrariesFolders", strings.Join(otherLibrariesDirs.AsStrings(), ","))
opts.SetPath("sketchLocation", sketch.FullPath)
var additionalFilesRelative []string
absPath := sketch.FullPath.Parent()
for _, f := range sketch.AdditionalFiles {
relPath, err := f.RelTo(absPath)
if err != nil {
continue // ignore
}
additionalFilesRelative = append(additionalFilesRelative, relPath.String())
}
opts.Set("fqbn", fqbn)
opts.Set("customBuildProperties", strings.Join(customBuildProperties, ","))
opts.Set("additionalFiles", strings.Join(additionalFilesRelative, ","))
opts.Set("compiler.optimization_flags", compilerOptimizationFlags)
func (s *CreateBuildOptionsMap) Run(ctx *types.Context) error {
buildOptions := ctx.ExtractBuildOptions()
bytes, err := json.MarshalIndent(buildOptions, "", " ")
buildOptionsJSON, err := json.MarshalIndent(opts, "", " ")
if err != nil {
return errors.WithStack(err)
return "", errors.WithStack(err)
}
ctx.BuildOptionsJson = string(bytes)
return nil
return string(buildOptionsJSON), nil
}
......@@ -23,23 +23,29 @@ import (
"regexp"
"strings"
"github.com/arduino/go-paths-helper"
properties "github.com/arduino/go-properties-orderedmap"
"golang.org/x/exp/slices"
"github.com/arduino/arduino-cli/arduino/builder/utils"
"github.com/arduino/arduino-cli/arduino/globals"
"github.com/arduino/arduino-cli/arduino/libraries"
"github.com/arduino/arduino-cli/arduino/sketch"
"github.com/arduino/arduino-cli/legacy/builder/constants"
"github.com/arduino/arduino-cli/legacy/builder/types"
)
type ExportProjectCMake struct {
// Was there an error while compiling the sketch?
SketchError bool
}
var lineMatcher = regexp.MustCompile(`^#line\s\d+\s"`)
func (s *ExportProjectCMake) Run(ctx *types.Context) error {
func ExportProjectCMake(
sketchError bool, // Was there an error while compiling the sketch?
buildPath, sketchBuildPath *paths.Path,
importedLibraries libraries.List,
buildProperties *properties.Map,
sketch *sketch.Sketch,
includeFolders paths.PathList,
lineOffset int,
onlyUpdateCompilationDatabase bool,
) ([]byte, []byte, error) {
// copies the contents of the file named src to the file named
// by dst. The file will be created if it does not already exist. If the
// destination file exists, all it's contents will be replaced by the contents
......@@ -175,12 +181,13 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error {
}
var validStaticLibExtensions = []string{".a"}
if s.SketchError || !canExportCmakeProject(ctx) {
return nil
// If sketch error or cannot export Cmake project
if sketchError || buildProperties.Get("compiler.export_cmake") == "" {
return nil, nil, nil
}
// Create new cmake subFolder - clean if the folder is already there
cmakeFolder := ctx.BuildPath.Join("_cmake")
cmakeFolder := buildPath.Join("_cmake")
if _, err := cmakeFolder.Stat(); err == nil {
cmakeFolder.RemoveAll()
}
......@@ -197,10 +204,10 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error {
cmakeFile := cmakeFolder.Join("CMakeLists.txt")
dynamicLibsFromPkgConfig := map[string]bool{}
for _, library := range ctx.SketchLibrariesDetector.ImportedLibraries() {
for _, library := range importedLibraries {
// Copy used libraries in the correct folder
libDir := libBaseFolder.Join(library.DirName)
mcu := ctx.BuildProperties.Get("build.mcu")
mcu := buildProperties.Get("build.mcu")
copyDir(library.InstallDir.String(), libDir.String(), validExportExtensions)
// Read cmake options if available
......@@ -231,20 +238,28 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error {
}
// Copy core + variant in use + preprocessed sketch in the correct folders
err := copyDir(ctx.BuildProperties.Get("build.core.path"), coreFolder.String(), validExportExtensions)
err := copyDir(buildProperties.Get("build.core.path"), coreFolder.String(), validExportExtensions)
if err != nil {
fmt.Println(err)
}
err = copyDir(ctx.BuildProperties.Get("build.variant.path"), coreFolder.Join("variant").String(), validExportExtensions)
err = copyDir(buildProperties.Get("build.variant.path"), coreFolder.Join("variant").String(), validExportExtensions)
if err != nil {
fmt.Println(err)
}
if err := PreprocessSketch(ctx); err != nil {
return err
normalOutput, verboseOutput, err := PreprocessSketch(
sketch,
buildPath,
includeFolders,
lineOffset,
buildProperties,
onlyUpdateCompilationDatabase,
)
if err != nil {
return normalOutput, verboseOutput, err
}
err = copyDir(ctx.SketchBuildPath.String(), cmakeFolder.Join("sketch").String(), validExportExtensions)
err = copyDir(sketchBuildPath.String(), cmakeFolder.Join("sketch").String(), validExportExtensions)
if err != nil {
fmt.Println(err)
}
......@@ -279,9 +294,9 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error {
var dynamicLibsFromGccMinusL []string
var linkDirectories []string
extractCompileFlags(ctx, constants.RECIPE_C_COMBINE_PATTERN, &defines, &dynamicLibsFromGccMinusL, &linkerflags, &linkDirectories)
extractCompileFlags(ctx, "recipe.c.o.pattern", &defines, &dynamicLibsFromGccMinusL, &linkerflags, &linkDirectories)
extractCompileFlags(ctx, "recipe.cpp.o.pattern", &defines, &dynamicLibsFromGccMinusL, &linkerflags, &linkDirectories)
extractCompileFlags(buildProperties, constants.RECIPE_C_COMBINE_PATTERN, &defines, &dynamicLibsFromGccMinusL, &linkerflags, &linkDirectories)
extractCompileFlags(buildProperties, "recipe.c.o.pattern", &defines, &dynamicLibsFromGccMinusL, &linkerflags, &linkDirectories)
extractCompileFlags(buildProperties, "recipe.cpp.o.pattern", &defines, &dynamicLibsFromGccMinusL, &linkerflags, &linkDirectories)
// Extract folders with .h in them for adding in include list
headerFiles, _ := utils.FindFilesInFolder(cmakeFolder, true, validHeaderExtensions...)
......@@ -292,7 +307,7 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error {
// Generate the CMakeLists global file
projectName := ctx.Sketch.Name
projectName := sketch.Name
cmakelist := "cmake_minimum_required(VERSION 3.5.0)\n"
cmakelist += "INCLUDE(FindPkgConfig)\n"
......@@ -349,14 +364,10 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error {
cmakeFile.WriteFile([]byte(cmakelist))
return nil
}
func canExportCmakeProject(ctx *types.Context) bool {
return ctx.BuildProperties.Get("compiler.export_cmake") != ""
return normalOutput, verboseOutput, nil
}
func extractCompileFlags(ctx *types.Context, recipe string, defines, dynamicLibs, linkerflags, linkDirectories *[]string) {
func extractCompileFlags(buildProperties *properties.Map, recipe string, defines, dynamicLibs, linkerflags, linkDirectories *[]string) {
appendIfNotPresent := func(target []string, elements ...string) []string {
for _, element := range elements {
if !slices.Contains(target, element) {
......@@ -366,7 +377,7 @@ func extractCompileFlags(ctx *types.Context, recipe string, defines, dynamicLibs
return target
}
command, _ := utils.PrepareCommandForRecipe(ctx.BuildProperties, recipe, true)
command, _ := utils.PrepareCommandForRecipe(buildProperties, recipe, true)
for _, arg := range command.GetArgs() {
if strings.HasPrefix(arg, "-D") {
......
......@@ -17,24 +17,20 @@ package builder
import (
"github.com/arduino/arduino-cli/legacy/builder/constants"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/go-paths-helper"
"github.com/pkg/errors"
)
type LoadPreviousBuildOptionsMap struct{}
func (s *LoadPreviousBuildOptionsMap) Run(ctx *types.Context) error {
buildOptionsFile := ctx.BuildPath.Join(constants.BUILD_OPTIONS_FILE)
func LoadPreviousBuildOptionsMap(buildPath *paths.Path) (string, error) {
buildOptionsFile := buildPath.Join(constants.BUILD_OPTIONS_FILE)
if buildOptionsFile.NotExist() {
return nil
return "", nil
}
bytes, err := buildOptionsFile.ReadFile()
buildOptionsJsonPrevious, err := buildOptionsFile.ReadFile()
if err != nil {
return errors.WithStack(err)
return "", errors.WithStack(err)
}
ctx.BuildOptionsJsonPrevious = string(bytes)
return nil
return string(buildOptionsJsonPrevious), nil
}
......@@ -20,29 +20,30 @@ import (
"strconv"
"strings"
"github.com/arduino/arduino-cli/arduino/sketch"
"github.com/arduino/arduino-cli/legacy/builder/constants"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/go-paths-helper"
"github.com/arduino/go-properties-orderedmap"
"github.com/marcinbor85/gohex"
"github.com/pkg/errors"
)
type MergeSketchWithBootloader struct{}
func (s *MergeSketchWithBootloader) Run(ctx *types.Context) error {
if ctx.OnlyUpdateCompilationDatabase {
func MergeSketchWithBootloader(
onlyUpdateCompilationDatabase, verbose bool,
buildPath *paths.Path,
sketch *sketch.Sketch,
buildProperties *properties.Map,
printInfoFn, printWarnFn func(string),
) error {
if onlyUpdateCompilationDatabase {
return nil
}
buildProperties := ctx.BuildProperties
if !buildProperties.ContainsKey(constants.BUILD_PROPERTIES_BOOTLOADER_NOBLINK) && !buildProperties.ContainsKey(constants.BUILD_PROPERTIES_BOOTLOADER_FILE) {
return nil
}
buildPath := ctx.BuildPath
sketch := ctx.Sketch
sketchFileName := sketch.MainFile.Base()
sketchInBuildPath := buildPath.Join(sketchFileName + ".hex")
sketchInSubfolder := buildPath.Join(constants.FOLDER_SKETCH, sketchFileName+".hex")
......@@ -65,8 +66,8 @@ func (s *MergeSketchWithBootloader) Run(ctx *types.Context) error {
bootloaderPath := buildProperties.GetPath("runtime.platform.path").Join(constants.FOLDER_BOOTLOADERS, bootloader)
if bootloaderPath.NotExist() {
if ctx.Verbose {
ctx.Warn(tr("Bootloader file specified but missing: %[1]s", bootloaderPath))
if verbose {
printWarnFn(tr("Bootloader file specified but missing: %[1]s", bootloaderPath))
}
return nil
}
......@@ -75,13 +76,13 @@ func (s *MergeSketchWithBootloader) Run(ctx *types.Context) error {
// Ignore merger errors for the first iteration
maximumBinSize := 16000000
if uploadMaxSize, ok := ctx.BuildProperties.GetOk("upload.maximum_size"); ok {
if uploadMaxSize, ok := buildProperties.GetOk("upload.maximum_size"); ok {
maximumBinSize, _ = strconv.Atoi(uploadMaxSize)
maximumBinSize *= 2
}
err := merge(builtSketchPath, bootloaderPath, mergedSketchPath, maximumBinSize)
if err != nil && ctx.Verbose {
ctx.Info(err.Error())
if err != nil && verbose {
printInfoFn(err.Error())
}
return nil
......
......@@ -16,31 +16,31 @@
package builder
import (
"bytes"
"time"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/arduino-cli/arduino/libraries"
)
type PrintUsedLibrariesIfVerbose struct{}
func (s *PrintUsedLibrariesIfVerbose) Run(ctx *types.Context) error {
if !ctx.Verbose || len(ctx.SketchLibrariesDetector.ImportedLibraries()) == 0 {
return nil
func PrintUsedLibrariesIfVerbose(verbose bool, importedLibraries libraries.List) ([]byte, error) {
if !verbose || len(importedLibraries) == 0 {
return nil, nil
}
for _, library := range ctx.SketchLibrariesDetector.ImportedLibraries() {
infoBuf := &bytes.Buffer{}
for _, library := range importedLibraries {
legacy := ""
if library.IsLegacy {
legacy = tr("(legacy)")
}
if library.Version.String() == "" {
ctx.Info(
infoBuf.WriteString(
tr("Using library %[1]s in folder: %[2]s %[3]s",
library.Name,
library.InstallDir,
legacy))
} else {
ctx.Info(
infoBuf.WriteString(
tr("Using library %[1]s at version %[2]s in folder: %[3]s %[4]s",
library.Name,
library.Version,
......@@ -50,5 +50,5 @@ func (s *PrintUsedLibrariesIfVerbose) Run(ctx *types.Context) error {
}
time.Sleep(100 * time.Millisecond)
return nil
return infoBuf.Bytes(), nil
}
......@@ -17,28 +17,30 @@ package builder
import (
"fmt"
"io"
"sort"
"strings"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/arduino-cli/arduino/builder/utils"
properties "github.com/arduino/go-properties-orderedmap"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
type RecipeByPrefixSuffixRunner struct {
Prefix string
Suffix string
SkipIfOnlyUpdatingCompilationDatabase bool
}
func (s *RecipeByPrefixSuffixRunner) Run(ctx *types.Context) error {
logrus.Debugf(fmt.Sprintf("Looking for recipes like %s", s.Prefix+"*"+s.Suffix))
func RecipeByPrefixSuffixRunner(
prefix, suffix string,
skipIfOnlyUpdatingCompilationDatabase, onlyUpdateCompilationDatabase, verbose bool,
buildProps *properties.Map,
stdoutWriter, stderrWriter io.Writer,
printInfoFn func(string),
) error {
logrus.Debugf(fmt.Sprintf("Looking for recipes like %s", prefix+"*"+suffix))
buildProperties := ctx.BuildProperties.Clone()
recipes := findRecipes(buildProperties, s.Prefix, s.Suffix)
// TODO is it necessary to use Clone?
buildProperties := buildProps.Clone()
recipes := findRecipes(buildProperties, prefix, suffix)
// TODO is it necessary to use Clone?
properties := buildProperties.Clone()
for _, recipe := range recipes {
logrus.Debugf(fmt.Sprintf("Running recipe: %s", recipe))
......@@ -48,16 +50,16 @@ func (s *RecipeByPrefixSuffixRunner) Run(ctx *types.Context) error {
return errors.WithStack(err)
}
if ctx.OnlyUpdateCompilationDatabase && s.SkipIfOnlyUpdatingCompilationDatabase {
if ctx.Verbose {
ctx.Info(tr("Skipping: %[1]s", strings.Join(command.GetArgs(), " ")))
if onlyUpdateCompilationDatabase && skipIfOnlyUpdatingCompilationDatabase {
if verbose {
printInfoFn(tr("Skipping: %[1]s", strings.Join(command.GetArgs(), " ")))
}
return nil
}
verboseInfo, _, _, err := utils.ExecCommand(ctx.Verbose, ctx.Stdout, ctx.Stderr, command, utils.ShowIfVerbose /* stdout */, utils.Show /* stderr */)
if ctx.Verbose {
ctx.Info(string(verboseInfo))
verboseInfo, _, _, err := utils.ExecCommand(verbose, stdoutWriter, stderrWriter, command, utils.ShowIfVerbose /* stdout */, utils.Show /* stderr */)
if verbose {
printInfoFn(string(verboseInfo))
}
if err != nil {
return errors.WithStack(err)
......@@ -65,7 +67,6 @@ func (s *RecipeByPrefixSuffixRunner) Run(ctx *types.Context) error {
}
return nil
}
func findRecipes(buildProperties *properties.Map, patternPrefix string, patternSuffix string) []string {
......
......@@ -17,12 +17,9 @@ package builder
import (
"github.com/arduino/arduino-cli/legacy/builder/constants"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/go-paths-helper"
)
type StoreBuildOptionsMap struct{}
func (s *StoreBuildOptionsMap) Run(ctx *types.Context) error {
ctx.BuildPath.Join(constants.BUILD_OPTIONS_FILE).WriteFile([]byte(ctx.BuildOptionsJson))
return nil
func StoreBuildOptionsMap(buildPath *paths.Path, buildOptionsJson string) error {
return buildPath.Join(constants.BUILD_OPTIONS_FILE).WriteFile([]byte(buildOptionsJson))
}
......@@ -91,13 +91,14 @@ func prepareBuilderTestContext(t *testing.T, ctx *types.Context, sketchPath *pat
pme, _ /* never release... */ := pm.NewExplorer()
ctx.PackageManager = pme
var sk *sketch.Sketch
if sketchPath != nil {
sk, err := sketch.New(sketchPath)
s, err := sketch.New(sketchPath)
require.NoError(t, err)
ctx.Sketch = sk
sk = s
}
ctx.Builder = bldr.NewBuilder(ctx.Sketch, nil, nil, false, nil)
ctx.Builder = bldr.NewBuilder(sk, nil, nil, false, nil, 0)
if fqbn != "" {
ctx.FQBN = parseFQBN(t, fqbn)
targetPackage, targetPlatform, targetBoard, boardBuildProperties, buildPlatform, err := pme.ResolveFQBN(ctx.FQBN)
......@@ -105,7 +106,7 @@ func prepareBuilderTestContext(t *testing.T, ctx *types.Context, sketchPath *pat
requiredTools, err := pme.FindToolsRequiredForBuild(targetPlatform, buildPlatform)
require.NoError(t, err)
ctx.Builder = bldr.NewBuilder(ctx.Sketch, boardBuildProperties, ctx.BuildPath, false /*OptimizeForDebug*/, nil)
ctx.Builder = bldr.NewBuilder(sk, boardBuildProperties, ctx.BuildPath, false /*OptimizeForDebug*/, nil, 0)
ctx.PackageManager = pme
ctx.TargetBoard = targetBoard
ctx.BuildProperties = ctx.Builder.GetBuildProperties()
......@@ -115,8 +116,8 @@ func prepareBuilderTestContext(t *testing.T, ctx *types.Context, sketchPath *pat
ctx.RequiredTools = requiredTools
}
if ctx.Sketch != nil {
require.False(t, ctx.BuildPath.Canonical().EqualsTo(ctx.Sketch.FullPath.Canonical()))
if sk != nil {
require.False(t, ctx.BuildPath.Canonical().EqualsTo(sk.FullPath.Canonical()))
}
if !stepToSkip[skipLibraries] {
......
......@@ -31,15 +31,17 @@ func TestCreateBuildOptionsMap(t *testing.T) {
HardwareDirs: paths.NewPathList("hardware", "hardware2"),
BuiltInToolsDirs: paths.NewPathList("tools"),
OtherLibrariesDirs: paths.NewPathList("libraries"),
Sketch: &sketch.Sketch{FullPath: paths.New("sketchLocation")},
FQBN: parseFQBN(t, "my:nice:fqbn"),
Verbose: true,
BuildPath: paths.New("buildPath"),
BuildProperties: properties.NewFromHashmap(map[string]string{"compiler.optimization_flags": "-Os"}),
}
create := builder.CreateBuildOptionsMap{}
err := create.Run(ctx)
buildPropertiesJSON, err := builder.CreateBuildOptionsMap(
ctx.HardwareDirs, ctx.BuiltInToolsDirs, ctx.OtherLibrariesDirs,
ctx.BuiltInLibrariesDirs, &sketch.Sketch{FullPath: paths.New("sketchLocation")}, ctx.CustomBuildProperties,
ctx.FQBN.String(), ctx.BuildProperties.Get("compiler.optimization_flags"),
)
require.NoError(t, err)
require.Equal(t, `{
......@@ -51,5 +53,5 @@ func TestCreateBuildOptionsMap(t *testing.T) {
"hardwareFolders": "hardware,hardware2",
"otherLibrariesFolders": "libraries",
"sketchLocation": "sketchLocation"
}`, ctx.BuildOptionsJson)
}`, buildPropertiesJSON)
}
......@@ -33,11 +33,10 @@ func TestLoadPreviousBuildOptionsMap(t *testing.T) {
err := buildPath.Join(constants.BUILD_OPTIONS_FILE).WriteFile([]byte("test"))
require.NoError(t, err)
command := builder.LoadPreviousBuildOptionsMap{}
err = command.Run(ctx)
buildOptionsJsonPrevious, err := builder.LoadPreviousBuildOptionsMap(ctx.BuildPath)
require.NoError(t, err)
require.Equal(t, "test", ctx.BuildOptionsJsonPrevious)
require.Equal(t, "test", buildOptionsJsonPrevious)
}
func TestLoadPreviousBuildOptionsMapMissingFile(t *testing.T) {
......@@ -46,9 +45,7 @@ func TestLoadPreviousBuildOptionsMapMissingFile(t *testing.T) {
buildPath := SetupBuildPath(t, ctx)
defer buildPath.RemoveAll()
command := builder.LoadPreviousBuildOptionsMap{}
err := command.Run(ctx)
buildOptionsJsonPrevious, err := builder.LoadPreviousBuildOptionsMap(ctx.BuildPath)
require.NoError(t, err)
require.Empty(t, ctx.BuildOptionsJsonPrevious)
require.Empty(t, buildOptionsJsonPrevious)
}
......@@ -69,14 +69,13 @@ func TestMergeSketchWithBootloader(t *testing.T) {
err = buildPath.Join("sketch", "sketch1.ino.hex").WriteFile([]byte(fakeSketchHex))
require.NoError(t, err)
commands := []types.Command{
&builder.MergeSketchWithBootloader{},
}
for _, command := range commands {
err := command.Run(ctx)
require.NoError(t, err)
}
err = builder.MergeSketchWithBootloader(
ctx.OnlyUpdateCompilationDatabase, ctx.Verbose,
ctx.BuildPath, ctx.Builder.Sketch(), ctx.BuildProperties,
func(s string) { ctx.Info(s) },
func(s string) { ctx.Warn(s) },
)
require.NoError(t, err)
bytes, err := buildPath.Join("sketch", "sketch1.ino.with_bootloader.hex").ReadFile()
require.NoError(t, err)
......@@ -127,14 +126,13 @@ func TestMergeSketchWithBootloaderSketchInBuildPath(t *testing.T) {
err = buildPath.Join("sketch1.ino.hex").WriteFile([]byte(fakeSketchHex))
require.NoError(t, err)
commands := []types.Command{
&builder.MergeSketchWithBootloader{},
}
for _, command := range commands {
err := command.Run(ctx)
require.NoError(t, err)
}
err = builder.MergeSketchWithBootloader(
ctx.OnlyUpdateCompilationDatabase, ctx.Verbose,
ctx.BuildPath, ctx.Builder.Sketch(), ctx.BuildProperties,
func(s string) { ctx.Info(s) },
func(s string) { ctx.Warn(s) },
)
require.NoError(t, err)
bytes, err := buildPath.Join("sketch1.ino.with_bootloader.hex").ReadFile()
require.NoError(t, err)
......@@ -154,8 +152,12 @@ func TestMergeSketchWithBootloaderWhenNoBootloaderAvailable(t *testing.T) {
buildProperties.Remove(constants.BUILD_PROPERTIES_BOOTLOADER_NOBLINK)
buildProperties.Remove(constants.BUILD_PROPERTIES_BOOTLOADER_FILE)
command := &builder.MergeSketchWithBootloader{}
err := command.Run(ctx)
err := builder.MergeSketchWithBootloader(
ctx.OnlyUpdateCompilationDatabase, ctx.Verbose,
ctx.BuildPath, ctx.Builder.Sketch(), ctx.BuildProperties,
func(s string) { ctx.Info(s) },
func(s string) { ctx.Warn(s) },
)
require.NoError(t, err)
exist, err := buildPath.Join("sketch.ino.with_bootloader.hex").ExistCheck()
......@@ -210,14 +212,13 @@ func TestMergeSketchWithBootloaderPathIsParameterized(t *testing.T) {
err = buildPath.Join("sketch", "sketch1.ino.hex").WriteFile([]byte(fakeSketchHex))
require.NoError(t, err)
commands := []types.Command{
&builder.MergeSketchWithBootloader{},
}
for _, command := range commands {
err := command.Run(ctx)
require.NoError(t, err)
}
err = builder.MergeSketchWithBootloader(
ctx.OnlyUpdateCompilationDatabase, ctx.Verbose,
ctx.BuildPath, ctx.Builder.Sketch(), ctx.BuildProperties,
func(s string) { ctx.Info(s) },
func(s string) { ctx.Warn(s) },
)
require.NoError(t, err)
bytes, err := buildPath.Join("sketch", "sketch1.ino.with_bootloader.hex").ReadFile()
require.NoError(t, err)
......
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.
package test
import (
"testing"
"github.com/arduino/arduino-cli/legacy/builder"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/go-properties-orderedmap"
"github.com/stretchr/testify/require"
)
// TODO
// I can't find a command I can run on linux, mac and windows
// and that allows to test if the recipe is actually run
// So this test is pretty useless
func TestRecipeRunner(t *testing.T) {
ctx := &types.Context{}
buildProperties := properties.NewMap()
ctx.BuildProperties = buildProperties
buildProperties.Set("recipe.hooks.prebuild.1.pattern", "echo")
commands := []types.Command{
&builder.RecipeByPrefixSuffixRunner{Prefix: "recipe.hooks.prebuild", Suffix: ".pattern"},
}
for _, command := range commands {
err := command.Run(ctx)
require.NoError(t, err)
}
}
......@@ -33,7 +33,6 @@ func TestStoreBuildOptionsMap(t *testing.T) {
BuiltInToolsDirs: paths.NewPathList("tools"),
BuiltInLibrariesDirs: paths.New("built-in libraries"),
OtherLibrariesDirs: paths.NewPathList("libraries"),
Sketch: &sketch.Sketch{FullPath: paths.New("sketchLocation")},
FQBN: parseFQBN(t, "my:nice:fqbn"),
CustomBuildProperties: []string{"custom=prop"},
Verbose: true,
......@@ -43,15 +42,16 @@ func TestStoreBuildOptionsMap(t *testing.T) {
buildPath := SetupBuildPath(t, ctx)
defer buildPath.RemoveAll()
commands := []types.Command{
&builder.CreateBuildOptionsMap{},
&builder.StoreBuildOptionsMap{},
}
buildPropertiesJSON, err := builder.CreateBuildOptionsMap(
ctx.HardwareDirs, ctx.BuiltInToolsDirs, ctx.OtherLibrariesDirs,
ctx.BuiltInLibrariesDirs, &sketch.Sketch{FullPath: paths.New("sketchLocation")}, ctx.CustomBuildProperties,
ctx.FQBN.String(), ctx.BuildProperties.Get("compiler.optimization_flags"),
)
require.NoError(t, err)
ctx.BuildOptionsJson = buildPropertiesJSON
for _, command := range commands {
err := command.Run(ctx)
require.NoError(t, err)
}
err = builder.StoreBuildOptionsMap(ctx.BuildPath, ctx.BuildOptionsJson)
require.NoError(t, err)
exist, err := buildPath.Join(constants.BUILD_OPTIONS_FILE).ExistCheck()
require.NoError(t, err)
......
......@@ -42,8 +42,10 @@ func TestUnusedCompiledLibrariesRemover(t *testing.T) {
)
ctx.SketchLibrariesDetector.AppendImportedLibraries(&libraries.Library{Name: "Bridge"})
cmd := builder.UnusedCompiledLibrariesRemover{}
err = cmd.Run(ctx)
err = builder.UnusedCompiledLibrariesRemover(
ctx.LibrariesBuildPath,
ctx.SketchLibrariesDetector.ImportedLibraries(),
)
require.NoError(t, err)
exist, err := temp.Join("SPI").ExistCheck()
......@@ -65,8 +67,10 @@ func TestUnusedCompiledLibrariesRemoverLibDoesNotExist(t *testing.T) {
)
ctx.SketchLibrariesDetector.AppendImportedLibraries(&libraries.Library{Name: "Bridge"})
cmd := builder.UnusedCompiledLibrariesRemover{}
err := cmd.Run(ctx)
err := builder.UnusedCompiledLibrariesRemover(
ctx.LibrariesBuildPath,
ctx.SketchLibrariesDetector.ImportedLibraries(),
)
require.NoError(t, err)
}
......@@ -85,8 +89,10 @@ func TestUnusedCompiledLibrariesRemoverNoUsedLibraries(t *testing.T) {
)
ctx.LibrariesBuildPath = temp
cmd := builder.UnusedCompiledLibrariesRemover{}
err = cmd.Run(ctx)
err = builder.UnusedCompiledLibrariesRemover(
ctx.LibrariesBuildPath,
ctx.SketchLibrariesDetector.ImportedLibraries(),
)
require.NoError(t, err)
exist, err := temp.Join("SPI").ExistCheck()
......
......@@ -34,14 +34,14 @@ func TestWipeoutBuildPathIfBuildOptionsChanged(t *testing.T) {
buildPath.Join("should_be_deleted.txt").Truncate()
commands := []types.Command{
&builder.WipeoutBuildPathIfBuildOptionsChanged{},
}
for _, command := range commands {
err := command.Run(ctx)
require.NoError(t, err)
}
_, err := builder.WipeoutBuildPathIfBuildOptionsChanged(
ctx.Clean,
ctx.BuildPath,
ctx.BuildOptionsJson,
ctx.BuildOptionsJsonPrevious,
ctx.BuildProperties,
)
require.NoError(t, err)
exist, err := buildPath.ExistCheck()
require.NoError(t, err)
......@@ -66,14 +66,14 @@ func TestWipeoutBuildPathIfBuildOptionsChangedNoPreviousBuildOptions(t *testing.
require.NoError(t, buildPath.Join("should_not_be_deleted.txt").Truncate())
commands := []types.Command{
&builder.WipeoutBuildPathIfBuildOptionsChanged{},
}
for _, command := range commands {
err := command.Run(ctx)
require.NoError(t, err)
}
_, err := builder.WipeoutBuildPathIfBuildOptionsChanged(
ctx.Clean,
ctx.BuildPath,
ctx.BuildOptionsJson,
ctx.BuildOptionsJsonPrevious,
ctx.BuildProperties,
)
require.NoError(t, err)
exist, err := buildPath.ExistCheck()
require.NoError(t, err)
......
......@@ -19,7 +19,6 @@ import (
"fmt"
"io"
"os"
"strings"
"sync"
"github.com/arduino/arduino-cli/arduino/builder"
......@@ -27,7 +26,6 @@ import (
"github.com/arduino/arduino-cli/arduino/builder/progress"
"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/arduino/sketch"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
paths "github.com/arduino/go-paths-helper"
properties "github.com/arduino/go-properties-orderedmap"
......@@ -67,7 +65,6 @@ type Context struct {
LibrariesObjectFiles paths.PathList
SketchObjectFiles paths.PathList
Sketch *sketch.Sketch
WarningsLevel string
// C++ Parsing
......@@ -84,9 +81,6 @@ type Context struct {
// Custom build properties defined by user (line by line as "key=value" pairs)
CustomBuildProperties []string
// Parallel processes
Jobs int
// Out and Err stream to redirect all output
Stdout io.Writer
Stderr io.Writer
......@@ -106,31 +100,6 @@ type Context struct {
SourceOverride map[string]string
}
func (ctx *Context) ExtractBuildOptions() *properties.Map {
opts := properties.NewMap()
opts.Set("hardwareFolders", strings.Join(ctx.HardwareDirs.AsStrings(), ","))
opts.Set("builtInToolsFolders", strings.Join(ctx.BuiltInToolsDirs.AsStrings(), ","))
if ctx.BuiltInLibrariesDirs != nil {
opts.Set("builtInLibrariesFolders", ctx.BuiltInLibrariesDirs.String())
}
opts.Set("otherLibrariesFolders", strings.Join(ctx.OtherLibrariesDirs.AsStrings(), ","))
opts.SetPath("sketchLocation", ctx.Sketch.FullPath)
var additionalFilesRelative []string
absPath := ctx.Sketch.FullPath.Parent()
for _, f := range ctx.Sketch.AdditionalFiles {
relPath, err := f.RelTo(absPath)
if err != nil {
continue // ignore
}
additionalFilesRelative = append(additionalFilesRelative, relPath.String())
}
opts.Set("fqbn", ctx.FQBN.String())
opts.Set("customBuildProperties", strings.Join(ctx.CustomBuildProperties, ","))
opts.Set("additionalFiles", strings.Join(additionalFilesRelative, ","))
opts.Set("compiler.optimization_flags", ctx.BuildProperties.Get("compiler.optimization_flags"))
return opts
}
func (ctx *Context) PushProgress() {
if ctx.ProgressCB != nil {
ctx.ProgressCB(&rpc.TaskProgress{
......
// This file is part of arduino-cli.
//
// Copyright 2022 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.
package types
import (
"testing"
"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/sketch"
paths "github.com/arduino/go-paths-helper"
"github.com/arduino/go-properties-orderedmap"
"github.com/stretchr/testify/require"
)
func TestInjectBuildOption(t *testing.T) {
fqbn, err := cores.ParseFQBN("aaa:bbb:ccc")
require.NoError(t, err)
{
ctx := &Context{
HardwareDirs: paths.NewPathList("aaa", "bbb"),
BuiltInToolsDirs: paths.NewPathList("ccc", "ddd"),
BuiltInLibrariesDirs: paths.New("eee"),
OtherLibrariesDirs: paths.NewPathList("fff", "ggg"),
Sketch: &sketch.Sketch{FullPath: paths.New("hhh")},
FQBN: fqbn,
CustomBuildProperties: []string{"jjj", "kkk"},
BuildProperties: properties.NewFromHashmap(map[string]string{"compiler.optimization_flags": "lll"}),
}
opts := ctx.ExtractBuildOptions()
require.Equal(t, `properties.Map{
"hardwareFolders": "aaa,bbb",
"builtInToolsFolders": "ccc,ddd",
"builtInLibrariesFolders": "eee",
"otherLibrariesFolders": "fff,ggg",
"sketchLocation": "hhh",
"fqbn": "aaa:bbb:ccc",
"customBuildProperties": "jjj,kkk",
"additionalFiles": "",
"compiler.optimization_flags": "lll",
}`, opts.Dump())
}
}
......@@ -17,26 +17,22 @@ package builder
import (
"github.com/arduino/arduino-cli/arduino/libraries"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/go-paths-helper"
"github.com/pkg/errors"
"golang.org/x/exp/slices"
)
type UnusedCompiledLibrariesRemover struct{}
func (s *UnusedCompiledLibrariesRemover) Run(ctx *types.Context) error {
librariesBuildPath := ctx.LibrariesBuildPath
func UnusedCompiledLibrariesRemover(librariesBuildPath *paths.Path, importedLibraries libraries.List) error {
if librariesBuildPath.NotExist() {
return nil
}
libraryNames := toLibraryNames(ctx.SketchLibrariesDetector.ImportedLibraries())
files, err := librariesBuildPath.ReadDir()
if err != nil {
return errors.WithStack(err)
}
libraryNames := toLibraryNames(importedLibraries)
for _, file := range files {
if file.IsDir() {
if !slices.Contains(libraryNames, file.Base()) {
......
......@@ -18,30 +18,28 @@ package builder
import (
"strings"
"github.com/arduino/arduino-cli/legacy/builder/constants"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/libraries"
)
type WarnAboutArchIncompatibleLibraries struct{}
func (s *WarnAboutArchIncompatibleLibraries) Run(ctx *types.Context) error {
targetPlatform := ctx.TargetPlatform
buildProperties := ctx.BuildProperties
func WarnAboutArchIncompatibleLibraries(
targetPlatform *cores.PlatformRelease,
overrides string,
importedLibraries libraries.List,
printInfoFn func(string),
) {
archs := []string{targetPlatform.Platform.Architecture}
if overrides, ok := buildProperties.GetOk(constants.BUILD_PROPERTIES_ARCH_OVERRIDE_CHECK); ok {
if overrides != "" {
archs = append(archs, strings.Split(overrides, ",")...)
}
for _, importedLibrary := range ctx.SketchLibrariesDetector.ImportedLibraries() {
for _, importedLibrary := range importedLibraries {
if !importedLibrary.SupportsAnyArchitectureIn(archs...) {
ctx.Info(
printInfoFn(
tr("WARNING: library %[1]s claims to run on %[2]s architecture(s) and may be incompatible with your current board which runs on %[3]s architecture(s).",
importedLibrary.Name,
strings.Join(importedLibrary.Architectures, ", "),
strings.Join(archs, ", ")))
}
}
return nil
}
......@@ -21,23 +21,23 @@ import (
"github.com/arduino/arduino-cli/arduino/builder/utils"
"github.com/arduino/arduino-cli/legacy/builder/constants"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/go-paths-helper"
properties "github.com/arduino/go-properties-orderedmap"
"github.com/pkg/errors"
)
type WipeoutBuildPathIfBuildOptionsChanged struct{}
func (s *WipeoutBuildPathIfBuildOptionsChanged) Run(ctx *types.Context) error {
if ctx.Clean {
return doCleanup(ctx.BuildPath)
func WipeoutBuildPathIfBuildOptionsChanged(
clean bool,
buildPath *paths.Path,
buildOptionsJson, buildOptionsJsonPrevious string,
buildProperties *properties.Map,
) (string, error) {
if clean {
return "", doCleanup(buildPath)
}
if ctx.BuildOptionsJsonPrevious == "" {
return nil
if buildOptionsJsonPrevious == "" {
return "", nil
}
buildOptionsJson := ctx.BuildOptionsJson
previousBuildOptionsJson := ctx.BuildOptionsJsonPrevious
var opts *properties.Map
if err := json.Unmarshal([]byte(buildOptionsJson), &opts); err != nil || opts == nil {
......@@ -45,9 +45,8 @@ func (s *WipeoutBuildPathIfBuildOptionsChanged) Run(ctx *types.Context) error {
}
var prevOpts *properties.Map
if err := json.Unmarshal([]byte(previousBuildOptionsJson), &prevOpts); err != nil || prevOpts == nil {
ctx.Info(tr("%[1]s invalid, rebuilding all", constants.BUILD_OPTIONS_FILE))
return doCleanup(ctx.BuildPath)
if err := json.Unmarshal([]byte(buildOptionsJsonPrevious), &prevOpts); err != nil || prevOpts == nil {
return tr("%[1]s invalid, rebuilding all", constants.BUILD_OPTIONS_FILE), doCleanup(buildPath)
}
// If SketchLocation path is different but filename is the same, consider it equal
......@@ -61,21 +60,20 @@ func (s *WipeoutBuildPathIfBuildOptionsChanged) Run(ctx *types.Context) error {
// check if any of the files contained in the core folders has changed
// since the json was generated - like platform.txt or similar
// if so, trigger a "safety" wipe
buildProperties := ctx.BuildProperties
targetCoreFolder := buildProperties.GetPath("runtime.platform.path")
coreFolder := buildProperties.GetPath("build.core.path")
realCoreFolder := coreFolder.Parent().Parent()
jsonPath := ctx.BuildPath.Join(constants.BUILD_OPTIONS_FILE)
jsonPath := buildPath.Join(constants.BUILD_OPTIONS_FILE)
coreUnchanged, _ := utils.DirContentIsOlderThan(realCoreFolder, jsonPath, ".txt")
if coreUnchanged && targetCoreFolder != nil && !realCoreFolder.EqualsTo(targetCoreFolder) {
coreUnchanged, _ = utils.DirContentIsOlderThan(targetCoreFolder, jsonPath, ".txt")
}
if coreUnchanged {
return nil
return "", nil
}
}
return doCleanup(ctx.BuildPath)
return "", doCleanup(buildPath)
}
func doCleanup(buildPath *paths.Path) error {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment