Skip to content

Commit

Permalink
heavily refactored the ContainerBuildOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
alessio-perugini committed Sep 12, 2023
1 parent 900b67e commit 41d66c6
Show file tree
Hide file tree
Showing 15 changed files with 307 additions and 498 deletions.
183 changes: 183 additions & 0 deletions arduino/builder/build_options_manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// 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 [email protected].

package builder

import (
"encoding/json"
"path/filepath"
"strings"

"github.com/arduino/arduino-cli/arduino/builder/logger"
"github.com/arduino/arduino-cli/arduino/builder/utils"
"github.com/arduino/arduino-cli/arduino/sketch"
"github.com/arduino/go-paths-helper"
properties "github.com/arduino/go-properties-orderedmap"
"github.com/pkg/errors"
)

// BuildOptionsManager fixdoc
type BuildOptionsManager struct {
currentOptions *properties.Map
currentBuildOptionsJSON []byte

hardwareDirs paths.PathList
builtInToolsDirs paths.PathList
otherLibrariesDirs paths.PathList
builtInLibrariesDirs *paths.Path
buildPath *paths.Path
runtimePlatformPath *paths.Path
buildCorePath *paths.Path
sketch *sketch.Sketch
customBuildProperties []string
fqbn string
compilerOptimizationFlags string
clean bool
builderLogger *logger.BuilderLogger
}

// NewBuildOptionsManager fixdoc
func NewBuildOptionsManager(
hardwareDirs, builtInToolsDirs, otherLibrariesDirs paths.PathList,
builtInLibrariesDirs, buildPath *paths.Path,
sketch *sketch.Sketch,
customBuildProperties []string,
fqbn string,
clean bool,
compilerOptimizationFlags string,
runtimePlatformPath, buildCorePath *paths.Path,
buildLogger *logger.BuilderLogger,
) *BuildOptionsManager {
opts := properties.NewMap()

opts.Set("hardwareFolders", strings.Join(hardwareDirs.AsStrings(), ","))
opts.Set("builtInToolsFolders", strings.Join(builtInToolsDirs.AsStrings(), ","))
opts.Set("otherLibrariesFolders", strings.Join(otherLibrariesDirs.AsStrings(), ","))
opts.SetPath("sketchLocation", sketch.FullPath)
opts.Set("fqbn", fqbn)
opts.Set("customBuildProperties", strings.Join(customBuildProperties, ","))
opts.Set("compiler.optimization_flags", compilerOptimizationFlags)

if builtInLibrariesDirs != nil {
opts.Set("builtInLibrariesFolders", builtInLibrariesDirs.String())
}

absPath := sketch.FullPath.Parent()
var additionalFilesRelative []string
for _, f := range sketch.AdditionalFiles {
relPath, err := f.RelTo(absPath)
if err != nil {
continue // ignore
}
additionalFilesRelative = append(additionalFilesRelative, relPath.String())
}
opts.Set("additionalFiles", strings.Join(additionalFilesRelative, ","))

return &BuildOptionsManager{
currentOptions: opts,
hardwareDirs: hardwareDirs,
builtInToolsDirs: builtInToolsDirs,
otherLibrariesDirs: otherLibrariesDirs,
builtInLibrariesDirs: builtInLibrariesDirs,
buildPath: buildPath,
runtimePlatformPath: runtimePlatformPath,
buildCorePath: buildCorePath,
sketch: sketch,
customBuildProperties: customBuildProperties,
fqbn: fqbn,
compilerOptimizationFlags: compilerOptimizationFlags,
clean: clean,
builderLogger: buildLogger,
}
}

// WipeBuildPath fixdoc
func (m *BuildOptionsManager) WipeBuildPath() error {
buildOptionsJSON, err := json.MarshalIndent(m.currentOptions, "", " ")
if err != nil {
return errors.WithStack(err)
}
m.currentBuildOptionsJSON = buildOptionsJSON

if err := m.wipeBuildPath(); err != nil {
return errors.WithStack(err)
}
return m.buildPath.Join("build.options.json").WriteFile(buildOptionsJSON)
}

func (m *BuildOptionsManager) wipeBuildPath() error {
wipe := func() error {
// FIXME: this should go outside legacy and behind a `logrus` call so users can
// control when this should be printed.
// logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_BUILD_OPTIONS_CHANGED + constants.MSG_REBUILD_ALL)
if err := m.buildPath.RemoveAll(); err != nil {
return errors.WithMessage(err, tr("cleaning build path"))
}
if err := m.buildPath.MkdirAll(); err != nil {
return errors.WithMessage(err, tr("cleaning build path"))
}
return nil
}

if m.clean {
return wipe()
}

// Load previous build options map
var buildOptionsJSONPrevious []byte
var _err error
if buildOptionsFile := m.buildPath.Join("build.options.json"); buildOptionsFile.Exist() {
buildOptionsJSONPrevious, _err = buildOptionsFile.ReadFile()
if _err != nil {
return errors.WithStack(_err)
}
}

if len(buildOptionsJSONPrevious) == 0 {
return nil
}

var prevOpts *properties.Map
if err := json.Unmarshal(buildOptionsJSONPrevious, &prevOpts); err != nil || prevOpts == nil {
m.builderLogger.Info(tr("%[1]s invalid, rebuilding all", "build.options.json"))
return wipe()
}

// If SketchLocation path is different but filename is the same, consider it equal
if filepath.Base(m.currentOptions.Get("sketchLocation")) == filepath.Base(prevOpts.Get("sketchLocation")) {
m.currentOptions.Remove("sketchLocation")
prevOpts.Remove("sketchLocation")
}

// If options are not changed check if core has
if m.currentOptions.Equals(prevOpts) {
// 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
targetCoreFolder := m.runtimePlatformPath
coreFolder := m.buildCorePath
realCoreFolder := coreFolder.Parent().Parent()
jsonPath := m.buildPath.Join("build.options.json")
coreUnchanged, _ := utils.DirContentIsOlderThan(realCoreFolder, jsonPath, ".txt")
if coreUnchanged && targetCoreFolder != nil && !realCoreFolder.EqualsTo(targetCoreFolder) {
coreUnchanged, _ = utils.DirContentIsOlderThan(targetCoreFolder, jsonPath, ".txt")
}
if coreUnchanged {
return nil
}
}

return wipe()
}
29 changes: 28 additions & 1 deletion arduino/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ type Builder struct {
coreBuildCachePath *paths.Path

logger *logger.BuilderLogger

*BuildOptionsManager

hardwareDirs, builtInToolsDirs, otherLibrariesDirs paths.PathList
builtInLibrariesDirs *paths.Path
fqbn string
clean bool

compilerOptimizationFlags string
runtimePlatformPath, buildCorePath *paths.Path
}

// NewBuilder creates a sketch Builder.
Expand All @@ -59,6 +69,10 @@ func NewBuilder(
coreBuildCachePath *paths.Path,
jobs int,
requestBuildProperties []string,
hardwareDirs, builtInToolsDirs, otherLibrariesDirs paths.PathList,
builtInLibrariesDirs *paths.Path,
fqbn string,
clean bool,
logger *logger.BuilderLogger,
) (*Builder, error) {
buildProperties := properties.NewMap()
Expand Down Expand Up @@ -89,6 +103,7 @@ func NewBuilder(
return nil, fmt.Errorf("invalid build properties: %w", err)
}
buildProperties.Merge(customBuildProperties)
customBuildPropertiesArgs := append(requestBuildProperties, "build.warn_data_percentage=75")

sketchBuildPath, err := buildPath.Join("sketch").Abs()
if err != nil {
Expand All @@ -115,9 +130,21 @@ func NewBuilder(
coreBuildPath: coreBuildPath,
librariesBuildPath: librariesBuildPath,
jobs: jobs,
customBuildProperties: append(requestBuildProperties, "build.warn_data_percentage=75"),
customBuildProperties: customBuildPropertiesArgs,
coreBuildCachePath: coreBuildCachePath,
logger: logger,
BuildOptionsManager: NewBuildOptionsManager(
hardwareDirs, builtInToolsDirs, otherLibrariesDirs,
builtInLibrariesDirs, buildPath,
sk,
customBuildPropertiesArgs,
fqbn,
clean,
buildProperties.Get("compiler.optimization_flags"),
buildProperties.GetPath("runtime.platform.path"),
buildProperties.GetPath("build.core.path"), // TODO can we buildCorePath ?
logger,
),
}, nil
}

Expand Down
10 changes: 7 additions & 3 deletions arduino/builder/sketch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ func TestMergeSketchSources(t *testing.T) {
}
mergedSources := strings.ReplaceAll(string(mergedBytes), "%s", pathToGoldenSource)

b, err := NewBuilder(sk, nil, paths.New("testdata"), false, nil, 0, nil, nil)
b, err := NewBuilder(
sk, nil, paths.New("testdata"), false, nil, 0, nil,
nil, nil, nil, nil, "", false, nil)
require.NoError(t, err)

offset, source, err := b.sketchMergeSources(nil)
Expand All @@ -63,7 +65,8 @@ func TestMergeSketchSourcesArduinoIncluded(t *testing.T) {
require.NotNil(t, sk)

// ensure not to include Arduino.h when it's already there
b, err := NewBuilder(sk, nil, paths.New("testdata"), false, nil, 0, nil, nil)
b, err := NewBuilder(sk, nil, paths.New("testdata"), false, nil, 0, nil,
nil, nil, nil, nil, "", false, nil)
require.NoError(t, err)

_, source, err := b.sketchMergeSources(nil)
Expand All @@ -80,7 +83,8 @@ 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, err := NewBuilder(sk1, nil, paths.New("testdata"), false, nil, 0, nil, nil)
b1, err := NewBuilder(sk1, nil, paths.New("testdata"), false, nil, 0, nil,
nil, nil, nil, nil, "", false, nil)
require.NoError(t, err)

// copy the sketch over, create a fake main file we don't care about it
Expand Down
6 changes: 6 additions & 0 deletions commands/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
coreBuildCachePath,
int(req.GetJobs()),
req.GetBuildProperties(),
builderCtx.HardwareDirs,
builderCtx.BuiltInToolsDirs,
builderCtx.OtherLibrariesDirs,
builderCtx.BuiltInLibrariesDirs,
builderCtx.FQBN.String(),
builderCtx.Clean,
builderLogger,
)
if err != nil {
Expand Down
19 changes: 1 addition & 18 deletions legacy/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,24 +408,7 @@ func recipeByPrefixSuffixRunner(ctx *types.Context, prefix, suffix string, skipI

func containerBuildOptions(ctx *types.Context) types.BareCommand {
return types.BareCommand(func(ctx *types.Context) error {
// TODO here we can pass only the properties we're reading from the
// ctx.Builder.GetBuildProperties()
buildOptionsJSON, buildOptionsJSONPrevious, infoMessage, err := ContainerBuildOptions(
ctx.HardwareDirs, ctx.BuiltInToolsDirs, ctx.OtherLibrariesDirs,
ctx.BuiltInLibrariesDirs, ctx.Builder.GetBuildPath(), ctx.Builder.Sketch(), ctx.Builder.CustomBuildProperties(),
ctx.FQBN.String(), ctx.Clean, ctx.Builder.GetBuildProperties(),
)
if infoMessage != "" {
ctx.BuilderLogger.Info(infoMessage)
}
if err != nil {
return err
}

ctx.BuildOptionsJson = buildOptionsJSON
ctx.BuildOptionsJsonPrevious = buildOptionsJSONPrevious

return nil
return ctx.Builder.BuildOptionsManager.WipeBuildPath()
})
}

Expand Down
60 changes: 0 additions & 60 deletions legacy/builder/container_build_options.go

This file was deleted.

Loading

0 comments on commit 41d66c6

Please sign in to comment.