diff --git a/arduino/cores/fqbn.go b/arduino/cores/fqbn.go index 6df5598682a..35f48c2207e 100644 --- a/arduino/cores/fqbn.go +++ b/arduino/cores/fqbn.go @@ -76,6 +76,16 @@ func (fqbn *FQBN) String() string { return res } +// Clone returns a copy of this FQBN. +func (fqbn *FQBN) Clone() *FQBN { + return &FQBN{ + Package: fqbn.Package, + PlatformArch: fqbn.PlatformArch, + BoardID: fqbn.BoardID, + Configs: fqbn.Configs.Clone(), + } +} + // Match check if the target FQBN corresponds to the receiver one. // The core parts are checked for exact equality while board options are loosely // matched: the set of boards options of the target must be fully contained within diff --git a/arduino/cores/packagemanager/package_manager.go b/arduino/cores/packagemanager/package_manager.go index f385faf2299..8c2b9c88627 100644 --- a/arduino/cores/packagemanager/package_manager.go +++ b/arduino/cores/packagemanager/package_manager.go @@ -826,3 +826,26 @@ func (pme *Explorer) FindMonitorDependency(discovery *cores.MonitorDependency) * return toolRelease.GetLatestInstalled() } } + +// NormalizeFQBN return a normalized copy of the given FQBN, that is the same +// FQBN but with the unneeded or invalid options removed. +func (pme *Explorer) NormalizeFQBN(fqbn *cores.FQBN) (*cores.FQBN, error) { + _, _, board, _, _, err := pme.ResolveFQBN(fqbn) + if err != nil { + return nil, err + } + normalizedFqbn := fqbn.Clone() + for _, option := range fqbn.Configs.Keys() { + values := board.GetConfigOptionValues(option) + if values == nil || values.Size() == 0 { + normalizedFqbn.Configs.Remove(option) + continue + } + + defaultValue := values.Keys()[0] + if fqbn.Configs.Get(option) == defaultValue { + normalizedFqbn.Configs.Remove(option) + } + } + return normalizedFqbn, nil +} diff --git a/arduino/cores/packagemanager/package_manager_test.go b/arduino/cores/packagemanager/package_manager_test.go index afae83f9b55..cf14d9939f6 100644 --- a/arduino/cores/packagemanager/package_manager_test.go +++ b/arduino/cores/packagemanager/package_manager_test.go @@ -67,116 +67,154 @@ func TestResolveFQBN(t *testing.T) { pme, release := pm.NewExplorer() defer release() - fqbn, err := cores.ParseFQBN("arduino:avr:uno") - require.Nil(t, err) - require.NotNil(t, fqbn) - pkg, platformRelease, board, props, buildPlatformRelease, err := pme.ResolveFQBN(fqbn) - require.Nil(t, err) - require.Equal(t, pkg, platformRelease.Platform.Package) - require.NotNil(t, platformRelease) - require.NotNil(t, platformRelease.Platform) - require.Equal(t, platformRelease.Platform.String(), "arduino:avr") - require.NotNil(t, board) - require.Equal(t, board.Name(), "Arduino Uno") - require.NotNil(t, props) - require.Equal(t, platformRelease, buildPlatformRelease) + { + testNormalization := func(in, expected string) { + fqbn, err := cores.ParseFQBN(in) + require.Nil(t, err) + require.NotNil(t, fqbn) + normalized, err := pme.NormalizeFQBN(fqbn) + if expected == "ERROR" { + require.Error(t, err) + require.Nil(t, normalized) + } else { + require.NoError(t, err) + require.NotNil(t, normalized) + require.Equal(t, expected, normalized.String()) + } + } + testNormalization("arduino:avr:mega", "arduino:avr:mega") + testNormalization("arduino:avr:mega:cpu=atmega2560", "arduino:avr:mega") + testNormalization("arduino:avr:mega:cpu=atmega1280", "arduino:avr:mega:cpu=atmega1280") + testNormalization("esp8266:esp8266:generic:baud=57600,wipe=sdk", "esp8266:esp8266:generic:baud=57600,wipe=sdk") + testNormalization("esp8266:esp8266:generic:baud=115200,wipe=sdk", "esp8266:esp8266:generic:wipe=sdk") + testNormalization("arduino:avr:mega:cpu=nonexistent", "ERROR") + testNormalization("arduino:avr:mega:nonexistent=blah", "ERROR") + } - fqbn, err = cores.ParseFQBN("arduino:avr:mega") - require.Nil(t, err) - require.NotNil(t, fqbn) - pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn) - require.Nil(t, err) - require.Equal(t, pkg, platformRelease.Platform.Package) - require.NotNil(t, platformRelease) - require.NotNil(t, platformRelease.Platform) - require.Equal(t, platformRelease.Platform.String(), "arduino:avr") - require.NotNil(t, board) - require.Equal(t, board.Name(), "Arduino Mega or Mega 2560") - require.NotNil(t, props) - require.Equal(t, platformRelease, buildPlatformRelease) + { + fqbn, err := cores.ParseFQBN("arduino:avr:uno") + require.Nil(t, err) + require.NotNil(t, fqbn) + pkg, platformRelease, board, props, buildPlatformRelease, err := pme.ResolveFQBN(fqbn) + require.Nil(t, err) + require.Equal(t, pkg, platformRelease.Platform.Package) + require.NotNil(t, platformRelease) + require.NotNil(t, platformRelease.Platform) + require.Equal(t, platformRelease.Platform.String(), "arduino:avr") + require.NotNil(t, board) + require.Equal(t, board.Name(), "Arduino Uno") + require.NotNil(t, props) + require.Equal(t, platformRelease, buildPlatformRelease) + } - // Test a board referenced from the main AVR arduino platform - fqbn, err = cores.ParseFQBN("referenced:avr:uno") - require.Nil(t, err) - require.NotNil(t, fqbn) - pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn) - require.Nil(t, err) - require.Equal(t, pkg, platformRelease.Platform.Package) - require.NotNil(t, platformRelease) - require.NotNil(t, platformRelease.Platform) - require.Equal(t, platformRelease.Platform.String(), "referenced:avr") - require.NotNil(t, board) - require.Equal(t, board.Name(), "Referenced Uno") - require.NotNil(t, props) - require.NotNil(t, buildPlatformRelease) - require.NotNil(t, buildPlatformRelease.Platform) - require.Equal(t, buildPlatformRelease.Platform.String(), "arduino:avr") - - // Test a board referenced from the Adafruit SAMD core (this tests - // deriving where the package and core name are different) - fqbn, err = cores.ParseFQBN("referenced:samd:feather_m0") - require.Nil(t, err) - require.NotNil(t, fqbn) - pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn) - require.Nil(t, err) - require.Equal(t, pkg, platformRelease.Platform.Package) - require.NotNil(t, platformRelease) - require.NotNil(t, platformRelease.Platform) - require.Equal(t, platformRelease.Platform.String(), "referenced:samd") - require.NotNil(t, board) - require.Equal(t, board.Name(), "Referenced Feather M0") - require.NotNil(t, props) - require.NotNil(t, buildPlatformRelease) - require.NotNil(t, buildPlatformRelease.Platform) - require.Equal(t, buildPlatformRelease.Platform.String(), "adafruit:samd") - - // Test a board referenced from a non-existent package - fqbn, err = cores.ParseFQBN("referenced:avr:dummy_invalid_package") - require.Nil(t, err) - require.NotNil(t, fqbn) - pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn) - require.NotNil(t, err) - require.Equal(t, pkg, platformRelease.Platform.Package) - require.NotNil(t, platformRelease) - require.NotNil(t, platformRelease.Platform) - require.Equal(t, platformRelease.Platform.String(), "referenced:avr") - require.NotNil(t, board) - require.Equal(t, board.Name(), "Referenced dummy with invalid package") - require.Nil(t, props) - require.Nil(t, buildPlatformRelease) + { + fqbn, err := cores.ParseFQBN("arduino:avr:mega") + require.Nil(t, err) + require.NotNil(t, fqbn) + pkg, platformRelease, board, props, buildPlatformRelease, err := pme.ResolveFQBN(fqbn) + require.Nil(t, err) + require.Equal(t, pkg, platformRelease.Platform.Package) + require.NotNil(t, platformRelease) + require.NotNil(t, platformRelease.Platform) + require.Equal(t, platformRelease.Platform.String(), "arduino:avr") + require.NotNil(t, board) + require.Equal(t, board.Name(), "Arduino Mega or Mega 2560") + require.NotNil(t, props) + require.Equal(t, platformRelease, buildPlatformRelease) + } - // Test a board referenced from a non-existent platform/architecture - fqbn, err = cores.ParseFQBN("referenced:avr:dummy_invalid_platform") - require.Nil(t, err) - require.NotNil(t, fqbn) - pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn) - require.NotNil(t, err) - require.Equal(t, pkg, platformRelease.Platform.Package) - require.NotNil(t, platformRelease) - require.NotNil(t, platformRelease.Platform) - require.Equal(t, platformRelease.Platform.String(), "referenced:avr") - require.NotNil(t, board) - require.Equal(t, board.Name(), "Referenced dummy with invalid platform") - require.Nil(t, props) - require.Nil(t, buildPlatformRelease) + { + // Test a board referenced from the main AVR arduino platform + fqbn, err := cores.ParseFQBN("referenced:avr:uno") + require.Nil(t, err) + require.NotNil(t, fqbn) + pkg, platformRelease, board, props, buildPlatformRelease, err := pme.ResolveFQBN(fqbn) + require.Nil(t, err) + require.Equal(t, pkg, platformRelease.Platform.Package) + require.NotNil(t, platformRelease) + require.NotNil(t, platformRelease.Platform) + require.Equal(t, platformRelease.Platform.String(), "referenced:avr") + require.NotNil(t, board) + require.Equal(t, board.Name(), "Referenced Uno") + require.NotNil(t, props) + require.NotNil(t, buildPlatformRelease) + require.NotNil(t, buildPlatformRelease.Platform) + require.Equal(t, buildPlatformRelease.Platform.String(), "arduino:avr") + } - // Test a board referenced from a non-existent core - // Note that ResolveFQBN does not actually check this currently - fqbn, err = cores.ParseFQBN("referenced:avr:dummy_invalid_core") - require.Nil(t, err) - require.NotNil(t, fqbn) - pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn) - require.Nil(t, err) - require.Equal(t, pkg, platformRelease.Platform.Package) - require.NotNil(t, platformRelease) - require.NotNil(t, platformRelease.Platform) - require.Equal(t, platformRelease.Platform.String(), "referenced:avr") - require.NotNil(t, board) - require.Equal(t, board.Name(), "Referenced dummy with invalid core") - require.NotNil(t, props) - require.NotNil(t, buildPlatformRelease) - require.NotNil(t, buildPlatformRelease.Platform) - require.Equal(t, buildPlatformRelease.Platform.String(), "arduino:avr") + { + // Test a board referenced from the Adafruit SAMD core (this tests + // deriving where the package and core name are different) + fqbn, err := cores.ParseFQBN("referenced:samd:feather_m0") + require.Nil(t, err) + require.NotNil(t, fqbn) + pkg, platformRelease, board, props, buildPlatformRelease, err := pme.ResolveFQBN(fqbn) + require.Nil(t, err) + require.Equal(t, pkg, platformRelease.Platform.Package) + require.NotNil(t, platformRelease) + require.NotNil(t, platformRelease.Platform) + require.Equal(t, platformRelease.Platform.String(), "referenced:samd") + require.NotNil(t, board) + require.Equal(t, board.Name(), "Referenced Feather M0") + require.NotNil(t, props) + require.NotNil(t, buildPlatformRelease) + require.NotNil(t, buildPlatformRelease.Platform) + require.Equal(t, buildPlatformRelease.Platform.String(), "adafruit:samd") + } + + { + // Test a board referenced from a non-existent package + fqbn, err := cores.ParseFQBN("referenced:avr:dummy_invalid_package") + require.Nil(t, err) + require.NotNil(t, fqbn) + pkg, platformRelease, board, props, buildPlatformRelease, err := pme.ResolveFQBN(fqbn) + require.NotNil(t, err) + require.Equal(t, pkg, platformRelease.Platform.Package) + require.NotNil(t, platformRelease) + require.NotNil(t, platformRelease.Platform) + require.Equal(t, platformRelease.Platform.String(), "referenced:avr") + require.NotNil(t, board) + require.Equal(t, board.Name(), "Referenced dummy with invalid package") + require.Nil(t, props) + require.Nil(t, buildPlatformRelease) + } + + { + // Test a board referenced from a non-existent platform/architecture + fqbn, err := cores.ParseFQBN("referenced:avr:dummy_invalid_platform") + require.Nil(t, err) + require.NotNil(t, fqbn) + pkg, platformRelease, board, props, buildPlatformRelease, err := pme.ResolveFQBN(fqbn) + require.NotNil(t, err) + require.Equal(t, pkg, platformRelease.Platform.Package) + require.NotNil(t, platformRelease) + require.NotNil(t, platformRelease.Platform) + require.Equal(t, platformRelease.Platform.String(), "referenced:avr") + require.NotNil(t, board) + require.Equal(t, board.Name(), "Referenced dummy with invalid platform") + require.Nil(t, props) + require.Nil(t, buildPlatformRelease) + } + + { + // Test a board referenced from a non-existent core + // Note that ResolveFQBN does not actually check this currently + fqbn, err := cores.ParseFQBN("referenced:avr:dummy_invalid_core") + require.Nil(t, err) + require.NotNil(t, fqbn) + pkg, platformRelease, board, props, buildPlatformRelease, err := pme.ResolveFQBN(fqbn) + require.Nil(t, err) + require.Equal(t, pkg, platformRelease.Platform.Package) + require.NotNil(t, platformRelease) + require.NotNil(t, platformRelease.Platform) + require.Equal(t, platformRelease.Platform.String(), "referenced:avr") + require.NotNil(t, board) + require.Equal(t, board.Name(), "Referenced dummy with invalid core") + require.NotNil(t, props) + require.NotNil(t, buildPlatformRelease) + require.NotNil(t, buildPlatformRelease.Platform) + require.Equal(t, buildPlatformRelease.Platform.String(), "arduino:avr") + } } func TestBoardOptionsFunctions(t *testing.T) { diff --git a/legacy/builder/target_board_resolver.go b/legacy/builder/target_board_resolver.go index c8d4f4a4b96..0d66a435b19 100644 --- a/legacy/builder/target_board_resolver.go +++ b/legacy/builder/target_board_resolver.go @@ -36,9 +36,18 @@ func (s *TargetBoardResolver) Run(ctx *types.Context) error { core = "arduino" } // select the core name in case of "package:core" format + normalizedFQBN, err := ctx.PackageManager.NormalizeFQBN(ctx.FQBN) + if err != nil { + ctx.Warn(fmt.Sprintf("Could not normalize FQBN: %s", err)) + normalizedFQBN = ctx.FQBN + } + ctx.Info(fmt.Sprintf("FQBN: %s", normalizedFQBN)) + core = core[strings.Index(core, ":")+1:] ctx.Info(tr("Using board '%[1]s' from platform in folder: %[2]s", targetBoard.BoardID, targetPlatform.InstallDir)) ctx.Info(tr("Using core '%[1]s' from platform in folder: %[2]s", core, buildPlatform.InstallDir)) + + ctx.Info("") } if buildProperties.Get("build.board") == "" {